Skip to content

fix(gix-config-value)!: expand ~ and ~user like git does - #2984

Merged
Sebastian Thiel (Byron) merged 4 commits into
GitoxideLabs:mainfrom
justonemorenight:fix/config-path-tilde-parity
Sep 9, 2026
Merged

fix(gix-config-value)!: expand ~ and ~user like git does#2984
Sebastian Thiel (Byron) merged 4 commits into
GitoxideLabs:mainfrom
justonemorenight:fix/config-path-tilde-parity

Conversation

@justonemorenight

Copy link
Copy Markdown

Written with assistance from the Zed coding agent through Just One More Night (@justonemorenight)'s account, per the identification rule in CONTRIBUTING.md.

Git expands ~ and ~user paths via interpolate_path() in path.c. In gix-config-value, Path::interpolate() previously required a trailing slash for the current user (~/) and required a slash for named users (self.starts_with(b"~") && self.contains(&b'/')). Consequently:

  • A standalone ~ was left unexpanded as a literal "~".
  • A standalone ~user without a trailing slash was left unexpanded as a literal "~user".
  • A nonexistent user without a slash (~nonexistent) silently returned the literal instead of producing a user lookup error.

Parity with Git

Recorded from git -c t.k=<input> config --type=path t.k on git 2.50.1:

input git before after
~ /home/user "~" /home/user
~/ /home/user/ /home/user /home/user
~/foo /home/user/foo /home/user/foo /home/user/foo
~user /home/user "~user" /home/user
~user/ /home/user/ /home/user /home/user
~user/foo /home/user/foo /home/user/foo /home/user/foo
~nonexistent error "~nonexistent" error

Changes

  • Expand ~ to home_dir when standalone, matching ~/.
  • In interpolate_user, allow paths without / (e.g. ~user) to expand directly to the user's home directory.
  • Update tests/value/path.rs: replace tilde_alone_does_not_interpolate with tilde_alone_substitutes_current_user, and add tests for ~user and missing user error cases.

Marked breaking (!): ~ and ~user without trailing slashes now interpolate instead of returning literal strings.

Verification

  • cargo test -p gix-config-value (56 tests + 2 doctests pass)
  • cargo test -p gix-config (366 tests pass)
  • cargo clippy -p gix-config-value (clean)
  • cargo fmt --check (clean)

Git expands `~` and `~user` paths via `interpolate_path()` in `path.c`.
In `gix-config-value`, `Path::interpolate()` previously required a trailing
slash for the current user (`~/`) and required a slash for named users
(`self.starts_with(b"~") && self.contains(&b'/')`). Consequently:
- A standalone `~` was left unexpanded as a literal `"~"`.
- A standalone `~user` without a trailing slash was left unexpanded as a literal `"~user"`.
- A nonexistent user without a slash (`~nonexistent`) silently returned the literal instead of producing a user lookup error.

Recorded from `git -c t.k=<input> config --type=path t.k` on git 2.50.1:

| input | git | before | after |
|---|---|---|---|
| `~` | `/home/user` | `"~"` | `/home/user` |
| `~/` | `/home/user/` | `/home/user` | `/home/user` |
| `~/foo` | `/home/user/foo` | `/home/user/foo` | `/home/user/foo` |
| `~user` | `/home/user` | `"~user"` | `/home/user` |
| `~user/` | `/home/user/` | `/home/user` | `/home/user` |
| `~user/foo` | `/home/user/foo` | `/home/user/foo` | `/home/user/foo` |
| `~nonexistent` | error | `"~nonexistent"` | error |

Changes:
- Expand `~` to `home_dir` when standalone, matching `~/`.
- In `interpolate_user`, allow paths without `/` (e.g. `~user`) to expand directly to the user's home directory.
- Update `tests/value/path.rs` with tests for `~`, `~user`, and missing user error cases.

Marked breaking (`!`): `~` and `~user` without trailing slashes now interpolate instead of returning literal strings.
@Byron

Copy link
Copy Markdown
Member

Thanks for the hint!

- remove OS specific home resolution which hardcoded 'unsupported',
  even though the closure can decide.
- simplified expansion logic

Assisted-by: GPT 6.0
Co-authored-by: GPT 6.0 <[email protected]>
<!-- agent -->
Fixture commands already ignore external Git configuration, but inherited
`GIT_TEMPLATE_DIR` could still inject personal template files into repositories
created by `git init`, making fixtures depend on the caller's environment.

Clear that variable in the shared command setup used by fixture scripts and
isolated Git helpers. Keep Git's installed templates available because existing
fixtures rely on their standard files and directory layout.

Document the isolation behavior and add a regression that supplies an external
template containing a marker file, then verifies that `git init` does not copy
it into the fixture repository.

Assisted-by: GPT 6.0
Co-authored-by: GPT 6.0 <[email protected]>
<!-- agent -->
- [P2] Preserve literal worktree paths when expanding bare tildes —
  gix-config-value/src/path.rs:196-200 With `core.worktree = "~"`,
  the caller in `gix/src/open/repository.rs` now selects `$HOME`,
  or fails under `Options::isolated()`. Git and the previous code
  instead use the literal `<git-dir>/~`: Git does not interpolate
  this setting. Adapt the worktree caller alongside this change so
  existing repositories continue opening correctly .
- [P2] Preserve failed-user fallback for conditional include patterns —
  gix-config-value/src/path.rs:191-194 For a bare repository
  named `~repo` where `repo` is not a system user, `[includeIf
  "gitdir:~repo"]` matches in Git and before this patch. It now
  produces a lookup error, which `gix-config`'s `gitdir_matches()`
  converts into `false`, silently omitting the included settings. Git's
  `prepare_include_condition_pattern()` preserves the original pattern
  when expansion fails; retain that fallback in the caller.

Assisted-by: GPT 6.0
Co-authored-by: GPT 6.0 <[email protected]>
@Byron
Sebastian Thiel (Byron) merged commit 92b6508 into GitoxideLabs:main Sep 9, 2026
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants