diff options
Diffstat (limited to 'builtin/branch.c')
-rw-r--r-- | builtin/branch.c | 117 |
1 files changed, 76 insertions, 41 deletions
diff --git a/builtin/branch.c b/builtin/branch.c index 3f6c825db1..7df05437f1 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -20,6 +20,7 @@ #include "utf8.h" #include "wt-status.h" #include "ref-filter.h" +#include "worktree.h" static const char * const builtin_branch_usage[] = { N_("git branch [<options>] [-r | -a] [--merged | --no-merged]"), @@ -211,25 +212,30 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, die(_("Couldn't look up commit object for HEAD")); } for (i = 0; i < argc; i++, strbuf_release(&bname)) { - const char *target; + char *target = NULL; int flags = 0; strbuf_branchname(&bname, argv[i]); - if (kinds == FILTER_REFS_BRANCHES && !strcmp(head, bname.buf)) { - error(_("Cannot delete the branch '%s' " - "which you are currently on."), bname.buf); - ret = 1; - continue; - } - free(name); - name = mkpathdup(fmt, bname.buf); - target = resolve_ref_unsafe(name, - RESOLVE_REF_READING - | RESOLVE_REF_NO_RECURSE - | RESOLVE_REF_ALLOW_BAD_NAME, - sha1, &flags); + + if (kinds == FILTER_REFS_BRANCHES) { + const struct worktree *wt = + find_shared_symref("HEAD", name); + if (wt) { + error(_("Cannot delete branch '%s' " + "checked out at '%s'"), + bname.buf, wt->path); + ret = 1; + continue; + } + } + + target = resolve_refdup(name, + RESOLVE_REF_READING + | RESOLVE_REF_NO_RECURSE + | RESOLVE_REF_ALLOW_BAD_NAME, + sha1, &flags); if (!target) { error(remote_branch ? _("remote-tracking branch '%s' not found.") @@ -242,7 +248,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, check_branch_commit(bname.buf, name, sha1, head_rev, kinds, force)) { ret = 1; - continue; + goto next; } if (delete_ref(name, is_null_sha1(sha1) ? NULL : sha1, @@ -252,7 +258,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, : _("Error deleting branch '%s'"), bname.buf); ret = 1; - continue; + goto next; } if (!quiet) { printf(remote_branch @@ -264,6 +270,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, : find_unique_abbrev(sha1, DEFAULT_ABBREV)); } delete_branch_config(bname.buf); + + next: + free(target); } free(name); @@ -369,12 +378,14 @@ static char *get_head_description(void) strbuf_addf(&desc, _("(no branch, bisect started on %s)"), state.branch); else if (state.detached_from) { - /* TRANSLATORS: make sure these match _("HEAD detached at ") - and _("HEAD detached from ") in wt-status.c */ if (state.detached_at) + /* TRANSLATORS: make sure this matches + "HEAD detached at " in wt-status.c */ strbuf_addf(&desc, _("(HEAD detached at %s)"), state.detached_from); else + /* TRANSLATORS: make sure this matches + "HEAD detached from " in wt-status.c */ strbuf_addf(&desc, _("(HEAD detached from %s)"), state.detached_from); } @@ -393,22 +404,25 @@ static void format_and_print_ref_item(struct ref_array_item *item, int maxwidth, int current = 0; int color; struct strbuf out = STRBUF_INIT, name = STRBUF_INIT; - const char *prefix = ""; + const char *prefix_to_show = ""; + const char *prefix_to_skip = NULL; const char *desc = item->refname; char *to_free = NULL; switch (item->kind) { case FILTER_REFS_BRANCHES: - skip_prefix(desc, "refs/heads/", &desc); + prefix_to_skip = "refs/heads/"; + skip_prefix(desc, prefix_to_skip, &desc); if (!filter->detached && !strcmp(desc, head)) current = 1; else color = BRANCH_COLOR_LOCAL; break; case FILTER_REFS_REMOTES: - skip_prefix(desc, "refs/remotes/", &desc); + prefix_to_skip = "refs/remotes/"; + skip_prefix(desc, prefix_to_skip, &desc); color = BRANCH_COLOR_REMOTE; - prefix = remote_prefix; + prefix_to_show = remote_prefix; break; case FILTER_REFS_DETACHED_HEAD: desc = to_free = get_head_description(); @@ -425,7 +439,7 @@ static void format_and_print_ref_item(struct ref_array_item *item, int maxwidth, color = BRANCH_COLOR_CURRENT; } - strbuf_addf(&name, "%s%s", prefix, desc); + strbuf_addf(&name, "%s%s", prefix_to_show, desc); if (filter->verbose) { int utf8_compensation = strlen(name.buf) - utf8_strwidth(name.buf); strbuf_addf(&out, "%c %s%-*s%s", c, branch_get_color(color), @@ -436,8 +450,10 @@ static void format_and_print_ref_item(struct ref_array_item *item, int maxwidth, name.buf, branch_get_color(BRANCH_COLOR_RESET)); if (item->symref) { - skip_prefix(item->symref, "refs/remotes/", &desc); - strbuf_addf(&out, " -> %s", desc); + const char *symref = item->symref; + if (prefix_to_skip) + skip_prefix(symref, prefix_to_skip, &symref); + strbuf_addf(&out, " -> %s", symref); } else if (filter->verbose) /* " f7c0c00 [ahead 58, behind 197] vcs-svn: drop obj_pool.h" */ @@ -513,6 +529,29 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin ref_array_clear(&array); } +static void reject_rebase_or_bisect_branch(const char *target) +{ + struct worktree **worktrees = get_worktrees(); + int i; + + for (i = 0; worktrees[i]; i++) { + struct worktree *wt = worktrees[i]; + + if (!wt->is_detached) + continue; + + if (is_worktree_being_rebased(wt, target)) + die(_("Branch %s is being rebased at %s"), + target, wt->path); + + if (is_worktree_being_bisected(wt, target)) + die(_("Branch %s is being bisected at %s"), + target, wt->path); + } + + free_worktrees(worktrees); +} + static void rename_branch(const char *oldname, const char *newname, int force) { struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT; @@ -542,6 +581,8 @@ static void rename_branch(const char *oldname, const char *newname, int force) validate_new_branchname(newname, &newref, force, clobber_head_ok); + reject_rebase_or_bisect_branch(oldref.buf); + strbuf_addf(&logmsg, "Branch: renamed %s to %s", oldref.buf, newref.buf); @@ -552,8 +593,7 @@ static void rename_branch(const char *oldname, const char *newname, int force) if (recovery) warning(_("Renamed a misnamed branch '%s' away"), oldref.buf + 11); - /* no need to pass logmsg here as HEAD didn't really move */ - if (!strcmp(oldname, head) && create_symref("HEAD", newref.buf, NULL)) + if (replace_each_worktree_head_symref(oldref.buf, newref.buf)) die(_("Branch renamed to %s, but HEAD is not updated!"), newname); strbuf_addf(&oldsection, "branch.%s", oldref.buf + 11); @@ -570,7 +610,6 @@ static const char edit_description[] = "BRANCH_DESCRIPTION"; static int edit_branch_description(const char *branch_name) { - int status; struct strbuf buf = STRBUF_INIT; struct strbuf name = STRBUF_INIT; @@ -578,15 +617,11 @@ static int edit_branch_description(const char *branch_name) if (!buf.len || buf.buf[buf.len-1] != '\n') strbuf_addch(&buf, '\n'); strbuf_commented_addf(&buf, - "Please edit the description for the branch\n" - " %s\n" - "Lines starting with '%c' will be stripped.\n", + _("Please edit the description for the branch\n" + " %s\n" + "Lines starting with '%c' will be stripped.\n"), branch_name, comment_line_char); - if (write_file_gently(git_path(edit_description), "%s", buf.buf)) { - strbuf_release(&buf); - return error(_("could not write branch description template: %s"), - strerror(errno)); - } + write_file_buf(git_path(edit_description), buf.buf, buf.len); strbuf_reset(&buf); if (launch_editor(git_path(edit_description), &buf, NULL)) { strbuf_release(&buf); @@ -595,11 +630,11 @@ static int edit_branch_description(const char *branch_name) strbuf_stripspace(&buf, 1); strbuf_addf(&name, "branch.%s.description", branch_name); - status = git_config_set(name.buf, buf.len ? buf.buf : NULL); + git_config_set(name.buf, buf.len ? buf.buf : NULL); strbuf_release(&name); strbuf_release(&buf); - return status; + return 0; } int cmd_branch(int argc, const char **argv, const char *prefix) @@ -621,7 +656,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) BRANCH_TRACK_EXPLICIT), OPT_SET_INT( 0, "set-upstream", &track, N_("change upstream info"), BRANCH_TRACK_OVERRIDE), - OPT_STRING('u', "set-upstream-to", &new_upstream, "upstream", "change the upstream info"), + OPT_STRING('u', "set-upstream-to", &new_upstream, N_("upstream"), N_("change the upstream info")), OPT_BOOL(0, "unset-upstream", &unset_upstream, "Unset the upstream info"), OPT__COLOR(&branch_use_color, N_("use colored output")), OPT_SET_INT('r', "remotes", &filter.kind, N_("act on remote-tracking branches"), @@ -829,8 +864,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix) if (argc == 1 && track == BRANCH_TRACK_OVERRIDE && !branch_existed && remote_tracking) { fprintf(stderr, _("\nIf you wanted to make '%s' track '%s', do this:\n\n"), head, branch->name); - fprintf(stderr, _(" git branch -d %s\n"), branch->name); - fprintf(stderr, _(" git branch --set-upstream-to %s\n"), branch->name); + fprintf(stderr, " git branch -d %s\n", branch->name); + fprintf(stderr, " git branch --set-upstream-to %s\n", branch->name); } } else |