Skip to content

Commit 3ee9b63

Browse files
arumugamramaswamyEliahKagan
authored andcommitted
fix: worktree when .git is symlink (#2052)
Co-authored-by: Eliah Kagan <[email protected]>
1 parent 442f800 commit 3ee9b63

File tree

4 files changed

+63
-2
lines changed

4 files changed

+63
-2
lines changed

gix/src/open/repository.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,18 @@ impl ThreadSafeRepository {
301301
| gix_config::Source::EnvOverride => wt_path,
302302
_ => git_dir.join(wt_path).into(),
303303
};
304-
worktree_dir = gix_path::normalize(wt_path, current_dir).map(Cow::into_owned);
304+
305+
// the reason we use realpath instead of gix_path::normalize here is because there
306+
// could be any intermediate symlinks (for example due to a symlinked .git
307+
// directory)
308+
worktree_dir = gix_path::realpath(&wt_path).ok();
309+
// restore the relative path if possible after resolving the absolute path
310+
if wt_path.is_relative() {
311+
if let Some(rel_path) = worktree_dir.as_deref().and_then(|p| p.strip_prefix(current_dir).ok()) {
312+
worktree_dir = Some(rel_path.to_path_buf());
313+
}
314+
}
315+
305316
#[allow(unused_variables)]
306317
if let Some(worktree_path) = worktree_dir.as_deref().filter(|wtd| !wtd.is_dir()) {
307318
gix_trace::warn!("The configured worktree path '{}' is not a directory or doesn't exist - `core.worktree` may be misleading", worktree_path.display());

gix/tests/fixtures/generated-archives/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88
/make_signatures_repo.tar
99
/make_diff_repos.tar
1010
/make_submodule_with_worktree.tar
11-
/repo_with_untracked_files.tar
11+
/repo_with_untracked_files.tar
12+
/make_submodule_with_symlinked_git_dir.tar
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env bash
2+
set -eu -o pipefail
3+
4+
git init -q module1
5+
(cd module1
6+
touch this
7+
mkdir subdir
8+
touch subdir/that
9+
git add .
10+
git commit -q -m c1
11+
echo hello >> this
12+
git commit -q -am c2
13+
touch untracked
14+
)
15+
16+
mkdir symlinked-git-dir
17+
(cd symlinked-git-dir
18+
git init -q r1
19+
(cd r1
20+
git commit -q --allow-empty -m "init"
21+
)
22+
23+
git config -f r1/.git/config core.worktree "$(pwd)"
24+
ln -s r1/.git .git
25+
26+
git -c protocol.file.allow=always submodule add ../module1 m1
27+
git commit -m "add module 1"
28+
)

gix/tests/gix/status.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,27 @@ mod index_worktree {
310310
);
311311
}
312312

313+
#[test]
314+
fn submodule_in_symlinked_dir() -> crate::Result {
315+
use crate::util::named_subrepo_opts;
316+
let repo = named_subrepo_opts(
317+
"make_submodule_with_symlinked_git_dir.sh",
318+
"symlinked-git-dir",
319+
gix::open::Options::isolated(),
320+
)?;
321+
let status = repo
322+
.status(gix::progress::Discard)?
323+
.index_worktree_options_mut(|opts| {
324+
opts.sorting =
325+
Some(gix::status::plumbing::index_as_worktree_with_renames::Sorting::ByPathCaseSensitive);
326+
})
327+
.into_index_worktree_iter(None)?;
328+
for change in status {
329+
change?;
330+
}
331+
Ok(())
332+
}
333+
313334
#[test]
314335
fn submodule_modification() -> crate::Result {
315336
let repo = submodule_repo("modified-untracked-and-submodule-head-changed-and-modified")?;

0 commit comments

Comments
 (0)