19
N_("git worktree lock [<options>] <path>"),
20
N_("git worktree move <worktree> <new-path>"),
21
N_("git worktree prune [<options>]"),
22
+ N_("git worktree remove [<options>] <worktree>"),
23
N_("git worktree unlock <path>"),
24
NULL
25
};
625
discard_index(&istate);
626
627
if (found_submodules)
627
- die(_("working trees containing submodules cannot be moved"));
628
+ die(_("working trees containing submodules cannot be moved or removed"));
629
}
630
631
static int move_worktree(int ac, const char **av, const char *prefix)
689
return 0;
690
}
691
692
+/*
693
+ * Note, "git status --porcelain" is used to determine if it's safe to
694
+ * delete a whole worktree. "git status" does not ignore user
695
+ * configuration, so if a normal "git status" shows "clean" for the
696
+ * user, then it's ok to remove it.
697
+ *
698
+ * This assumption may be a bad one. We may want to ignore
699
+ * (potentially bad) user settings and only delete a worktree when
700
+ * it's absolutely safe to do so from _our_ point of view because we
701
+ * know better.
702
+ */
703
+static void check_clean_worktree(struct worktree *wt,
704
+ const char *original_path)
705
+{
706
+ struct argv_array child_env = ARGV_ARRAY_INIT;
707
+ struct child_process cp;
708
+ char buf[1];
709
+ int ret;
710
+
711
+ /*
712
+ * Until we sort this out, all submodules are "dirty" and
713
+ * will abort this function.
714
+ */
715
+ validate_no_submodules(wt);
716
+
717
+ argv_array_pushf(&child_env, "%s=%s/.git",
718
+ GIT_DIR_ENVIRONMENT, wt->path);
719
+ argv_array_pushf(&child_env, "%s=%s",
720
+ GIT_WORK_TREE_ENVIRONMENT, wt->path);
721
+ memset(&cp, 0, sizeof(cp));
722
+ argv_array_pushl(&cp.args, "status",
723
+ "--porcelain", "--ignore-submodules=none",
724
+ NULL);
725
+ cp.env = child_env.argv;
726
+ cp.git_cmd = 1;
727
+ cp.dir = wt->path;
728
+ cp.out = -1;
729
+ ret = start_command(&cp);
730
+ if (ret)
731
+ die_errno(_("failed to run 'git status' on '%s'"),
732
+ original_path);
733
+ ret = xread(cp.out, buf, sizeof(buf));
734
+ if (ret)
735
+ die(_("'%s' is dirty, use --force to delete it"),
736
+ original_path);
737
+ close(cp.out);
738
+ ret = finish_command(&cp);
739
+ if (ret)
740
+ die_errno(_("failed to run 'git status' on '%s', code %d"),
741
+ original_path, ret);
742
+}
743
+
744
+static int delete_git_work_tree(struct worktree *wt)
745
+{
746
+ struct strbuf sb = STRBUF_INIT;
747
+ int ret = 0;
748
+
749
+ strbuf_addstr(&sb, wt->path);
750
+ if (remove_dir_recursively(&sb, 0)) {
751
+ error_errno(_("failed to delete '%s'"), sb.buf);
752
+ ret = -1;
753
+ }
754
+ strbuf_release(&sb);
755
+ return ret;
756
+}
757
+
758
+static int delete_git_dir(struct worktree *wt)
759
+{
760
+ struct strbuf sb = STRBUF_INIT;
761
+ int ret = 0;
762
+
763
+ strbuf_addstr(&sb, git_common_path("worktrees/%s", wt->id));
764
+ if (remove_dir_recursively(&sb, 0)) {
765
+ error_errno(_("failed to delete '%s'"), sb.buf);
766
+ ret = -1;
767
+ }
768
+ strbuf_release(&sb);
769
+ return ret;
770
+}
771
+
772
+static int remove_worktree(int ac, const char **av, const char *prefix)
773
+{
774
+ int force = 0;
775
+ struct option options[] = {
776
+ OPT_BOOL(0, "force", &force,
777
+ N_("force removing even if the worktree is dirty")),
778
+ OPT_END()
779
+ };
780
+ struct worktree **worktrees, *wt;
781
+ struct strbuf errmsg = STRBUF_INIT;
782
+ const char *reason;
783
+ int ret = 0;
784
+
785
+ ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
786
+ if (ac != 1)
787
+ usage_with_options(worktree_usage, options);
788
+
789
+ worktrees = get_worktrees(0);
790
+ wt = find_worktree(worktrees, prefix, av[0]);
791
+ if (!wt)
792
+ die(_("'%s' is not a working tree"), av[0]);
793
+ if (is_main_worktree(wt))
794
+ die(_("'%s' is a main working tree"), av[0]);
795
+ reason = is_worktree_locked(wt);
796
+ if (reason) {
797
+ if (*reason)
798
+ die(_("cannot remove a locked working tree, lock reason: %s"),
799
+ reason);
800
+ die(_("cannot remove a locked working tree"));
801
+ }
802
+ if (validate_worktree(wt, &errmsg))
803
+ die(_("validation failed, cannot remove working tree: %s"),
804
+ errmsg.buf);
805
+ strbuf_release(&errmsg);
806
+
807
+ if (!force)
808
+ check_clean_worktree(wt, av[0]);
809
+
810
+ ret |= delete_git_work_tree(wt);
811
+ /*
812
+ * continue on even if ret is non-zero, there's no going back
813
+ * from here.
814
+ */
815
+ ret |= delete_git_dir(wt);
816
+
817
+ free_worktrees(worktrees);
818
+ return ret;
819
+}
820
+
821
int cmd_worktree(int ac, const char **av, const char *prefix)
822
{
823
struct option options[] = {
842
return unlock_worktree(ac - 1, av + 1, prefix);
843
if (!strcmp(av[1], "move"))
844
return move_worktree(ac - 1, av + 1, prefix);
845
+ if (!strcmp(av[1], "remove"))
846
+ return remove_worktree(ac - 1, av + 1, prefix);
847
usage_with_options(worktree_usage, options);
848
}