diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2018-02-12 16:49:36 +0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2018-02-12 13:13:35 -0800 |
commit | 9f792bb4721066ce27ee98c4ad38d6d146b64fcf (patch) | |
tree | 503b7967b302c7b804cc4a89c6a671849b295910 /builtin | |
parent | worktree.c: add update_worktree_location() (diff) | |
download | tgif-9f792bb4721066ce27ee98c4ad38d6d146b64fcf.tar.xz |
worktree move: new command
This command allows to relocate linked worktrees. Main worktree cannot
(yet) be moved.
There are two options to move the main worktree, but both have
complications, so it's not implemented yet. Anyway the options are:
- convert the main worktree to a linked one and move it away, leave
the git repository where it is. The repo essentially becomes bare
after this move.
- move the repository with the main worktree. The tricky part is make
sure all file descriptors to the repository are closed, or it may
fail on Windows.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin')
-rw-r--r-- | builtin/worktree.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/builtin/worktree.c b/builtin/worktree.c index 7cef5b120b..8b9482d1e5 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -17,6 +17,7 @@ static const char * const worktree_usage[] = { N_("git worktree add [<options>] <path> [<branch>]"), N_("git worktree list [<options>]"), N_("git worktree lock [<options>] <path>"), + N_("git worktree move <worktree> <new-path>"), N_("git worktree prune [<options>]"), N_("git worktree unlock <path>"), NULL @@ -605,6 +606,56 @@ static int unlock_worktree(int ac, const char **av, const char *prefix) return ret; } +static int move_worktree(int ac, const char **av, const char *prefix) +{ + struct option options[] = { + OPT_END() + }; + struct worktree **worktrees, *wt; + struct strbuf dst = STRBUF_INIT; + struct strbuf errmsg = STRBUF_INIT; + const char *reason; + char *path; + + ac = parse_options(ac, av, prefix, options, worktree_usage, 0); + if (ac != 2) + usage_with_options(worktree_usage, options); + + path = prefix_filename(prefix, av[1]); + strbuf_addstr(&dst, path); + free(path); + + worktrees = get_worktrees(0); + wt = find_worktree(worktrees, prefix, av[0]); + if (!wt) + die(_("'%s' is not a working tree"), av[0]); + if (is_main_worktree(wt)) + die(_("'%s' is a main working tree"), av[0]); + if (file_exists(dst.buf)) + die(_("target '%s' already exists"), av[1]); + + reason = is_worktree_locked(wt); + if (reason) { + if (*reason) + die(_("cannot move a locked working tree, lock reason: %s"), + reason); + die(_("cannot move a locked working tree")); + } + if (validate_worktree(wt, &errmsg)) + die(_("validation failed, cannot move working tree: %s"), + errmsg.buf); + strbuf_release(&errmsg); + + if (rename(wt->path, dst.buf) == -1) + die_errno(_("failed to move '%s' to '%s'"), wt->path, dst.buf); + + update_worktree_location(wt, dst.buf); + + strbuf_release(&dst); + free_worktrees(worktrees); + return 0; +} + int cmd_worktree(int ac, const char **av, const char *prefix) { struct option options[] = { @@ -627,5 +678,7 @@ int cmd_worktree(int ac, const char **av, const char *prefix) return lock_worktree(ac - 1, av + 1, prefix); if (!strcmp(av[1], "unlock")) return unlock_worktree(ac - 1, av + 1, prefix); + if (!strcmp(av[1], "move")) + return move_worktree(ac - 1, av + 1, prefix); usage_with_options(worktree_usage, options); } |