Skip to content

Commit 1bf8a23

Browse files
tibo-openaiowenlin0
authored andcommitted
fix: resume lookup for gitignored CODEX_HOME (openai#5311)
Walk the sessions tree instead of using file_search so gitignored CODEX_HOME directories can resume sessions. Add a regression test that covers a .gitignore'd sessions directory. Fixes openai#5247 Fixes openai#5412 --------- Co-authored-by: Owen Lin <[email protected]>
1 parent 2a26e29 commit 1bf8a23

File tree

5 files changed

+51
-6
lines changed

5 files changed

+51
-6
lines changed

codex-rs/app-server/src/fuzzy_file_search.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ pub(crate) async fn run_fuzzy_file_search(
4646
threads,
4747
cancel_flag,
4848
COMPUTE_INDICES,
49+
true,
4950
) {
5051
Ok(res) => Ok((root, res)),
5152
Err(err) => Err((root, err)),

codex-rs/core/src/rollout/list.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
use std::cmp::Reverse;
22
use std::io::{self};
3+
use std::num::NonZero;
34
use std::path::Path;
45
use std::path::PathBuf;
5-
6-
use codex_file_search as file_search;
7-
use std::num::NonZero;
86
use std::sync::Arc;
97
use std::sync::atomic::AtomicBool;
8+
109
use time::OffsetDateTime;
1110
use time::PrimitiveDateTime;
1211
use time::format_description::FormatItem;
@@ -15,6 +14,7 @@ use uuid::Uuid;
1514

1615
use super::SESSIONS_SUBDIR;
1716
use crate::protocol::EventMsg;
17+
use codex_file_search as file_search;
1818
use codex_protocol::protocol::RolloutItem;
1919
use codex_protocol::protocol::RolloutLine;
2020
use codex_protocol::protocol::SessionSource;
@@ -515,6 +515,7 @@ pub async fn find_conversation_path_by_id_str(
515515
threads,
516516
cancel,
517517
compute_indices,
518+
false,
518519
)
519520
.map_err(|e| io::Error::other(format!("file search failed: {e}")))?;
520521

codex-rs/core/tests/suite/rollout_list_find.rs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![allow(clippy::unwrap_used, clippy::expect_used)]
22
use std::io::Write;
3+
use std::path::Path;
34
use std::path::PathBuf;
45

56
use codex_core::find_conversation_path_by_id_str;
@@ -8,8 +9,8 @@ use uuid::Uuid;
89

910
/// Create sessions/YYYY/MM/DD and write a minimal rollout file containing the
1011
/// provided conversation id in the SessionMeta line. Returns the absolute path.
11-
fn write_minimal_rollout_with_id(codex_home: &TempDir, id: Uuid) -> PathBuf {
12-
let sessions = codex_home.path().join("sessions/2024/01/01");
12+
fn write_minimal_rollout_with_id(codex_home: &Path, id: Uuid) -> PathBuf {
13+
let sessions = codex_home.join("sessions/2024/01/01");
1314
std::fs::create_dir_all(&sessions).unwrap();
1415

1516
let file = sessions.join(format!("rollout-2024-01-01T00-00-00-{id}.jsonl"));
@@ -40,11 +41,41 @@ fn write_minimal_rollout_with_id(codex_home: &TempDir, id: Uuid) -> PathBuf {
4041
async fn find_locates_rollout_file_by_id() {
4142
let home = TempDir::new().unwrap();
4243
let id = Uuid::new_v4();
43-
let expected = write_minimal_rollout_with_id(&home, id);
44+
let expected = write_minimal_rollout_with_id(home.path(), id);
4445

4546
let found = find_conversation_path_by_id_str(home.path(), &id.to_string())
4647
.await
4748
.unwrap();
4849

4950
assert_eq!(found.unwrap(), expected);
5051
}
52+
53+
#[tokio::test]
54+
async fn find_handles_gitignore_covering_codex_home_directory() {
55+
let repo = TempDir::new().unwrap();
56+
let codex_home = repo.path().join(".codex");
57+
std::fs::create_dir_all(&codex_home).unwrap();
58+
std::fs::write(repo.path().join(".gitignore"), ".codex/**\n").unwrap();
59+
let id = Uuid::new_v4();
60+
let expected = write_minimal_rollout_with_id(&codex_home, id);
61+
62+
let found = find_conversation_path_by_id_str(&codex_home, &id.to_string())
63+
.await
64+
.unwrap();
65+
66+
assert_eq!(found, Some(expected));
67+
}
68+
69+
#[tokio::test]
70+
async fn find_ignores_granular_gitignore_rules() {
71+
let home = TempDir::new().unwrap();
72+
let id = Uuid::new_v4();
73+
let expected = write_minimal_rollout_with_id(home.path(), id);
74+
std::fs::write(home.path().join("sessions/.gitignore"), "*.jsonl\n").unwrap();
75+
76+
let found = find_conversation_path_by_id_str(home.path(), &id.to_string())
77+
.await
78+
.unwrap();
79+
80+
assert_eq!(found, Some(expected));
81+
}

codex-rs/file-search/src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ pub async fn run_main<T: Reporter>(
105105
threads,
106106
cancel_flag,
107107
compute_indices,
108+
true,
108109
)?;
109110
let match_count = matches.len();
110111
let matches_truncated = total_match_count > match_count;
@@ -121,6 +122,7 @@ pub async fn run_main<T: Reporter>(
121122

122123
/// The worker threads will periodically check `cancel_flag` to see if they
123124
/// should stop processing files.
125+
#[allow(clippy::too_many_arguments)]
124126
pub fn run(
125127
pattern_text: &str,
126128
limit: NonZero<usize>,
@@ -129,6 +131,7 @@ pub fn run(
129131
threads: NonZero<usize>,
130132
cancel_flag: Arc<AtomicBool>,
131133
compute_indices: bool,
134+
respect_gitignore: bool,
132135
) -> anyhow::Result<FileSearchResults> {
133136
let pattern = create_pattern(pattern_text);
134137
// Create one BestMatchesList per worker thread so that each worker can
@@ -157,6 +160,14 @@ pub fn run(
157160
.hidden(false)
158161
// Don't require git to be present to apply to apply git-related ignore rules.
159162
.require_git(false);
163+
if !respect_gitignore {
164+
walk_builder
165+
.git_ignore(false)
166+
.git_global(false)
167+
.git_exclude(false)
168+
.ignore(false)
169+
.parents(false);
170+
}
160171

161172
if !exclude.is_empty() {
162173
let mut override_builder = OverrideBuilder::new(search_directory);

codex-rs/tui/src/file_search.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ impl FileSearchManager {
172172
NUM_FILE_SEARCH_THREADS,
173173
cancellation_token.clone(),
174174
compute_indices,
175+
true,
175176
)
176177
.map(|res| res.matches)
177178
.unwrap_or_default();

0 commit comments

Comments
 (0)