worktree move: refuse to move worktrees with submodules

Submodules contains .git files with relative paths. After a worktree move, these files need to be updated or they may point to nowhere. This is a bandage patch to make sure "worktree move" don't break people's worktrees by accident. When .git file update code is in place, this validate_no_submodules() could be removed. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Feb 12, 2018 at 16:49 UTC 78d986b252359351a579dc2629c8384d5c8eb8ff
2 files changed +24 -1
Documentation/git-worktree.txt
+1 -1
@@ -79,7 +79,7 @@ with `--reason`.
79 move::
80
81 Move a working tree to a new location. Note that the main working tree
82 -cannot be moved.
82 +or linked working trees containing submodules cannot be moved.
83
84 prune::
85
builtin/worktree.c
+23
@@ -606,6 +606,27 @@ static int unlock_worktree(int ac, const char **av, const char *prefix)
606 return ret;
607 }
608
609 +static void validate_no_submodules(const struct worktree *wt)
610 +{
611 + struct index_state istate = { NULL };
612 + int i, found_submodules = 0;
613 +
614 + if (read_index_from(&istate, worktree_git_path(wt, "index")) > 0) {
615 + for (i = 0; i < istate.cache_nr; i++) {
616 + struct cache_entry *ce = istate.cache[i];
617 +
618 + if (S_ISGITLINK(ce->ce_mode)) {
619 + found_submodules = 1;
620 + break;
621 + }
622 + }
623 + }
624 + discard_index(&istate);
625 +
626 + if (found_submodules)
627 + die(_("working trees containing submodules cannot be moved"));
628 +}
629 +
630 static int move_worktree(int ac, const char **av, const char *prefix)
631 {
632 struct option options[] = {
@@ -643,6 +664,8 @@ static int move_worktree(int ac, const char **av, const char *prefix)
664 if (file_exists(dst.buf))
665 die(_("target '%s' already exists"), dst.buf);
666
667 + validate_no_submodules(wt);
668 +
669 reason = is_worktree_locked(wt);
670 if (reason) {
671 if (*reason)