From: Junio C Hamano Date: Tue, 31 Jan 2017 21:14:58 +0000 (-0800) Subject: Merge branch 'st/verify-tag' X-Git-Tag: v2.12.0-rc0~36 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/237bdd9ddbe52eb651787af1929d8832ce37c322?hp=-c Merge branch 'st/verify-tag' "git tag" and "git verify-tag" learned to put GPG verification status in their "--format=" output format. * st/verify-tag: t/t7004-tag: Add --format specifier tests t/t7030-verify-tag: Add --format specifier tests builtin/tag: add --format argument for tag -v builtin/verify-tag: add --format to verify-tag ref-filter: add function to print single ref_array_item gpg-interface, tag: add GPG_VERIFY_OMIT_STATUS flag --- 237bdd9ddbe52eb651787af1929d8832ce37c322 diff --combined Documentation/git-tag.txt index 5055a96823,3bb5e3c23f..8e70c5b6a4 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.txt @@@ -15,7 -15,7 +15,7 @@@ SYNOPSI 'git tag' [-n[]] -l [--contains ] [--points-at ] [--column[=] | --no-column] [--create-reflog] [--sort=] [--format=] [--[no-]merged []] [...] - 'git tag' -v ... + 'git tag' -v [--format=] ... DESCRIPTION ----------- @@@ -101,17 -101,13 +101,17 @@@ OPTION multiple times, in which case the last key becomes the primary key. Also supports "version:refname" or "v:refname" (tag names are treated as versions). The "version:refname" sort - order can also be affected by the - "versionsort.prereleaseSuffix" configuration variable. + order can also be affected by the "versionsort.suffix" + configuration variable. The keys supported are the same as those in `git for-each-ref`. Sort order defaults to the value configured for the `tag.sort` variable if it exists, or lexicographic order otherwise. See linkgit:git-config[1]. +-i:: +--ignore-case:: + Sorting and filtering tags are case insensitive. + --column[=]:: --no-column:: Display tag listing in columns. See configuration variable @@@ -257,8 -253,9 +257,8 @@@ On Automatic followin ~~~~~~~~~~~~~~~~~~~~~~ If you are following somebody else's tree, you are most likely -using remote-tracking branches (`refs/heads/origin` in traditional -layout, or `refs/remotes/origin/master` in the separate-remote -layout). You usually want the tags from the other end. +using remote-tracking branches (eg. `refs/remotes/origin/master`). +You usually want the tags from the other end. On the other hand, if you are fetching because you would want a one-shot merge from somebody else, you typically do not want to diff --combined builtin/tag.c index 73df728114,fbb85ba3dc..e40c4a9676 --- a/builtin/tag.c +++ b/builtin/tag.c @@@ -24,7 -24,7 +24,7 @@@ static const char * const git_tag_usage N_("git tag -d ..."), N_("git tag -l [-n[]] [--contains ] [--points-at ]" "\n\t\t[--format=] [--[no-]merged []] [...]"), - N_("git tag -v ..."), + N_("git tag -v [--format=] ..."), NULL }; @@@ -66,9 -66,10 +66,10 @@@ static int list_tags(struct ref_filter } typedef int (*each_tag_name_fn)(const char *name, const char *ref, - const unsigned char *sha1); + const unsigned char *sha1, const void *cb_data); - static int for_each_tag_name(const char **argv, each_tag_name_fn fn) + static int for_each_tag_name(const char **argv, each_tag_name_fn fn, + const void *cb_data) { const char **p; char ref[PATH_MAX]; @@@ -87,14 -88,14 +88,14 @@@ had_error = 1; continue; } - if (fn(*p, ref, sha1)) + if (fn(*p, ref, sha1, cb_data)) had_error = 1; } return had_error; } static int delete_tag(const char *name, const char *ref, - const unsigned char *sha1) + const unsigned char *sha1, const void *cb_data) { if (delete_ref(ref, sha1, 0)) return 1; @@@ -103,9 -104,22 +104,22 @@@ } static int verify_tag(const char *name, const char *ref, - const unsigned char *sha1) + const unsigned char *sha1, const void *cb_data) { - return gpg_verify_tag(sha1, name, GPG_VERIFY_VERBOSE); + int flags; + const char *fmt_pretty = cb_data; + flags = GPG_VERIFY_VERBOSE; + + if (fmt_pretty) + flags = GPG_VERIFY_OMIT_STATUS; + + if (gpg_verify_tag(sha1, name, flags)) + return -1; + + if (fmt_pretty) + pretty_print_ref(name, sha1, fmt_pretty); + + return 0; } static int do_sign(struct strbuf *buffer) @@@ -335,7 -349,6 +349,7 @@@ int cmd_tag(int argc, const char **argv struct ref_filter filter; static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting; const char *format = NULL; + int icase = 0; struct option options[] = { OPT_CMDMODE('l', "list", &cmdmode, N_("list tag names"), 'l'), { OPTION_INTEGER, 'n', NULL, &filter.lines, N_("n"), @@@ -371,7 -384,6 +385,7 @@@ N_("print only tags of the object"), 0, parse_opt_object_name }, OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")), + OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")), OPT_END() }; @@@ -403,8 -415,6 +417,8 @@@ } if (!sorting) sorting = ref_default_sorting(); + sorting->ignore_case = icase; + filter.ignore_case = icase; if (cmdmode == 'l') { int ret; if (column_active(colopts)) { @@@ -428,9 -438,12 +442,12 @@@ if (filter.merge_commit) die(_("--merged and --no-merged option are only allowed with -l")); if (cmdmode == 'd') - return for_each_tag_name(argv, delete_tag); - if (cmdmode == 'v') - return for_each_tag_name(argv, verify_tag); + return for_each_tag_name(argv, delete_tag, NULL); + if (cmdmode == 'v') { + if (format) + verify_ref_format(format); + return for_each_tag_name(argv, verify_tag, format); + } if (msg.given || msgfile) { if (msg.given && msgfile) diff --combined ref-filter.c index 1a978405e6,77d4e53342..5f4b08792b --- a/ref-filter.c +++ b/ref-filter.c @@@ -13,7 -13,6 +13,7 @@@ #include "utf8.h" #include "git-compat-util.h" #include "version.h" +#include "trailer.h" typedef enum { FIELD_STR, FIELD_ULONG, FIELD_TIME } cmp_type; @@@ -41,7 -40,7 +41,7 @@@ static struct used_atom enum { RR_NORMAL, RR_SHORTEN, RR_TRACK, RR_TRACKSHORT } remote_ref; struct { - enum { C_BARE, C_BODY, C_BODY_DEP, C_LINES, C_SIG, C_SUB } option; + enum { C_BARE, C_BODY, C_BODY_DEP, C_LINES, C_SIG, C_SUB, C_TRAILERS } option; unsigned int nlines; } contents; enum { O_FULL, O_SHORT } objectname; @@@ -86,13 -85,6 +86,13 @@@ static void subject_atom_parser(struct atom->u.contents.option = C_SUB; } +static void trailers_atom_parser(struct used_atom *atom, const char *arg) +{ + if (arg) + die(_("%%(trailers) does not take arguments")); + atom->u.contents.option = C_TRAILERS; +} + static void contents_atom_parser(struct used_atom *atom, const char *arg) { if (!arg) @@@ -103,8 -95,6 +103,8 @@@ atom->u.contents.option = C_SIG; else if (!strcmp(arg, "subject")) atom->u.contents.option = C_SUB; + else if (!strcmp(arg, "trailers")) + atom->u.contents.option = C_TRAILERS; else if (skip_prefix(arg, "lines=", &arg)) { atom->u.contents.option = C_LINES; if (strtoul_ui(arg, 10, &atom->u.contents.nlines)) @@@ -204,7 -194,6 +204,7 @@@ static struct { "creatordate", FIELD_TIME }, { "subject", FIELD_STR, subject_atom_parser }, { "body", FIELD_STR, body_atom_parser }, + { "trailers", FIELD_STR, trailers_atom_parser }, { "contents", FIELD_STR, contents_atom_parser }, { "upstream", FIELD_STR, remote_ref_atom_parser }, { "push", FIELD_STR, remote_ref_atom_parser }, @@@ -246,7 -235,7 +246,7 @@@ int parse_ref_filter_atom(const char *a { const char *sp; const char *arg; - int i, at; + int i, at, atom_len; sp = atom; if (*sp == '*' && sp < ep) @@@ -261,19 -250,19 +261,19 @@@ return i; } + /* + * If the atom name has a colon, strip it and everything after + * it off - it specifies the format for this entry, and + * shouldn't be used for checking against the valid_atom + * table. + */ + arg = memchr(sp, ':', ep - sp); + atom_len = (arg ? arg : ep) - sp; + /* Is the atom a valid one? */ for (i = 0; i < ARRAY_SIZE(valid_atom); i++) { int len = strlen(valid_atom[i].name); - - /* - * If the atom name has a colon, strip it and everything after - * it off - it specifies the format for this entry, and - * shouldn't be used for checking against the valid_atom - * table. - */ - arg = memchr(sp, ':', ep - sp); - if (len == (arg ? arg : ep) - sp && - !memcmp(valid_atom[i].name, sp, len)) + if (len == atom_len && !memcmp(valid_atom[i].name, sp, len)) break; } @@@ -796,7 -785,6 +796,7 @@@ static void grab_sub_body_contents(stru name++; if (strcmp(name, "subject") && strcmp(name, "body") && + strcmp(name, "trailers") && !starts_with(name, "contents")) continue; if (!subpos) @@@ -820,14 -808,6 +820,14 @@@ /* Size is the length of the message after removing the signature */ append_lines(&s, subpos, contents_end - subpos, atom->u.contents.nlines); v->s = strbuf_detach(&s, NULL); + } else if (atom->u.contents.option == C_TRAILERS) { + struct trailer_info info; + + /* Search for trailer info */ + trailer_info_get(&info, subpos); + v->s = xmemdupz(info.trailer_start, + info.trailer_end - info.trailer_start); + trailer_info_release(&info); } else if (atom->u.contents.option == C_BARE) v->s = xstrdup(subpos); } @@@ -1037,7 -1017,7 +1037,7 @@@ static void populate_value(struct ref_a head = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, sha1, NULL); - if (!strcmp(ref->refname, head)) + if (head && !strcmp(ref->refname, head)) v->s = "*"; else v->s = " "; @@@ -1251,14 -1231,8 +1251,14 @@@ static int commit_contains(struct ref_f * matches a pattern "refs/heads/mas") or a wildcard (e.g. the same ref * matches "refs/heads/mas*", too). */ -static int match_pattern(const char **patterns, const char *refname) +static int match_pattern(const struct ref_filter *filter, const char *refname) { + const char **patterns = filter->name_patterns; + unsigned flags = 0; + + if (filter->ignore_case) + flags |= WM_CASEFOLD; + /* * When no '--format' option is given we need to skip the prefix * for matching refs of tags and branches. @@@ -1269,7 -1243,7 +1269,7 @@@ skip_prefix(refname, "refs/", &refname)); for (; *patterns; patterns++) { - if (!wildmatch(*patterns, refname, 0, NULL)) + if (!wildmatch(*patterns, refname, flags, NULL)) return 1; } return 0; @@@ -1281,15 -1255,9 +1281,15 @@@ * matches a pattern "refs/heads/" but not "refs/heads/m") or a * wildcard (e.g. the same ref matches "refs/heads/m*", too). */ -static int match_name_as_path(const char **pattern, const char *refname) +static int match_name_as_path(const struct ref_filter *filter, const char *refname) { + const char **pattern = filter->name_patterns; int namelen = strlen(refname); + unsigned flags = WM_PATHNAME; + + if (filter->ignore_case) + flags |= WM_CASEFOLD; + for (; *pattern; pattern++) { const char *p = *pattern; int plen = strlen(p); @@@ -1312,8 -1280,8 +1312,8 @@@ static int filter_pattern_match(struct if (!*filter->name_patterns) return 1; /* No pattern always matches */ if (filter->match_as_path) - return match_name_as_path(filter->name_patterns, refname); - return match_pattern(filter->name_patterns, refname); + return match_name_as_path(filter, refname); + return match_pattern(filter, refname); } /* @@@ -1361,7 -1329,7 +1361,7 @@@ static struct ref_array_item *new_ref_a return ref; } - static int filter_ref_kind(struct ref_filter *filter, const char *refname) + static int ref_kind_from_refname(const char *refname) { unsigned int i; @@@ -1374,11 -1342,7 +1374,7 @@@ { "refs/tags/", FILTER_REFS_TAGS} }; - if (filter->kind == FILTER_REFS_BRANCHES || - filter->kind == FILTER_REFS_REMOTES || - filter->kind == FILTER_REFS_TAGS) - return filter->kind; - else if (!strcmp(refname, "HEAD")) + if (!strcmp(refname, "HEAD")) return FILTER_REFS_DETACHED_HEAD; for (i = 0; i < ARRAY_SIZE(ref_kind); i++) { @@@ -1389,6 -1353,15 +1385,15 @@@ return FILTER_REFS_OTHERS; } + static int filter_ref_kind(struct ref_filter *filter, const char *refname) + { + if (filter->kind == FILTER_REFS_BRANCHES || + filter->kind == FILTER_REFS_REMOTES || + filter->kind == FILTER_REFS_TAGS) + return filter->kind; + return ref_kind_from_refname(refname); + } + /* * A call-back given to for_each_ref(). Filter refs and keep them for * later object processing. @@@ -1568,20 -1541,18 +1573,20 @@@ static int cmp_ref_sorting(struct ref_s struct atom_value *va, *vb; int cmp; cmp_type cmp_type = used_atom[s->atom].type; + int (*cmp_fn)(const char *, const char *); get_ref_atom_value(a, s->atom, &va); get_ref_atom_value(b, s->atom, &vb); + cmp_fn = s->ignore_case ? strcasecmp : strcmp; if (s->version) cmp = versioncmp(va->s, vb->s); else if (cmp_type == FIELD_STR) - cmp = strcmp(va->s, vb->s); + cmp = cmp_fn(va->s, vb->s); else { if (va->ul < vb->ul) cmp = -1; else if (va->ul == vb->ul) - cmp = strcmp(a->refname, b->refname); + cmp = cmp_fn(a->refname, b->refname); else cmp = 1; } @@@ -1607,7 -1578,7 +1612,7 @@@ static int compare_refs(const void *a_ void ref_array_sort(struct ref_sorting *sorting, struct ref_array *array) { ref_sorting = sorting; - qsort(array->items, array->nr, sizeof(struct ref_array_item *), compare_refs); + QSORT(array->items, array->nr, compare_refs); } static void append_literal(const char *cp, const char *ep, struct ref_formatting_state *state) @@@ -1671,6 -1642,16 +1676,16 @@@ void show_ref_array_item(struct ref_arr putchar('\n'); } + void pretty_print_ref(const char *name, const unsigned char *sha1, + const char *format) + { + struct ref_array_item *ref_item; + ref_item = new_ref_array_item(name, sha1, 0); + ref_item->kind = ref_kind_from_refname(name); + show_ref_array_item(ref_item, format, 0); + free_array_item(ref_item); + } + /* If no sorting option is given, use refname to sort as default */ struct ref_sorting *ref_default_sorting(void) { diff --combined ref-filter.h index fc55fa3574,3cf3d3f590..7b05592baf --- a/ref-filter.h +++ b/ref-filter.h @@@ -29,7 -29,6 +29,7 @@@ struct ref_sorting struct ref_sorting *next; int atom; /* index into used_atom array (internal) */ unsigned reverse : 1, + ignore_case : 1, version : 1; }; @@@ -63,7 -62,6 +63,7 @@@ struct ref_filter unsigned int with_commit_tag_algo : 1, match_as_path : 1, + ignore_case : 1, detached : 1; unsigned int kind, lines; @@@ -109,4 -107,11 +109,11 @@@ struct ref_sorting *ref_default_sorting /* Function to parse --merged and --no-merged options */ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset); + /* + * Print a single ref, outside of any ref-filter. Note that the + * name must be a fully qualified refname. + */ + void pretty_print_ref(const char *name, const unsigned char *sha1, + const char *format); + #endif /* REF_FILTER_H */ diff --combined t/t7004-tag.sh index 1cfa8a21d2,b53a2e5e41..b676b90c7d --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@@ -27,30 -27,6 +27,30 @@@ test_expect_success 'listing all tags i test $(git tag | wc -l) -eq 0 ' +test_expect_success 'sort tags, ignore case' ' + ( + git init sort && + cd sort && + test_commit initial && + git tag tag-one && + git tag TAG-two && + git tag -l >actual && + cat >expected <<-\EOF && + TAG-two + initial + tag-one + EOF + test_cmp expected actual && + git tag -l -i >actual && + cat >expected <<-\EOF && + initial + tag-one + TAG-two + EOF + test_cmp expected actual + ) +' + test_expect_success 'looking for a tag in an empty tree should fail' \ '! (tag_exists mytag)' @@@ -105,9 -81,6 +105,9 @@@ test_expect_success 'listing all tags i test_expect_success 'listing a tag using a matching pattern should succeed' \ 'git tag -l mytag' +test_expect_success 'listing a tag with --ignore-case' \ + 'test $(git tag -l --ignore-case MYTAG) = mytag' + test_expect_success \ 'listing a tag using a matching pattern should output that tag' \ 'test $(git tag -l mytag) = mytag' @@@ -149,11 -122,11 +149,11 @@@ test_expect_success '--force can creat tag_exists mytag' test_expect_success '--force is moot with a non-existing tag name' ' + test_when_finished git tag -d newtag forcetag && git tag newtag >expect && git tag --force forcetag >actual && test_cmp expect actual ' -git tag -d newtag forcetag # deleting tags: @@@ -324,9 -297,11 +324,9 @@@ EO ' test_expect_success 'listing tags in column with column.*' ' - git config column.tag row && - git config column.ui dense && + test_config column.tag row && + test_config column.ui dense && COLUMNS=40 git tag -l >actual && - git config --unset column.ui && - git config --unset column.tag && cat >expected <<\EOF && a1 aa1 cba t210 t211 v0.2.1 v1.0 v1.0.1 v1.1.3 @@@ -339,8 -314,9 +339,8 @@@ test_expect_success 'listing tag with - ' test_expect_success 'listing tags -n in column with column.ui ignored' ' - git config column.ui "row dense" && + test_config column.ui "row dense" && COLUMNS=40 git tag -l -n >actual && - git config --unset column.ui && cat >expected <<\EOF && a1 Foo aa1 Foo @@@ -871,6 -847,22 +871,22 @@@ test_expect_success GPG 'verifying a fo test_must_fail git tag -v forged-tag ' + test_expect_success 'verifying a proper tag with --format pass and format accordingly' ' + cat >expect <<-\EOF + tagname : signed-tag + EOF && + git tag -v --format="tagname : %(tag)" "signed-tag" >actual && + test_cmp expect actual + ' + + test_expect_success 'verifying a forged tag with --format fail and format accordingly' ' + cat >expect <<-\EOF + tagname : forged-tag + EOF && + test_must_fail git tag -v --format="tagname : %(tag)" "forged-tag" >actual && + test_cmp expect actual + ' + # blank and empty messages for signed tags: get_tag_header empty-signed-tag $commit commit $time >expect @@@ -1224,10 -1216,11 +1240,10 @@@ test_expect_success GPG,RFC1991 ' # try to sign with bad user.signingkey -git config user.signingkey BobTheMouse test_expect_success GPG \ 'git tag -s fails if gpg is misconfigured (bad key)' \ - 'test_must_fail git tag -s -m tail tag-gpg-failure' -git config --unset user.signingkey + 'test_config user.signingkey BobTheMouse && + test_must_fail git tag -s -m tail tag-gpg-failure' # try to produce invalid signature test_expect_success GPG \ @@@ -1507,7 -1500,7 +1523,7 @@@ test_expect_success 'reverse lexical so ' test_expect_success 'configured lexical sort' ' - git config tag.sort "v:refname" && + test_config tag.sort "v:refname" && git tag -l "foo*" >actual && cat >expect <<-\EOF && foo1.3 @@@ -1518,7 -1511,6 +1534,7 @@@ ' test_expect_success 'option override configured sort' ' + test_config tag.sort "v:refname" && git tag -l --sort=-refname "foo*" >actual && cat >expect <<-\EOF && foo1.6 @@@ -1533,12 -1525,13 +1549,12 @@@ test_expect_success 'invalid sort param ' test_expect_success 'invalid sort parameter in configuratoin' ' - git config tag.sort "v:notvalid" && + test_config tag.sort "v:notvalid" && test_must_fail git tag -l "foo*" ' test_expect_success 'version sort with prerelease reordering' ' - git config --unset tag.sort && - git config versionsort.prereleaseSuffix -rc && + test_config versionsort.prereleaseSuffix -rc && git tag foo1.6-rc1 && git tag foo1.6-rc2 && git tag -l --sort=version:refname "foo*" >actual && @@@ -1553,7 -1546,6 +1569,7 @@@ ' test_expect_success 'reverse version sort with prerelease reordering' ' + test_config versionsort.prereleaseSuffix -rc && git tag -l --sort=-version:refname "foo*" >actual && cat >expect <<-\EOF && foo1.10 @@@ -1565,103 -1557,6 +1581,103 @@@ test_cmp expect actual ' +test_expect_success 'version sort with prerelease reordering and common leading character' ' + test_config versionsort.prereleaseSuffix -before && + git tag foo1.7-before1 && + git tag foo1.7 && + git tag foo1.7-after1 && + git tag -l --sort=version:refname "foo1.7*" >actual && + cat >expect <<-\EOF && + foo1.7-before1 + foo1.7 + foo1.7-after1 + EOF + test_cmp expect actual +' + +test_expect_success 'version sort with prerelease reordering, multiple suffixes and common leading character' ' + test_config versionsort.prereleaseSuffix -before && + git config --add versionsort.prereleaseSuffix -after && + git tag -l --sort=version:refname "foo1.7*" >actual && + cat >expect <<-\EOF && + foo1.7-before1 + foo1.7-after1 + foo1.7 + EOF + test_cmp expect actual +' + +test_expect_success 'version sort with prerelease reordering, multiple suffixes match the same tag' ' + test_config versionsort.prereleaseSuffix -bar && + git config --add versionsort.prereleaseSuffix -foo-baz && + git config --add versionsort.prereleaseSuffix -foo-bar && + git tag foo1.8-foo-bar && + git tag foo1.8-foo-baz && + git tag foo1.8 && + git tag -l --sort=version:refname "foo1.8*" >actual && + cat >expect <<-\EOF && + foo1.8-foo-baz + foo1.8-foo-bar + foo1.8 + EOF + test_cmp expect actual +' + +test_expect_success 'version sort with prerelease reordering, multiple suffixes match starting at the same position' ' + test_config versionsort.prereleaseSuffix -pre && + git config --add versionsort.prereleaseSuffix -prerelease && + git tag foo1.9-pre1 && + git tag foo1.9-pre2 && + git tag foo1.9-prerelease1 && + git tag -l --sort=version:refname "foo1.9*" >actual && + cat >expect <<-\EOF && + foo1.9-pre1 + foo1.9-pre2 + foo1.9-prerelease1 + EOF + test_cmp expect actual +' + +test_expect_success 'version sort with general suffix reordering' ' + test_config versionsort.suffix -alpha && + git config --add versionsort.suffix -beta && + git config --add versionsort.suffix "" && + git config --add versionsort.suffix -gamma && + git config --add versionsort.suffix -delta && + git tag foo1.10-alpha && + git tag foo1.10-beta && + git tag foo1.10-gamma && + git tag foo1.10-delta && + git tag foo1.10-unlisted-suffix && + git tag -l --sort=version:refname "foo1.10*" >actual && + cat >expect <<-\EOF && + foo1.10-alpha + foo1.10-beta + foo1.10 + foo1.10-unlisted-suffix + foo1.10-gamma + foo1.10-delta + EOF + test_cmp expect actual +' + +test_expect_success 'versionsort.suffix overrides versionsort.prereleaseSuffix' ' + test_config versionsort.suffix -before && + test_config versionsort.prereleaseSuffix -after && + git tag -l --sort=version:refname "foo1.7*" >actual && + cat >expect <<-\EOF && + foo1.7-before1 + foo1.7 + foo1.7-after1 + EOF + test_cmp expect actual +' + +test_expect_success 'version sort with very long prerelease suffix' ' + test_config versionsort.prereleaseSuffix -very-looooooooooooooooooooooooong-prerelease-suffix && + git tag -l --sort=version:refname +' + run_with_limited_stack () { (ulimit -s 128 && "$@") } @@@ -1690,11 -1585,13 +1706,11 @@@ EOF test_expect_success '--format should list tags as per format given' ' cat >expect <<-\EOF && - refname : refs/tags/foo1.10 - refname : refs/tags/foo1.3 - refname : refs/tags/foo1.6 - refname : refs/tags/foo1.6-rc1 - refname : refs/tags/foo1.6-rc2 + refname : refs/tags/v1.0 + refname : refs/tags/v1.0.1 + refname : refs/tags/v1.1.3 EOF - git tag -l --format="refname : %(refname)" "foo*" >actual && + git tag -l --format="refname : %(refname)" "v1*" >actual && test_cmp expect actual '