mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
core: load AGENTS.md from foreign environments (#28958)
## Why Make it possible to load AGENTS.md from remote exec-servers whose OS is different than app-server. ## What - keep `AGENTS.md` discovery and provenance as `PathUri`, with root-aware parent and ancestor traversal - expose lifecycle instruction sources as legacy app-server path strings in events while retaining `PathUri` internally - preserve and test mixed POSIX and Windows paths in model context and TUI status output - cover remote Windows loading end to end by seeding the Wine prefix through host filesystem APIs - fix bug in `PathUri`'s parent() implementation that would erase Windows drive letters
This commit is contained in:
@@ -209,13 +209,28 @@ impl PathUri {
|
||||
PathBuf::from(self.inferred_native_path_string())
|
||||
}
|
||||
|
||||
/// Returns the parent URI, or `None` for the URI root or an opaque fallback
|
||||
/// URI created by [`Self::from_abs_path`].
|
||||
/// Returns the lexical parent without crossing the inferred native path root.
|
||||
///
|
||||
/// POSIX `/`, Windows drive roots, Windows UNC share roots, and opaque fallback
|
||||
/// URIs created by [`Self::from_abs_path`] have no parent.
|
||||
pub fn parent(&self) -> Option<Self> {
|
||||
if self.encoded_path() == "/" || decode_bad_path_uri(&self.0).is_some() {
|
||||
if decode_bad_path_uri(&self.0).is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let convention = self.infer_path_convention()?;
|
||||
// In URI form, both a Windows drive root (`file:///C:`) and a UNC share root
|
||||
// (`file://server/share`) retain one non-empty path segment. Keep that segment as the
|
||||
// anchor so parent traversal cannot produce a URI that is not an absolute Windows path.
|
||||
let anchor_depth = usize::from(convention == PathConvention::Windows);
|
||||
let depth = self
|
||||
.0
|
||||
.path_segments()?
|
||||
.filter(|segment| !segment.is_empty())
|
||||
.count();
|
||||
if depth <= anchor_depth {
|
||||
return None;
|
||||
}
|
||||
let mut url = self.0.clone();
|
||||
{
|
||||
let mut segments = match url.path_segments_mut() {
|
||||
@@ -227,6 +242,11 @@ impl PathUri {
|
||||
Some(Self(url))
|
||||
}
|
||||
|
||||
/// Returns this URI and each lexical parent up to its inferred native path root.
|
||||
pub fn ancestors(&self) -> impl Iterator<Item = Self> {
|
||||
std::iter::successors(Some(self.clone()), Self::parent)
|
||||
}
|
||||
|
||||
/// Lexically resolves native absolute or relative path text against this URI.
|
||||
///
|
||||
/// Path text is interpreted using the POSIX or Windows convention inferred
|
||||
|
||||
@@ -522,7 +522,7 @@ fn path_buf_uses_the_inferred_native_spelling() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parent_uses_uri_hierarchy_and_preserves_authority() {
|
||||
fn parent_stops_at_posix_drive_and_unc_roots() {
|
||||
for (input, expected) in [
|
||||
(
|
||||
"file:///workspace/src/lib.rs",
|
||||
@@ -531,12 +531,13 @@ fn parent_uses_uri_hierarchy_and_preserves_authority() {
|
||||
("file:///workspace", Some("file:///")),
|
||||
("file:///", None),
|
||||
("file:///C:/Users", Some("file:///C:")),
|
||||
("file:///C:/", Some("file:///")),
|
||||
("file:///C:/", None),
|
||||
("file:///C:", None),
|
||||
(
|
||||
"file://server/share/src/main.rs",
|
||||
Some("file://server/share/src"),
|
||||
),
|
||||
("file://server/share", Some("file://server/")),
|
||||
("file://server/share", None),
|
||||
] {
|
||||
let uri = PathUri::parse(input).expect("valid file URI");
|
||||
let expected = expected.map(|value| PathUri::parse(value).expect("valid expected URI"));
|
||||
@@ -544,6 +545,35 @@ fn parent_uses_uri_hierarchy_and_preserves_authority() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ancestors_include_self_and_stop_at_native_path_roots() {
|
||||
for (input, expected) in [
|
||||
(
|
||||
"file:///workspace/src",
|
||||
vec!["file:///workspace/src", "file:///workspace", "file:///"],
|
||||
),
|
||||
(
|
||||
"file:///C:/workspace/src",
|
||||
vec![
|
||||
"file:///C:/workspace/src",
|
||||
"file:///C:/workspace",
|
||||
"file:///C:",
|
||||
],
|
||||
),
|
||||
(
|
||||
"file://server/share/project",
|
||||
vec!["file://server/share/project", "file://server/share"],
|
||||
),
|
||||
] {
|
||||
let uri = PathUri::parse(input).expect("valid file URI");
|
||||
let ancestors = uri
|
||||
.ancestors()
|
||||
.map(|path| path.to_string())
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(ancestors, expected, "ancestors for {input}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn join_normalizes_relative_uri_segments() {
|
||||
for (base, relative, expected) in [
|
||||
|
||||
Reference in New Issue
Block a user