mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
unified-exec: preserve PathUri through exec-server (#28681)
## Why It should be possible for app-server to handle "foreign" OS paths in unified_exec working directories, allowing e.g. a Linux app-server to run processes on e.g. a Windows exec-server. ## What Convert the core unified_exec cwd values to use `PathUri`. Adds fallible path conversion in several places to try to minimize the scope of this change. The only time this change suppresses errors from converting `PathUri` to an `AbsolutePathBuf` is when the turn is configured with no sandboxing at all to allow us to make progress testing without sandboxing. Future changes to apply_patch and sandboxing will clean up these error paths. A tool's cwd is resolved from joining a model-provided workdir to the environment's cwd. When using `AbsolutePathBuf::join()`, an absolute-path workdir would overwrite the environment's cwd and we would resolve permissions/sandboxing against the model-provided path. This change extends `PathUri::join()` to also treat an absolute rhs as an override of the base/lhs. This also removes some coverage from the remove_env_windows tests until a follow-up converts foreign paths in command exec events correctly. ## Breaking Changes When using `AbsolutePathBuf::join()` for workdir resolution, we ended up resolving tilde-prefixed paths against the app-server's `$HOME`, e.g. `~/foo/bar` becomes `/home/anp/foo/bar`. It's difficult to do this with `PathUri` joining, so after offline discussion this PR no longer implements it. A quick check of some power users' rollouts suggests that models don't actually generate home-prefixed absolute working directories for their spawns, so this shouldn't have any real blast radius.
This commit is contained in:
1 parent
cca39d51ba
commit
5867b529ae
33 files changed
+634
-206
No files matched your search
@@ -522,13 +522,72 @@ fn join_normalizes_relative_uri_segments() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn join_rejects_absolute_and_null_paths() {
|
||||
fn join_replaces_posix_absolute_path() {
|
||||
let base = PathUri::parse("file:///workspace").expect("valid base URI");
|
||||
|
||||
assert!(matches!(
|
||||
assert_eq!(
|
||||
base.join("/src"),
|
||||
Err(PathUriParseError::JoinPathMustBeRelative(path)) if path == "/src"
|
||||
));
|
||||
Ok(PathUri::parse("file:///src").expect("valid absolute URI"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn join_replaces_windows_absolute_path() {
|
||||
let base = PathUri::parse("file:///C:/workspace/src").expect("valid base URI");
|
||||
|
||||
assert_eq!(
|
||||
base.join(r"D:\tmp\test.rs"),
|
||||
Ok(PathUri::parse("file:///D:/tmp/test.rs").expect("valid absolute URI"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn join_windows_root_relative_path_preserves_drive_or_share() {
|
||||
for (base, path, expected) in [
|
||||
("file:///C:/base/dir", r"\Windows", "file:///C:/Windows"),
|
||||
(
|
||||
"file://server/share/base/dir",
|
||||
r"\Windows",
|
||||
"file://server/share/Windows",
|
||||
),
|
||||
] {
|
||||
let base = PathUri::parse(base).expect("valid base URI");
|
||||
let expected = PathUri::parse(expected).expect("valid expected URI");
|
||||
assert_eq!(base.join(path), Ok(expected), "joining {path}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn join_rejects_windows_drive_relative_path() {
|
||||
let base = PathUri::parse("file:///C:/base").expect("valid base URI");
|
||||
|
||||
assert_eq!(
|
||||
base.join(r"D:tmp"),
|
||||
Err(PathUriParseError::InvalidFileUriPath {
|
||||
path: r"D:tmp".to_string(),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn join_parent_segments_preserve_windows_drive_or_share_anchor() {
|
||||
for (base, expected) in [
|
||||
("file:///C:/base/dir", "file:///C:/Windows"),
|
||||
(
|
||||
"file://server/share/base/dir",
|
||||
"file://server/share/Windows",
|
||||
),
|
||||
] {
|
||||
let base = PathUri::parse(base).expect("valid base URI");
|
||||
let expected = PathUri::parse(expected).expect("valid expected URI");
|
||||
assert_eq!(base.join(r"..\..\..\Windows"), Ok(expected));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn join_rejects_null_paths() {
|
||||
let base = PathUri::parse("file:///workspace").expect("valid base URI");
|
||||
|
||||
assert_eq!(
|
||||
base.join("src\0file"),
|
||||
Err(PathUriParseError::InvalidFileUriPath {
|
||||
@@ -537,6 +596,26 @@ fn join_rejects_absolute_and_null_paths() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn join_uses_the_base_uri_path_convention() {
|
||||
for (base, path, expected) in [
|
||||
(
|
||||
"file:///workspace/src",
|
||||
"../tests/test.rs",
|
||||
"file:///workspace/tests/test.rs",
|
||||
),
|
||||
(
|
||||
"file:///C:/workspace/src",
|
||||
r"..\tests\test.rs",
|
||||
"file:///C:/workspace/tests/test.rs",
|
||||
),
|
||||
] {
|
||||
let base = PathUri::parse(base).expect("valid base URI");
|
||||
let expected = PathUri::parse(expected).expect("valid expected URI");
|
||||
assert_eq!(base.join(path), Ok(expected), "joining {path}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_url_returns_the_validated_url() {
|
||||
let uri = PathUri::parse("file://localhost/workspace/a%20file.rs").expect("valid file URI");
|
||||
|
||||
Reference in new issue
Block a user