Skip to content

Commit cea085c

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

File tree

5 files changed

+70
-11
lines changed

5 files changed

+70
-11
lines changed

gix/src/open/repository.rs

Lines changed: 26 additions & 8 deletions
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());
Binary file not shown.

gix/tests/fixtures/make_basic_repo.sh

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,12 @@ git clone --bare . non-bare-without-worktree
4343
git config core.bare false
4444
)
4545

46-
git init unborn;
46+
git init unborn;
47+
48+
git init non-bare-turned-bare
49+
(cd non-bare-turned-bare
50+
git commit --allow-empty -m 'empty'
51+
git config core.bare true
52+
53+
git worktree add ../worktree-of-bare-repo
54+
)

gix/tests/gix/repository/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,11 @@ mod dirwalk {
5959
("bare.git".into(), Directory),
6060
("empty-core-excludes".into(), Repository),
6161
("non-bare-repo-without-index".into(), Repository),
62+
("non-bare-turned-bare".into(), Repository),
6263
("non-bare-without-worktree".into(), Directory),
6364
("some".into(), Directory),
6465
("unborn".into(), Repository),
66+
("worktree-of-bare-repo".into(), Repository),
6567
];
6668
assert_eq!(
6769
collect

gix/tests/gix/repository/open.rs

Lines changed: 33 additions & 2 deletions
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_basic_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_basic_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)