fix: handle relative worktree linking files#2599
Conversation
0a6aa7f to
48723fc
Compare
4b30cde to
17e1f6b
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates gix-discover and gix worktree handling to correctly resolve relative linked-worktree metadata written by newer Git versions (notably the backlink worktrees/<id>/gitdir file), including symlink-related semantics.
Changes:
- Added
gix_discover::path::from_plain_file_relative_to_file()to resolve relative “plain path” files against the containing file’s directory. - Switched linked-worktree backlink resolution to use the new helper in both discovery and
gix::worktree::Proxy::base(). - Added fixture scripts and regression tests covering relative linking files (plus symlink scenarios on Unix).
Reviewed changes
Copilot reviewed 7 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| gix-discover/src/path.rs | Adds helper to resolve relative plain-path file contents relative to the file location. |
| gix-discover/src/is.rs | Uses new helper when reading linked-worktree backlink (gitdir) from private git dir. |
| gix/src/worktree/proxy.rs | Uses new helper so Proxy::base() resolves relative backlink paths correctly. |
| gix-discover/tests/discover/upwards/mod.rs | Adds regression tests for discovery from linked checkout and private git dir with relative linking files (+ symlink case). |
| gix/tests/gix/repository/worktree.rs | Adds regression tests validating Repository::worktrees() proxy base resolution for relative linking files (+ symlinked main repo on Unix). |
| gix-discover/tests/fixtures/make_worktree_relative_linking.sh | New fixture generator for relative linked-worktree metadata (+ symlinked linked checkout). |
| gix/tests/fixtures/make_worktree_relative_linking.sh | New fixture generator for relative linked-worktree metadata (+ symlinked main repo). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 17e1f6b40e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "Codex (@codex) review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "Codex (@codex) address that feedback".
b726bd6 to
f374a10
Compare
f374a10 to
84f991c
Compare
The GitHub Actions `test-fast (windows-latest)` check was failing in PR #2599 because two symlink-specific relative worktree tests ran on Windows. The generated fixtures intentionally tolerate unavailable symlink creation there, leaving `main-symlink` and `linked-symlink` inaccessible. Mark only those symlink-specific tests as Unix-only so Windows continues to exercise the non-symlink relative linking coverage while avoiding fixture paths that cannot be opened on that platform. Validation: - cargo test -p gix-discover --test discover from_symlinked_worktree_with_relative_linking_files - cargo test -p gix --test gix repository::worktree::linked_worktree_proxy_base_with_symlinked_main_repo - cargo fmt --all --check
Co-authored-by: Sebastian Thiel <sebastian.thiel@icloud.com>
Git 2.48 can link worktrees with relative paths. In that layout the checkout .git file points at the private git dir relative to the checkout, while worktrees/<id>/gitdir points back to the checkout relative to the private git dir. Discovery already handled the checkout-side gitdir file, but paths read from the private git dir were treated as-is. That made discovery from .git/worktrees/<id> and Repository::worktrees() proxy base resolution produce relative paths anchored to the process cwd instead of the gitdir file location. Git reference: /Users/byron/dev/github.com/git/git worktree.c:write_worktree_linking_files writes both relative links with `relative_path()`, and t/t2400-worktree-add.sh covers the resulting relative files. Co-authored-by: Sebastian Thiel <sebastian.thiel@icloud.com>
a25dc80 to
fa54a5c
Compare
- need to make sure the ignored-archive tests skip if the version isn't recent enough. - only works on Unix it seems, on Windows the flag doesn't exist. Related to symlinks. Co-authored-by: Sebastian Thiel <sebastian.thiel@icloud.com>
fa54a5c to
1d80b47
Compare
Pull request was converted to draft
| @@ -74,15 +98,21 @@ pub fn repository_kind(git_dir: &Path) -> Option<RepositoryKind> { | |||
|
|
|||
| /// Reads a plain path from a file that contains it as its only content, with trailing newlines trimmed. | |||
| /// Reads a plain path from a file like [`from_plain_file()`], resolving relative paths against | ||
| /// the file's containing directory as needed. | ||
| pub fn from_plain_file_relative_to_file(path: &std::path::Path) -> Option<std::io::Result<PathBuf>> { | ||
| read_plain_file_content(path).map(|res| { | ||
| res.map(|buf| { | ||
| let plain_path = gix_path::from_bstring(buf); | ||
| match (plain_path.is_relative(), path.parent()) { | ||
| (true, Some(parent)) => parent.join(plain_path), | ||
| _ => plain_path, | ||
| } | ||
| }) | ||
| }) | ||
| } |
| git -C "$base" init -q main | ||
| ( | ||
| cd "$base/main" | ||
| git commit -q --allow-empty -m init |
| git -C "$base" init -q main | ||
| ( | ||
| cd "$base/main" | ||
| git commit -q --allow-empty -m init |
…`from_plain_file` Follow up on review comments from PR #2599 after the PR was merged. Update plain-path docs to describe trailing-whitespace trimming, invalid empty path files, and relative path-file semantics for single-component relative paths.

Tasks
Created by Codex on behalf of Byron. Byron will review before this is ready to merge.
Summary
Handle Git 2.48 relative linked-worktree metadata by resolving plain backlink files relative to their containing
gitdirfile, and use filesystem-aware realpath resolution for worktree backlinks so symlinked repository access keeps Git-compatible semantics.Reported issue
Can you check that we can handle relative worktree paths, which are available as of Git 2.48?
For reference, here is the location of Git source code: /Users/byron/dev/github.com/git/git .
Git Reference
Git's
worktree.c::write_worktree_linking_files()writes both sides of relative worktree links withrelative_path(): the checkout.gitfile points to the private git dir, and.git/worktrees/<id>/gitdirpoints back to the checkout. Git'st/t2400-worktree-add.shcovers the resulting relative files forgit worktree add --relative-paths.Changes
gix-discoverhelper for plain path files whose relative values are anchored at the containing file.Repository::worktrees()proxy base lookup.Validation
cargo fmt --all --checkcargo test -p gix-discover --test discovercargo test -p gix --test gix repository::worktreegit diff --checkcodex review --commit 0a6aa7f870c6f4ad20f9af6932d4c78a738fbc2d