diff --git a/Cargo.toml b/Cargo.toml index 96d6afa519e..301404a443e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ default = ["max"] ## ## As fast as possible, tracing, with TUI progress, progress line rendering with autoconfiguration, all transports based on their most mature implementation (HTTP), all `ein` tools, CLI colors and local-time support, JSON output, regex support for rev-specs. ## Can be amended with the `http-client-curl-rustls` feature to avoid `openssl` as backend. -max = ["max-control", "fast", "gitoxide-core-blocking-client", "http-client-curl"] +max = ["max-control", "fast", "gitoxide-core-tools-query", "gitoxide-core-tools-corpus", "gitoxide-core-blocking-client", "http-client-curl"] ## Like `max`, but only Rust is allowed. ## @@ -47,9 +47,9 @@ max = ["max-control", "fast", "gitoxide-core-blocking-client", "http-client-curl max-pure = ["max-control", "gix-features/rustsha1", "gix-features/zlib-rust-backend", "http-client-reqwest", "gitoxide-core-blocking-client"] ## Like `max`, but with more control for configuration. See the *Package Maintainers* headline for more information. -max-control = ["tracing", "fast-safe", "pretty-cli", "gitoxide-core-tools-query", "gitoxide-core-tools-corpus", "gitoxide-core-tools", "prodash-render-line", "prodash-render-tui", "prodash/render-line-autoconfigure", "gix/revparse-regex"] +max-control = ["tracing", "fast-safe", "pretty-cli", "gitoxide-core-tools", "prodash-render-line", "prodash-render-tui", "prodash/render-line-autoconfigure", "gix/revparse-regex"] -## All of the good stuff, with less fanciness for smaller binaries. +## All the good stuff, with less fanciness for smaller binaries. ## ## As fast as possible, progress line rendering, all transports based on their most mature implementation (HTTP), all `ein` tools, CLI colors and local-time support, JSON output. lean = ["fast", "tracing", "pretty-cli", "http-client-curl", "gitoxide-core-tools-query", "gitoxide-core-tools-corpus", "gitoxide-core-tools", "gitoxide-core-blocking-client", "prodash-render-line"] diff --git a/gix/src/open/repository.rs b/gix/src/open/repository.rs index e22ac6114cf..a8099ec3552 100644 --- a/gix/src/open/repository.rs +++ b/gix/src/open/repository.rs @@ -303,15 +303,33 @@ impl ThreadSafeRepository { } } - match worktree_dir { - None if !config.is_bare && refs.git_dir().file_name() == Some(OsStr::new(gix_discover::DOT_GIT_DIR)) => { - worktree_dir = Some(git_dir.parent().expect("parent is always available").to_owned()); - } - Some(_) => { - // note that we might be bare even with a worktree directory - work trees don't have to be - // the parent of a non-bare repository. + { + let looks_like_standard_git_dir = + || refs.git_dir().file_name() == Some(OsStr::new(gix_discover::DOT_GIT_DIR)); + match worktree_dir { + None if !config.is_bare && looks_like_standard_git_dir() => { + worktree_dir = Some(git_dir.parent().expect("parent is always available").to_owned()); + } + Some(_) => { + // We may assume that the presence of a worktree-dir means it's not bare, but only if there + // is no configuration saying otherwise. + // Thus, if we are here and the common-dir config claims it's bare and we have inferred a worktree anyway, + // forget about it. + if looks_like_standard_git_dir() + && config + .resolved + .boolean_filter("core.bare", |md| md.source == gix_config::Source::Local) + .transpose() + .ok() + .flatten() + .is_some() + && config.is_bare + { + worktree_dir = None; + } + } + None => {} } - None => {} } refs.write_reflog = config::cache::util::reflog_or_default(config.reflog, worktree_dir.is_some()); diff --git a/gix/tests/fixtures/make_worktree_repo.sh b/gix/tests/fixtures/make_worktree_repo.sh index b7681a351d8..b9617b953fe 100755 --- a/gix/tests/fixtures/make_worktree_repo.sh +++ b/gix/tests/fixtures/make_worktree_repo.sh @@ -56,3 +56,11 @@ mkdir $worktree && touch $worktree/file git add file git commit -m "make sure na index exists" ) + +git init non-bare-turned-bare +(cd non-bare-turned-bare + git commit --allow-empty -m 'empty' + git config core.bare true + + git worktree add ../worktree-of-bare-repo +) diff --git a/gix/tests/gix/repository/open.rs b/gix/tests/gix/repository/open.rs index cea3bf8ceca..c70d0cc83ce 100644 --- a/gix/tests/gix/repository/open.rs +++ b/gix/tests/gix/repository/open.rs @@ -66,6 +66,37 @@ fn bare_repo_with_index() -> crate::Result { Ok(()) } +#[test] +fn non_bare_turned_bare() -> crate::Result { + let repo = named_subrepo_opts( + "make_worktree_repo.sh", + "non-bare-turned-bare", + gix::open::Options::isolated(), + )?; + assert!( + repo.is_bare(), + "the configuration dictates this, even though it looks like a main worktree" + ); + assert_eq!(repo.work_dir(), None); + Ok(()) +} + +#[test] +fn worktree_of_bare_repo() -> crate::Result { + let repo = named_subrepo_opts( + "make_worktree_repo.sh", + "worktree-of-bare-repo", + gix::open::Options::isolated(), + )?; + assert!(!repo.is_bare(), "even though the main worktree is bare, this isn't"); + assert_ne!( + repo.work_dir(), + None, + "we have opened the repo through a worktree, which is never bare" + ); + Ok(()) +} + #[test] fn non_bare_non_git_repo_without_worktree() -> crate::Result { let repo = named_subrepo_opts( @@ -182,12 +213,12 @@ mod missing_config_file { "worktree-no-config", gix::open::Options::isolated(), )?; - assert!(repo.work_dir().is_some()); - assert!(repo.worktree().is_some()); assert!( !repo.is_bare(), "without config, we can't really know what the repo is actually but can guess as there is a worktree" ); + assert!(repo.work_dir().is_some()); + assert!(repo.worktree().is_some()); assert_eq!( repo.config_snapshot().meta().source, gix::config::Source::Local,