Skip to content

Commit 88d9d43

Browse files
committed
fix: respect core.bare=true in conjunction with the main worktree (#1683)
1 parent 3506afb commit 88d9d43

File tree

3 files changed

+67
-10
lines changed

3 files changed

+67
-10
lines changed

gix/src/open/repository.rs

+26-8
Original file line numberDiff line numberDiff line change
@@ -303,15 +303,33 @@ impl ThreadSafeRepository {
303303
}
304304
}
305305

306-
match worktree_dir {
307-
None if !config.is_bare && refs.git_dir().file_name() == Some(OsStr::new(gix_discover::DOT_GIT_DIR)) => {
308-
worktree_dir = Some(git_dir.parent().expect("parent is always available").to_owned());
309-
}
310-
Some(_) => {
311-
// note that we might be bare even with a worktree directory - work trees don't have to be
312-
// the parent of a non-bare repository.
306+
{
307+
let looks_like_standard_git_dir =
308+
|| refs.git_dir().file_name() == Some(OsStr::new(gix_discover::DOT_GIT_DIR));
309+
match worktree_dir {
310+
None if !config.is_bare && looks_like_standard_git_dir() => {
311+
worktree_dir = Some(git_dir.parent().expect("parent is always available").to_owned());
312+
}
313+
Some(_) => {
314+
// We may assume that the presence of a worktree-dir means it's not bare, but only if there
315+
// is no configuration saying otherwise.
316+
// Thus, if we are here and the common-dir config claims it's bare and we have inferred a worktree anyway,
317+
// forget about it.
318+
if looks_like_standard_git_dir()
319+
&& config
320+
.resolved
321+
.boolean_filter("core.bare", |md| md.source == gix_config::Source::Local)
322+
.transpose()
323+
.ok()
324+
.flatten()
325+
.is_some()
326+
&& config.is_bare
327+
{
328+
worktree_dir = None;
329+
}
330+
}
331+
None => {}
313332
}
314-
None => {}
315333
}
316334

317335
refs.write_reflog = config::cache::util::reflog_or_default(config.reflog, worktree_dir.is_some());

gix/tests/fixtures/make_worktree_repo.sh

+8
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,11 @@ mkdir $worktree && touch $worktree/file
5656
git add file
5757
git commit -m "make sure na index exists"
5858
)
59+
60+
git init non-bare-turned-bare
61+
(cd non-bare-turned-bare
62+
git commit --allow-empty -m 'empty'
63+
git config core.bare true
64+
65+
git worktree add ../worktree-of-bare-repo
66+
)

gix/tests/gix/repository/open.rs

+33-2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,37 @@ fn bare_repo_with_index() -> crate::Result {
6666
Ok(())
6767
}
6868

69+
#[test]
70+
fn non_bare_turned_bare() -> crate::Result {
71+
let repo = named_subrepo_opts(
72+
"make_worktree_repo.sh",
73+
"non-bare-turned-bare",
74+
gix::open::Options::isolated(),
75+
)?;
76+
assert!(
77+
repo.is_bare(),
78+
"the configuration dictates this, even though it looks like a main worktree"
79+
);
80+
assert_eq!(repo.work_dir(), None);
81+
Ok(())
82+
}
83+
84+
#[test]
85+
fn worktree_of_bare_repo() -> crate::Result {
86+
let repo = named_subrepo_opts(
87+
"make_worktree_repo.sh",
88+
"worktree-of-bare-repo",
89+
gix::open::Options::isolated(),
90+
)?;
91+
assert!(!repo.is_bare(), "even though the main worktree is bare, this isn't");
92+
assert_ne!(
93+
repo.work_dir(),
94+
None,
95+
"we have opened the repo through a worktree, which is never bare"
96+
);
97+
Ok(())
98+
}
99+
69100
#[test]
70101
fn non_bare_non_git_repo_without_worktree() -> crate::Result {
71102
let repo = named_subrepo_opts(
@@ -182,12 +213,12 @@ mod missing_config_file {
182213
"worktree-no-config",
183214
gix::open::Options::isolated(),
184215
)?;
185-
assert!(repo.work_dir().is_some());
186-
assert!(repo.worktree().is_some());
187216
assert!(
188217
!repo.is_bare(),
189218
"without config, we can't really know what the repo is actually but can guess as there is a worktree"
190219
);
220+
assert!(repo.work_dir().is_some());
221+
assert!(repo.worktree().is_some());
191222
assert_eq!(
192223
repo.config_snapshot().meta().source,
193224
gix::config::Source::Local,

0 commit comments

Comments
 (0)