Nguyễn Thái Ngọc Duy  <pclo...@gmail.com> writes:

> Uninitialized submodules have nothing valueable for us to be worried
> about. They are just SHA-1. Let "worktree remove" and "worktree move"
> continue in this case so that people can still use multiple worktrees
> on repos with optional submodules that are never populated, like
> sha1collisiondetection in git.git when checked out by doc-diff script.
>
> Note that for "worktree remove", it is possible that a user
> initializes a submodule (*), makes some commits (but not push), then
> deinitializes it. At that point, the submodule is unpopulated, but the
> precious new commits are still in
>
>     $GIT_COMMON_DIR/worktrees/<worktree>/modules/<submodule>
>
> directory and we should not allow removing the worktree or we lose
> those commits forever. The new directory check is added to prevent
> this.
>
> (*) yes they are screwed anyway by doing this since "git submodule"
>     would add submodule.* in $GIT_COMMON_DIR/config, which is shared
>     across multiple worktrees. But it does not mean we let them be
>     screwed even more.
>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
> ---
>  Fixed Eric's comment. I was a bit annoyed by the duplicate die() too
>  but didn't think of adding "else" in front of "if (read_index"
>
>  builtin/worktree.c | 29 +++++++++++++++++++++++------
>  1 file changed, 23 insertions(+), 6 deletions(-)

Is this a fair description for this 1-patch topic?

        "git worktree remove" and "git worktree move" failed to work
        when there is an uninitialized submodule, which has been fixed.

If so, can we have a test case to cover this fix?

Thanks.

> diff --git a/builtin/worktree.c b/builtin/worktree.c
> index 5e84026177..3f9907fcc9 100644
> --- a/builtin/worktree.c
> +++ b/builtin/worktree.c
> @@ -9,6 +9,7 @@
>  #include "refs.h"
>  #include "run-command.h"
>  #include "sigchain.h"
> +#include "submodule.h"
>  #include "refs.h"
>  #include "utf8.h"
>  #include "worktree.h"
> @@ -724,20 +725,36 @@ static int unlock_worktree(int ac, const char **av, 
> const char *prefix)
>  static void validate_no_submodules(const struct worktree *wt)
>  {
>       struct index_state istate = { NULL };
> +     struct strbuf path = STRBUF_INIT;
>       int i, found_submodules = 0;
>  
> -     if (read_index_from(&istate, worktree_git_path(wt, "index"),
> -                         get_worktree_git_dir(wt)) > 0) {
> +     if (is_directory(worktree_git_path(wt, "modules"))) {
> +             /*
> +              * There could be false positives, e.g. the "modules"
> +              * directory exists but is empty. But it's a rare case and
> +              * this simpler check is probably good enough for now.
> +              */
> +             found_submodules = 1;
> +     } else if (read_index_from(&istate, worktree_git_path(wt, "index"),
> +                                get_worktree_git_dir(wt)) > 0) {
>               for (i = 0; i < istate.cache_nr; i++) {
>                       struct cache_entry *ce = istate.cache[i];
> +                     int err;
>  
> -                     if (S_ISGITLINK(ce->ce_mode)) {
> -                             found_submodules = 1;
> -                             break;
> -                     }
> +                     if (!S_ISGITLINK(ce->ce_mode))
> +                             continue;
> +
> +                     strbuf_reset(&path);
> +                     strbuf_addf(&path, "%s/%s", wt->path, ce->name);
> +                     if (!is_submodule_populated_gently(path.buf, &err))
> +                             continue;
> +
> +                     found_submodules = 1;
> +                     break;
>               }
>       }
>       discard_index(&istate);
> +     strbuf_release(&path);
>  
>       if (found_submodules)
>               die(_("working trees containing submodules cannot be moved or 
> removed"));

Reply via email to