diff options
Diffstat (limited to 'builtin/worktree.c')
-rw-r--r-- | builtin/worktree.c | 87 |
1 files changed, 79 insertions, 8 deletions
diff --git a/builtin/worktree.c b/builtin/worktree.c index 96a2834a18..5c4854d3e4 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -13,8 +13,10 @@ static const char * const worktree_usage[] = { N_("git worktree add [<options>] <path> [<branch>]"), - N_("git worktree prune [<options>]"), N_("git worktree list [<options>]"), + N_("git worktree lock [<options>] <path>"), + N_("git worktree prune [<options>]"), + N_("git worktree unlock <path>"), NULL }; @@ -95,7 +97,7 @@ static void prune_worktrees(void) if (!dir) return; while ((d = readdir(dir)) != NULL) { - if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + if (is_dot_or_dotdot(d->d_name)) continue; strbuf_reset(&reason); if (!prune_worktree(d->d_name, &reason)) @@ -192,7 +194,7 @@ static int add_worktree(const char *path, const char *refname, struct strbuf sb = STRBUF_INIT; const char *name; struct stat st; - struct child_process cp; + struct child_process cp = CHILD_PROCESS_INIT; struct argv_array child_env = ARGV_ARRAY_INIT; int counter = 0, len, ret; struct strbuf symref = STRBUF_INIT; @@ -262,7 +264,7 @@ static int add_worktree(const char *path, const char *refname, */ strbuf_reset(&sb); strbuf_addf(&sb, "%s/HEAD", sb_repo.buf); - write_file(sb.buf, "0000000000000000000000000000000000000000"); + write_file(sb.buf, "%s", sha1_to_hex(null_sha1)); strbuf_reset(&sb); strbuf_addf(&sb, "%s/commondir", sb_repo.buf); write_file(sb.buf, "../.."); @@ -271,7 +273,6 @@ static int add_worktree(const char *path, const char *refname, argv_array_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf); argv_array_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path); - memset(&cp, 0, sizeof(cp)); cp.git_cmd = 1; if (commit) @@ -337,9 +338,12 @@ static int add(int ac, const char **av, const char *prefix) if (ac < 1 || ac > 2) usage_with_options(worktree_usage, options); - path = prefix ? prefix_filename(prefix, strlen(prefix), av[0]) : av[0]; + path = prefix_filename(prefix, strlen(prefix), av[0]); branch = ac < 2 ? "HEAD" : av[1]; + if (!strcmp(branch, "-")) + branch = "@{-1}"; + opts.force_new_branch = !!new_branch_force; if (opts.force_new_branch) { struct strbuf symref = STRBUF_INIT; @@ -360,8 +364,7 @@ static int add(int ac, const char **av, const char *prefix) } if (opts.new_branch) { - struct child_process cp; - memset(&cp, 0, sizeof(cp)); + struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; argv_array_push(&cp.args, "branch"); if (opts.force_new_branch) @@ -459,19 +462,87 @@ static int list(int ac, const char **av, const char *prefix) return 0; } +static int lock_worktree(int ac, const char **av, const char *prefix) +{ + const char *reason = "", *old_reason; + struct option options[] = { + OPT_STRING(0, "reason", &reason, N_("string"), + N_("reason for locking")), + OPT_END() + }; + struct worktree **worktrees, *wt; + + ac = parse_options(ac, av, prefix, options, worktree_usage, 0); + if (ac != 1) + usage_with_options(worktree_usage, options); + + worktrees = get_worktrees(); + wt = find_worktree(worktrees, prefix, av[0]); + if (!wt) + die(_("'%s' is not a working tree"), av[0]); + if (is_main_worktree(wt)) + die(_("The main working tree cannot be locked or unlocked")); + + old_reason = is_worktree_locked(wt); + if (old_reason) { + if (*old_reason) + die(_("'%s' is already locked, reason: %s"), + av[0], old_reason); + die(_("'%s' is already locked"), av[0]); + } + + write_file(git_common_path("worktrees/%s/locked", wt->id), + "%s", reason); + free_worktrees(worktrees); + return 0; +} + +static int unlock_worktree(int ac, const char **av, const char *prefix) +{ + struct option options[] = { + OPT_END() + }; + struct worktree **worktrees, *wt; + int ret; + + ac = parse_options(ac, av, prefix, options, worktree_usage, 0); + if (ac != 1) + usage_with_options(worktree_usage, options); + + worktrees = get_worktrees(); + wt = find_worktree(worktrees, prefix, av[0]); + if (!wt) + die(_("'%s' is not a working tree"), av[0]); + if (is_main_worktree(wt)) + die(_("The main working tree cannot be locked or unlocked")); + if (!is_worktree_locked(wt)) + die(_("'%s' is not locked"), av[0]); + ret = unlink_or_warn(git_common_path("worktrees/%s/locked", wt->id)); + free_worktrees(worktrees); + return ret; +} + int cmd_worktree(int ac, const char **av, const char *prefix) { struct option options[] = { OPT_END() }; + git_config(git_default_config, NULL); + if (ac < 2) usage_with_options(worktree_usage, options); + if (!prefix) + prefix = ""; if (!strcmp(av[1], "add")) return add(ac - 1, av + 1, prefix); if (!strcmp(av[1], "prune")) return prune(ac - 1, av + 1, prefix); if (!strcmp(av[1], "list")) return list(ac - 1, av + 1, prefix); + if (!strcmp(av[1], "lock")) + return lock_worktree(ac - 1, av + 1, prefix); + if (!strcmp(av[1], "unlock")) + return unlock_worktree(ac - 1, av + 1, prefix); usage_with_options(worktree_usage, options); } |