tag: support configuring --sort via .gitconfig

Add support for configuring default sort ordering for git tags. Command line option will override this configured value, using the exact same syntax. Cc: Jeff King <peff@peff.net> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jacob Keller committed Jul 16, 2014 at 14:48 UTC b150794dafb0a7a1c5caba6fdf7d517a1a15cb59
4 files changed +95 -19
Documentation/config.txt
+5
@@ -2351,6 +2351,11 @@ submodule.<name>.ignore::
2351 "--ignore-submodules" option. The 'git submodule' commands are not
2352 affected by this setting.
2353
2354 +tag.sort::
2355 + This variable controls the sort ordering of tags when displayed by
2356 + linkgit:git-tag[1]. Without the "--sort=<value>" option provided, the
2357 + value of this variable will be used as the default.
2358 +
2359 tar.umask::
2360 This variable can be used to restrict the permission bits of
2361 tar archive entries. The default is 0002, which turns off the
Documentation/git-tag.txt
+4 -1
@@ -99,7 +99,9 @@ OPTIONS
99 Sort in a specific order. Supported type is "refname"
100 (lexicographic order), "version:refname" or "v:refname" (tag
101 names are treated as versions). Prepend "-" to reverse sort
102 - order.
102 + order. When this option is not given, the sort order defaults to the
103 + value configured for the 'tag.sort' variable if it exists, or
104 + lexicographic order otherwise. See linkgit:git-config[1].
105
106 --column[=<options>]::
107 --no-column::
@@ -317,6 +319,7 @@ include::date-formats.txt[]
319 SEE ALSO
320 --------
321 linkgit:git-check-ref-format[1].
322 +linkgit:git-config[1].
323
324 GIT
325 ---
builtin/tag.c
+50 -18
@@ -32,6 +32,8 @@ static const char * const git_tag_usage[] = {
32 #define SORT_MASK 0x7fff
33 #define REVERSE_SORT 0x8000
34
35 +static int tag_sort;
36 +
37 struct tag_filter {
38 const char **patterns;
39 int lines;
@@ -346,9 +348,51 @@ static const char tag_template_nocleanup[] =
348 "Lines starting with '%c' will be kept; you may remove them"
349 " yourself if you want to.\n");
350
351 +/*
352 + * Parse a sort string, and return 0 if parsed successfully. Will return
353 + * non-zero when the sort string does not parse into a known type. If var is
354 + * given, the error message becomes a warning and includes information about
355 + * the configuration value.
356 + */
357 +static int parse_sort_string(const char *var, const char *arg, int *sort)
358 +{
359 + int type = 0, flags = 0;
360 +
361 + if (skip_prefix(arg, "-", &arg))
362 + flags |= REVERSE_SORT;
363 +
364 + if (skip_prefix(arg, "version:", &arg) || skip_prefix(arg, "v:", &arg))
365 + type = VERCMP_SORT;
366 + else
367 + type = STRCMP_SORT;
368 +
369 + if (strcmp(arg, "refname")) {
370 + if (!var)
371 + return error(_("unsupported sort specification '%s'"), arg);
372 + else {
373 + warning(_("unsupported sort specification '%s' in variable '%s'"),
374 + var, arg);
375 + return -1;
376 + }
377 + }
378 +
379 + *sort = (type | flags);
380 +
381 + return 0;
382 +}
383 +
384 static int git_tag_config(const char *var, const char *value, void *cb)
385 {
351 - int status = git_gpg_config(var, value, cb);
386 + int status;
387 +
388 + if (!strcmp(var, "tag.sort")) {
389 + if (!value)
390 + return config_error_nonbool(var);
391 + parse_sort_string(var, value, &tag_sort);
392 + return 0;
393 + }
394 +
395 + status = git_gpg_config(var, value, cb);
396 if (status)
397 return status;
398 if (starts_with(var, "column."))
@@ -522,20 +566,8 @@ static int parse_opt_points_at(const struct option *opt __attribute__((unused)),
566 static int parse_opt_sort(const struct option *opt, const char *arg, int unset)
567 {
568 int *sort = opt->value;
525 - int flags = 0;
569
527 - if (skip_prefix(arg, "-", &arg))
528 - flags |= REVERSE_SORT;
529 -
530 - if (skip_prefix(arg, "version:", &arg) || skip_prefix(arg, "v:", &arg))
531 - *sort = VERCMP_SORT;
532 - else
533 - *sort = STRCMP_SORT;
534 -
535 - if (strcmp(arg, "refname"))
536 - die(_("unsupported sort specification %s"), arg);
537 - *sort |= flags;
538 - return 0;
570 + return parse_sort_string(NULL, arg, sort);
571 }
572
573 int cmd_tag(int argc, const char **argv, const char *prefix)
@@ -548,7 +580,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
580 struct create_tag_options opt;
581 char *cleanup_arg = NULL;
582 int annotate = 0, force = 0, lines = -1;
551 - int cmdmode = 0, sort = 0;
583 + int cmdmode = 0;
584 const char *msgfile = NULL, *keyid = NULL;
585 struct msg_arg msg = { 0, STRBUF_INIT };
586 struct commit_list *with_commit = NULL;
@@ -574,7 +606,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
606 OPT__FORCE(&force, N_("replace the tag if exists")),
607 OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")),
608 {
577 - OPTION_CALLBACK, 0, "sort", &sort, N_("type"), N_("sort tags"),
609 + OPTION_CALLBACK, 0, "sort", &tag_sort, N_("type"), N_("sort tags"),
610 PARSE_OPT_NONEG, parse_opt_sort
611 },
612
@@ -630,9 +662,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
662 copts.padding = 2;
663 run_column_filter(colopts, &copts);
664 }
633 - if (lines != -1 && sort)
665 + if (lines != -1 && tag_sort)
666 die(_("--sort and -n are incompatible"));
635 - ret = list_tags(argv, lines == -1 ? 0 : lines, with_commit, sort);
667 + ret = list_tags(argv, lines == -1 ? 0 : lines, with_commit, tag_sort);
668 if (column_active(colopts))
669 stop_column_filter();
670 return ret;
t/t7004-tag.sh
+36
@@ -1423,6 +1423,42 @@ test_expect_success 'reverse lexical sort' '
1423 test_cmp expect actual
1424 '
1425
1426 +test_expect_success 'configured lexical sort' '
1427 + git config tag.sort "v:refname" &&
1428 + git tag -l "foo*" >actual &&
1429 + cat >expect <<-\EOF &&
1430 + foo1.3
1431 + foo1.6
1432 + foo1.10
1433 + EOF
1434 + test_cmp expect actual
1435 +'
1436 +
1437 +test_expect_success 'option override configured sort' '
1438 + git tag -l --sort=-refname "foo*" >actual &&
1439 + cat >expect <<-\EOF &&
1440 + foo1.6
1441 + foo1.3
1442 + foo1.10
1443 + EOF
1444 + test_cmp expect actual
1445 +'
1446 +
1447 +test_expect_success 'invalid sort parameter on command line' '
1448 + test_must_fail git tag -l --sort=notvalid "foo*" >actual
1449 +'
1450 +
1451 +test_expect_success 'invalid sort parameter in configuratoin' '
1452 + git config tag.sort "v:notvalid" &&
1453 + git tag -l "foo*" >actual &&
1454 + cat >expect <<-\EOF &&
1455 + foo1.10
1456 + foo1.3
1457 + foo1.6
1458 + EOF
1459 + test_cmp expect actual
1460 +'
1461 +
1462 run_with_limited_stack () {
1463 (ulimit -s 64 && "$@")
1464 }