Merge branch 'jk/tag-sort'

* jk/tag-sort:
  tag: support configuring --sort via .gitconfig
  tag: fix --sort tests to use cat<<-\EOF format
This commit is contained in:
Junio C Hamano 2014-07-23 11:35:45 -07:00
commit c3d2bc720c
4 changed files with 115 additions and 39 deletions

View file

@ -2354,6 +2354,11 @@ submodule.<name>.ignore::
"--ignore-submodules" option. The 'git submodule' commands are not "--ignore-submodules" option. The 'git submodule' commands are not
affected by this setting. affected by this setting.
tag.sort::
This variable controls the sort ordering of tags when displayed by
linkgit:git-tag[1]. Without the "--sort=<value>" option provided, the
value of this variable will be used as the default.
tar.umask:: tar.umask::
This variable can be used to restrict the permission bits of This variable can be used to restrict the permission bits of
tar archive entries. The default is 0002, which turns off the tar archive entries. The default is 0002, which turns off the

View file

@ -99,7 +99,9 @@ OPTIONS
Sort in a specific order. Supported type is "refname" Sort in a specific order. Supported type is "refname"
(lexicographic order), "version:refname" or "v:refname" (tag (lexicographic order), "version:refname" or "v:refname" (tag
names are treated as versions). Prepend "-" to reverse sort names are treated as versions). Prepend "-" to reverse sort
order. order. When this option is not given, the sort order defaults to the
value configured for the 'tag.sort' variable if it exists, or
lexicographic order otherwise. See linkgit:git-config[1].
--column[=<options>]:: --column[=<options>]::
--no-column:: --no-column::
@ -317,6 +319,7 @@ include::date-formats.txt[]
SEE ALSO SEE ALSO
-------- --------
linkgit:git-check-ref-format[1]. linkgit:git-check-ref-format[1].
linkgit:git-config[1].
GIT GIT
--- ---

View file

@ -32,6 +32,8 @@ static const char * const git_tag_usage[] = {
#define SORT_MASK 0x7fff #define SORT_MASK 0x7fff
#define REVERSE_SORT 0x8000 #define REVERSE_SORT 0x8000
static int tag_sort;
struct tag_filter { struct tag_filter {
const char **patterns; const char **patterns;
int lines; int lines;
@ -346,9 +348,51 @@ static const char tag_template_nocleanup[] =
"Lines starting with '%c' will be kept; you may remove them" "Lines starting with '%c' will be kept; you may remove them"
" yourself if you want to.\n"); " yourself if you want to.\n");
/*
* Parse a sort string, and return 0 if parsed successfully. Will return
* non-zero when the sort string does not parse into a known type. If var is
* given, the error message becomes a warning and includes information about
* the configuration value.
*/
static int parse_sort_string(const char *var, const char *arg, int *sort)
{
int type = 0, flags = 0;
if (skip_prefix(arg, "-", &arg))
flags |= REVERSE_SORT;
if (skip_prefix(arg, "version:", &arg) || skip_prefix(arg, "v:", &arg))
type = VERCMP_SORT;
else
type = STRCMP_SORT;
if (strcmp(arg, "refname")) {
if (!var)
return error(_("unsupported sort specification '%s'"), arg);
else {
warning(_("unsupported sort specification '%s' in variable '%s'"),
var, arg);
return -1;
}
}
*sort = (type | flags);
return 0;
}
static int git_tag_config(const char *var, const char *value, void *cb) static int git_tag_config(const char *var, const char *value, void *cb)
{ {
int status = git_gpg_config(var, value, cb); int status;
if (!strcmp(var, "tag.sort")) {
if (!value)
return config_error_nonbool(var);
parse_sort_string(var, value, &tag_sort);
return 0;
}
status = git_gpg_config(var, value, cb);
if (status) if (status)
return status; return status;
if (starts_with(var, "column.")) if (starts_with(var, "column."))
@ -522,20 +566,8 @@ static int parse_opt_points_at(const struct option *opt __attribute__((unused)),
static int parse_opt_sort(const struct option *opt, const char *arg, int unset) static int parse_opt_sort(const struct option *opt, const char *arg, int unset)
{ {
int *sort = opt->value; int *sort = opt->value;
int flags = 0;
if (skip_prefix(arg, "-", &arg)) return parse_sort_string(NULL, arg, sort);
flags |= REVERSE_SORT;
if (skip_prefix(arg, "version:", &arg) || skip_prefix(arg, "v:", &arg))
*sort = VERCMP_SORT;
else
*sort = STRCMP_SORT;
if (strcmp(arg, "refname"))
die(_("unsupported sort specification %s"), arg);
*sort |= flags;
return 0;
} }
int cmd_tag(int argc, const char **argv, const char *prefix) 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)
struct create_tag_options opt; struct create_tag_options opt;
char *cleanup_arg = NULL; char *cleanup_arg = NULL;
int annotate = 0, force = 0, lines = -1; int annotate = 0, force = 0, lines = -1;
int cmdmode = 0, sort = 0; int cmdmode = 0;
const char *msgfile = NULL, *keyid = NULL; const char *msgfile = NULL, *keyid = NULL;
struct msg_arg msg = { 0, STRBUF_INIT }; struct msg_arg msg = { 0, STRBUF_INIT };
struct commit_list *with_commit = NULL; struct commit_list *with_commit = NULL;
@ -574,7 +606,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
OPT__FORCE(&force, N_("replace the tag if exists")), OPT__FORCE(&force, N_("replace the tag if exists")),
OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")), OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")),
{ {
OPTION_CALLBACK, 0, "sort", &sort, N_("type"), N_("sort tags"), OPTION_CALLBACK, 0, "sort", &tag_sort, N_("type"), N_("sort tags"),
PARSE_OPT_NONEG, parse_opt_sort PARSE_OPT_NONEG, parse_opt_sort
}, },
@ -630,9 +662,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
copts.padding = 2; copts.padding = 2;
run_column_filter(colopts, &copts); run_column_filter(colopts, &copts);
} }
if (lines != -1 && sort) if (lines != -1 && tag_sort)
die(_("--sort and -n are incompatible")); die(_("--sort and -n are incompatible"));
ret = list_tags(argv, lines == -1 ? 0 : lines, with_commit, sort); ret = list_tags(argv, lines == -1 ? 0 : lines, with_commit, tag_sort);
if (column_active(colopts)) if (column_active(colopts))
stop_column_filter(); stop_column_filter();
return ret; return ret;

