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 *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"), N_("create a new branch")), OPT_STRING('B', NULL, &new_branch_force, N_("branch"), N_("create or reset a branch")), OPT_BOOL(0, "detach", &opts.detach, N_("detach HEAD at named commit")), OPT_BOOL(0, "checkout", &opts.checkout, N_("populate the new working tree")), OPT_BOOL(0, "lock", &opts.keep_locked, N_("keep the new working tree locked")), OPT_PASSTHRU(0, "track", &opt_track, NULL, N_("set up tracking mode (see git-branch(1))"), PARSE_OPT_NOARG | PARSE_OPT_OPTARG), OPT_BOOL(0, "guess-remote", &guess_remote, N_("try to match the new branch name with a remote-tracking branch")), OPT_END() }; 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) die(_("-b, -B, and --detach are mutually exclusive")); if (ac < 1 || ac > 2) usage_with_options(worktree_usage, options); path = prefix_filename(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; opts.new_branch = new_branch_force; if (!opts.force && !strbuf_check_branch_ref(&symref, opts.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 && !opts.new_branch && !opts.detach) { struct object_id oid; struct commit *commit; const char *remote; commit = lookup_commit_reference_by_name(branch); if (!commit) { remote = unique_tracking_name(branch, &oid); if (remote) { opts.new_branch = branch; branch = remote; } } } if (opts.new_branch) { struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; argv_array_push(&cp.args, "branch"); if (opts.force_new_branch) argv_array_push(&cp.args, "--force"); argv_array_push(&cp.args, opts.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; } else if (opt_track) { die(_("--[no-]track can only be used if a new branch is created")); } UNLEAK(path); UNLEAK(opts); return add_worktree(path, branch, &opts); }
static int add(int ac, const char **av, const char *prefix) { struct add_opts opts; const char *new_branch_force = NULL; const char *path, *branch; struct option options[] = { OPT__FORCE(&opts.force, N_("checkout <branch> even if already checked out in other worktree")), OPT_STRING('b', NULL, &opts.new_branch, N_("branch"), N_("create a new branch")), OPT_STRING('B', NULL, &new_branch_force, N_("branch"), N_("create or reset a branch")), OPT_BOOL(0, "detach", &opts.detach, N_("detach HEAD at named commit")), OPT_BOOL(0, "checkout", &opts.checkout, N_("populate the new working tree")), OPT_END() }; 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) die(_("-b, -B, and --detach are mutually exclusive")); if (ac < 1 || ac > 2) usage_with_options(worktree_usage, options); 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; opts.new_branch = new_branch_force; if (!opts.force && !strbuf_check_branch_ref(&symref, opts.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 (opts.new_branch) { struct child_process cp; memset(&cp, 0, sizeof(cp)); cp.git_cmd = 1; argv_array_push(&cp.args, "branch"); if (opts.force_new_branch) argv_array_push(&cp.args, "--force"); argv_array_push(&cp.args, opts.new_branch); argv_array_push(&cp.args, branch); if (run_command(&cp)) return -1; branch = opts.new_branch; } return add_worktree(path, branch, &opts); }