path-uri: clarify host-native path conversion (#29501)

## Why

Downstream refactors are producing confusing code with this
functionality having a very generic name. Encoding the specific
conversion approach in the method name makes it clearer.

## What

Rename `PathUri::from_path` to `PathUri::from_host_native_path` and
update its Rust call sites.
This commit is contained in:
Adam Perry @ OpenAI
2026-06-22 17:02:33 -07:00
committed by GitHub
Unverified
parent c53b1dae09
commit 11fab432be
31 changed files with 250 additions and 198 deletions
+15 -13
View File
@@ -500,7 +500,7 @@ mod tests {
assert_matches!(
maybe_parse_apply_patch_verified(
&args,
&PathUri::from_path(dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(dir.path()).expect("absolute test path"),
LOCAL_FS.as_ref(),
/*sandbox*/ None,
)
@@ -517,7 +517,7 @@ mod tests {
assert_matches!(
maybe_parse_apply_patch_verified(
&args,
&PathUri::from_path(dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(dir.path()).expect("absolute test path"),
LOCAL_FS.as_ref(),
/*sandbox*/ None,
)
@@ -752,7 +752,7 @@ PATCH"#,
_ => panic!("Expected a single UpdateFile hunk"),
};
let path_uri = PathUri::from_path(&path).expect("absolute test path");
let path_uri = PathUri::from_host_native_path(&path).expect("absolute test path");
let diff =
unified_diff_from_chunks(&path_uri, chunks, LOCAL_FS.as_ref(), /*sandbox*/ None)
.await
@@ -792,7 +792,7 @@ PATCH"#,
_ => panic!("Expected a single UpdateFile hunk"),
};
let path_uri = PathUri::from_path(&path).expect("absolute test path");
let path_uri = PathUri::from_host_native_path(&path).expect("absolute test path");
let diff =
unified_diff_from_chunks(&path_uri, chunks, LOCAL_FS.as_ref(), /*sandbox*/ None)
.await
@@ -832,7 +832,7 @@ PATCH"#,
let result = maybe_parse_apply_patch_verified(
&argv,
&PathUri::from_path(session_dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(session_dir.path()).expect("absolute test path"),
LOCAL_FS.as_ref(),
/*sandbox*/ None,
)
@@ -844,7 +844,7 @@ PATCH"#,
result,
MaybeApplyPatchVerified::Body(ApplyPatchAction {
changes: HashMap::from([(
PathUri::from_path(session_dir.path().join(relative_path))
PathUri::from_host_native_path(session_dir.path().join(relative_path))
.expect("absolute test path"),
ApplyPatchFileChange::Update {
unified_diff: r#"@@ -1 +1 @@
@@ -857,7 +857,8 @@ PATCH"#,
},
)]),
patch: argv[1].clone(),
cwd: PathUri::from_path(session_dir.path()).expect("absolute test path"),
cwd: PathUri::from_host_native_path(session_dir.path())
.expect("absolute test path"),
})
);
}
@@ -887,7 +888,7 @@ PATCH"#,
let result = maybe_parse_apply_patch_verified(
&argv,
&PathUri::from_path(session_dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(session_dir.path()).expect("absolute test path"),
LOCAL_FS.as_ref(),
/*sandbox*/ None,
)
@@ -902,8 +903,8 @@ PATCH"#,
worktree_dir.as_path()
);
let source_path =
PathUri::from_path(worktree_dir.join(source_name)).expect("absolute test path");
let source_path = PathUri::from_host_native_path(worktree_dir.join(source_name))
.expect("absolute test path");
let change = action
.changes()
.get(&source_path)
@@ -912,7 +913,8 @@ PATCH"#,
match change {
ApplyPatchFileChange::Update { move_path, .. } => {
let expected_move_path =
PathUri::from_path(worktree_dir.join(dest_name)).expect("absolute test path");
PathUri::from_host_native_path(worktree_dir.join(dest_name))
.expect("absolute test path");
assert_eq!(move_path.as_ref(), Some(&expected_move_path));
}
other => panic!("expected update change, got {other:?}"),
@@ -923,7 +925,7 @@ PATCH"#,
async fn test_unreadable_destinations_still_verify() {
let session_dir = tempdir().unwrap();
fs::write(session_dir.path().join("binary.dat"), [0xff, 0xfe, 0xfd]).unwrap();
let cwd = PathUri::from_path(session_dir.path()).expect("absolute test path");
let cwd = PathUri::from_host_native_path(session_dir.path()).expect("absolute test path");
let add_argv = vec![
"apply_patch".to_string(),
"*** Begin Patch\n*** Add File: binary.dat\n+text\n*** End Patch".to_string(),
@@ -966,7 +968,7 @@ PATCH"#,
let result = maybe_parse_apply_patch_verified(
&argv,
&PathUri::from_path(session_dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(session_dir.path()).expect("absolute test path"),
LOCAL_FS.as_ref(),
/*sandbox*/ None,
)
+19 -19
View File
@@ -913,7 +913,7 @@ mod tests {
let mut stderr = Vec::new();
apply_patch(
&patch,
&PathUri::from_path(dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(dir.path()).expect("absolute test path"),
&mut stdout,
&mut stderr,
LOCAL_FS.as_ref(),
@@ -937,7 +937,7 @@ mod tests {
#[tokio::test]
async fn test_apply_patch_hunks_accept_relative_and_absolute_paths() {
let dir = tempdir().unwrap();
let cwd = PathUri::from_path(dir.path()).expect("absolute test path");
let cwd = PathUri::from_host_native_path(dir.path()).expect("absolute test path");
let relative_add = dir.path().join("relative-add.txt");
let absolute_add = dir.path().join("absolute-add.txt");
let relative_delete = dir.path().join("relative-delete.txt");
@@ -1016,7 +1016,7 @@ mod tests {
let mut stderr = Vec::new();
apply_patch(
&patch,
&PathUri::from_path(dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(dir.path()).expect("absolute test path"),
&mut stdout,
&mut stderr,
LOCAL_FS.as_ref(),
@@ -1052,7 +1052,7 @@ mod tests {
let mut stderr = Vec::new();
apply_patch(
&patch,
&PathUri::from_path(dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(dir.path()).expect("absolute test path"),
&mut stdout,
&mut stderr,
LOCAL_FS.as_ref(),
@@ -1092,7 +1092,7 @@ mod tests {
let mut stderr = Vec::new();
apply_patch(
&patch,
&PathUri::from_path(dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(dir.path()).expect("absolute test path"),
&mut stdout,
&mut stderr,
LOCAL_FS.as_ref(),
@@ -1136,7 +1136,7 @@ mod tests {
let mut stderr = Vec::new();
let failure = apply_patch(
&patch,
&PathUri::from_path(dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(dir.path()).expect("absolute test path"),
&mut stdout,
&mut stderr,
LOCAL_FS.as_ref(),
@@ -1196,7 +1196,7 @@ mod tests {
let mut stderr = Vec::new();
apply_patch(
&patch,
&PathUri::from_path(dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(dir.path()).expect("absolute test path"),
&mut stdout,
&mut stderr,
LOCAL_FS.as_ref(),
@@ -1254,7 +1254,7 @@ mod tests {
let mut stderr = Vec::new();
apply_patch(
&patch,
&PathUri::from_path(dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(dir.path()).expect("absolute test path"),
&mut stdout,
&mut stderr,
LOCAL_FS.as_ref(),
@@ -1298,7 +1298,7 @@ mod tests {
let mut stderr = Vec::new();
apply_patch(
&patch,
&PathUri::from_path(dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(dir.path()).expect("absolute test path"),
&mut stdout,
&mut stderr,
LOCAL_FS.as_ref(),
@@ -1341,7 +1341,7 @@ mod tests {
let mut stderr = Vec::new();
apply_patch(
&patch,
&PathUri::from_path(dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(dir.path()).expect("absolute test path"),
&mut stdout,
&mut stderr,
LOCAL_FS.as_ref(),
@@ -1391,7 +1391,7 @@ mod tests {
[Hunk::UpdateFile { chunks, .. }] => chunks,
_ => panic!("Expected a single UpdateFile hunk"),
};
let path_uri = PathUri::from_path(&path).expect("absolute test path");
let path_uri = PathUri::from_host_native_path(&path).expect("absolute test path");
let diff = unified_diff_from_chunks(
&path_uri,
update_file_chunks,
@@ -1439,7 +1439,7 @@ mod tests {
_ => panic!("Expected a single UpdateFile hunk"),
};
let resolved_path = PathUri::from_path(&path).expect("absolute test path");
let resolved_path = PathUri::from_host_native_path(&path).expect("absolute test path");
let diff = unified_diff_from_chunks(
&resolved_path,
chunks,
@@ -1485,7 +1485,7 @@ mod tests {
_ => panic!("Expected a single UpdateFile hunk"),
};
let resolved_path = PathUri::from_path(&path).expect("absolute test path");
let resolved_path = PathUri::from_host_native_path(&path).expect("absolute test path");
let diff = unified_diff_from_chunks(
&resolved_path,
chunks,
@@ -1529,7 +1529,7 @@ mod tests {
_ => panic!("Expected a single UpdateFile hunk"),
};
let path_uri = PathUri::from_path(&path).expect("absolute test path");
let path_uri = PathUri::from_host_native_path(&path).expect("absolute test path");
let diff =
unified_diff_from_chunks(&path_uri, chunks, LOCAL_FS.as_ref(), /*sandbox*/ None)
.await
@@ -1580,7 +1580,7 @@ mod tests {
_ => panic!("Expected a single UpdateFile hunk"),
};
let path_uri = PathUri::from_path(&path).expect("absolute test path");
let path_uri = PathUri::from_host_native_path(&path).expect("absolute test path");
let diff =
unified_diff_from_chunks(&path_uri, chunks, LOCAL_FS.as_ref(), /*sandbox*/ None)
.await
@@ -1610,7 +1610,7 @@ mod tests {
let mut stderr = Vec::new();
apply_patch(
&patch,
&PathUri::from_path(dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(dir.path()).expect("absolute test path"),
&mut stdout,
&mut stderr,
LOCAL_FS.as_ref(),
@@ -1648,7 +1648,7 @@ g
let mut stderr = Vec::new();
let result = apply_patch(
&patch,
&PathUri::from_path(dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(dir.path()).expect("absolute test path"),
&mut stdout,
&mut stderr,
LOCAL_FS.as_ref(),
@@ -1667,7 +1667,7 @@ g
let dir = tempdir().unwrap();
let path = dir.path().join("binary.dat");
fs::write(dir.path().join("source.txt"), "before\n").unwrap();
let cwd = PathUri::from_path(dir.path()).expect("absolute test path");
let cwd = PathUri::from_host_native_path(dir.path()).expect("absolute test path");
for patch in [
wrap_patch("*** Add File: binary.dat\n+text"),
@@ -1705,7 +1705,7 @@ g
let mut stderr = Vec::new();
let delta = apply_patch(
&patch,
&PathUri::from_path(dir.path()).expect("absolute test path"),
&PathUri::from_host_native_path(dir.path()).expect("absolute test path"),
&mut stdout,
&mut stderr,
LOCAL_FS.as_ref(),
+1 -1
View File
@@ -480,7 +480,7 @@ fn test_parse_patch_accepts_relative_and_absolute_hunk_paths() {
#[test]
fn test_hunk_resolve_path_accepts_relative_and_absolute_paths() {
let cwd_dir = tempfile::tempdir().unwrap();
let cwd = PathUri::from_path(cwd_dir.path()).unwrap();
let cwd = PathUri::from_host_native_path(cwd_dir.path()).unwrap();
let absolute_dir = tempfile::tempdir().unwrap();
let absolute_add = absolute_dir.path().join("absolute-add.py").abs();
let absolute_delete = absolute_dir.path().join("absolute-delete.py").abs();
+1 -1
View File
@@ -8,7 +8,7 @@ use tempfile::tempdir;
fn convert_apply_patch_maps_add_variant() {
let tmp = tempdir().expect("tmp");
let path = tmp.path().join("a.txt");
let path_uri = PathUri::from_path(&path).expect("absolute test path");
let path_uri = PathUri::from_host_native_path(&path).expect("absolute test path");
let action = ApplyPatchAction::new_add_for_test(&path_uri, "hello".to_string());
let got = convert_apply_patch_to_protocol(&action);
+3 -3
View File
@@ -645,7 +645,7 @@ mod tests {
make_session_and_context_with_dynamic_tools_and_rx(Vec::new()).await;
let tracker = Arc::new(Mutex::new(TurnDiffTracker::new()));
let dir = tempdir().expect("tempdir");
let cwd = PathUri::from_path(dir.path()).expect("absolute cwd");
let cwd = PathUri::from_host_native_path(dir.path()).expect("absolute cwd");
let mut stdout = Vec::new();
let mut stderr = Vec::new();
let delta = codex_apply_patch::apply_patch(
@@ -729,7 +729,7 @@ mod tests {
make_session_and_context_with_dynamic_tools_and_rx(Vec::new()).await;
let tracker = Arc::new(Mutex::new(TurnDiffTracker::new()));
let dir = tempdir().expect("tempdir");
let cwd = PathUri::from_path(dir.path()).expect("absolute cwd");
let cwd = PathUri::from_host_native_path(dir.path()).expect("absolute cwd");
for patch in [
"*** Begin Patch\n*** Add File: a.txt\n+one\n*** End Patch",
@@ -782,7 +782,7 @@ mod tests {
make_session_and_context_with_dynamic_tools_and_rx(Vec::new()).await;
let tracker = Arc::new(Mutex::new(TurnDiffTracker::new()));
let dir = tempdir().expect("tempdir");
let cwd = PathUri::from_path(dir.path()).expect("absolute cwd");
let cwd = PathUri::from_host_native_path(dir.path()).expect("absolute cwd");
let mut stdout = Vec::new();
let mut stderr = Vec::new();
let delta = codex_apply_patch::apply_patch(
+1 -1
View File
@@ -18,7 +18,7 @@ fn git_blob_sha1_hex(data: &str) -> String {
}
async fn apply_verified_patch(root: &Path, patch: &str) -> AppliedPatchDelta {
let cwd = PathUri::from_path(root).expect("absolute tempdir path");
let cwd = PathUri::from_host_native_path(root).expect("absolute tempdir path");
let argv = vec!["apply_patch".to_string(), patch.to_string()];
match codex_apply_patch::maybe_parse_apply_patch_verified(
&argv,
+4 -4
View File
@@ -998,7 +998,7 @@ impl TestCodexHarness {
) -> Result<()> {
let abs_path = self.path_abs(rel);
if let Some(parent) = abs_path.parent() {
let parent_uri = PathUri::from_path(&parent)?;
let parent_uri = PathUri::from_host_native_path(&parent)?;
self.test
.fs()
.create_directory(
@@ -1008,7 +1008,7 @@ impl TestCodexHarness {
)
.await?;
}
let abs_path_uri = PathUri::from_path(&abs_path)?;
let abs_path_uri = PathUri::from_host_native_path(&abs_path)?;
self.test
.fs()
.write_file(
@@ -1022,7 +1022,7 @@ impl TestCodexHarness {
pub async fn read_file_text(&self, rel: impl AsRef<Path>) -> Result<String> {
let path = self.path_abs(rel);
let path_uri = PathUri::from_path(&path)?;
let path_uri = PathUri::from_host_native_path(&path)?;
Ok(self
.test
.fs()
@@ -1032,7 +1032,7 @@ impl TestCodexHarness {
pub async fn create_dir_all(&self, rel: impl AsRef<Path>) -> Result<()> {
let path = self.path_abs(rel);
let path_uri = PathUri::from_path(&path)?;
let path_uri = PathUri::from_host_native_path(&path)?;
self.test
.fs()
.create_directory(
+18 -17
View File
@@ -141,8 +141,8 @@ async fn agents_override_is_preferred_over_agents_md() -> Result<()> {
agents_instructions(test_codex().with_workspace_setup(|cwd, fs| async move {
let agents_md = cwd.join("AGENTS.md");
let override_md = cwd.join("AGENTS.override.md");
let agents_md_uri = PathUri::from_path(&agents_md)?;
let override_md_uri = PathUri::from_path(&override_md)?;
let agents_md_uri = PathUri::from_host_native_path(&agents_md)?;
let override_md_uri = PathUri::from_host_native_path(&override_md)?;
fs.write_file(&agents_md_uri, b"base doc".to_vec(), /*sandbox*/ None)
.await?;
fs.write_file(
@@ -177,8 +177,8 @@ async fn configured_fallback_is_used_when_agents_candidate_is_directory() -> Res
.with_workspace_setup(|cwd, fs| async move {
let agents_dir = cwd.join("AGENTS.md");
let fallback = cwd.join("WORKFLOW.md");
let agents_dir_uri = PathUri::from_path(&agents_dir)?;
let fallback_uri = PathUri::from_path(&fallback)?;
let agents_dir_uri = PathUri::from_host_native_path(&agents_dir)?;
let fallback_uri = PathUri::from_host_native_path(&fallback)?;
fs.create_directory(
&agents_dir_uri,
CreateDirectoryOptions { recursive: true },
@@ -220,10 +220,10 @@ async fn agents_docs_are_concatenated_from_project_root_to_cwd() -> Result<()> {
let root_agents = root.join("AGENTS.md");
let git_marker = root.join(".git");
let nested_agents = nested.join("AGENTS.md");
let nested_uri = PathUri::from_path(&nested)?;
let root_agents_uri = PathUri::from_path(&root_agents)?;
let git_marker_uri = PathUri::from_path(&git_marker)?;
let nested_agents_uri = PathUri::from_path(&nested_agents)?;
let nested_uri = PathUri::from_host_native_path(&nested)?;
let root_agents_uri = PathUri::from_host_native_path(&root_agents)?;
let git_marker_uri = PathUri::from_host_native_path(&git_marker)?;
let nested_agents_uri = PathUri::from_host_native_path(&nested_agents)?;
fs.create_directory(
&nested_uri,
@@ -363,7 +363,7 @@ async fn selected_environment_sources_match_model_visible_instructions() -> Resu
let mut builder = test_codex()
.with_home(home)
.with_workspace_setup(|cwd, fs| async move {
let agents_md_uri = PathUri::from_path(cwd.join("AGENTS.md"))?;
let agents_md_uri = PathUri::from_host_native_path(cwd.join("AGENTS.md"))?;
fs.write_file(
&agents_md_uri,
b"project doc".to_vec(),
@@ -420,7 +420,8 @@ async fn loads_user_instructions_without_a_primary_environment() -> Result<()> {
.with_home(Arc::clone(&home))
.with_user_instructions_provider(provider.clone())
.with_workspace_setup(|cwd, fs| async move {
let project_agents_uri = PathUri::from_path(cwd.join(GLOBAL_AGENTS_FILENAME))?;
let project_agents_uri =
PathUri::from_host_native_path(cwd.join(GLOBAL_AGENTS_FILENAME))?;
fs.write_file(
&project_agents_uri,
PROJECT_INSTRUCTIONS.as_bytes().to_vec(),
@@ -505,7 +506,7 @@ async fn fresh_thread_composes_global_before_project_and_reports_sources() -> Re
let mut builder = test_codex()
.with_home(Arc::clone(&home))
.with_workspace_setup(|cwd, fs| async move {
let agents_md_uri = PathUri::from_path(cwd.join("AGENTS.md"))?;
let agents_md_uri = PathUri::from_host_native_path(cwd.join("AGENTS.md"))?;
fs.write_file(
&agents_md_uri,
PROJECT_INSTRUCTIONS.as_bytes().to_vec(),
@@ -534,7 +535,7 @@ async fn fresh_thread_composes_global_before_project_and_reports_sources() -> Re
)?;
test.fs()
.write_file(
&PathUri::from_path(&project_source)?,
&PathUri::from_host_native_path(&project_source)?,
NEW_PROJECT_INSTRUCTIONS.as_bytes().to_vec(),
/*sandbox*/ None,
)
@@ -631,7 +632,7 @@ async fn multi_environment_thread_loads_every_project_and_keeps_creation_snapsho
.with_user_instructions_provider(provider.clone())
.with_workspace_setup(|cwd, fs| async move {
fs.write_file(
&PathUri::from_path(cwd.join(GLOBAL_AGENTS_FILENAME))?,
&PathUri::from_host_native_path(cwd.join(GLOBAL_AGENTS_FILENAME))?,
b"remote project instructions".to_vec(),
/*sandbox*/ None,
)
@@ -658,7 +659,7 @@ async fn multi_environment_thread_loads_every_project_and_keeps_creation_snapsho
},
TurnEnvironmentSelection {
environment_id: LOCAL_ENVIRONMENT_ID.to_string(),
cwd: PathUri::from_path(local_root.path())?,
cwd: PathUri::from_host_native_path(local_root.path())?,
},
],
thread_extension_init: Default::default(),
@@ -671,7 +672,7 @@ async fn multi_environment_thread_loads_every_project_and_keeps_creation_snapsho
vec![
PathUri::from_abs_path(&global_source),
PathUri::from_abs_path(&remote_source),
PathUri::from_path(&local_source)?,
PathUri::from_host_native_path(&local_source)?,
]
);
@@ -684,7 +685,7 @@ async fn multi_environment_thread_loads_every_project_and_keeps_creation_snapsho
)?;
test.fs()
.write_file(
&PathUri::from_path(test.config.cwd.join(GLOBAL_AGENTS_OVERRIDE_FILENAME))?,
&PathUri::from_host_native_path(test.config.cwd.join(GLOBAL_AGENTS_OVERRIDE_FILENAME))?,
b"new remote project instructions".to_vec(),
/*sandbox*/ None,
)
@@ -712,7 +713,7 @@ async fn multi_environment_thread_loads_every_project_and_keeps_creation_snapsho
vec![
PathUri::from_abs_path(&global_source),
PathUri::from_abs_path(&remote_source),
PathUri::from_path(&local_source)?,
PathUri::from_host_native_path(&local_source)?,
]
);
+6 -6
View File
@@ -1329,7 +1329,7 @@ async fn apply_patch_turn_diff_paths_stay_repo_relative_when_session_cwd_is_nest
config.cwd = config.cwd.join("subdir");
})
.with_workspace_setup(|cwd, fs| async move {
let cwd_uri = PathUri::from_path(&cwd)?;
let cwd_uri = PathUri::from_host_native_path(&cwd)?;
fs.create_directory(
&cwd_uri,
CreateDirectoryOptions { recursive: true },
@@ -1337,8 +1337,8 @@ async fn apply_patch_turn_diff_paths_stay_repo_relative_when_session_cwd_is_nest
)
.await?;
let repo_root = cwd.parent().expect("nested cwd should have parent");
let git_uri = PathUri::from_path(repo_root.join(".git"))?;
let repo_file_uri = PathUri::from_path(repo_root.join("repo.txt"))?;
let git_uri = PathUri::from_host_native_path(repo_root.join(".git"))?;
let repo_file_uri = PathUri::from_host_native_path(repo_root.join("repo.txt"))?;
fs.write_file(
&git_uri,
b"gitdir: /tmp/fake-worktree\n".to_vec(),
@@ -1586,7 +1586,7 @@ async fn apply_patch_turn_diff_tracks_local_and_remote_environment_paths() -> Re
SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis()
))
.abs();
let shared_cwd_uri = PathUri::from_path(&shared_cwd)?;
let shared_cwd_uri = PathUri::from_host_native_path(&shared_cwd)?;
let _ = fs::remove_dir_all(shared_cwd.as_path());
test.fs()
.remove(
@@ -1689,7 +1689,7 @@ async fn apply_patch_turn_diff_tracks_local_and_remote_environment_paths() -> Re
assert_eq!(
test.fs()
.read_file_text(
&PathUri::from_path(shared_cwd.join(file_name))?,
&PathUri::from_host_native_path(shared_cwd.join(file_name))?,
/*sandbox*/ None,
)
.await?,
@@ -1859,7 +1859,7 @@ async fn apply_patch_clears_aggregated_diff_after_inexact_delta() -> Result<()>
let harness = apply_patch_harness_with(|builder| {
builder.with_workspace_setup(|cwd, fs| async move {
let binary_path_uri = PathUri::from_path(cwd.join("binary.dat"))?;
let binary_path_uri = PathUri::from_host_native_path(cwd.join("binary.dat"))?;
fs.write_file(
&binary_path_uri,
vec![0xff, 0xfe, 0xfd],
@@ -74,7 +74,7 @@ async fn approved_network_host_for_one_environment_still_prompts_in_another() ->
SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis()
))
.abs();
let remote_cwd_uri = PathUri::from_path(&remote_cwd)?;
let remote_cwd_uri = PathUri::from_host_native_path(&remote_cwd)?;
test.fs()
.create_directory(
&remote_cwd_uri,
+25 -22
View File
@@ -173,7 +173,7 @@ async fn remote_test_env_can_connect_and_use_filesystem() -> Result<()> {
let file_system = test_env.environment().get_filesystem();
let file_path_abs = test_env.cwd().join("remote-test-env-ok");
let file_path_uri = PathUri::from_path(&file_path_abs)?;
let file_path_uri = PathUri::from_host_native_path(&file_path_abs)?;
let payload = b"remote-test-env-ok".to_vec();
file_system
@@ -329,8 +329,8 @@ async fn remote_sandbox_denial_requests_approval_and_retries() -> Result<()> {
let nonce = SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis();
let remote_cwd = PathBuf::from(format!("/tmp/codex-remote-denial-cwd-{nonce}")).abs();
let target_path = PathBuf::from(format!("/tmp/codex-remote-denial-target-{nonce}")).abs();
let remote_cwd_uri = PathUri::from_path(&remote_cwd)?;
let target_uri = PathUri::from_path(&target_path)?;
let remote_cwd_uri = PathUri::from_host_native_path(&remote_cwd)?;
let target_uri = PathUri::from_host_native_path(&target_path)?;
test.fs()
.create_directory(
&remote_cwd_uri,
@@ -801,8 +801,8 @@ async fn exec_command_routes_to_selected_remote_environment() -> Result<()> {
))
.abs();
let remote_marker_name = "marker.txt";
let remote_cwd_uri = PathUri::from_path(&remote_cwd)?;
let remote_marker_uri = PathUri::from_path(remote_cwd.join(remote_marker_name))?;
let remote_cwd_uri = PathUri::from_host_native_path(&remote_cwd)?;
let remote_marker_uri = PathUri::from_host_native_path(remote_cwd.join(remote_marker_name))?;
test.fs()
.create_directory(
&remote_cwd_uri,
@@ -900,7 +900,7 @@ async fn remote_request_permissions_grant_unblocks_later_remote_exec() -> Result
let local_write_root = local_cwd.path().join(relative_write_root);
let local_target_path = local_cwd.path().join(relative_target_path);
fs::create_dir(&local_write_root)?;
let remote_write_root_uri = PathUri::from_path(&remote_write_root)?;
let remote_write_root_uri = PathUri::from_host_native_path(&remote_write_root)?;
test.fs()
.create_directory(
&remote_write_root_uri,
@@ -1040,7 +1040,7 @@ async fn remote_request_permissions_grant_unblocks_later_remote_exec() -> Result
assert_eq!(
test.fs()
.read_file_text(
&PathUri::from_path(&remote_target_path)?,
&PathUri::from_host_native_path(&remote_target_path)?,
/*sandbox*/ None,
)
.await?,
@@ -1084,7 +1084,7 @@ async fn apply_patch_freeform_routes_to_selected_remote_environment() -> Result<
SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis()
))
.abs();
let remote_cwd_uri = PathUri::from_path(&remote_cwd)?;
let remote_cwd_uri = PathUri::from_host_native_path(&remote_cwd)?;
test.fs()
.create_directory(
&remote_cwd_uri,
@@ -1129,7 +1129,7 @@ async fn apply_patch_freeform_routes_to_selected_remote_environment() -> Result<
let remote_contents = test
.fs()
.read_file_text(
&PathUri::from_path(remote_cwd.join(file_name))?,
&PathUri::from_host_native_path(remote_cwd.join(file_name))?,
/*sandbox*/ None,
)
.await?;
@@ -1174,7 +1174,7 @@ async fn apply_patch_approvals_are_remembered_per_environment() -> Result<()> {
SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis()
))
.abs();
let remote_cwd_uri = PathUri::from_path(&remote_cwd)?;
let remote_cwd_uri = PathUri::from_host_native_path(&remote_cwd)?;
test.fs()
.create_directory(
&remote_cwd_uri,
@@ -1188,7 +1188,7 @@ async fn apply_patch_approvals_are_remembered_per_environment() -> Result<()> {
SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis()
))
.abs();
let target_path_uri = PathUri::from_path(&target_path)?;
let target_path_uri = PathUri::from_host_native_path(&target_path)?;
let _ = fs::remove_file(&target_path);
test.fs()
.remove(
@@ -1362,7 +1362,7 @@ async fn apply_patch_intercepted_exec_command_routes_to_selected_remote_environm
SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis()
))
.abs();
let remote_cwd_uri = PathUri::from_path(&remote_cwd)?;
let remote_cwd_uri = PathUri::from_host_native_path(&remote_cwd)?;
test.fs()
.create_directory(
&remote_cwd_uri,
@@ -1417,7 +1417,7 @@ async fn apply_patch_intercepted_exec_command_routes_to_selected_remote_environm
let remote_contents = test
.fs()
.read_file_text(
&PathUri::from_path(remote_cwd.join(file_name))?,
&PathUri::from_host_native_path(remote_cwd.join(file_name))?,
/*sandbox*/ None,
)
.await?;
@@ -1455,8 +1455,8 @@ async fn remote_test_env_sandboxed_read_allows_readable_root() -> Result<()> {
let allowed_dir = PathBuf::from(format!("/tmp/codex-remote-readable-{}", std::process::id()));
let file_path = allowed_dir.join("note.txt");
let allowed_dir_uri = PathUri::from_path(&allowed_dir)?;
let file_path_uri = PathUri::from_path(&file_path)?;
let allowed_dir_uri = PathUri::from_host_native_path(&allowed_dir)?;
let file_path_uri = PathUri::from_host_native_path(&file_path)?;
file_system
.create_directory(
&allowed_dir_uri,
@@ -1516,7 +1516,7 @@ async fn remote_test_env_sandboxed_read_rejects_symlink_parent_dotdot_escape() -
))?;
let requested_path =
PathUri::from_path(allowed_dir.join("link").join("..").join("secret.txt"))?;
PathUri::from_host_native_path(allowed_dir.join("link").join("..").join("secret.txt"))?;
let sandbox = read_only_sandbox(allowed_dir.clone());
let error = match file_system.read_file(&requested_path, Some(&sandbox)).await {
Ok(_) => anyhow::bail!("read should fail after path normalization"),
@@ -1564,7 +1564,7 @@ async fn remote_test_env_remove_removes_symlink_not_target() -> Result<()> {
let sandbox = workspace_write_sandbox(allowed_dir.clone());
file_system
.remove(
&PathUri::from_path(&symlink_path)?,
&PathUri::from_host_native_path(&symlink_path)?,
RemoveOptions {
recursive: false,
force: false,
@@ -1582,13 +1582,16 @@ async fn remote_test_env_remove_removes_symlink_not_target() -> Result<()> {
.is_ok();
assert!(!symlink_exists);
let outside = file_system
.read_file_text(&PathUri::from_path(&outside_file)?, /*sandbox*/ None)
.read_file_text(
&PathUri::from_host_native_path(&outside_file)?,
/*sandbox*/ None,
)
.await?;
assert_eq!(outside, "outside");
file_system
.remove(
&PathUri::from_path(&root)?,
&PathUri::from_host_native_path(&root)?,
RemoveOptions {
recursive: true,
force: true,
@@ -1630,8 +1633,8 @@ async fn remote_test_env_copy_preserves_symlink_source() -> Result<()> {
let sandbox = workspace_write_sandbox(allowed_dir.clone());
file_system
.copy(
&PathUri::from_path(&source_symlink)?,
&PathUri::from_path(&copied_symlink)?,
&PathUri::from_host_native_path(&source_symlink)?,
&PathUri::from_host_native_path(&copied_symlink)?,
CopyOptions { recursive: false },
Some(&sandbox),
)
@@ -1664,7 +1667,7 @@ async fn remote_test_env_copy_preserves_symlink_source() -> Result<()> {
file_system
.remove(
&PathUri::from_path(&root)?,
&PathUri::from_host_native_path(&root)?,
RemoveOptions {
recursive: true,
force: true,
+1 -1
View File
@@ -747,7 +747,7 @@ async fn stdio_server_uses_configured_cwd_before_runtime_fallback() -> anyhow::R
let fixture = test_codex()
.with_workspace_setup(|cwd, fs| async move {
let configured_cwd = cwd.join("mcp-configured-cwd");
let configured_cwd_uri = PathUri::from_path(&configured_cwd)?;
let configured_cwd_uri = PathUri::from_host_native_path(&configured_cwd)?;
fs.create_directory(
&configured_cwd_uri,
CreateDirectoryOptions { recursive: true },
+2 -2
View File
@@ -31,7 +31,7 @@ async fn write_repo_skill(
body: &str,
) -> Result<()> {
let skill_dir = cwd.join(".agents").join("skills").join(name);
let skill_dir_uri = PathUri::from_path(&skill_dir)?;
let skill_dir_uri = PathUri::from_host_native_path(&skill_dir)?;
fs.create_directory(
&skill_dir_uri,
CreateDirectoryOptions { recursive: true },
@@ -40,7 +40,7 @@ async fn write_repo_skill(
.await?;
let contents = format!("---\nname: {name}\ndescription: {description}\n---\n\n{body}\n");
let path = skill_dir.join("SKILL.md");
let path_uri = PathUri::from_path(&path)?;
let path_uri = PathUri::from_host_native_path(&path)?;
fs.write_file(&path_uri, contents.into_bytes(), /*sandbox*/ None)
.await?;
Ok(())
+4 -4
View File
@@ -229,7 +229,7 @@ async fn create_workspace_directory(
rel_path: impl AsRef<std::path::Path>,
) -> Result<std::path::PathBuf> {
let abs_path = test.config.cwd.join(rel_path.as_ref());
let abs_path_uri = PathUri::from_path(&abs_path)?;
let abs_path_uri = PathUri::from_host_native_path(&abs_path)?;
test.fs()
.create_directory(
&abs_path_uri,
@@ -437,7 +437,7 @@ async fn unified_exec_emits_exec_command_begin_event() -> Result<()> {
assert_command(&begin_event.command, "-lc", "/bin/echo hello unified exec");
assert_eq!(begin_event.cwd, PathUri::from_path(&cwd)?);
assert_eq!(begin_event.cwd, PathUri::from_host_native_path(&cwd)?);
wait_for_event(&test.codex, |event| {
matches!(event, EventMsg::TurnComplete(_))
@@ -508,7 +508,7 @@ async fn unified_exec_resolves_relative_workdir() -> Result<()> {
assert_eq!(
begin_event.cwd,
PathUri::from_path(&workdir)?,
PathUri::from_host_native_path(&workdir)?,
"exec_command cwd should resolve relative workdir against turn cwd",
);
@@ -570,7 +570,7 @@ async fn unified_exec_respects_workdir_override() -> Result<()> {
assert_eq!(
begin_event.cwd,
PathUri::from_path(&workdir)?,
PathUri::from_host_native_path(&workdir)?,
"exec_command cwd should reflect the requested workdir override"
);
+5 -5
View File
@@ -133,7 +133,7 @@ fn png_bytes(width: u32, height: u32, rgba: [u8; 4]) -> anyhow::Result<Vec<u8>>
async fn create_workspace_directory(test: &TestCodex, rel_path: &str) -> anyhow::Result<PathBuf> {
let abs_path = test.config.cwd.join(rel_path);
let abs_path_uri = PathUri::from_path(&abs_path)?;
let abs_path_uri = PathUri::from_host_native_path(&abs_path)?;
test.fs()
.create_directory(
&abs_path_uri,
@@ -151,7 +151,7 @@ async fn write_workspace_file(
) -> anyhow::Result<PathBuf> {
let abs_path = test.config.cwd.join(rel_path);
if let Some(parent) = abs_path.parent() {
let parent_uri = PathUri::from_path(&parent)?;
let parent_uri = PathUri::from_host_native_path(&parent)?;
test.fs()
.create_directory(
&parent_uri,
@@ -160,7 +160,7 @@ async fn write_workspace_file(
)
.await?;
}
let abs_path_uri = PathUri::from_path(&abs_path)?;
let abs_path_uri = PathUri::from_host_native_path(&abs_path)?;
test.fs()
.write_file(&abs_path_uri, contents, /*sandbox*/ None)
.await?;
@@ -589,7 +589,7 @@ async fn view_image_routes_to_selected_remote_environment() -> anyhow::Result<()
))
.abs();
let image_path = remote_cwd.join("remote.png");
let remote_cwd_uri = PathUri::from_path(&remote_cwd)?;
let remote_cwd_uri = PathUri::from_host_native_path(&remote_cwd)?;
test.fs()
.create_directory(
&remote_cwd_uri,
@@ -598,7 +598,7 @@ async fn view_image_routes_to_selected_remote_environment() -> anyhow::Result<()
)
.await?;
let png = png_bytes(/*width*/ 1, /*height*/ 1, [0, 255, 0, 255])?;
let image_path_uri = PathUri::from_path(&image_path)?;
let image_path_uri = PathUri::from_host_native_path(&image_path)?;
test.fs()
.write_file(&image_path_uri, png, /*sandbox*/ None)
.await?;
+8 -4
View File
@@ -1151,8 +1151,10 @@ mod tests {
.start(crate::ExecParams {
process_id: ProcessId::from("default-env-proc"),
argv: vec!["true".to_string()],
cwd: PathUri::from_path(std::env::current_dir().expect("read current dir"))
.expect("cwd URI"),
cwd: PathUri::from_host_native_path(
std::env::current_dir().expect("read current dir"),
)
.expect("cwd URI"),
env_policy: None,
env: Default::default(),
tty: false,
@@ -1188,8 +1190,10 @@ mod tests {
.start(crate::ExecParams {
process_id: ProcessId::from("local-sandbox-proc"),
argv: vec!["true".to_string()],
cwd: PathUri::from_path(std::env::current_dir().expect("read current dir"))
.expect("cwd URI"),
cwd: PathUri::from_host_native_path(
std::env::current_dir().expect("read current dir"),
)
.expect("cwd URI"),
env_policy: None,
env: Default::default(),
tty: false,
+3 -2
View File
@@ -314,8 +314,9 @@ mod tests {
#[test]
fn helper_protocol_uses_path_uris() -> serde_json::Result<()> {
let local_path = PathUri::from_path(std::env::current_dir().expect("cwd").join("file"))
.expect("path URI");
let local_path =
PathUri::from_host_native_path(std::env::current_dir().expect("cwd").join("file"))
.expect("path URI");
let paths = [
local_path,
PathUri::parse("file://server/share/file").expect("path URI"),
+2 -1
View File
@@ -956,7 +956,8 @@ mod tests {
ExecParams {
process_id: ProcessId::from("env-test"),
argv: vec!["true".to_string()],
cwd: PathUri::from_path(std::env::current_dir().expect("cwd")).expect("cwd URI"),
cwd: PathUri::from_host_native_path(std::env::current_dir().expect("cwd"))
.expect("cwd URI"),
env_policy: None,
env,
tty: false,
+2 -2
View File
@@ -519,7 +519,7 @@ mod tests {
let legacy_cwd = std::env::current_dir().expect("current directory");
let native_sandbox = FileSystemSandboxContext::from_permission_profile_with_cwd(
PermissionProfile::default(),
PathUri::from_path(&legacy_cwd).expect("cwd URI"),
PathUri::from_host_native_path(&legacy_cwd).expect("cwd URI"),
);
let mut legacy_sandbox =
serde_json::to_value(&native_sandbox).expect("sandbox should serialize");
@@ -531,7 +531,7 @@ mod tests {
.expect("legacy absolute path should deserialize");
let expected_sandbox = native_sandbox;
let expected = FsReadFileParams {
path: PathUri::from_path(legacy_path).expect("path URI"),
path: PathUri::from_host_native_path(legacy_path).expect("path URI"),
sandbox: Some(expected_sandbox.clone()),
};
@@ -274,7 +274,7 @@ mod tests {
)
.expect("runtime paths");
let handler = FileSystemHandler::new(runtime_paths);
let sandbox_cwd = PathUri::from_path(temp_dir.path()).expect("tempdir URI");
let sandbox_cwd = PathUri::from_host_native_path(temp_dir.path()).expect("tempdir URI");
let sandbox_context = |sandbox_policy| {
FileSystemSandboxContext::from_legacy_sandbox_policy(
sandbox_policy,
@@ -292,7 +292,8 @@ mod tests {
},
),
] {
let path = PathUri::from_path(temp_dir.path().join(file_name)).expect("path URI");
let path =
PathUri::from_host_native_path(temp_dir.path().join(file_name)).expect("path URI");
handler
.write_file(FsWriteFileParams {
@@ -312,7 +313,7 @@ mod tests {
.expect("canonicalize file");
assert_eq!(
canonicalized.path,
PathUri::from_path(
PathUri::from_host_native_path(
std::fs::canonicalize(temp_dir.path().join(file_name)).expect("canonical path"),
)
.expect("canonical path URI"),
@@ -27,7 +27,8 @@ fn exec_params_with_argv(process_id: &str, argv: Vec<String>) -> ExecParams {
ExecParams {
process_id: ProcessId::from(process_id),
argv,
cwd: PathUri::from_path(std::env::current_dir().expect("cwd")).expect("cwd URI"),
cwd: PathUri::from_host_native_path(std::env::current_dir().expect("cwd"))
.expect("cwd URI"),
env_policy: None,
env: inherited_path_env(),
tty: false,
+2 -1
View File
@@ -432,7 +432,8 @@ mod tests {
ExecParams {
process_id,
argv: sleep_then_print_argv(),
cwd: PathUri::from_path(std::env::current_dir().expect("cwd")).expect("cwd URI"),
cwd: PathUri::from_host_native_path(std::env::current_dir().expect("cwd"))
.expect("cwd URI"),
env_policy: None,
env,
tty: false,
+12 -12
View File
@@ -75,7 +75,7 @@ async fn assert_exec_process_starts_and_exits(use_remote: bool) -> Result<()> {
.start(ExecParams {
process_id: ProcessId::from("proc-1"),
argv: vec!["true".to_string()],
cwd: PathUri::from_path(std::env::current_dir()?)?,
cwd: PathUri::from_host_native_path(std::env::current_dir()?)?,
env_policy: /*env_policy*/ None,
env: Default::default(),
tty: false,
@@ -218,7 +218,7 @@ async fn assert_exec_process_streams_output(use_remote: bool) -> Result<()> {
"-c".to_string(),
"sleep 0.05; printf 'session output\\n'".to_string(),
],
cwd: PathUri::from_path(std::env::current_dir()?)?,
cwd: PathUri::from_host_native_path(std::env::current_dir()?)?,
env_policy: /*env_policy*/ None,
env: Default::default(),
tty: false,
@@ -251,7 +251,7 @@ async fn assert_exec_process_pushes_events(use_remote: bool) -> Result<()> {
"-c".to_string(),
"printf 'event output\\n'; sleep 0.1; printf 'event err\\n' >&2; sleep 0.1; exit 7".to_string(),
],
cwd: PathUri::from_path(std::env::current_dir()?)?,
cwd: PathUri::from_host_native_path(std::env::current_dir()?)?,
env_policy: /*env_policy*/ None,
env: Default::default(),
tty: false,
@@ -300,7 +300,7 @@ async fn assert_exec_process_replays_events_after_close(use_remote: bool) -> Res
"-c".to_string(),
"printf 'late one\\n'; printf 'late two\\n'".to_string(),
],
cwd: PathUri::from_path(std::env::current_dir()?)?,
cwd: PathUri::from_host_native_path(std::env::current_dir()?)?,
env_policy: /*env_policy*/ None,
env: Default::default(),
tty: false,
@@ -350,7 +350,7 @@ async fn assert_exec_process_retains_output_after_exit_until_streams_close(
DELAYED_OUTPUT_AFTER_EXIT_PARENT_ARG.to_string(),
release_path.to_string_lossy().into_owned(),
],
cwd: PathUri::from_path(std::env::current_dir()?)?,
cwd: PathUri::from_host_native_path(std::env::current_dir()?)?,
env_policy: /*env_policy*/ None,
env: Default::default(),
tty: false,
@@ -425,7 +425,7 @@ async fn assert_exec_process_write_then_read(use_remote: bool) -> Result<()> {
"-c".to_string(),
"IFS= read line; printf 'from-stdin:%s\\n' \"$line\"".to_string(),
],
cwd: PathUri::from_path(std::env::current_dir()?)?,
cwd: PathUri::from_host_native_path(std::env::current_dir()?)?,
env_policy: /*env_policy*/ None,
env: Default::default(),
tty: true,
@@ -464,7 +464,7 @@ async fn assert_exec_process_write_then_read_without_tty(use_remote: bool) -> Re
"-c".to_string(),
"IFS= read line; printf 'from-stdin:%s\\n' \"$line\"".to_string(),
],
cwd: PathUri::from_path(std::env::current_dir()?)?,
cwd: PathUri::from_host_native_path(std::env::current_dir()?)?,
env_policy: /*env_policy*/ None,
env: Default::default(),
tty: false,
@@ -499,7 +499,7 @@ async fn assert_exec_process_rejects_write_without_pipe_stdin(use_remote: bool)
"-c".to_string(),
"sleep 0.3; if IFS= read -r line; then printf 'read:%s\\n' \"$line\"; else printf 'eof\\n'; fi".to_string(),
],
cwd: PathUri::from_path(std::env::current_dir()?)?,
cwd: PathUri::from_host_native_path(std::env::current_dir()?)?,
env_policy: /*env_policy*/ None,
env: Default::default(),
tty: false,
@@ -535,7 +535,7 @@ async fn assert_exec_process_signal_interrupts_process(use_remote: bool) -> Resu
"-c".to_string(),
"trap 'printf \"signal:2\\n\"; exit 7' INT; printf 'ready\\n'; while :; do :; done".to_string(),
],
cwd: PathUri::from_path(std::env::current_dir()?)?,
cwd: PathUri::from_host_native_path(std::env::current_dir()?)?,
env_policy: /*env_policy*/ None,
env: Default::default(),
tty: false,
@@ -590,7 +590,7 @@ async fn assert_exec_process_signal_reports_unsupported_on_windows(use_remote: b
"/C".to_string(),
"echo ready && ping -n 30 127.0.0.1 >NUL".to_string(),
],
cwd: PathUri::from_path(std::env::current_dir()?)?,
cwd: PathUri::from_host_native_path(std::env::current_dir()?)?,
env_policy: /*env_policy*/ None,
env: Default::default(),
tty: false,
@@ -632,7 +632,7 @@ async fn assert_exec_process_preserves_queued_events_before_subscribe(
"-c".to_string(),
"printf 'queued output\\n'".to_string(),
],
cwd: PathUri::from_path(std::env::current_dir()?)?,
cwd: PathUri::from_host_native_path(std::env::current_dir()?)?,
env_policy: /*env_policy*/ None,
env: Default::default(),
tty: false,
@@ -683,7 +683,7 @@ async fn remote_exec_process_recovers_after_transport_disconnect() -> Result<()>
)
.to_string(),
],
cwd: PathUri::from_path(std::env::current_dir()?)?,
cwd: PathUri::from_host_native_path(std::env::current_dir()?)?,
env_policy: /*env_policy*/ None,
env: HashMap::from([
(
+16 -10
View File
@@ -45,7 +45,10 @@ async fn stream_stops_after_an_exact_block_boundary() -> Result<()> {
std::fs::write(&path, vec![b'x'; BLOCK_SIZE * 2])?;
let chunks = file_system
.read_file_stream(&PathUri::from_path(path)?, /*sandbox*/ None)
.read_file_stream(
&PathUri::from_host_native_path(path)?,
/*sandbox*/ None,
)
.await?
.try_collect::<Vec<_>>()
.await?;
@@ -64,7 +67,7 @@ async fn completed_streams_release_handle_capacity() -> Result<()> {
let tmp = TempDir::new()?;
let path = tmp.path().join("repeated.txt");
std::fs::write(&path, b"repeated")?;
let path = PathUri::from_path(path)?;
let path = PathUri::from_host_native_path(path)?;
for _ in 0..=OPEN_FILE_LIMIT {
let chunks = file_system
@@ -88,7 +91,7 @@ async fn stream_rejects_platform_sandbox() -> Result<()> {
let result = file_system
.read_file_stream(
&PathUri::from_path(&path)?,
&PathUri::from_host_native_path(&path)?,
Some(&read_only_sandbox(tmp.path().to_path_buf())),
)
.await;
@@ -120,7 +123,7 @@ async fn file_reads_reject_fifo_without_waiting_for_a_writer() -> Result<()> {
);
}
let path_uri = PathUri::from_path(&path)?;
let path_uri = PathUri::from_host_native_path(&path)?;
let read_error = timeout(
Duration::from_secs(1),
file_system.read_file(&path_uri, /*sandbox*/ None),
@@ -158,7 +161,7 @@ async fn file_reads_reject_named_pipes() -> Result<()> {
let read_error = timeout(
Duration::from_secs(1),
file_system.read_file(
&PathUri::from_path(std::path::Path::new(&read_path))?,
&PathUri::from_host_native_path(std::path::Path::new(&read_path))?,
/*sandbox*/ None,
),
)
@@ -173,7 +176,7 @@ async fn file_reads_reject_named_pipes() -> Result<()> {
let stream_result = timeout(
Duration::from_secs(1),
file_system.read_file_stream(
&PathUri::from_path(std::path::Path::new(&stream_path))?,
&PathUri::from_host_native_path(std::path::Path::new(&stream_path))?,
/*sandbox*/ None,
),
)
@@ -202,7 +205,10 @@ async fn stream_keeps_reading_the_open_file_after_path_replacement() -> Result<(
let path = tmp.path().join("replaceable.bin");
std::fs::write(&path, vec![b'a'; BLOCK_SIZE + 1])?;
let mut stream = file_system
.read_file_stream(&PathUri::from_path(&path)?, /*sandbox*/ None)
.read_file_stream(
&PathUri::from_host_native_path(&path)?,
/*sandbox*/ None,
)
.await?;
assert_eq!(
@@ -236,7 +242,7 @@ async fn read_block_supports_non_sequential_offsets_and_lengths() -> Result<()>
let open = client
.fs_open(FsOpenParams {
handle_id: Uuid::new_v4().simple().to_string(),
path: PathUri::from_path(path)?,
path: PathUri::from_host_native_path(path)?,
sandbox: None,
})
.await?;
@@ -295,7 +301,7 @@ async fn open_enforces_the_per_connection_limit_and_close_releases_capacity() ->
let tmp = TempDir::new()?;
let path = tmp.path().join("limited.bin");
std::fs::write(&path, b"limited")?;
let path = PathUri::from_path(path)?;
let path = PathUri::from_host_native_path(path)?;
let mut handles = Vec::with_capacity(OPEN_FILE_LIMIT);
for _ in 0..OPEN_FILE_LIMIT {
let open = client
@@ -359,7 +365,7 @@ async fn open_rejects_handle_ids_longer_than_32_bytes() -> Result<()> {
let error = client
.fs_open(FsOpenParams {
handle_id: "x".repeat(33),
path: PathUri::from_path(path)?,
path: PathUri::from_host_native_path(path)?,
sandbox: None,
})
.await
@@ -66,7 +66,10 @@ async fn file_system_get_metadata_reports_files_and_directories(
std::fs::create_dir(&directory_path)?;
let file_metadata = file_system
.get_metadata(&PathUri::from_path(&file_path)?, /*sandbox*/ None)
.get_metadata(
&PathUri::from_host_native_path(&file_path)?,
/*sandbox*/ None,
)
.await
.with_context(|| format!("mode={implementation}"))?;
assert_eq!(
@@ -83,7 +86,10 @@ async fn file_system_get_metadata_reports_files_and_directories(
assert!(file_metadata.modified_at_ms > 0);
let directory_metadata = file_system
.get_metadata(&PathUri::from_path(&directory_path)?, /*sandbox*/ None)
.get_metadata(
&PathUri::from_host_native_path(&directory_path)?,
/*sandbox*/ None,
)
.await
.with_context(|| format!("mode={implementation}"))?;
assert_eq!(
@@ -116,7 +122,7 @@ async fn file_system_create_directory_creates_nested_directories(
file_system
.create_directory(
&PathUri::from_path(&nested_dir)?,
&PathUri::from_host_native_path(&nested_dir)?,
CreateDirectoryOptions { recursive: true },
/*sandbox*/ None,
)
@@ -140,7 +146,7 @@ async fn file_system_write_file_writes_bytes(
let file_path = tmp.path().join("note.txt");
file_system
.write_file(
&PathUri::from_path(&file_path)?,
&PathUri::from_host_native_path(&file_path)?,
b"hello from trait".to_vec(),
/*sandbox*/ None,
)
@@ -155,21 +161,21 @@ async fn file_system_write_file_writes_bytes(
fn path_uri_join_and_parent_preserve_lexical_paths() -> Result<()> {
let tmp = TempDir::new()?;
let source_dir = tmp.path().join("source");
let source_dir_uri = PathUri::from_path(&source_dir)?;
let source_dir_uri = PathUri::from_host_native_path(&source_dir)?;
let joined_nested = source_dir_uri.join("nested/note.txt")?;
assert_eq!(
joined_nested,
PathUri::from_path(source_dir.join("nested").join("note.txt"))?
PathUri::from_host_native_path(source_dir.join("nested").join("note.txt"))?
);
let joined_parent = joined_nested.parent();
assert_eq!(
joined_parent,
Some(PathUri::from_path(source_dir.join("nested"))?)
Some(PathUri::from_host_native_path(source_dir.join("nested"))?)
);
let joined_parent_traversal = source_dir_uri.join("../outside")?;
assert_eq!(
joined_parent_traversal,
PathUri::from_path(source_dir.join("../outside"))?
PathUri::from_host_native_path(source_dir.join("../outside"))?
);
Ok(())
}
@@ -188,7 +194,10 @@ async fn file_system_read_file_returns_bytes(
std::fs::write(&file_path, "hello from trait")?;
let contents = file_system
.read_file(&PathUri::from_path(&file_path)?, /*sandbox*/ None)
.read_file(
&PathUri::from_host_native_path(&file_path)?,
/*sandbox*/ None,
)
.await
.with_context(|| format!("mode={implementation}"))?;
assert_eq!(contents, b"hello from trait");
@@ -213,7 +222,10 @@ async fn file_system_read_file_stream_returns_bounded_chunks(
std::fs::write(&file_path, &contents)?;
let chunks = file_system
.read_file_stream(&PathUri::from_path(file_path)?, /*sandbox*/ None)
.read_file_stream(
&PathUri::from_host_native_path(file_path)?,
/*sandbox*/ None,
)
.await
.with_context(|| format!("mode={implementation}"))?
.try_collect::<Vec<_>>()
@@ -249,7 +261,10 @@ async fn file_system_read_file_text_returns_string(
std::fs::write(&file_path, "hello from trait")?;
let contents = file_system
.read_file_text(&PathUri::from_path(&file_path)?, /*sandbox*/ None)
.read_file_text(
&PathUri::from_host_native_path(&file_path)?,
/*sandbox*/ None,
)
.await
.with_context(|| format!("mode={implementation}"))?;
assert_eq!(contents, "hello from trait");
@@ -271,8 +286,8 @@ async fn file_system_copy_copies_file(implementation: FileSystemImplementation)
file_system
.copy(
&PathUri::from_path(&source_file)?,
&PathUri::from_path(&copied_file)?,
&PathUri::from_host_native_path(&source_file)?,
&PathUri::from_host_native_path(&copied_file)?,
CopyOptions { recursive: false },
/*sandbox*/ None,
)
@@ -302,8 +317,8 @@ async fn file_system_copy_copies_directory_recursively(
file_system
.copy(
&PathUri::from_path(&source_dir)?,
&PathUri::from_path(&copied_dir)?,
&PathUri::from_host_native_path(&source_dir)?,
&PathUri::from_host_native_path(&copied_dir)?,
CopyOptions { recursive: true },
/*sandbox*/ None,
)
@@ -332,7 +347,10 @@ async fn file_system_read_directory_lists_entries(
std::fs::write(source_dir.join("root.txt"), "hello")?;
let mut entries = file_system
.read_directory(&PathUri::from_path(&source_dir)?, /*sandbox*/ None)
.read_directory(
&PathUri::from_host_native_path(&source_dir)?,
/*sandbox*/ None,
)
.await
.with_context(|| format!("mode={implementation}"))?;
entries.sort_by(|left, right| left.file_name.cmp(&right.file_name));
@@ -370,7 +388,7 @@ async fn file_system_remove_removes_directory(
file_system
.remove(
&PathUri::from_path(&directory_path)?,
&PathUri::from_host_native_path(&directory_path)?,
RemoveOptions {
recursive: true,
force: true,
@@ -398,7 +416,7 @@ async fn file_system_write_file_reports_missing_parent(
let error = match file_system
.write_file(
&PathUri::from_path(&missing_parent_path)?,
&PathUri::from_host_native_path(&missing_parent_path)?,
b"hello from trait".to_vec(),
/*sandbox*/ None,
)
@@ -432,8 +450,8 @@ async fn file_system_copy_rejects_directory_without_recursive(
let error = file_system
.copy(
&PathUri::from_path(&source_dir)?,
&PathUri::from_path(tmp.path().join("dest"))?,
&PathUri::from_host_native_path(&source_dir)?,
&PathUri::from_host_native_path(tmp.path().join("dest"))?,
CopyOptions { recursive: false },
/*sandbox*/ None,
)
@@ -465,7 +483,7 @@ async fn file_system_sandboxed_metadata_and_read_allow_readable_root(
let sandbox = read_only_sandbox(allowed_dir);
let metadata = file_system
.get_metadata(&PathUri::from_path(&file_path)?, Some(&sandbox))
.get_metadata(&PathUri::from_host_native_path(&file_path)?, Some(&sandbox))
.await
.with_context(|| format!("mode={implementation}"))?;
assert_eq!(
@@ -481,7 +499,7 @@ async fn file_system_sandboxed_metadata_and_read_allow_readable_root(
);
let contents = file_system
.read_file(&PathUri::from_path(&file_path)?, Some(&sandbox))
.read_file(&PathUri::from_host_native_path(&file_path)?, Some(&sandbox))
.await
.with_context(|| format!("mode={implementation}"))?;
assert_eq!(contents, b"sandboxed hello");
@@ -505,8 +523,8 @@ pub(crate) async fn assert_canonicalize_resolves_directory_alias(
std::fs::write(&file_path, "canonical hello")?;
create_directory_alias(&source_dir, &alias_dir)?;
let requested_path = PathUri::from_path(alias_dir.join("nested").join("note.txt"))?;
let expected_path = PathUri::from_path(std::fs::canonicalize(&file_path)?)?;
let requested_path = PathUri::from_host_native_path(alias_dir.join("nested").join("note.txt"))?;
let expected_path = PathUri::from_host_native_path(std::fs::canonicalize(&file_path)?)?;
assert_ne!(requested_path, expected_path);
let canonical_path = file_system
@@ -535,8 +553,8 @@ pub(crate) async fn assert_sandboxed_canonicalize_resolves_directory_alias(
create_directory_alias(&source_dir, &alias_dir)?;
let sandbox = read_only_sandbox(tmp.path().to_path_buf());
let requested_path = PathUri::from_path(alias_dir.join("nested").join("note.txt"))?;
let expected_path = PathUri::from_path(std::fs::canonicalize(&file_path)?)?;
let requested_path = PathUri::from_host_native_path(alias_dir.join("nested").join("note.txt"))?;
let expected_path = PathUri::from_host_native_path(std::fs::canonicalize(&file_path)?)?;
assert_ne!(requested_path, expected_path);
let canonical_path = file_system
@@ -591,7 +609,7 @@ async fn file_system_sandboxed_write_allows_additional_write_root(
file_system
.write_file(
&PathUri::from_path(&file_path)?,
&PathUri::from_host_native_path(&file_path)?,
b"created".to_vec(),
Some(&sandbox),
)
@@ -617,8 +635,8 @@ async fn file_system_copy_rejects_copying_directory_into_descendant(
let error = file_system
.copy(
&PathUri::from_path(&source_dir)?,
&PathUri::from_path(source_dir.join("nested").join("copy"))?,
&PathUri::from_host_native_path(&source_dir)?,
&PathUri::from_host_native_path(source_dir.join("nested").join("copy"))?,
CopyOptions { recursive: true },
/*sandbox*/ None,
)
+34 -25
View File
@@ -187,7 +187,7 @@ async fn sandboxed_file_system_helper_finds_bwrap_on_preserved_path() -> Result<
file_system
.write_file(
&PathUri::from_path(&file_path)?,
&PathUri::from_host_native_path(&file_path)?,
b"written through fs helper".to_vec(),
Some(&sandbox),
)
@@ -221,7 +221,10 @@ async fn file_system_get_metadata_reports_symlink_targets(
let symlink_path = tmp.path().join("note-link.txt");
symlink(&file_path, &symlink_path)?;
let symlink_metadata = file_system
.get_metadata(&PathUri::from_path(&symlink_path)?, /*sandbox*/ None)
.get_metadata(
&PathUri::from_host_native_path(&symlink_path)?,
/*sandbox*/ None,
)
.await
.with_context(|| format!("mode={implementation}"))?;
assert_eq!(
@@ -243,7 +246,7 @@ async fn file_system_get_metadata_reports_symlink_targets(
symlink(&dir_path, &dir_symlink_path)?;
let dir_symlink_metadata = file_system
.get_metadata(
&PathUri::from_path(&dir_symlink_path)?,
&PathUri::from_host_native_path(&dir_symlink_path)?,
/*sandbox*/ None,
)
.await
@@ -278,7 +281,7 @@ async fn file_system_sandboxed_write_rejects_unwritable_path(
let sandbox = read_only_sandbox(tmp.path().to_path_buf());
let error = match file_system
.write_file(
&PathUri::from_path(&blocked_path)?,
&PathUri::from_host_native_path(&blocked_path)?,
b"nope".to_vec(),
Some(&sandbox),
)
@@ -314,7 +317,7 @@ async fn file_system_sandboxed_write_allows_explicit_alias_roots(
file_system
.write_file(
&PathUri::from_path(&file_path)?,
&PathUri::from_host_native_path(&file_path)?,
b"created".to_vec(),
Some(&sandbox),
)
@@ -345,7 +348,10 @@ async fn file_system_sandboxed_read_rejects_symlink_escape(
let requested_path = allowed_dir.join("link").join("secret.txt");
let sandbox = read_only_sandbox(allowed_dir);
let error = match file_system
.read_file(&PathUri::from_path(&requested_path)?, Some(&sandbox))
.read_file(
&PathUri::from_host_native_path(&requested_path)?,
Some(&sandbox),
)
.await
{
Ok(_) => anyhow::bail!("read should be blocked"),
@@ -375,7 +381,7 @@ async fn file_system_sandboxed_read_rejects_symlink_parent_dotdot_escape(
symlink(&outside_dir, allowed_dir.join("link"))?;
let requested_path =
PathUri::from_path(allowed_dir.join("link").join("..").join("secret.txt"))?;
PathUri::from_host_native_path(allowed_dir.join("link").join("..").join("secret.txt"))?;
let sandbox = read_only_sandbox(allowed_dir);
let error = match file_system.read_file(&requested_path, Some(&sandbox)).await {
Ok(_) => anyhow::bail!("read should fail after path normalization"),
@@ -411,7 +417,7 @@ async fn file_system_sandboxed_write_rejects_symlink_escape(
let sandbox = workspace_write_sandbox(allowed_dir);
let error = match file_system
.write_file(
&PathUri::from_path(&requested_path)?,
&PathUri::from_host_native_path(&requested_path)?,
b"nope".to_vec(),
Some(&sandbox),
)
@@ -449,7 +455,7 @@ async fn file_system_sandboxed_write_preserves_existing_hard_link(
let sandbox = workspace_write_sandbox(allowed_dir);
file_system
.write_file(
&PathUri::from_path(&hard_link)?,
&PathUri::from_host_native_path(&hard_link)?,
b"updated through existing hard link\n".to_vec(),
Some(&sandbox),
)
@@ -495,7 +501,7 @@ async fn file_system_create_directory_rejects_symlink_escape(
let sandbox = workspace_write_sandbox(allowed_dir);
let error = match file_system
.create_directory(
&PathUri::from_path(&requested_path)?,
&PathUri::from_host_native_path(&requested_path)?,
CreateDirectoryOptions { recursive: false },
Some(&sandbox),
)
@@ -530,7 +536,10 @@ async fn file_system_read_directory_rejects_symlink_escape(
let requested_path = allowed_dir.join("link");
let sandbox = read_only_sandbox(allowed_dir);
let error = match file_system
.read_directory(&PathUri::from_path(&requested_path)?, Some(&sandbox))
.read_directory(
&PathUri::from_host_native_path(&requested_path)?,
Some(&sandbox),
)
.await
{
Ok(_) => anyhow::bail!("read_directory should be blocked"),
@@ -562,8 +571,8 @@ async fn file_system_copy_rejects_symlink_escape_destination(
let sandbox = workspace_write_sandbox(allowed_dir.clone());
let error = match file_system
.copy(
&PathUri::from_path(allowed_dir.join("source.txt"))?,
&PathUri::from_path(&requested_destination)?,
&PathUri::from_host_native_path(allowed_dir.join("source.txt"))?,
&PathUri::from_host_native_path(&requested_destination)?,
CopyOptions { recursive: false },
Some(&sandbox),
)
@@ -600,7 +609,7 @@ async fn file_system_remove_removes_symlink_not_target(
let sandbox = workspace_write_sandbox(allowed_dir);
file_system
.remove(
&PathUri::from_path(&symlink_path)?,
&PathUri::from_host_native_path(&symlink_path)?,
RemoveOptions {
recursive: false,
force: false,
@@ -640,8 +649,8 @@ async fn file_system_copy_preserves_symlink_source(
let sandbox = workspace_write_sandbox(allowed_dir.clone());
file_system
.copy(
&PathUri::from_path(&source_symlink)?,
&PathUri::from_path(&copied_symlink)?,
&PathUri::from_host_native_path(&source_symlink)?,
&PathUri::from_host_native_path(&copied_symlink)?,
CopyOptions { recursive: false },
Some(&sandbox),
)
@@ -677,7 +686,7 @@ async fn file_system_remove_rejects_symlink_escape(
let sandbox = workspace_write_sandbox(allowed_dir);
let error = match file_system
.remove(
&PathUri::from_path(&requested_path)?,
&PathUri::from_host_native_path(&requested_path)?,
RemoveOptions {
recursive: false,
force: false,
@@ -718,8 +727,8 @@ async fn file_system_copy_rejects_symlink_escape_source(
let sandbox = workspace_write_sandbox(allowed_dir);
let error = match file_system
.copy(
&PathUri::from_path(&requested_source)?,
&PathUri::from_path(&requested_destination)?,
&PathUri::from_host_native_path(&requested_source)?,
&PathUri::from_host_native_path(&requested_destination)?,
CopyOptions { recursive: false },
Some(&sandbox),
)
@@ -752,8 +761,8 @@ async fn file_system_copy_preserves_symlinks_in_recursive_copy(
file_system
.copy(
&PathUri::from_path(&source_dir)?,
&PathUri::from_path(&copied_dir)?,
&PathUri::from_host_native_path(&source_dir)?,
&PathUri::from_host_native_path(&copied_dir)?,
CopyOptions { recursive: true },
/*sandbox*/ None,
)
@@ -798,8 +807,8 @@ async fn file_system_copy_ignores_unknown_special_files_in_recursive_copy(
file_system
.copy(
&PathUri::from_path(&source_dir)?,
&PathUri::from_path(&copied_dir)?,
&PathUri::from_host_native_path(&source_dir)?,
&PathUri::from_host_native_path(&copied_dir)?,
CopyOptions { recursive: true },
/*sandbox*/ None,
)
@@ -837,8 +846,8 @@ async fn file_system_copy_rejects_standalone_fifo_source(
let error = file_system
.copy(
&PathUri::from_path(&fifo_path)?,
&PathUri::from_path(tmp.path().join("copied"))?,
&PathUri::from_host_native_path(&fifo_path)?,
&PathUri::from_host_native_path(tmp.path().join("copied"))?,
CopyOptions { recursive: false },
/*sandbox*/ None,
)
@@ -74,7 +74,10 @@ async fn file_system_remote_fs_helper_respects_windows_sandbox_write_policy() ->
let readable_file = readonly_dir.join("readable.txt");
std::fs::write(&readable_file, b"readable")?;
let read_result = file_system
.read_file(&PathUri::from_path(&readable_file)?, Some(&sandbox))
.read_file(
&PathUri::from_host_native_path(&readable_file)?,
Some(&sandbox),
)
.await;
// Some local Windows hosts cannot create restricted tokens. Reaching that
// error still proves the remote fs helper went through the Windows sandbox
@@ -87,7 +90,7 @@ async fn file_system_remote_fs_helper_respects_windows_sandbox_write_policy() ->
let blocked_file = readonly_dir.join("blocked.txt");
let error = file_system
.write_file(
&PathUri::from_path(&blocked_file)?,
&PathUri::from_host_native_path(&blocked_file)?,
b"blocked".to_vec(),
Some(&sandbox),
)
@@ -104,7 +107,7 @@ async fn file_system_remote_fs_helper_respects_windows_sandbox_write_policy() ->
fn read_only_sandbox_for_cwd(cwd: std::path::PathBuf) -> Result<FileSystemSandboxContext> {
Ok(FileSystemSandboxContext::from_legacy_sandbox_policy(
SandboxPolicy::new_read_only_policy(),
PathUri::from_path(cwd)?,
PathUri::from_host_native_path(cwd)?,
)?)
}
+2 -2
View File
@@ -144,7 +144,7 @@ async fn remote_environment_routes_encrypted_exec_server_rpc() -> Result<()> {
.exec(ExecParams {
process_id: ProcessId::from("proc-1"),
argv: vec!["true".to_string()],
cwd: PathUri::from_path(std::env::current_dir()?)?,
cwd: PathUri::from_host_native_path(std::env::current_dir()?)?,
env_policy: None,
env: HashMap::new(),
tty: false,
@@ -167,7 +167,7 @@ async fn remote_environment_routes_encrypted_exec_server_rpc() -> Result<()> {
std::fs::write(&large_file_path, &large_file_contents)?;
let read_response = client
.fs_read_file(FsReadFileParams {
path: PathUri::from_path(large_file_path)?,
path: PathUri::from_host_native_path(large_file_path)?,
sandbox: None,
})
.await?;
@@ -488,7 +488,7 @@ impl ExecutorStdioServerLauncher {
// before sending an executor request.
let argv = Self::process_api_argv(&program, &args).map_err(io::Error::other)?;
let env = Self::process_api_env(envs).map_err(io::Error::other)?;
let cwd = PathUri::from_path(cwd)?;
let cwd = PathUri::from_host_native_path(cwd)?;
let process_id = ExecutorProcessTransport::next_process_id();
// Start the MCP server process on the executor with raw pipes. `tty=false`
// keeps stdout as a clean protocol stream, while `pipe_stdin=true` lets
+1 -1
View File
@@ -121,7 +121,7 @@ impl PathUri {
/// Relative paths are reported as invalid input. Absolute paths without a
/// valid URI representation use the fallback documented on
/// [`Self::from_abs_path`].
pub fn from_path(path: impl AsRef<Path>) -> io::Result<Self> {
pub fn from_host_native_path(path: impl AsRef<Path>) -> io::Result<Self> {
let path = AbsolutePathBuf::from_absolute_path_checked(path)
.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?;
Ok(Self::from_abs_path(&path))
+2 -1
View File
@@ -423,7 +423,8 @@ fn path_uri_deserializes_legacy_absolute_paths() {
#[test]
fn path_uri_rejects_relative_native_paths() {
let error = PathUri::from_path("src/lib.rs").expect_err("relative path should be rejected");
let error =
PathUri::from_host_native_path("src/lib.rs").expect_err("relative path should be rejected");
assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
}