Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions codex-rs/app-server/src/codex_message_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ use codex_core::find_thread_name_by_id;
use codex_core::find_thread_names_by_ids;
use codex_core::find_thread_path_by_id_str;
use codex_core::parse_cursor;
use codex_core::path_utils;
use codex_core::plugins::MarketplaceError;
use codex_core::plugins::MarketplacePluginSource;
use codex_core::plugins::OPENAI_CURATED_MARKETPLACE_NAME;
Expand Down Expand Up @@ -4768,9 +4769,9 @@ impl CodexMessageProcessor {
if source_kind_filter
.as_ref()
.is_none_or(|filter| source_kind_matches(&summary.source, filter))
&& cwd
.as_ref()
.is_none_or(|expected_cwd| &summary.cwd == expected_cwd)
&& cwd.as_ref().is_none_or(|expected_cwd| {
path_utils::paths_match_after_normalization(&summary.cwd, expected_cwd)
})
{
filtered.push(summary);
if filtered.len() >= remaining {
Expand Down
9 changes: 1 addition & 8 deletions codex-rs/core/src/config/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -629,14 +629,7 @@ fn validate_config(value: &TomlValue) -> Result<(), toml::de::Error> {
}

fn paths_match(expected: impl AsRef<Path>, provided: impl AsRef<Path>) -> bool {
if let (Ok(expanded_expected), Ok(expanded_provided)) = (
path_utils::normalize_for_path_comparison(&expected),
path_utils::normalize_for_path_comparison(&provided),
) {
expanded_expected == expanded_provided
} else {
expected.as_ref() == provided.as_ref()
}
path_utils::paths_match_after_normalization(expected, provided)
}

fn value_at_path<'a>(root: &'a TomlValue, segments: &[String]) -> Option<&'a TomlValue> {
Expand Down
9 changes: 1 addition & 8 deletions codex-rs/core/src/tools/runtimes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,7 @@ pub(crate) fn maybe_wrap_shell_lc_with_snapshot(
return command.to_vec();
}

if if let (Ok(snapshot_cwd), Ok(command_cwd)) = (
path_utils::normalize_for_path_comparison(snapshot.cwd.as_path()),
path_utils::normalize_for_path_comparison(cwd),
) {
snapshot_cwd != command_cwd
} else {
snapshot.cwd != cwd
} {
if !path_utils::paths_match_after_normalization(snapshot.cwd.as_path(), cwd) {
return command.to_vec();
}

Expand Down
8 changes: 1 addition & 7 deletions codex-rs/exec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1205,13 +1205,7 @@ async fn parse_latest_turn_context_cwd(path: &Path) -> Option<PathBuf> {
}

fn cwds_match(current_cwd: &Path, session_cwd: &Path) -> bool {
match (
path_utils::normalize_for_path_comparison(current_cwd),
path_utils::normalize_for_path_comparison(session_cwd),
) {
(Ok(current), Ok(session)) => current == session,
_ => current_cwd == session_cwd,
}
path_utils::paths_match_after_normalization(current_cwd, session_cwd)
}

async fn resolve_resume_thread_id(
Expand Down
8 changes: 1 addition & 7 deletions codex-rs/rollout/src/recorder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1342,13 +1342,7 @@ async fn select_resume_path_from_db_page(
}

fn cwd_matches(session_cwd: &Path, cwd: &Path) -> bool {
if let (Ok(ca), Ok(cb)) = (
path_utils::normalize_for_path_comparison(session_cwd),
path_utils::normalize_for_path_comparison(cwd),
) {
return ca == cb;
}
session_cwd == cwd
path_utils::paths_match_after_normalization(session_cwd, cwd)
}

#[cfg(test)]
Expand Down
8 changes: 1 addition & 7 deletions codex-rs/tui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1524,13 +1524,7 @@ async fn read_latest_turn_context(path: &Path) -> Option<TurnContextItem> {
}

pub(crate) fn cwds_differ(current_cwd: &Path, session_cwd: &Path) -> bool {
match (
path_utils::normalize_for_path_comparison(current_cwd),
path_utils::normalize_for_path_comparison(session_cwd),
) {
(Ok(current), Ok(session)) => current != session,
_ => current_cwd != session_cwd,
}
!path_utils::paths_match_after_normalization(current_cwd, session_cwd)
}

pub(crate) enum ResolveCwdOutcome {
Expand Down
8 changes: 1 addition & 7 deletions codex-rs/tui/src/resume_picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1148,13 +1148,7 @@ fn thread_list_params(
}

fn paths_match(a: &Path, b: &Path) -> bool {
if let (Ok(ca), Ok(cb)) = (
path_utils::normalize_for_path_comparison(a),
path_utils::normalize_for_path_comparison(b),
) {
return ca == cb;
}
a == b
path_utils::paths_match_after_normalization(a, b)
}

#[cfg_attr(not(test), allow(dead_code))]
Expand Down
13 changes: 13 additions & 0 deletions codex-rs/utils/path-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,19 @@ pub fn normalize_for_path_comparison(path: impl AsRef<Path>) -> std::io::Result<
Ok(normalize_for_wsl(canonical))
}

/// Compare paths after applying Codex's filesystem normalization.
///
/// If either path cannot be normalized, this falls back to direct path equality.
pub fn paths_match_after_normalization(left: impl AsRef<Path>, right: impl AsRef<Path>) -> bool {
if let (Ok(left), Ok(right)) = (
normalize_for_path_comparison(left.as_ref()),
normalize_for_path_comparison(right.as_ref()),
) {
return left == right;
}
left.as_ref() == right.as_ref()
}

pub fn normalize_for_native_workdir(path: impl AsRef<Path>) -> PathBuf {
normalize_for_native_workdir_with_flag(path.as_ref().to_path_buf(), cfg!(windows))
}
Expand Down
35 changes: 35 additions & 0 deletions codex-rs/utils/path-utils/src/path_utils_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,38 @@ mod native_workdir {
assert_eq!(normalized, path);
}
}

mod path_comparison {
use super::super::paths_match_after_normalization;
use std::path::PathBuf;

#[test]
fn matches_identical_existing_paths() -> std::io::Result<()> {
let dir = tempfile::tempdir()?;

assert!(paths_match_after_normalization(dir.path(), dir.path()));
Ok(())
}

#[test]
fn falls_back_to_raw_equality_when_paths_cannot_be_normalized() {
assert!(paths_match_after_normalization(
PathBuf::from("missing"),
PathBuf::from("missing"),
));
assert!(!paths_match_after_normalization(
PathBuf::from("missing-a"),
PathBuf::from("missing-b"),
));
}

#[cfg(windows)]
#[test]
fn matches_windows_verbatim_paths() -> std::io::Result<()> {
let dir = tempfile::tempdir()?;
let verbatim_dir = PathBuf::from(format!(r"\\?\{}", dir.path().display()));

assert!(paths_match_after_normalization(verbatim_dir, dir.path()));
Ok(())
}
}
Loading