From ffdd02a55d994da202acd2c792cc1218bbfa8197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Wed, 6 Jan 2021 11:01:35 +0100 Subject: [PATCH 1/7] branch: change "--local" to "--list" in comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There has never been a "git branch --local", this is just a typo for "--list". Fixes a comment added in 23e714df91c (branch: roll show_detached HEAD into regular ref_list, 2015-09-23). Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- builtin/branch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/branch.c b/builtin/branch.c index 9b68591add..045866a51a 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -726,7 +726,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) print_current_branch_name(); return 0; } else if (list) { - /* git branch --local also shows HEAD when it is detached */ + /* git branch --list also shows HEAD when it is detached */ if ((filter.kind & FILTER_REFS_BRANCHES) && filter.detached) filter.kind |= FILTER_REFS_DETACHED_HEAD; filter.name_patterns = argv; From 08bf6a8bc351a720f07e1afecb46b1bfae64c7ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Wed, 6 Jan 2021 11:01:36 +0100 Subject: [PATCH 2/7] branch tests: add to --sort tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Further stress the --sort callback in ref-filter.c. The implementation uses certain short-circuiting logic, let's make sure it behaves the same way on e.g. name & version sort. Improves a test added in aedcb7dc75e (branch.c: use 'ref-filter' APIs, 2015-09-23). I don't think all of this output makes sense, but let's test for the behavior as-is, we can fix bugs in it in a later commit. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- t/t3203-branch-output.sh | 51 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index b945faf470..f92fb3aab9 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -210,7 +210,7 @@ EOF test_i18ncmp expect actual ' -test_expect_success 'git branch `--sort` option' ' +test_expect_success 'git branch `--sort=[-]objectsize` option' ' cat >expect <<-\EOF && * (HEAD detached from fromtag) branch-two @@ -218,6 +218,55 @@ test_expect_success 'git branch `--sort` option' ' main EOF git branch --sort=objectsize >actual && + test_i18ncmp expect actual && + + cat >expect <<-\EOF && + branch-one + main + * (HEAD detached from fromtag) + branch-two + EOF + git branch --sort=-objectsize >actual && + test_i18ncmp expect actual +' + +test_expect_success 'git branch `--sort=[-]type` option' ' + cat >expect <<-\EOF && + * (HEAD detached from fromtag) + branch-one + branch-two + main + EOF + git branch --sort=type >actual && + test_i18ncmp expect actual && + + cat >expect <<-\EOF && + * (HEAD detached from fromtag) + branch-one + branch-two + main + EOF + git branch --sort=-type >actual && + test_i18ncmp expect actual +' + +test_expect_success 'git branch `--sort=[-]version:refname` option' ' + cat >expect <<-\EOF && + * (HEAD detached from fromtag) + branch-one + branch-two + main + EOF + git branch --sort=version:refname >actual && + test_i18ncmp expect actual && + + cat >expect <<-\EOF && + main + branch-two + branch-one + * (HEAD detached from fromtag) + EOF + git branch --sort=-version:refname >actual && test_i18ncmp expect actual ' From 75c50e599ca4fe2fcf864cfa491c8035513e6cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Thu, 7 Jan 2021 10:51:49 +0100 Subject: [PATCH 3/7] ref-filter: add braces to if/else if/else chain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per the CodingGuidelines add braces to an if/else if/else chain where only the "else" had braces. This is in preparation for a subsequent change where the "else if" will have lines added to it. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- ref-filter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ref-filter.c b/ref-filter.c index aa260bfd09..e4c162a8c3 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -2364,11 +2364,11 @@ static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, stru die("%s", err.buf); strbuf_release(&err); cmp_fn = s->ignore_case ? strcasecmp : strcmp; - if (s->version) + if (s->version) { cmp = versioncmp(va->s, vb->s); - else if (cmp_type == FIELD_STR) + } else if (cmp_type == FIELD_STR) { cmp = cmp_fn(va->s, vb->s); - else { + } else { if (va->value < vb->value) cmp = -1; else if (va->value == vb->value) From d0947483a3386204918447775b617ab3dac833b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Thu, 7 Jan 2021 10:51:50 +0100 Subject: [PATCH 4/7] ref-filter: move "cmp_fn" assignment into "else if" arm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Further amend code changed in 7c5045fc180 (ref-filter: apply fallback refname sort only after all user sorts, 2020-05-03) to move an assignment only used in the "else if" arm to happen there. Before that commit the cmp_fn would be used outside of it. We could also just skip the "cmp_fn" assignment and use strcasecmp/strcmp directly in a ternary statement here, but this is probably more readable. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- ref-filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ref-filter.c b/ref-filter.c index e4c162a8c3..8882128cd3 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -2355,7 +2355,6 @@ static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, stru struct atom_value *va, *vb; int cmp; cmp_type cmp_type = used_atom[s->atom].type; - int (*cmp_fn)(const char *, const char *); struct strbuf err = STRBUF_INIT; if (get_ref_atom_value(a, s->atom, &va, &err)) @@ -2363,10 +2362,11 @@ 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); - cmp_fn = s->ignore_case ? strcasecmp : strcmp; if (s->version) { cmp = versioncmp(va->s, vb->s); } else if (cmp_type == FIELD_STR) { + int (*cmp_fn)(const char *, const char *); + cmp_fn = s->ignore_case ? strcasecmp : strcmp; cmp = cmp_fn(va->s, vb->s); } else { if (va->value < vb->value) From 7c269a7b162027d0465d52203e778903a2ddbdbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Thu, 7 Jan 2021 10:51:51 +0100 Subject: [PATCH 5/7] ref-filter: move ref_sorting flags to a bitfield MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the reverse/ignore_case/version sort flags in the ref_sorting struct into a bitfield. Having three of them was already a bit unwieldy, but it would be even more so if another flag needed a function like ref_sorting_icase_all() introduced in 76f9e569adb (ref-filter: apply --ignore-case to all sorting keys, 2020-05-03). A follow-up change will introduce such a flag, so let's move this over to a bitfield. Instead of using the usual '#define' pattern I'm using the "enum" pattern from builtin/rebase.c's b4c8eb024af (builtin rebase: support --quiet, 2018-09-04). Perhaps there's a more idiomatic way of doing the "for each in list amend mask" pattern than this "mask/on" variable combo. This function doesn't allow us to e.g. do any arbitrary changes to the bitfield for multiple flags, but I think in this case that's fine. The common case is that we're calling this with a list of one. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- builtin/branch.c | 2 +- builtin/for-each-ref.c | 2 +- builtin/tag.c | 2 +- ref-filter.c | 24 +++++++++++++++--------- ref-filter.h | 12 +++++++----- 5 files changed, 25 insertions(+), 17 deletions(-) diff --git a/builtin/branch.c b/builtin/branch.c index 045866a51a..2dd51a8653 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -739,7 +739,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix) */ if (!sorting) sorting = ref_default_sorting(); - ref_sorting_icase_all(sorting, icase); + ref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase); print_ref_list(&filter, sorting, &format); print_columns(&output, colopts, NULL); string_list_clear(&output, 0); diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 9d1ecda2b8..cb9c81a046 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -70,7 +70,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) if (!sorting) sorting = ref_default_sorting(); - ref_sorting_icase_all(sorting, icase); + ref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase); filter.ignore_case = icase; filter.name_patterns = argv; diff --git a/builtin/tag.c b/builtin/tag.c index ecf011776d..24d35b746d 100644 --- a/builtin/tag.c +++ b/builtin/tag.c @@ -485,7 +485,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix) } if (!sorting) sorting = ref_default_sorting(); - ref_sorting_icase_all(sorting, icase); + ref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase); filter.ignore_case = icase; if (cmdmode == 'l') { int ret; diff --git a/ref-filter.c b/ref-filter.c index 8882128cd3..fe587afb80 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -2362,11 +2362,12 @@ 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->version) { + 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 *); - cmp_fn = s->ignore_case ? strcasecmp : strcmp; + cmp_fn = s->sort_flags & REF_SORTING_ICASE + ? strcasecmp : strcmp; cmp = cmp_fn(va->s, vb->s); } else { if (va->value < vb->value) @@ -2377,7 +2378,7 @@ static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, stru cmp = 1; } - return (s->reverse) ? -cmp : cmp; + return (s->sort_flags & REF_SORTING_REVERSE) ? -cmp : cmp; } static int compare_refs(const void *a_, const void *b_, void *ref_sorting) @@ -2392,15 +2393,20 @@ static int compare_refs(const void *a_, const void *b_, void *ref_sorting) return cmp; } s = ref_sorting; - return s && s->ignore_case ? + return s && s->sort_flags & REF_SORTING_ICASE ? strcasecmp(a->refname, b->refname) : strcmp(a->refname, b->refname); } -void ref_sorting_icase_all(struct ref_sorting *sorting, int flag) +void ref_sorting_set_sort_flags_all(struct ref_sorting *sorting, + unsigned int mask, int on) { - for (; sorting; sorting = sorting->next) - sorting->ignore_case = !!flag; + for (; sorting; sorting = sorting->next) { + if (on) + sorting->sort_flags |= mask; + else + sorting->sort_flags &= ~mask; + } } void ref_array_sort(struct ref_sorting *sorting, struct ref_array *array) @@ -2537,12 +2543,12 @@ void parse_ref_sorting(struct ref_sorting **sorting_tail, const char *arg) *sorting_tail = s; if (*arg == '-') { - s->reverse = 1; + s->sort_flags |= REF_SORTING_REVERSE; arg++; } if (skip_prefix(arg, "version:", &arg) || skip_prefix(arg, "v:", &arg)) - s->version = 1; + s->sort_flags |= REF_SORTING_VERSION; s->atom = parse_sorting_atom(arg); } diff --git a/ref-filter.h b/ref-filter.h index feaef4a8fd..6296ae8bb2 100644 --- a/ref-filter.h +++ b/ref-filter.h @@ -28,9 +28,11 @@ struct atom_value; struct ref_sorting { struct ref_sorting *next; int atom; /* index into used_atom array (internal) */ - unsigned reverse : 1, - ignore_case : 1, - version : 1; + enum { + REF_SORTING_REVERSE = 1<<0, + REF_SORTING_ICASE = 1<<1, + REF_SORTING_VERSION = 1<<2, + } sort_flags; }; struct ref_array_item { @@ -109,8 +111,8 @@ void ref_array_clear(struct ref_array *array); int verify_ref_format(struct ref_format *format); /* Sort the given ref_array as per the ref_sorting provided */ void ref_array_sort(struct ref_sorting *sort, struct ref_array *array); -/* Set the ignore_case flag for all elements of a sorting list */ -void ref_sorting_icase_all(struct ref_sorting *sorting, int flag); +/* Set REF_SORTING_* sort_flags for all elements of a sorting list */ +void ref_sorting_set_sort_flags_all(struct ref_sorting *sorting, unsigned int mask, int on); /* Based on the given format and quote_style, fill the strbuf */ int format_ref_array_item(struct ref_array_item *info, const struct ref_format *format, From 2708ce62d2105c4470399a2c839b6d451c9c148f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Thu, 7 Jan 2021 10:51:52 +0100 Subject: [PATCH 6/7] branch: sort detached HEAD based on a flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 ) 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 Signed-off-by: Junio C Hamano --- builtin/branch.c | 2 ++ ref-filter.c | 44 +++++++++++++++++++++++----------------- ref-filter.h | 1 + t/t3203-branch-output.sh | 4 ++-- wt-status.c | 4 ++-- wt-status.h | 2 -- 6 files changed, 32 insertions(+), 25 deletions(-) diff --git a/builtin/branch.c b/builtin/branch.c index 2dd51a8653..8c0b428104 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -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); diff --git a/ref-filter.c b/ref-filter.c index fe587afb80..8d0739b997 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -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 *); diff --git a/ref-filter.h b/ref-filter.h index 6296ae8bb2..19ea4c4134 100644 --- a/ref-filter.h +++ b/ref-filter.h @@ -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; }; diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index f92fb3aab9..8f53b08136 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -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 diff --git a/wt-status.c b/wt-status.c index 7074bbdd53..40b59be478 100644 --- a/wt-status.c +++ b/wt-status.c @@ -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."); diff --git a/wt-status.h b/wt-status.h index 35b44c388e..0d32799b28 100644 --- a/wt-status.h +++ b/wt-status.h @@ -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 { From 4045f659bdccb5108800bdc2ec96bc6f3945ff40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Thu, 7 Jan 2021 10:51:53 +0100 Subject: [PATCH 7/7] branch: show "HEAD detached" first under reverse sort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the output of the likes of "git branch -l --sort=-objectsize" to show the "(HEAD detached at )" message at the start of the output. Before the compare_detached_head() function added in a preceding commit we'd emit this output as an emergent effect. It doesn't make any sense to consider the objectsize, type or other non-attribute of the "(HEAD detached at )" message for the purposes of sorting. Let's always emit it at the top instead. The only reason it was sorted in the first place is because we're injecting it into the ref-filter machinery so builtin/branch.c doesn't need to do its own "am I detached?" detection. Signed-off-by: Ævar Arnfjörð Bjarmason Signed-off-by: Junio C Hamano --- ref-filter.c | 5 ++++- t/t3203-branch-output.sh | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ref-filter.c b/ref-filter.c index 8d0739b997..ee337df232 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -2357,6 +2357,7 @@ static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, stru { struct atom_value *va, *vb; int cmp; + int cmp_detached_head = 0; cmp_type cmp_type = used_atom[s->atom].type; struct strbuf err = STRBUF_INIT; @@ -2368,6 +2369,7 @@ static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, stru if (s->sort_flags & REF_SORTING_DETACHED_HEAD_FIRST && ((a->kind | b->kind) & FILTER_REFS_DETACHED_HEAD)) { cmp = compare_detached_head(a, b); + cmp_detached_head = 1; } else if (s->sort_flags & REF_SORTING_VERSION) { cmp = versioncmp(va->s, vb->s); } else if (cmp_type == FIELD_STR) { @@ -2384,7 +2386,8 @@ static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, stru cmp = 1; } - return (s->sort_flags & REF_SORTING_REVERSE) ? -cmp : cmp; + return (s->sort_flags & REF_SORTING_REVERSE && !cmp_detached_head) + ? -cmp : cmp; } static int compare_refs(const void *a_, const void *b_, void *ref_sorting) diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index 8f53b08136..5e0577d5c7 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -221,10 +221,10 @@ test_expect_success 'git branch `--sort=[-]objectsize` option' ' test_i18ncmp expect actual && cat >expect <<-\EOF && + * (HEAD detached from fromtag) branch-one main 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 @@ -261,10 +261,10 @@ test_expect_success 'git branch `--sort=[-]version:refname` option' ' test_i18ncmp expect actual && cat >expect <<-\EOF && + * (HEAD detached from fromtag) main branch-two branch-one - * (HEAD detached from fromtag) EOF git branch --sort=-version:refname >actual && test_i18ncmp expect actual