Unified · Split
| @@ -230,7 +230,7 @@ pub fn into( · 229 unmodified lines | |||
| 230 | Ok(gix_discover::repository::Path::from_dot_git_dir( | 230 | Ok(gix_discover::repository::Path::from_dot_git_dir( |
| 231 | dot_git, | 231 | dot_git, |
| 232 | if bare { | 232 | if bare { |
| 233 | gix_discover::repository::Kind::Bare | 233 | gix_discover::repository::Kind::PossiblyBare |
| 234 | } else { | 234 | } else { |
| 235 | gix_discover::repository::Kind::WorkTree { linked_git_dir: None } | 235 | gix_discover::repository::Kind::WorkTree { linked_git_dir: None } |
| 236 | }, | 236 | }, |
| @@ -240,10 +240,20 @@ impl ThreadSafeRepository { · 239 unmodified lines | |||
| 240 | let wt_path = wt | 240 | let wt_path = wt |
| 241 | .interpolate(interpolate_context(git_install_dir.as_deref(), home.as_deref())) | 241 | .interpolate(interpolate_context(git_install_dir.as_deref(), home.as_deref())) |
| 242 | .map_err(config::Error::PathInterpolation)?; | 242 | .map_err(config::Error::PathInterpolation)?; |
| 243 | worktree_dir = { | 243 | worktree_dir = gix_path::normalize(git_dir.join(wt_path).into(), current_dir).map(Cow::into_owned); |
| 244 | gix_path::normalize(git_dir.join(wt_path).into(), current_dir) | 244 | #[allow(unused_variables)] |
| 245 | .and_then(|wt| wt.as_ref().is_dir().then(|| wt.into_owned())) | 245 | if let Some(worktree_path) = worktree_dir.as_deref().filter(|wtd| !wtd.is_dir()) { |
| 246 | gix_trace::warn!("The configured worktree path '{}' is not a directory or doesn't exist - `core.worktree` may be misleading", worktree_path.display()); | ||
| 246 | } | 247 | } |
| 248 | } else if !config.lenient_config | ||
| 249 | && config | ||
| 250 | .resolved | ||
| 251 | .boolean_filter("core", None, Core::WORKTREE.name, &mut filter_config_section) | ||
| 252 | .is_some() | ||
| 253 | { | ||
| 254 | return Err(Error::from(config::Error::ConfigTypedString( | ||
| 255 | config::key::GenericErrorWithValue::from(&Core::WORKTREE), | ||
| 256 | ))); | ||
| 247 | } | 257 | } |
| 248 | } | 258 | } |
| 249 | 259 | ||
| @@ -13,7 +13,7 @@ impl From<gix_discover::repository::Kind> for Kind { · 12 unmodified lines | |||
| 13 | gix_discover::repository::Kind::Submodule { .. } | gix_discover::repository::Kind::SubmoduleGitDir => { | 13 | gix_discover::repository::Kind::Submodule { .. } | gix_discover::repository::Kind::SubmoduleGitDir => { |
| 14 | Kind::WorkTree { is_linked: false } | 14 | Kind::WorkTree { is_linked: false } |
| 15 | } | 15 | } |
| 16 | gix_discover::repository::Kind::Bare => Kind::Bare, | 16 | gix_discover::repository::Kind::PossiblyBare => Kind::Bare, |
| 17 | gix_discover::repository::Kind::WorkTreeGitDir { .. } => Kind::WorkTree { is_linked: true }, | 17 | gix_discover::repository::Kind::WorkTreeGitDir { .. } => Kind::WorkTree { is_linked: true }, |
| 18 | gix_discover::repository::Kind::WorkTree { linked_git_dir } => Kind::WorkTree { | 18 | gix_discover::repository::Kind::WorkTree { linked_git_dir } => Kind::WorkTree { |
| 19 | is_linked: linked_git_dir.is_some(), | 19 | is_linked: linked_git_dir.is_some(), |
| @@ -17,18 +17,42 @@ mkdir repo · 16 unmodified lines | |||
| 17 | git commit -q -am c2 | 17 | git commit -q -am c2 |
| 18 | ) | 18 | ) |
| 19 | 19 | ||
| 20 | if [ "$bare" == "bare" ]; then | 20 | (if [ "$bare" == "bare" ]; then |
| 21 | git clone --bare --shared repo repo.git | 21 | git clone --bare --shared repo repo.git |
| 22 | cd repo.git | 22 | cd repo.git |
| 23 | else | 23 | else |
| 24 | cd repo | 24 | cd repo |
| 25 | fi | 25 | fi |
| 26 | 26 | ||
| 27 | git worktree add ../wt-a | 27 | git worktree add ../wt-a |
| 28 | git worktree add ../prev/wt-a HEAD~1 | 28 | git worktree add ../prev/wt-a HEAD~1 |
| 29 | git worktree add ../wt-b HEAD~1 | 29 | git worktree add ../wt-b HEAD~1 |
| 30 | git worktree add ../wt-a/nested-wt-b HEAD~1 | 30 | git worktree add ../wt-a/nested-wt-b HEAD~1 |
| 31 | git worktree add --lock ../wt-c-locked | 31 | git worktree add --lock ../wt-c-locked |
| 32 | git worktree add ../wt-deleted && rm -Rf ../wt-deleted | 32 | git worktree add ../wt-deleted && rm -Rf ../wt-deleted |
| 33 | 33 | ||
| 34 | git worktree list --porcelain > ../worktree-list.baseline | 34 | git worktree list --porcelain > ../worktree-list.baseline |
| 35 | ) | ||
| 36 | |||
| 37 | |||
| 38 | git --git-dir=repo-with-worktree-in-config-unborn-no-worktreedir --work-tree=does-not-exist-yet init | ||
| 39 | worktree=repo-with-worktree-in-config-unborn-worktree | ||
| 40 | git --git-dir=repo-with-worktree-in-config-unborn --work-tree=$worktree init && mkdir $worktree | ||
| 41 | |||
| 42 | repo=repo-with-worktree-in-config-unborn-empty-worktreedir | ||
| 43 | git --git-dir=$repo --work-tree="." init | ||
| 44 | git -C $repo config core.worktree '' | ||
| 45 | |||
| 46 | repo=repo-with-worktree-in-config-unborn-worktreedir-missing-value | ||
| 47 | git --git-dir=$repo init | ||
| 48 | touch $repo/index | ||
| 49 | git -C $repo config core.bare false | ||
| 50 | echo " worktree" >> $repo/config | ||
| 51 | |||
| 52 | worktree=repo-with-worktree-in-config-worktree | ||
| 53 | git --git-dir=repo-with-worktree-in-config --work-tree=$worktree init | ||
| 54 | mkdir $worktree && touch $worktree/file | ||
| 55 | (cd repo-with-worktree-in-config | ||
| 56 | git add file | ||
| 57 | git commit -m "make sure na index exists" | ||
| 58 | ) | ||
| @@ -1,4 +1,5 @@ | |||
| 1 | use crate::util::named_subrepo_opts; | 1 | use crate::util::named_subrepo_opts; |
| 2 | use std::error::Error; | ||
| 2 | 3 | ||
| 3 | #[test] | 4 | #[test] |
| 4 | fn bare_repo_with_index() -> crate::Result { | 5 | fn bare_repo_with_index() -> crate::Result { |
| @@ -26,6 +27,59 @@ fn none_bare_repo_without_index() -> crate::Result { · 21 unmodified lines | |||
| 26 | Ok(()) | 27 | Ok(()) |
| 27 | } | 28 | } |
| 28 | 29 | ||
| 30 | #[test] | ||
| 31 | fn non_bare_split_worktree() -> crate::Result { | ||
| 32 | for (name, worktree_exists) in [ | ||
| 33 | ("repo-with-worktree-in-config-unborn-no-worktreedir", false), | ||
| 34 | ("repo-with-worktree-in-config-unborn", true), | ||
| 35 | ("repo-with-worktree-in-config", true), | ||
| 36 | ] { | ||
| 37 | let repo = named_subrepo_opts("make_worktree_repo.sh", name, gix::open::Options::isolated())?; | ||
| 38 | assert!(repo.git_dir().is_dir()); | ||
| 39 | assert!( | ||
| 40 | !repo.is_bare(), | ||
| 41 | "worktree is actually configured, and it's non-bare by configuration" | ||
| 42 | ); | ||
| 43 | assert_eq!( | ||
| 44 | repo.work_dir().expect("worktree is configured").is_dir(), | ||
| 45 | worktree_exists | ||
| 46 | ); | ||
| 47 | } | ||
| 48 | Ok(()) | ||
| 49 | } | ||
| 50 | |||
| 51 | #[test] | ||
| 52 | fn non_bare_split_worktree_invalid_worktree_path_boolean() -> crate::Result { | ||
| 53 | let err = named_subrepo_opts( | ||
| 54 | "make_worktree_repo.sh", | ||
| 55 | "repo-with-worktree-in-config-unborn-worktreedir-missing-value", | ||
| 56 | gix::open::Options::isolated().strict_config(true), | ||
| 57 | ) | ||
| 58 | .unwrap_err(); | ||
| 59 | assert_eq!( | ||
| 60 | err.source().expect("present").to_string(), | ||
| 61 | "The key \"core.worktree\" (possibly from GIT_WORK_TREE) was invalid", | ||
| 62 | "in strict mode, we fail just like git does" | ||
| 63 | ); | ||
| 64 | Ok(()) | ||
| 65 | } | ||
| 66 | |||
| 67 | #[test] | ||
| 68 | fn non_bare_split_worktree_invalid_worktree_path_empty() -> crate::Result { | ||
| 69 | // "repo-with-worktree-in-config-unborn-worktreedir-missing-value", | ||
| 70 | let err = named_subrepo_opts( | ||
| 71 | "make_worktree_repo.sh", | ||
| 72 | "repo-with-worktree-in-config-unborn-empty-worktreedir", | ||
| 73 | gix::open::Options::isolated(), | ||
| 74 | ) | ||
| 75 | .unwrap_err(); | ||
| 76 | assert!( | ||
| 77 | matches!(err, gix::open::Error::Config(gix::config::Error::PathInterpolation(_))), | ||
| 78 | "DEVIATION: could not read path at core.worktree as empty is always invalid, git tries to use an empty path, even though it's better to reject it" | ||
| 79 | ); | ||
| 80 | Ok(()) | ||
| 81 | } | ||
| 82 | |||
| 29 | mod missing_config_file { | 83 | mod missing_config_file { |
| 30 | 84 | ||
| 31 | use crate::util::named_subrepo_opts; | 85 | use crate::util::named_subrepo_opts; |
| @@ -91,10 +91,10 @@ mod with_core_worktree_config { · 90 unmodified lines | |||
| 91 | "git can't chdir into missing worktrees, has no error handling there" | 91 | "git can't chdir into missing worktrees, has no error handling there" |
| 92 | ); | 92 | ); |
| 93 | 93 | ||
| 94 | assert_eq!( | 94 | assert!( |
| 95 | repo.work_dir(), | 95 | !repo.work_dir().expect("configured").exists(), |
| 96 | repo.git_dir().parent(), | 96 | "non-existing or invalid worktrees (this one is a file) are taken verbatim and \ |
| 97 | "we just ignore missing configured worktree dirs and fall back to the default one" | 97 | may lead to errors later - just like in `git` and we explicitly do not try to be smart about it" |
| 98 | ) | 98 | ) |
| 99 | } | 99 | } |
| 100 | 100 | ||
| @@ -103,11 +103,11 @@ mod with_core_worktree_config { · 2 unmodified lines | |||
| 103 | let repo = repo("relative-worktree-file"); | 103 | let repo = repo("relative-worktree-file"); |
| 104 | assert_eq!(count_deleted(repo.git_dir()), 0, "git can't chdir into a file"); | 104 | assert_eq!(count_deleted(repo.git_dir()), 0, "git can't chdir into a file"); |
| 105 | 105 | ||
| 106 | assert_eq!( | 106 | assert!( |
| 107 | repo.work_dir(), | 107 | repo.work_dir().expect("configured").is_file(), |
| 108 | repo.git_dir().parent(), | 108 | "non-existing or invalid worktrees (this one is a file) are taken verbatim and \ |
| 109 | "we just ignore missing configured worktree dirs and fall back to the default one" | 109 | may lead to errors later - just like in `git` and we explicitly do not try to be smart about it" |
| 110 | ) | 110 | ); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | #[test] | 113 | #[test] |
| @@ -1,6 +1,10 @@ | |||
| 1 | pub fn repo(name: &str) -> crate::Result<gix::Repository> { | 1 | pub fn repo(name: &str) -> crate::Result<gix::Repository> { |
| 2 | use crate::util::named_subrepo_opts; | 2 | use crate::util::named_subrepo_opts; |
| 3 | named_subrepo_opts("make_submodules.sh", name, gix::open::Options::isolated()) | 3 | Ok(named_subrepo_opts( |
| 4 | "make_submodules.sh", | ||
| 5 | name, | ||
| 6 | gix::open::Options::isolated(), | ||
| 7 | )?) | ||
| 4 | } | 8 | } |
| 5 | 9 | ||
| 6 | mod open { | 10 | mod open { |
| @@ -34,8 +34,12 @@ pub fn named_repo(name: &str) -> Result<Repository> { · 33 unmodified lines | |||
| 34 | Ok(ThreadSafeRepository::open_opts(repo_path, restricted())?.to_thread_local()) | 34 | Ok(ThreadSafeRepository::open_opts(repo_path, restricted())?.to_thread_local()) |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | pub fn named_subrepo_opts(fixture: &str, name: &str, opts: open::Options) -> Result<Repository> { | 37 | pub fn named_subrepo_opts( |
| 38 | let repo_path = gix_testtools::scripted_fixture_read_only(fixture)?.join(name); | 38 | fixture: &str, |
| 39 | name: &str, | ||
| 40 | opts: open::Options, | ||
| 41 | ) -> std::result::Result<Repository, gix::open::Error> { | ||
| 42 | let repo_path = gix_testtools::scripted_fixture_read_only(fixture).unwrap().join(name); | ||
| 39 | Ok(ThreadSafeRepository::open_opts(repo_path, opts)?.to_thread_local()) | 43 | Ok(ThreadSafeRepository::open_opts(repo_path, opts)?.to_thread_local()) |
| 40 | } | 44 | } |
| 41 | 45 | ||