branch: fix shortening of non-remote symrefs
authorJeff King <peff@peff.net>
Sun, 3 Apr 2016 04:14:26 +0000 (00:14 -0400)
committerJunio C Hamano <gitster@pobox.com>
Tue, 5 Apr 2016 06:35:05 +0000 (23:35 -0700)
Commit aedcb7d (branch.c: use 'ref-filter' APIs, 2015-09-23)
adjusted the symref-printing code to look like this:

if (item->symref) {
skip_prefix(item->symref, "refs/remotes/", &desc);
strbuf_addf(&out, " -> %s", desc);
}

This has three bugs in it:

1. It always skips past "refs/remotes/", instead of
skipping past the prefix associated with the branch we
are showing (so commonly we see "refs/remotes/" for the
refs/remotes/origin/HEAD symref, but the previous code
would skip "refs/heads/" when showing a symref it found
in refs/heads/.

2. If skip_prefix() does not match, it leaves "desc"
untouched, and we show whatever happened to be in it
(which is the refname from a call to skip_prefix()
earlier in the function).

3. If we do match with skip_prefix(), we stomp on the
"desc" variable, which is later passed to
add_verbose_info(). We probably want to retain the
original refname there (though it likely doesn't matter
in practice, since after all, one points to the other).

The fix to match the original code is fairly easy: record
the prefix to strip based on item->kind, and use it here.
However, since we already have a local variable named "prefix",
let's give the two prefixes verbose names so we don't
confuse them.

Signed-off-by: Jeff King <peff@peff.net>
Acked-by: Karthik Nayak <karthik.188@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/branch.c
t/t3203-branch-output.sh
index 7b45b6bd6b80613de9f894cfbe8e9d2dcae77b09..f6c23bf5dd600cd8f1bc7029de757d577abdfd02 100644 (file)
@@ -393,22 +393,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 +428,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 +439,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" */
index 4261403cf62542e82d40487e47733f586e106a75..c6a3ccba1b992cff7412bcf8139da7557981de94 100755 (executable)
@@ -184,4 +184,16 @@ test_expect_success 'ambiguous branch/tag not marked' '
        test_cmp expect actual
 '
 
+test_expect_success 'local-branch symrefs shortened properly' '
+       git symbolic-ref refs/heads/ref-to-branch refs/heads/branch-one &&
+       git symbolic-ref refs/heads/ref-to-remote refs/remotes/origin/branch-one &&
+       cat >expect <<-\EOF &&
+         ref-to-branch -> branch-one
+         ref-to-remote -> refs/remotes/origin/branch-one
+       EOF
+       git branch >actual.raw &&
+       grep ref-to <actual.raw >actual &&
+       test_cmp expect actual
+'
+
 test_done