-
-
Notifications
You must be signed in to change notification settings - Fork 385
fix: submodule worktree incorrect with symlinked .git
dir (#2052)
#2182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -301,7 +301,18 @@ impl ThreadSafeRepository { | |
| gix_config::Source::EnvOverride => wt_path, | ||
_ => git_dir.join(wt_path).into(), | ||
}; | ||
worktree_dir = gix_path::normalize(wt_path, current_dir).map(Cow::into_owned); | ||
|
||
// the reason we use realpath instead of gix_path::normalize here is because there | ||
// could be any intermediate symlinks (for example due to a symlinked .git | ||
// directory) | ||
worktree_dir = gix_path::realpath(&wt_path).ok(); | ||
// restore the relative path if possible after resolving the absolute path | ||
if wt_path.is_relative() { | ||
if let Some(rel_path) = worktree_dir.as_deref().and_then(|p| p.strip_prefix(current_dir).ok()) { | ||
worktree_dir = Some(rel_path.to_path_buf()); | ||
} | ||
} | ||
Comment on lines
+311
to
+314
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we have this, there must be a test for this. Maybe it's OK to leave it out for now, since this symlink handling is already quite a special case. |
||
|
||
#[allow(unused_variables)] | ||
if let Some(worktree_path) = worktree_dir.as_deref().filter(|wtd| !wtd.is_dir()) { | ||
gix_trace::warn!("The configured worktree path '{}' is not a directory or doesn't exist - `core.worktree` may be misleading", worktree_path.display()); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#!/usr/bin/env bash | ||
set -eu -o pipefail | ||
|
||
git init -q module1 | ||
(cd module1 | ||
touch this | ||
mkdir subdir | ||
touch subdir/that | ||
git add . | ||
git commit -q -m c1 | ||
echo hello >> this | ||
git commit -q -am c2 | ||
touch untracked | ||
) | ||
|
||
mkdir symlinked-git-dir | ||
(cd symlinked-git-dir | ||
git init -q r1 | ||
(cd r1 | ||
git commit -q --allow-empty -m "init" | ||
) | ||
|
||
git config -f r1/.git/config core.worktree "$(pwd)" | ||
ln -s r1/.git .git | ||
|
||
git -c protocol.file.allow=always submodule add ../module1 m1 | ||
git commit -m "add module 1" | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -310,6 +310,27 @@ mod index_worktree { | |
); | ||
} | ||
|
||
#[test] | ||
fn submodule_in_symlinked_dir() -> crate::Result { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test should be removed in favor of specific tests which make clear what's under test.
|
||
use crate::util::named_subrepo_opts; | ||
let repo = named_subrepo_opts( | ||
"make_submodule_with_symlinked_git_dir.sh", | ||
"symlinked-git-dir", | ||
gix::open::Options::isolated(), | ||
)?; | ||
let status = repo | ||
.status(gix::progress::Discard)? | ||
.index_worktree_options_mut(|opts| { | ||
opts.sorting = | ||
Some(gix::status::plumbing::index_as_worktree_with_renames::Sorting::ByPathCaseSensitive); | ||
}) | ||
.into_index_worktree_iter(None)?; | ||
for change in status { | ||
change?; | ||
} | ||
Ok(()) | ||
} | ||
|
||
#[test] | ||
fn submodule_modification() -> crate::Result { | ||
let repo = submodule_repo("modified-untracked-and-submodule-head-changed-and-modified")?; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using realpath should be conditional, based on if the path exists or not.
Because what's under test here really is that
normalize
can mess up paths that have symlinks in them, yielding an invalid path.So I think there should even be a warning in
gix_path::normalize()
to tell people to check if the path is still valid.In a follow-up, one should check all call-sites as they will have the same issue.