]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'es/worktree-avoid-duplication-fix'
authorJunio C Hamano <gitster@pobox.com>
Thu, 5 Mar 2020 18:43:02 +0000 (10:43 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 5 Mar 2020 18:43:02 +0000 (10:43 -0800)
In rare cases "git worktree add <path>" could think that <path>
was already a registered worktree even when it wasn't and refuse
to add the new worktree. This has been corrected.

* es/worktree-avoid-duplication-fix:
  worktree: don't allow "add" validation to be fooled by suffix matching
  worktree: add utility to find worktree by pathname
  worktree: improve find_worktree() documentation

builtin/worktree.c
t/t2400-worktree-add.sh
worktree.c
worktree.h

index d6bc5263f175cedf42a87423da246c0a2f7f6f81..24f22800f38c759d123d7e307de488f0c8ee852f 100644 (file)
@@ -234,14 +234,7 @@ static void validate_worktree_add(const char *path, const struct add_opts *opts)
                die(_("'%s' already exists"), path);
 
        worktrees = get_worktrees(0);
-       /*
-        * find_worktree()'s suffix matching may undesirably find the main
-        * rather than a linked worktree (for instance, when the basenames
-        * of the main worktree and the one being created are the same).
-        * We're only interested in linked worktrees, so skip the main
-        * worktree with +1.
-        */
-       wt = find_worktree(worktrees + 1, NULL, path);
+       wt = find_worktree_by_path(worktrees, path);
        if (!wt)
                goto done;
 
index b5ece19460cde97e6102dc34097fe57fcee77ac9..5a7495474aa8723f77b296813381151ca39b4b8b 100755 (executable)
@@ -570,6 +570,15 @@ test_expect_success '"add" an existing locked but missing worktree' '
        git worktree add --force --force --detach gnoo
 '
 
+test_expect_success '"add" not tripped up by magic worktree matching"' '
+       # if worktree "sub1/bar" exists, "git worktree add bar" in distinct
+       # directory `sub2` should not mistakenly complain that `bar` is an
+       # already-registered worktree
+       mkdir sub1 sub2 &&
+       git -C sub1 --git-dir=../.git worktree add --detach bozo &&
+       git -C sub2 --git-dir=../.git worktree add --detach bozo
+'
+
 test_expect_success FUNNYNAMES 'sanitize generated worktree name' '
        git worktree add --detach ".  weird*..?.lock.lock" &&
        test -d .git/worktrees/---weird-.-
index 33c2655534b2902f115b38d7f9c6efd5a79a8fe1..52971f7082eb00d38282fad793264ab1bfd1a7e3 100644 (file)
@@ -211,7 +211,6 @@ struct worktree *find_worktree(struct worktree **list,
                               const char *arg)
 {
        struct worktree *wt;
-       char *path;
        char *to_free = NULL;
 
        if ((wt = find_worktree_by_suffix(list, arg)))
@@ -219,11 +218,17 @@ struct worktree *find_worktree(struct worktree **list,
 
        if (prefix)
                arg = to_free = prefix_filename(prefix, arg);
-       path = real_pathdup(arg, 0);
-       if (!path) {
-               free(to_free);
+       wt = find_worktree_by_path(list, arg);
+       free(to_free);
+       return wt;
+}
+
+struct worktree *find_worktree_by_path(struct worktree **list, const char *p)
+{
+       char *path = real_pathdup(p, 0);
+
+       if (!path)
                return NULL;
-       }
        for (; *list; list++) {
                const char *wt_path = real_path_if_valid((*list)->path);
 
@@ -231,7 +236,6 @@ struct worktree *find_worktree(struct worktree **list,
                        break;
        }
        free(path);
-       free(to_free);
        return *list;
 }
 
index caecc7a281cc6778447a5c70bc7a756306bbbd3b..d242a6e71c0333f80b76e44976f0c4356f99bec3 100644 (file)
@@ -44,13 +44,29 @@ int submodule_uses_worktrees(const char *path);
 const char *get_worktree_git_dir(const struct worktree *wt);
 
 /*
- * Search a worktree that can be unambiguously identified by
- * "arg". "prefix" must not be NULL.
+ * Search for the worktree identified unambiguously by `arg` -- typically
+ * supplied by the user via the command-line -- which may be a pathname or some
+ * shorthand uniquely identifying a worktree, thus making it convenient for the
+ * user to specify a worktree with minimal typing. For instance, if the last
+ * component (say, "foo") of a worktree's pathname is unique among worktrees
+ * (say, "work/foo" and "work/bar"), it can be used to identify the worktree
+ * unambiguously.
+ *
+ * `prefix` should be the `prefix` handed to top-level Git commands along with
+ * `argc` and `argv`.
+ *
+ * Return the worktree identified by `arg`, or NULL if not found.
  */
 struct worktree *find_worktree(struct worktree **list,
                               const char *prefix,
                               const char *arg);
 
+/*
+ * Return the worktree corresponding to `path`, or NULL if no such worktree
+ * exists.
+ */
+struct worktree *find_worktree_by_path(struct worktree **, const char *path);
+
 /*
  * Return true if the given worktree is the main one.
  */