Merge branch 'jk/for-each-ref-multi-key-sort-fix'
"git branch" and other "for-each-ref" variants accepted multiple --sort=<key> options in the increasing order of precedence, but it had a few breakages around "--ignore-case" handling, and tie-breaking with the refname, which have been fixed. * jk/for-each-ref-multi-key-sort-fix: ref-filter: apply fallback refname sort only after all user sorts ref-filter: apply --ignore-case to all sorting keys
This commit is contained in:
commit
6de1630898
@ -737,7 +737,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
|
||||
*/
|
||||
if (!sorting)
|
||||
sorting = ref_default_sorting();
|
||||
sorting->ignore_case = icase;
|
||||
ref_sorting_icase_all(sorting, icase);
|
||||
print_ref_list(&filter, sorting, &format);
|
||||
print_columns(&output, colopts, NULL);
|
||||
string_list_clear(&output, 0);
|
||||
|
@ -70,7 +70,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
|
||||
|
||||
if (!sorting)
|
||||
sorting = ref_default_sorting();
|
||||
sorting->ignore_case = icase;
|
||||
ref_sorting_icase_all(sorting, icase);
|
||||
filter.ignore_case = icase;
|
||||
|
||||
filter.name_patterns = argv;
|
||||
|
@ -485,7 +485,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
|
||||
}
|
||||
if (!sorting)
|
||||
sorting = ref_default_sorting();
|
||||
sorting->ignore_case = icase;
|
||||
ref_sorting_icase_all(sorting, icase);
|
||||
filter.ignore_case = icase;
|
||||
if (cmdmode == 'l') {
|
||||
int ret;
|
||||
|
13
ref-filter.c
13
ref-filter.c
@ -2295,7 +2295,7 @@ static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, stru
|
||||
if (va->value < vb->value)
|
||||
cmp = -1;
|
||||
else if (va->value == vb->value)
|
||||
cmp = cmp_fn(a->refname, b->refname);
|
||||
cmp = 0;
|
||||
else
|
||||
cmp = 1;
|
||||
}
|
||||
@ -2314,7 +2314,16 @@ static int compare_refs(const void *a_, const void *b_, void *ref_sorting)
|
||||
if (cmp)
|
||||
return cmp;
|
||||
}
|
||||
return 0;
|
||||
s = ref_sorting;
|
||||
return s && s->ignore_case ?
|
||||
strcasecmp(a->refname, b->refname) :
|
||||
strcmp(a->refname, b->refname);
|
||||
}
|
||||
|
||||
void ref_sorting_icase_all(struct ref_sorting *sorting, int flag)
|
||||
{
|
||||
for (; sorting; sorting = sorting->next)
|
||||
sorting->ignore_case = !!flag;
|
||||
}
|
||||
|
||||
void ref_array_sort(struct ref_sorting *sorting, struct ref_array *array)
|
||||
|
@ -114,6 +114,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);
|
||||
/* 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,
|
||||
|
@ -650,17 +650,59 @@ test_atom refs/tags/signed-long contents "subject line
|
||||
body contents
|
||||
$sig"
|
||||
|
||||
sort >expected <<EOF
|
||||
$(git rev-parse refs/tags/bogo) <committer@example.com> refs/tags/bogo
|
||||
$(git rev-parse refs/tags/master) <committer@example.com> refs/tags/master
|
||||
EOF
|
||||
test_expect_success 'set up multiple-sort tags' '
|
||||
for when in 100000 200000
|
||||
do
|
||||
for email in user1 user2
|
||||
do
|
||||
for ref in ref1 ref2
|
||||
do
|
||||
GIT_COMMITTER_DATE="@$when +0000" \
|
||||
GIT_COMMITTER_EMAIL="$email@example.com" \
|
||||
git tag -m "tag $ref-$when-$email" \
|
||||
multi-$ref-$when-$email || return 1
|
||||
done
|
||||
done
|
||||
done
|
||||
'
|
||||
|
||||
test_expect_success 'Verify sort with multiple keys' '
|
||||
git for-each-ref --format="%(objectname) %(taggeremail) %(refname)" --sort=objectname --sort=taggeremail \
|
||||
refs/tags/bogo refs/tags/master > actual &&
|
||||
cat >expected <<-\EOF &&
|
||||
100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
|
||||
100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
|
||||
100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
|
||||
100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
|
||||
200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
|
||||
200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
|
||||
200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
|
||||
200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
|
||||
EOF
|
||||
git for-each-ref \
|
||||
--format="%(taggerdate:unix) %(taggeremail) %(refname)" \
|
||||
--sort=-refname \
|
||||
--sort=taggeremail \
|
||||
--sort=taggerdate \
|
||||
"refs/tags/multi-*" >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'equivalent sorts fall back on refname' '
|
||||
cat >expected <<-\EOF &&
|
||||
100000 <user1@example.com> refs/tags/multi-ref1-100000-user1
|
||||
100000 <user2@example.com> refs/tags/multi-ref1-100000-user2
|
||||
100000 <user1@example.com> refs/tags/multi-ref2-100000-user1
|
||||
100000 <user2@example.com> refs/tags/multi-ref2-100000-user2
|
||||
200000 <user1@example.com> refs/tags/multi-ref1-200000-user1
|
||||
200000 <user2@example.com> refs/tags/multi-ref1-200000-user2
|
||||
200000 <user1@example.com> refs/tags/multi-ref2-200000-user1
|
||||
200000 <user2@example.com> refs/tags/multi-ref2-200000-user2
|
||||
EOF
|
||||
git for-each-ref \
|
||||
--format="%(taggerdate:unix) %(taggeremail) %(refname)" \
|
||||
--sort=taggerdate \
|
||||
"refs/tags/multi-*" >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_expect_success 'do not dereference NULL upon %(HEAD) on unborn branch' '
|
||||
test_when_finished "git checkout master" &&
|
||||
@ -895,4 +937,44 @@ test_expect_success 'for-each-ref --ignore-case ignores case' '
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'for-each-ref --ignore-case works on multiple sort keys' '
|
||||
# name refs numerically to avoid case-insensitive filesystem conflicts
|
||||
nr=0 &&
|
||||
for email in a A b B
|
||||
do
|
||||
for subject in a A b B
|
||||
do
|
||||
GIT_COMMITTER_EMAIL="$email@example.com" \
|
||||
git tag -m "tag $subject" icase-$(printf %02d $nr) &&
|
||||
nr=$((nr+1))||
|
||||
return 1
|
||||
done
|
||||
done &&
|
||||
git for-each-ref --ignore-case \
|
||||
--format="%(taggeremail) %(subject) %(refname)" \
|
||||
--sort=refname \
|
||||
--sort=subject \
|
||||
--sort=taggeremail \
|
||||
refs/tags/icase-* >actual &&
|
||||
cat >expect <<-\EOF &&
|
||||
<a@example.com> tag a refs/tags/icase-00
|
||||
<a@example.com> tag A refs/tags/icase-01
|
||||
<A@example.com> tag a refs/tags/icase-04
|
||||
<A@example.com> tag A refs/tags/icase-05
|
||||
<a@example.com> tag b refs/tags/icase-02
|
||||
<a@example.com> tag B refs/tags/icase-03
|
||||
<A@example.com> tag b refs/tags/icase-06
|
||||
<A@example.com> tag B refs/tags/icase-07
|
||||
<b@example.com> tag a refs/tags/icase-08
|
||||
<b@example.com> tag A refs/tags/icase-09
|
||||
<B@example.com> tag a refs/tags/icase-12
|
||||
<B@example.com> tag A refs/tags/icase-13
|
||||
<b@example.com> tag b refs/tags/icase-10
|
||||
<b@example.com> tag B refs/tags/icase-11
|
||||
<B@example.com> tag b refs/tags/icase-14
|
||||
<B@example.com> tag B refs/tags/icase-15
|
||||
EOF
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
Loading…
Reference in New Issue
Block a user