]> git.ipfire.org Git - thirdparty/git.git/commitdiff
branch: sort detached HEAD based on a flag
authorÆvar Arnfjörð Bjarmason <avarab@gmail.com>
Thu, 7 Jan 2021 09:51:52 +0000 (10:51 +0100)
committerJunio C Hamano <gitster@pobox.com>
Thu, 7 Jan 2021 23:13:21 +0000 (15:13 -0800)
Change the ref-filter sorting of detached HEAD to check the
FILTER_REFS_DETACHED_HEAD flag, instead of relying on the ref
description filled-in by get_head_description() to start with "(",
which in turn we expect to ASCII-sort before any other reference.

For context, we'd like the detached line to appear first at the start
of "git branch -l", e.g.:

    $ git branch -l
    * (HEAD detached at <hash>)
      master

This doesn't change that, but improves on a fix made in
28438e84e04 (ref-filter: sort detached HEAD lines firstly, 2019-06-18)
and gives the Chinese translation the ability to use its preferred
punctuation marks again.

In Chinese the fullwidth versions of punctuation like "()" are
typically written as (U+FF08 fullwidth left parenthesis), (U+FF09
fullwidth right parenthesis) instead[1]. This form is used in both
po/zh_{CN,TW}.po in most cases where "()" is translated in a string.

Aside from that improvement to the Chinese translation, it also just
makes for cleaner code that we mark any special cases in the ref_array
we're sorting with flags and make the sort function aware of them,
instead of piggy-backing on the general-case of strcmp() doing the
right thing.

As seen in the amended tests this made reverse sorting a bit more
consistent. Before this we'd sometimes sort this message in the
middle, now it's consistently at the beginning or end, depending on
whether we're doing a normal or reverse sort. Having it at the end
doesn't make much sense either, but at least it behaves consistently
now. A follow-up commit will make this behavior under reverse sorting
even better.

I'm removing the "TRANSLATORS" comments that were in the old code
while I'm at it. Those were added in d4919bb288e (ref-filter: move
get_head_description() from branch.c, 2017-01-10). I think it's
obvious from context, string and translation memory in typical
translation tools that these are the same or similar string.

1. https://en.wikipedia.org/wiki/Chinese_punctuation#Marks_similar_to_European_punctuation

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/branch.c
ref-filter.c
ref-filter.h
t/t3203-branch-output.sh
wt-status.c
wt-status.h

index 2dd51a8653b67c9e27c76af3c153b7197c3f8899..8c0b428104dcda765ec177172190c7a2807473c0 100644 (file)
@@ -740,6 +740,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                if (!sorting)
                        sorting = ref_default_sorting();
                ref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase);
+               ref_sorting_set_sort_flags_all(
+                       sorting, REF_SORTING_DETACHED_HEAD_FIRST, 1);
                print_ref_list(&filter, sorting, &format);
                print_columns(&output, colopts, NULL);
                string_list_clear(&output, 0);
index fe587afb80b951cd33eb2a3223dc8cbae2f9bcd5..8d0739b9972f8384c43a9b4a45f559361e32556e 100644 (file)
@@ -1536,36 +1536,27 @@ char *get_head_description(void)
        struct wt_status_state state;
        memset(&state, 0, sizeof(state));
        wt_status_get_state(the_repository, &state, 1);
-
-       /*
-        * The ( character must be hard-coded and not part of a localizable
-        * string, since the description is used as a sort key and compared
-        * with ref names.
-        */
-       strbuf_addch(&desc, '(');
        if (state.rebase_in_progress ||
            state.rebase_interactive_in_progress) {
                if (state.branch)
-                       strbuf_addf(&desc, _("no branch, rebasing %s"),
+                       strbuf_addf(&desc, _("(no branch, rebasing %s)"),
                                    state.branch);
                else
-                       strbuf_addf(&desc, _("no branch, rebasing detached HEAD %s"),
+                       strbuf_addf(&desc, _("(no branch, rebasing detached HEAD %s)"),
                                    state.detached_from);
        } else if (state.bisect_in_progress)
-               strbuf_addf(&desc, _("no branch, bisect started on %s"),
+               strbuf_addf(&desc, _("(no branch, bisect started on %s)"),
                            state.branch);
        else if (state.detached_from) {
                if (state.detached_at)
-                       strbuf_addstr(&desc, HEAD_DETACHED_AT);
+                       strbuf_addf(&desc, _("(HEAD detached at %s)"),
+                               state.detached_from);
                else
-                       strbuf_addstr(&desc, HEAD_DETACHED_FROM);
-               strbuf_addstr(&desc, state.detached_from);
-       }
-       else
-               strbuf_addstr(&desc, _("no branch"));
-       strbuf_addch(&desc, ')');
+                       strbuf_addf(&desc, _("(HEAD detached from %s)"),
+                               state.detached_from);
+       } else
+               strbuf_addstr(&desc, _("(no branch)"));
 
-       wt_status_state_free_buffers(&state);
        return strbuf_detach(&desc, NULL);
 }
 
@@ -2350,6 +2341,18 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
        return ret;
 }
 
