[codex] migrate ExecutorFileSystem paths to PathUri (#27424)

## Why

We're moving exec-server to use PathUri for its internal path
representations.

## What

Move `ExecutorFileSystem` APIs to use `PathUri` instead of
`AbsolutePathBuf`. Future changes will convert higher-level parts of
exec-server.
This commit is contained in:
Adam Perry @ OpenAI
2026-06-11 11:44:18 -07:00
committed by GitHub
Unverified
parent 4a05d3b282
commit b2a4e3be27
52 changed files with 1126 additions and 495 deletions
+3 -1
View File
@@ -10,6 +10,7 @@ use crate::strict_config::config_error_from_ignored_toml_value_fields;
use codex_file_system::ExecutorFileSystem;
use codex_utils_absolute_path::AbsolutePathBuf;
use codex_utils_absolute_path::AbsolutePathBufGuard;
use codex_utils_path_uri::PathUri;
use std::io;
use std::path::Path;
use std::path::PathBuf;
@@ -106,7 +107,8 @@ pub(super) async fn read_config_from_path(
log_missing_as_info: bool,
strict_config: bool,
) -> io::Result<Option<TomlValue>> {
match fs.read_file_text(path, /*sandbox*/ None).await {
let path_uri = PathUri::from_abs_path(path)?;
match fs.read_file_text(&path_uri, /*sandbox*/ None).await {
Ok(contents) => match toml::from_str::<TomlValue>(&contents) {
Ok(value) => {
if strict_config {
+21 -8
View File
@@ -40,6 +40,7 @@ use codex_protocol::config_types::TrustLevel;
use codex_protocol::protocol::AskForApproval;
use codex_utils_absolute_path::AbsolutePathBuf;
use codex_utils_absolute_path::AbsolutePathBufGuard;
use codex_utils_path_uri::PathUri;
use dunce::canonicalize as normalize_path;
use serde::Deserialize;
use std::io;
@@ -471,7 +472,8 @@ async fn load_config_toml_for_required_layer(
strict_config: bool,
create_entry: impl FnOnce(TomlValue) -> ConfigLayerEntry,
) -> io::Result<ConfigLayerEntry> {
let toml_value = match fs.read_file_text(toml_file, /*sandbox*/ None).await {
let toml_file_uri = PathUri::from_abs_path(toml_file)?;
let toml_value = match fs.read_file_text(&toml_file_uri, /*sandbox*/ None).await {
Ok(contents) => {
let config_parent = toml_file.as_path().parent().ok_or_else(|| {
io::Error::new(
@@ -566,8 +568,9 @@ pub async fn load_requirements_toml(
fs: &dyn ExecutorFileSystem,
requirements_toml_file: &AbsolutePathBuf,
) -> io::Result<Option<RequirementsLayerEntry>> {
let requirements_toml_file_uri = PathUri::from_abs_path(requirements_toml_file)?;
match fs
.read_file_text(requirements_toml_file, /*sandbox*/ None)
.read_file_text(&requirements_toml_file_uri, /*sandbox*/ None)
.await
{
Ok(contents) => {
@@ -1135,8 +1138,9 @@ async fn find_project_root(
for ancestor in cwd.ancestors() {
for marker in project_root_markers {
let marker_path = ancestor.join(marker);
let marker_path_uri = PathUri::from_abs_path(&marker_path)?;
if fs
.get_metadata(&marker_path, /*sandbox*/ None)
.get_metadata(&marker_path_uri, /*sandbox*/ None)
.await
.is_ok()
{
@@ -1151,14 +1155,20 @@ async fn find_git_checkout_root(
fs: &dyn ExecutorFileSystem,
cwd: &AbsolutePathBuf,
) -> Option<AbsolutePathBuf> {
let base = match fs.get_metadata(cwd, /*sandbox*/ None).await {
let cwd_uri = PathUri::from_abs_path(cwd).ok()?;
let base = match fs.get_metadata(&cwd_uri, /*sandbox*/ None).await {
Ok(metadata) if metadata.is_directory => cwd.clone(),
_ => cwd.parent()?,
};
for dir in base.ancestors() {
let dot_git = dir.join(".git");
if fs.get_metadata(&dot_git, /*sandbox*/ None).await.is_ok() {
let dot_git_uri = PathUri::from_abs_path(&dot_git).ok()?;
if fs
.get_metadata(&dot_git_uri, /*sandbox*/ None)
.await
.is_ok()
{
return Some(dir);
}
}
@@ -1206,8 +1216,9 @@ async fn load_project_layers(
let mut startup_warnings = Vec::new();
for dir in dirs {
let dot_codex_abs = dir.join(".codex");
let dot_codex_uri = PathUri::from_abs_path(&dot_codex_abs)?;
if !fs
.get_metadata(&dot_codex_abs, /*sandbox*/ None)
.get_metadata(&dot_codex_uri, /*sandbox*/ None)
.await
.map(|metadata| metadata.is_directory)
.unwrap_or(false)
@@ -1224,7 +1235,8 @@ async fn load_project_layers(
continue;
}
let config_file = dot_codex_abs.join(CONFIG_TOML_FILE);
match fs.read_file_text(&config_file, /*sandbox*/ None).await {
let config_file_uri = PathUri::from_abs_path(&config_file)?;
match fs.read_file_text(&config_file_uri, /*sandbox*/ None).await {
Ok(contents) => {
let config: TomlValue = match toml::from_str(&contents) {
Ok(config) => config,
@@ -1327,8 +1339,9 @@ async fn merge_root_checkout_project_hooks(
return Ok(config);
};
let hooks_config_file = hooks_config_folder.join(CONFIG_TOML_FILE);
let hooks_config_file_uri = PathUri::from_abs_path(&hooks_config_file)?;
let root_config = match fs
.read_file_text(&hooks_config_file, /*sandbox*/ None)
.read_file_text(&hooks_config_file_uri, /*sandbox*/ None)
.await
{
Ok(contents) => {
+15 -24
View File
@@ -7,8 +7,8 @@ use codex_file_system::FileSystemResult;
use codex_file_system::FileSystemSandboxContext;
use codex_file_system::ReadDirectoryEntry;
use codex_file_system::RemoveOptions;
use codex_utils_path_uri::PathUri;
use pretty_assertions::assert_eq;
use std::path::Path;
use tempfile::tempdir;
struct TestFileSystem;
@@ -17,35 +17,26 @@ struct TestFileSystem;
impl ExecutorFileSystem for TestFileSystem {
async fn canonicalize(
&self,
path: &AbsolutePathBuf,
path: &PathUri,
_sandbox: Option<&FileSystemSandboxContext>,
) -> FileSystemResult<AbsolutePathBuf> {
path.canonicalize()
}
async fn join(
&self,
base_path: &AbsolutePathBuf,
path: &Path,
) -> FileSystemResult<AbsolutePathBuf> {
Ok(base_path.join(path))
}
async fn parent(&self, path: &AbsolutePathBuf) -> FileSystemResult<Option<AbsolutePathBuf>> {
Ok(path.parent())
) -> FileSystemResult<PathUri> {
let path = path.to_abs_path()?;
let canonicalized = path.canonicalize()?;
PathUri::from_abs_path(&canonicalized)
}
async fn read_file(
&self,
path: &AbsolutePathBuf,
path: &PathUri,
_sandbox: Option<&FileSystemSandboxContext>,
) -> FileSystemResult<Vec<u8>> {
let path = path.to_abs_path()?;
tokio::fs::read(path.as_path()).await
}
async fn write_file(
&self,
_path: &AbsolutePathBuf,
_path: &PathUri,
_contents: Vec<u8>,
_sandbox: Option<&FileSystemSandboxContext>,
) -> FileSystemResult<()> {
@@ -54,7 +45,7 @@ impl ExecutorFileSystem for TestFileSystem {
async fn create_directory(
&self,
_path: &AbsolutePathBuf,
_path: &PathUri,
_create_directory_options: CreateDirectoryOptions,
_sandbox: Option<&FileSystemSandboxContext>,
) -> FileSystemResult<()> {
@@ -63,7 +54,7 @@ impl ExecutorFileSystem for TestFileSystem {
async fn get_metadata(
&self,
_path: &AbsolutePathBuf,
_path: &PathUri,
_sandbox: Option<&FileSystemSandboxContext>,
) -> FileSystemResult<FileMetadata> {
unimplemented!("test filesystem only supports reads")
@@ -71,7 +62,7 @@ impl ExecutorFileSystem for TestFileSystem {
async fn read_directory(
&self,
_path: &AbsolutePathBuf,
_path: &PathUri,
_sandbox: Option<&FileSystemSandboxContext>,
) -> FileSystemResult<Vec<ReadDirectoryEntry>> {
unimplemented!("test filesystem only supports reads")
@@ -79,7 +70,7 @@ impl ExecutorFileSystem for TestFileSystem {
async fn remove(
&self,
_path: &AbsolutePathBuf,
_path: &PathUri,
_remove_options: RemoveOptions,
_sandbox: Option<&FileSystemSandboxContext>,
) -> FileSystemResult<()> {
@@ -88,8 +79,8 @@ impl ExecutorFileSystem for TestFileSystem {
async fn copy(
&self,
_source_path: &AbsolutePathBuf,
_destination_path: &AbsolutePathBuf,
_source_path: &PathUri,
_destination_path: &PathUri,
_copy_options: CopyOptions,
_sandbox: Option<&FileSystemSandboxContext>,
) -> FileSystemResult<()> {