mingw: fix the shortlog --output=<file> test
[gitweb.git] / builtin / branch.c
index 7b45b6bd6b80613de9f894cfbe8e9d2dcae77b09..2ecde53bf838777e191926557c0c8190cdc7d09a 100644 (file)
@@ -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]"),
@@ -215,16 +216,21 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
                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);
+
+               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_ref_unsafe(name,
                                            RESOLVE_REF_READING
                                            | RESOLVE_REF_NO_RECURSE
@@ -369,12 +375,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 +401,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 +436,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 +447,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 +526,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 +578,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 +590,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);
@@ -583,8 +620,7 @@ static int edit_branch_description(const char *branch_name)
                    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));
+               return error_errno(_("could not write branch description template"));
        }
        strbuf_reset(&buf);
        if (launch_editor(git_path(edit_description), &buf, NULL)) {
@@ -620,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"),
@@ -828,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