View file

@ -1385,41 +1385,77 @@ test_expect_success 'lexical sort' '
git tag foo1.6 && git tag foo1.6 &&
git tag foo1.10 && git tag foo1.10 &&
git tag -l --sort=refname "foo*" >actual && git tag -l --sort=refname "foo*" >actual &&
cat >expect <<EOF && cat >expect <<-\EOF &&
foo1.10 foo1.10
foo1.3 foo1.3
foo1.6 foo1.6
EOF EOF
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'version sort' ' test_expect_success 'version sort' '
git tag -l --sort=version:refname "foo*" >actual && git tag -l --sort=version:refname "foo*" >actual &&
cat >expect <<EOF && cat >expect <<-\EOF &&
foo1.3 foo1.3
foo1.6 foo1.6
foo1.10 foo1.10
EOF EOF
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'reverse version sort' ' test_expect_success 'reverse version sort' '
git tag -l --sort=-version:refname "foo*" >actual && git tag -l --sort=-version:refname "foo*" >actual &&
cat >expect <<EOF && cat >expect <<-\EOF &&
foo1.10 foo1.10
foo1.6 foo1.6
foo1.3 foo1.3
EOF EOF
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'reverse lexical sort' ' test_expect_success 'reverse lexical sort' '
git tag -l --sort=-refname "foo*" >actual && git tag -l --sort=-refname "foo*" >actual &&
cat >expect <<EOF && cat >expect <<-\EOF &&
foo1.6 foo1.6
foo1.3 foo1.3
foo1.10 foo1.10
EOF EOF
test_cmp expect actual
'
test_expect_success 'configured lexical sort' '
git config tag.sort "v:refname" &&
git tag -l "foo*" >actual &&
cat >expect <<-\EOF &&
foo1.3
foo1.6
foo1.10
EOF
test_cmp expect actual
'
test_expect_success 'option override configured sort' '
git tag -l --sort=-refname "foo*" >actual &&
cat >expect <<-\EOF &&
foo1.6
foo1.3
foo1.10
EOF
test_cmp expect actual
'
test_expect_success 'invalid sort parameter on command line' '
test_must_fail git tag -l --sort=notvalid "foo*" >actual
'
test_expect_success 'invalid sort parameter in configuratoin' '
git config tag.sort "v:notvalid" &&
git tag -l "foo*" >actual &&
cat >expect <<-\EOF &&
foo1.10
foo1.3
foo1.6
EOF
test_cmp expect actual test_cmp expect actual
' '