+static int compare_detached_head(struct ref_array_item *a, struct ref_array_item *b)
+{
+       if (!(a->kind ^ b->kind))
+               BUG("ref_kind_from_refname() should only mark one ref as HEAD");
+       if (a->kind & FILTER_REFS_DETACHED_HEAD)
+               return -1;
+       else if (b->kind & FILTER_REFS_DETACHED_HEAD)
+               return 1;
+       BUG("should have died in the xor check above");
+       return 0;
+}
+
 static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, struct ref_array_item *b)
 {
        struct atom_value *va, *vb;
@@ -2362,7 +2365,10 @@ static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, stru
        if (get_ref_atom_value(b, s->atom, &vb, &err))
                die("%s", err.buf);
        strbuf_release(&err);
-       if (s->sort_flags & REF_SORTING_VERSION) {
+       if (s->sort_flags & REF_SORTING_DETACHED_HEAD_FIRST &&
+           ((a->kind | b->kind) & FILTER_REFS_DETACHED_HEAD)) {
+               cmp = compare_detached_head(a, b);
+       } else if (s->sort_flags & REF_SORTING_VERSION) {
                cmp = versioncmp(va->s, vb->s);
        } else if (cmp_type == FIELD_STR) {
                int (*cmp_fn)(const char *, const char *);
index 6296ae8bb2776e7c31a59b6a64bbcdb958cee6c2..19ea4c413409373b809ba4822214a8a7c47b3e73 100644 (file)
@@ -32,6 +32,7 @@ struct ref_sorting {
                REF_SORTING_REVERSE = 1<<0,
                REF_SORTING_ICASE = 1<<1,
                REF_SORTING_VERSION = 1<<2,
+               REF_SORTING_DETACHED_HEAD_FIRST = 1<<3,
        } sort_flags;
 };
 
index f92fb3aab9dc39b9fac28a7531205f67d599bf66..8f53b081365296a0e8758c113ceba0de8931109b 100755 (executable)
@@ -223,8 +223,8 @@ test_expect_success 'git branch `--sort=[-]objectsize` option' '
        cat >expect <<-\EOF &&
          branch-one
          main
-       * (HEAD detached from fromtag)
          branch-two
+       * (HEAD detached from fromtag)
        EOF
        git branch --sort=-objectsize >actual &&
        test_i18ncmp expect actual
@@ -241,10 +241,10 @@ test_expect_success 'git branch `--sort=[-]type` option' '
        test_i18ncmp expect actual &&
 
        cat >expect <<-\EOF &&
-       * (HEAD detached from fromtag)
          branch-one
          branch-two
          main
+       * (HEAD detached from fromtag)
        EOF
        git branch --sort=-type >actual &&
        test_i18ncmp expect actual
index 7074bbdd53cc1141c75546ad6e009b5ac74a63c2..40b59be478c9eb10227db2fa086d778e8cb73e77 100644 (file)
@@ -1742,9 +1742,9 @@ static void wt_longstatus_print(struct wt_status *s)
                        } else if (s->state.detached_from) {
                                branch_name = s->state.detached_from;
                                if (s->state.detached_at)
-                                       on_what = HEAD_DETACHED_AT;
+                                       on_what = _("HEAD detached at ");
                                else
-                                       on_what = HEAD_DETACHED_FROM;
+                                       on_what = _("HEAD detached from ");
                        } else {
                                branch_name = "";
                                on_what = _("Not currently on any branch.");
index 35b44c388edf0cd75cca00e1458b9995c8001538..0d32799b28e19af1a274acc5bd975dcf6dc3b44d 100644 (file)
@@ -77,8 +77,6 @@ enum wt_status_format {
        STATUS_FORMAT_UNSPECIFIED
 };
 
-#define HEAD_DETACHED_AT _("HEAD detached at ")
-#define HEAD_DETACHED_FROM _("HEAD detached from ")
 #define SPARSE_CHECKOUT_DISABLED -1
 
 struct wt_status_state {