Skip to content

Commit

Permalink
fix: Parse installation config path more robustly
Browse files Browse the repository at this point in the history
This adds the `-z`/`--null` and `--name-only` options in the `git`
invocation that tries to obtain the configuration file path
associated with the `git` installation itself. The benefits are:

- Parsing is more reliable for paths containing unusual characters,
  because `-z`/`--null` causes all paths to be output literally.

  Previously, `"` characters were trimmed from the ends, but this
  would not always extract a correct path, because when a path
  contains characters that cause `git` to enclose it in double
  quotes, those characters are usually represented in a symbolic
  form, usually with `\` escapes.

  In some scenarios, such as usually on Windows when the escaped
  character is itself a `\` and not in the leading position, the
  mangled path would be usable, but more often it would not.

- The volume of output is less, because `--name-only` casues values
  not to be included in the output.

- The combination of `-z`/`--null` and `--name-only` makes the
  output format simpler, and the parsing logic is accordingly
  simpler.

`git` has supported the `-z`/`--null` and `--name-only` options
even before support for `--show-origin` was added in Git 2.8.0, so
this change should have no effect on Git version compatibility.
  • Loading branch information
EliahKagan committed Aug 28, 2024
1 parent 9df57aa commit 650a1b5
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 8 deletions.
6 changes: 3 additions & 3 deletions gix-path/src/env/git/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ pub(super) static EXE_INFO: Lazy<Option<BString>> = Lazy::new(|| {
cmd.creation_flags(CREATE_NO_WINDOW);
}
// git 2.8.0 and higher support --show-origin.
cmd.args(["config", "-l", "--show-origin"])
cmd.args(["config", "-lz", "--show-origin", "--name-only"])
.current_dir(env::temp_dir())
.stdin(Stdio::null())
.stderr(Stdio::null());
Expand Down Expand Up @@ -138,8 +138,8 @@ pub(super) fn install_config_path() -> Option<&'static BStr> {

fn first_file_from_config_with_origin(source: &BStr) -> Option<&BStr> {
let file = source.strip_prefix(b"file:")?;
let end_pos = file.find_byte(b'\t')?;
file[..end_pos].trim_with(|c| c == '"').as_bstr().into()
let end_pos = file.find_byte(b'\0')?;
file[..end_pos].as_bstr().into()
}

/// Given `config_path` as obtained from `install_config_path()`, return the path of the git installation base.
Expand Down
13 changes: 8 additions & 5 deletions gix-path/src/env/git/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ fn config_to_base_path() {

#[test]
fn first_file_from_config_with_origin() {
let macos = "file:/Applications/Xcode.app/Contents/Developer/usr/share/git-core/gitconfig credential.helper=osxkeychain\nfile:/Users/byron/.gitconfig push.default=simple\n";
let macos =
"file:/Applications/Xcode.app/Contents/Developer/usr/share/git-core/gitconfig\0credential.helper\0file:/Users/byron/.gitconfig\0push.default\0";
let win_msys =
"file:C:/git-sdk-64/etc/gitconfig core.symlinks=false\r\nfile:C:/git-sdk-64/etc/gitconfig core.autocrlf=true";
let win_cmd = "file:C:/Program Files/Git/etc/gitconfig diff.astextplain.textconv=astextplain\r\nfile:C:/Program Files/Git/etc/gitconfig filter.lfs.clean=gix-lfs clean -- %f\r\n";
let win_msys_old = "file:\"C:\\ProgramData/Git/config\" diff.astextplain.textconv=astextplain\r\nfile:\"C:\\ProgramData/Git/config\" filter.lfs.clean=git-lfs clean -- %f\r\n";
let linux = "file:/home/parallels/.gitconfig core.excludesfile=~/.gitignore\n";
"file:C:/git-sdk-64/etc/gitconfig\0core.symlinks\0file:C:/git-sdk-64/etc/gitconfig\0core.autocrlf\0";
let win_cmd =
"file:C:/Program Files/Git/etc/gitconfig\0diff.astextplain.textconv\0file:C:/Program Files/Git/etc/gitconfig\0filter.lfs.clean\0";
let win_msys_old =
"file:C:\\ProgramData/Git/config\0diff.astextplain.textconv\0file:C:\\ProgramData/Git/config\0filter.lfs.clean\0";
let linux = "file:/home/parallels/.gitconfig\0core.excludesfile\0";
let bogus = "something unexpected";
let empty = "";

Expand Down

0 comments on commit 650a1b5

Please # to comment.