diff options
author | Junio C Hamano <gitster@pobox.com> | 2018-05-23 08:38:18 +0300 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2018-05-23 08:38:18 +0300 |
commit | 10174da9f1643eb939d93d479547494baf77377b (patch) | |
tree | 7984b987bc20e55d21c26d83569eabb11928256d /builtin | |
parent | 352cf6cfe138b1dbcf9c105c91ca793b67511d7b (diff) | |
parent | f60a7b763fe070161b332d3878f81a7f09ab6e44 (diff) |
Merge branch 'tg/worktree-add-existing-branch'
"git worktree add" learned to check out an existing branch.
* tg/worktree-add-existing-branch:
worktree: teach "add" to check out existing branches
worktree: factor out dwim_branch function
worktree: improve message when creating a new worktree
worktree: remove extra members from struct add_opts
Diffstat (limited to 'builtin')
-rw-r--r-- | builtin/worktree.c | 101 |
1 files changed, 74 insertions, 27 deletions
diff --git a/builtin/worktree.c b/builtin/worktree.c index 30647b30c5..5c7d2bb180 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -29,8 +29,6 @@ struct add_opts { int detach; int checkout; int keep_locked; - const char *new_branch; - int force_new_branch; }; static int show_only; @@ -298,8 +296,6 @@ static int add_worktree(const char *path, const char *refname, strbuf_addf(&sb, "%s/commondir", sb_repo.buf); write_file(sb.buf, "../.."); - fprintf_ln(stderr, _("Preparing %s (identifier %s)"), path, name); - 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); cp.git_cmd = 1; @@ -366,18 +362,75 @@ done: return ret; } +static void print_preparing_worktree_line(int detach, + const char *branch, + const char *new_branch, + int force_new_branch) +{ + if (force_new_branch) { + struct commit *commit = lookup_commit_reference_by_name(new_branch); + if (!commit) + printf_ln(_("Preparing worktree (new branch '%s')"), new_branch); + else + printf_ln(_("Preparing worktree (resetting branch '%s'; was at %s)"), + new_branch, + find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV)); + } else if (new_branch) { + printf_ln(_("Preparing worktree (new branch '%s')"), new_branch); + } else { + struct strbuf s = STRBUF_INIT; + if (!detach && !strbuf_check_branch_ref(&s, branch) && + ref_exists(s.buf)) + printf_ln(_("Preparing worktree (checking out '%s')"), + branch); + else { + struct commit *commit = lookup_commit_reference_by_name(branch); + if (!commit) + die(_("invalid reference: %s"), branch); + printf_ln(_("Preparing worktree (detached HEAD %s)"), + find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV)); + } + strbuf_release(&s); + } +} + +static const char *dwim_branch(const char *path, const char **new_branch) +{ + int n; + const char *s = worktree_basename(path, &n); + const char *branchname = xstrndup(s, n); + struct strbuf ref = STRBUF_INIT; + + UNLEAK(branchname); + if (!strbuf_check_branch_ref(&ref, branchname) && + ref_exists(ref.buf)) { + strbuf_release(&ref); + return branchname; + } + + *new_branch = branchname; + if (guess_remote) { + struct object_id oid; + const char *remote = + unique_tracking_name(*new_branch, &oid); + return remote; + } + return NULL; +} + static int add(int ac, const char **av, const char *prefix) { struct add_opts opts; const char *new_branch_force = NULL; char *path; const char *branch; + const char *new_branch = NULL; const char *opt_track = NULL; struct option options[] = { OPT__FORCE(&opts.force, N_("checkout <branch> even if already checked out in other worktree"), PARSE_OPT_NOCOMPLETE), - OPT_STRING('b', NULL, &opts.new_branch, N_("branch"), + OPT_STRING('b', NULL, &new_branch, N_("branch"), N_("create a new branch")), OPT_STRING('B', NULL, &new_branch_force, N_("branch"), N_("create or reset a branch")), @@ -395,7 +448,7 @@ static int add(int ac, const char **av, const char *prefix) memset(&opts, 0, sizeof(opts)); opts.checkout = 1; ac = parse_options(ac, av, prefix, options, worktree_usage, 0); - if (!!opts.detach + !!opts.new_branch + !!new_branch_force > 1) + if (!!opts.detach + !!new_branch + !!new_branch_force > 1) die(_("-b, -B, and --detach are mutually exclusive")); if (ac < 1 || ac > 2) usage_with_options(worktree_usage, options); @@ -406,33 +459,25 @@ static int add(int ac, const char **av, const char *prefix) if (!strcmp(branch, "-")) branch = "@{-1}"; - opts.force_new_branch = !!new_branch_force; - if (opts.force_new_branch) { + if (new_branch_force) { struct strbuf symref = STRBUF_INIT; - opts.new_branch = new_branch_force; + new_branch = new_branch_force; if (!opts.force && - !strbuf_check_branch_ref(&symref, opts.new_branch) && + !strbuf_check_branch_ref(&symref, new_branch) && ref_exists(symref.buf)) die_if_checked_out(symref.buf, 0); strbuf_release(&symref); } - if (ac < 2 && !opts.new_branch && !opts.detach) { - int n; - const char *s = worktree_basename(path, &n); - opts.new_branch = xstrndup(s, n); - if (guess_remote) { - struct object_id oid; - const char *remote = - unique_tracking_name(opts.new_branch, &oid); - if (remote) - branch = remote; - } + if (ac < 2 && !new_branch && !opts.detach) { + const char *s = dwim_branch(path, &new_branch); + if (s) + branch = s; } - if (ac == 2 && !opts.new_branch && !opts.detach) { + if (ac == 2 && !new_branch && !opts.detach) { struct object_id oid; struct commit *commit; const char *remote; @@ -441,25 +486,27 @@ static int add(int ac, const char **av, const char *prefix) if (!commit) { remote = unique_tracking_name(branch, &oid); if (remote) { - opts.new_branch = branch; + new_branch = branch; branch = remote; } } } - if (opts.new_branch) { + print_preparing_worktree_line(opts.detach, branch, new_branch, !!new_branch_force); + + if (new_branch) { struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; argv_array_push(&cp.args, "branch"); - if (opts.force_new_branch) + if (new_branch_force) argv_array_push(&cp.args, "--force"); - argv_array_push(&cp.args, opts.new_branch); + argv_array_push(&cp.args, new_branch); argv_array_push(&cp.args, branch); if (opt_track) argv_array_push(&cp.args, opt_track); if (run_command(&cp)) return -1; - branch = opts.new_branch; + branch = new_branch; } else if (opt_track) { die(_("--[no-]track can only be used if a new branch is created")); } |