mirror of
https://github.com/openai/codex.git
synced 2026-11-05 20:10:33 +00:00
git-utils: serialize Git error paths safely
This commit is contained in:
@@ -69,6 +69,64 @@ fn workspace_metadata_serializes_structured_has_changes_refusal() {
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(any(unix, windows))]
|
||||
#[test]
|
||||
fn turn_metadata_keeps_workspace_failure_with_non_utf8_repository_path() {
|
||||
use std::ffi::OsString;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::ffi::OsStringExt;
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
|
||||
let temp_dir = TempDir::new().expect("temp dir");
|
||||
#[cfg(unix)]
|
||||
let path = std::path::PathBuf::from(OsString::from_vec(b"/repo/\xff".to_vec()));
|
||||
#[cfg(windows)]
|
||||
let path = std::path::PathBuf::from(OsString::from_wide(&[
|
||||
b'C' as u16,
|
||||
b':' as u16,
|
||||
b'\\' as u16,
|
||||
0xd800,
|
||||
]));
|
||||
let lossy = path.to_string_lossy().into_owned();
|
||||
let (has_changes, has_changes_unavailable_reason) =
|
||||
split_has_changes(Err(codex_git_utils::GitReadError::NotRepository { path }));
|
||||
let workspace = WorkspaceGitMetadata {
|
||||
associated_remote_urls: None,
|
||||
latest_git_commit_hash: None,
|
||||
has_changes,
|
||||
has_changes_unavailable_reason,
|
||||
}
|
||||
.into();
|
||||
let state = TurnMetadataState::new(
|
||||
"session-a".to_string(),
|
||||
"thread-a".to_string(),
|
||||
/*forked_from_thread_id*/ None,
|
||||
/*parent_thread_id*/ None,
|
||||
&SessionSource::Exec,
|
||||
/*thread_source*/ None,
|
||||
"turn-a".to_string(),
|
||||
temp_dir.path().abs(),
|
||||
&PermissionProfile::read_only(),
|
||||
WindowsSandboxLevel::Disabled,
|
||||
/*enforce_managed_network*/ false,
|
||||
);
|
||||
*state.enriched_workspaces.write().expect("workspace lock") =
|
||||
Some(BTreeMap::from([("/repo".to_string(), workspace)]));
|
||||
|
||||
let metadata: Value = serde_json::from_str(&test_turn_metadata_header(&state))
|
||||
.expect("full turn metadata remains serializable");
|
||||
assert_eq!(
|
||||
metadata["workspaces"]["/repo"],
|
||||
serde_json::json!({
|
||||
"has_changes_unavailable_reason": {
|
||||
"reason": "notRepository",
|
||||
"path": lossy,
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
fn test_responses_metadata_json(
|
||||
state: &TurnMetadataState,
|
||||
window_id: &str,
|
||||
|
||||
@@ -49,10 +49,15 @@ pub enum GitReadError {
|
||||
#[error("no trusted Git executable is available")]
|
||||
NoTrustedGit,
|
||||
#[error("{path:?} is not a Git repository")]
|
||||
NotRepository { path: PathBuf },
|
||||
NotRepository {
|
||||
#[serde(with = "lossy_path")]
|
||||
path: PathBuf,
|
||||
},
|
||||
#[error("Git resolved {reported_root:?} instead of expected root {expected_root:?}")]
|
||||
RepositoryRootMismatch {
|
||||
#[serde(with = "lossy_path")]
|
||||
expected_root: PathBuf,
|
||||
#[serde(with = "lossy_path")]
|
||||
reported_root: PathBuf,
|
||||
},
|
||||
#[error("Git operation {operation:?} timed out")]
|
||||
@@ -67,3 +72,29 @@ pub enum GitReadError {
|
||||
#[error("executable filter {driver:?} is selected for {path:?}")]
|
||||
SelectedExecutableFilter { driver: String, path: String },
|
||||
}
|
||||
|
||||
/// Path fields in caller-visible diagnostic metadata use a deliberately lossy
|
||||
/// UTF-8 wire representation. The Rust API remains `PathBuf`; deserialization
|
||||
/// reconstructs the serialized path, not any replaced platform-native bytes.
|
||||
mod lossy_path {
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Deserializer;
|
||||
use serde::Serializer;
|
||||
|
||||
pub(super) fn serialize<S>(path: &Path, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&path.to_string_lossy())
|
||||
}
|
||||
|
||||
pub(super) fn deserialize<'de, D>(deserializer: D) -> Result<PathBuf, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
String::deserialize(deserializer).map(PathBuf::from)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user