Hi, sorry for top-posting, but I just noticed the "firstlyxy" typo in the subject ;-) Ciao, Dscho On Sun, 9 Jun 2019, Johannes Schindelin wrote: > Hi Matthew, > > On Thu, 6 Jun 2019, Matthew DeVore wrote: > > > Before this patch, "git branch" would put "(HEAD detached...)" and "(no > > branch, rebasing...)" lines before all the other branches *in most > > cases* and only because of the fact that "(" is a low codepoint. This > > would not hold in the Chinese locale, which uses a full-width "(" symbol > > (codepoint FF08). This meant that the detached HEAD line would appear > > after all local refs and even after the remote refs if there were any. > > > > Deliberately sort the detached HEAD refs before other refs when sorting > > by refname rather than rely on codepoint subtleties. > > This description is pretty convincing! > > > diff --git a/ref-filter.c b/ref-filter.c > > index 8500671bc6..cbfae790f9 100644 > > --- a/ref-filter.c > > +++ b/ref-filter.c > > @@ -2157,25 +2157,29 @@ static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, stru > > 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)) > > die("%s", err.buf); > > 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) > > + if (s->version) { > > cmp = versioncmp(va->s, vb->s); > > - else if (cmp_type == FIELD_STR) > > + } else if (cmp_type == FIELD_STR) { > > I find that it makes sense in general to suppress one's urges regarding > introducing `{ ... }` around one-liners when the patch does not actually > require it. > > For example, I found this patch harder than necessary to read because of > it. > > > + if ((a->kind & FILTER_REFS_DETACHED_HEAD) != > > + (b->kind & FILTER_REFS_DETACHED_HEAD)) { > > So in case that both are detached... > > > + return (a->kind & FILTER_REFS_DETACHED_HEAD) ? -1 : 1; > > + } > > cmp = cmp_fn(va->s, vb->s); > > ... we compare their commit hashes, is that right? Might be worth a code > comment. > > > - else { > > + } else { > > FWIW it would have been a much more obvious patch if it had done > > if (s->version) > [...] > + else if (cmp_type == FIELD_STR && > + (a->kind & FILTER_REFS_DETACHED_HEAD || > + b->kind & FILTER_REFS_DETACHED_HEAD)) > + return (a->kind & FILTER_REFS_DETACHED_HEAD) ? -1 : 1; > else if (cmp_type == FIELD_STR) > [...] > > Maybe still worth doing. > > FWIW I was *so* tempted to write > > ((a->kind ^ b->kind) & FILTER_REFS_DETACHED_HEAD) > > to make this code DRYer, but then, readers not intimately familiar with > Boolean arithmetic might not even know about the `^` operator, making the > code harder to read than necessary, too. > > > diff --git a/t/lib-gettext.sh b/t/lib-gettext.sh > > index 2139b427ca..de08d109dc 100644 > > --- a/t/lib-gettext.sh > > +++ b/t/lib-gettext.sh > > @@ -25,23 +25,29 @@ then > > p > > q > > }') > > # is_IS.ISO8859-1 on Solaris and FreeBSD, is_IS.iso88591 on Debian > > is_IS_iso_locale=$(locale -a 2>/dev/null | > > sed -n '/^is_IS\.[iI][sS][oO]8859-*1$/{ > > p > > q > > }') > > > > - # Export them as an environment variable so the t0202/test.pl Perl > > - # test can use it too > > - export is_IS_locale is_IS_iso_locale > > + zh_CN_locale=$(locale -a 2>/dev/null | > > + sed -n '/^zh_CN\.[uU][tT][fF]-*8$/{ > > + p > > + q > > + }') > > + > > + # Export them as environment variables so other tests can use them > > + # too > > + export is_IS_locale is_IS_iso_locale zh_CN_locale > > > > if test -n "$is_IS_locale" && > > test $GIT_INTERNAL_GETTEXT_SH_SCHEME != "fallthrough" > > then > > # Some of the tests need the reference Icelandic locale > > test_set_prereq GETTEXT_LOCALE > > > > # Exporting for t0202/test.pl > > GETTEXT_LOCALE=1 > > export GETTEXT_LOCALE > > @@ -53,11 +59,15 @@ then > > if test -n "$is_IS_iso_locale" && > > test $GIT_INTERNAL_GETTEXT_SH_SCHEME != "fallthrough" > > then > > # Some of the tests need the reference Icelandic locale > > test_set_prereq GETTEXT_ISO_LOCALE > > > > say "# lib-gettext: Found '$is_IS_iso_locale' as an is_IS ISO-8859-1 locale" > > else > > say "# lib-gettext: No is_IS ISO-8859-1 locale available" > > fi > > + > > + if test -z "$zh_CN_locale"; then > > + say "# lib-gettext: No zh_CN UTF-8 locale available" > > + fi > > I wonder why this hunk, unlike the previous one, does not imitate the > is_IS handling closely. > > > diff --git a/t/t3207-branch-intl.sh b/t/t3207-branch-intl.sh > > new file mode 100755 > > index 0000000000..9f6fcc7481 > > --- /dev/null > > +++ b/t/t3207-branch-intl.sh > > @@ -0,0 +1,38 @@ > > +#!/bin/sh > > + > > +test_description='git branch internationalization tests' > > + > > +. ./lib-gettext.sh > > + > > +test_expect_success 'init repo' ' > > + git init r1 && > > Why? > > > + touch r1/foo && > > + git -C r1 add foo && > > + git -C r1 commit -m foo > > +' > > Why not simply `test_commit foo`? > > > +test_expect_success 'detached head sorts before other branches' ' > > + # Ref sorting logic should put detached heads before the other > > + # branches, but this is not automatic when a branch name sorts > > + # lexically before "(" or the full-width "(" (Unicode codepoint FF08). > > + # The latter case is nearly guaranteed for the Chinese locale. > > + > > + git -C r1 checkout HEAD^{} -- && > > + git -C r1 branch !should_be_after_detached HEAD && > > I am not sure that `!` is a wise choice, as it might not be a legal file > name character everywhere. A `.` or `-` might make more sense. > > > + LC_ALL=$zh_CN_locale LC_MESSAGES=$zh_CN_locale \ > > + git -C r1 branch >actual && > > + git -C r1 checkout - && > > Why call `checkout` after `branch`? That's unnecessary, we do not verify > anything after that call. > > > + awk " > > + # We need full-width or half-width parens on the first line. > > + NR == 1 && (/[(].*[)]/ || /\xef\xbc\x88.*\xef\xbc\x89/) { > > + found_head = 1; > > + } > > + /!should_be_after_detached/ { > > + found_control_branch = 1; > > + } > > + END { exit !found_head || !found_control_branch } > > + " actual > > This might look beautiful for a fan of `awk`. For the vast majority of us, > this is not a good idea. > > Remember, you do *not* write those tests for your own pleasure, you do > *not* write those tests in order to help you catch problems while you > develop your patches, you do *not* develop these tests in order to just > catch future breakages. > > You *do* write those tests for *other* developers who you try to help in > preventing introducing regressions. > > As such, you *want* the tests to be > > - easy to understand for as wide a range of developers as you can make, > > - quick, > > - covering regressions, and *only* regressions, > > - helping diagnose *and* fix regressions. > > In the ideal case you won't even hear when developers found your test > helpful, and you will never, ever learn about regressions that have been > prevented. > > You most frequently will hear about your tests when they did not do their > job well. > > In this instance, I would have expected something like > > test_expect_lines = 3 actual && > > head -n 1 <actual >first && > test_i18ngrep "detached HEAD" first && > > tail -n 1 <actual >last && > grep should_be_after last > > instead of the "awk-ward" code above. > > Ciao, > Johannes > > > +' > > + > > +test_done > > -- > > 2.21.0 > > > > >