Skip to content

Commit 073e277

Browse files
committed
Explore also setting a ceiling directory
On Windows, where in theory it could matter if some version of Git performs upward traversal (even while not using configuration, due to `GIT_DIR` being set). The added complexity of doing this may not be justified.
1 parent 4e936bc commit 073e277

File tree

1 file changed

+24
-18
lines changed

1 file changed

+24
-18
lines changed

gix-path/src/env/git/mod.rs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -115,19 +115,6 @@ fn git_cmd(executable: PathBuf) -> Command {
115115
const CREATE_NO_WINDOW: u32 = 0x08000000;
116116
cmd.creation_flags(CREATE_NO_WINDOW);
117117
}
118-
// We will try to run `git` from a location fairly high in the filesystem. This can be faster
119-
// than running it from our own CWD, if we are deeply nested or on network storage.
120-
let cwd = if cfg!(windows) {
121-
// Try the Windows directory (usually `C:\Windows`) first. It is given by `SystemRoot`,
122-
// except in rare cases where our own parent has not passed down that environment variable.
123-
env::var_os("SystemRoot")
124-
.or_else(|| env::var_os("windir"))
125-
.map(PathBuf::from)
126-
.filter(|p| p.is_absolute())
127-
.unwrap_or_else(env::temp_dir)
128-
} else {
129-
"/".into()
130-
};
131118
// Git 2.8.0 and higher support --show-origin. The -l, -z, and --name-only options were
132119
// supported even before that. In contrast, --show-scope was introduced later, in Git 2.26.0.
133120
// Low versions of Git are still sometimes used, and this is sometimes reasonable because
@@ -139,13 +126,32 @@ fn git_cmd(executable: PathBuf) -> Command {
139126
// file under `/Library` is shown as an "unknown" scope but takes precedence over the system
140127
// scope. Although `GIT_CONFIG_NOSYSTEM` will suppress this as well, passing --system omits it.
141128
cmd.args(["config", "-lz", "--show-origin", "--name-only"])
142-
.current_dir(cwd)
143-
.env_remove("GIT_COMMON_DIR") // We are setting `GIT_DIR`.
129+
.stdin(Stdio::null())
130+
.stderr(Stdio::null())
131+
.env_remove("GIT_COMMON_DIR") // Because we are setting `GIT_DIR`.
144132
.env_remove("GIT_DISCOVERY_ACROSS_FILESYSTEM")
145133
.env("GIT_DIR", NULL_DEVICE) // Avoid getting local-scope config.
146-
.env("GIT_WORK_TREE", NULL_DEVICE) // Avoid confusion when debugging.
147-
.stdin(Stdio::null())
148-
.stderr(Stdio::null());
134+
.env("GIT_WORK_TREE", NULL_DEVICE); // Just to avoid confusion when debugging.
135+
136+
// We will run `git` from a location fairly high in the filesystem if we can. This can be
137+
// faster than running it from our own CWD, if we are deeply nested or on network storage.
138+
if cfg!(windows) {
139+
// We try the Windows directory (usually `C:\Windows`) first. It is given by `SystemRoot`,
140+
// except in rare cases where our own parent has not passed down that environment variable.
141+
let cwd = env::var_os("SystemRoot")
142+
.or_else(|| env::var_os("windir"))
143+
.map(PathBuf::from)
144+
.filter(|p| p.is_absolute())
145+
.unwrap_or_else(env::temp_dir);
146+
if let Some(parent) = cwd.parent().filter(|p| p.is_absolute() && *p != cwd) {
147+
cmd.env("GIT_CEILING_DIRECTORIES", parent);
148+
}
149+
cmd.current_dir(cwd);
150+
} else {
151+
// The root should always be available, with nothing above it to worry about traversing to.
152+
cmd.current_dir("/");
153+
}
154+
149155
cmd
150156
}
151157

0 commit comments

Comments
 (0)