tag: implicitly supply --list given another list-like option

Change the "tag" command to implicitly turn on its --list mode when
provided with a list-like option such as --contains, --points-at etc.

This is for consistency with how "branch" works. When "branch" is
given a list-like option, such as --contains, it implicitly provides
--list. Before this change "tag" would error out on those sorts of
invocations. I.e. while both of these worked for "branch":

    git branch --contains v2.8.0 <pattern>
    git branch --list --contains v2.8.0 <pattern>

Only the latter form worked for "tag":

    git tag --contains v2.8.0 '*rc*'
    git tag --list --contains v2.8.0 '*rc*'

Now "tag", like "branch", will implicitly supply --list when a
list-like option is provided, and no other conflicting non-list
options (such as -d) are present on the command-line.

Spelunking through the history via:

    git log --reverse -p -G'only allowed with' -- '*builtin*tag*c'

Reveals that there was no good reason for not allowing this in the
first place. The --contains option added in 32c35cfb1e ("git-tag: Add
--contains option", 2009-01-26) made this an error. All the other
subsequent list-like options that were added copied its pattern of
making this usage an error.

The only tests that break as a result of this change are tests that
were explicitly checking that this "branch-like" usage wasn't
permitted. Change those failing tests to check that this invocation
mode is permitted, add extra tests for the list-like options we
weren't testing, and tests to ensure that e.g. we don't toggle the
list mode in the presence of other conflicting non-list options.

With this change errors messages such as "--contains option is only
allowed with -l" don't make sense anymore, since options like
--contain turn on -l. Instead we error out when list-like options such
as --contain are used in conjunction with conflicting options such as
-d or -v.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Ævar Arnfjörð Bjarmason 2017-03-24 18:40:55 +00:00 коммит произвёл Junio C Hamano
Родитель c485b24c42
Коммит 6a338149f6
3 изменённых файлов: 73 добавлений и 17 удалений

Просмотреть файл

@ -82,10 +82,11 @@ OPTIONS
-n<num>:: -n<num>::
<num> specifies how many lines from the annotation, if any, <num> specifies how many lines from the annotation, if any,
are printed when using -l. are printed when using -l. Implies `--list`.
The default is not to print any annotation lines. +
If no number is given to `-n`, only the first line is printed. The default is not to print any annotation lines.
If the tag is not annotated, the commit message is displayed instead. If no number is given to `-n`, only the first line is printed.
If the tag is not annotated, the commit message is displayed instead.
-l:: -l::
--list:: --list::
@ -95,6 +96,10 @@ OPTIONS
Running "git tag" without arguments also lists all tags. The pattern Running "git tag" without arguments also lists all tags. The pattern
is a shell wildcard (i.e., matched using fnmatch(3)). Multiple is a shell wildcard (i.e., matched using fnmatch(3)). Multiple
patterns may be given; if any of them matches, the tag is shown. patterns may be given; if any of them matches, the tag is shown.
+
This option is implicitly supplied if any other list-like option such
as `--contains` is provided. See the documentation for each of those
options for details.
--sort=<key>:: --sort=<key>::
Sort based on the key given. Prefix `-` to sort in Sort based on the key given. Prefix `-` to sort in
@ -123,7 +128,7 @@ This option is only applicable when listing tags without annotation lines.
--contains [<commit>]:: --contains [<commit>]::
Only list tags which contain the specified commit (HEAD if not Only list tags which contain the specified commit (HEAD if not
specified). specified). Implies `--list`.
--merged [<commit>]:: --merged [<commit>]::
Only list tags whose commits are reachable from the specified Only list tags whose commits are reachable from the specified
@ -134,7 +139,7 @@ This option is only applicable when listing tags without annotation lines.
commit (`HEAD` if not specified), incompatible with `--merged`. commit (`HEAD` if not specified), incompatible with `--merged`.
--points-at <object>:: --points-at <object>::
Only list tags of the given object. Only list tags of the given object. Implies `--list`.
-m <msg>:: -m <msg>::
--message=<msg>:: --message=<msg>::

Просмотреть файл

@ -454,8 +454,14 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
} }
create_tag_object = (opt.sign || annotate || msg.given || msgfile); create_tag_object = (opt.sign || annotate || msg.given || msgfile);
if (argc == 0 && !cmdmode) if (!cmdmode) {
cmdmode = 'l'; if (argc == 0)
cmdmode = 'l';
else if (filter.with_commit ||
filter.points_at.nr || filter.merge_commit ||
filter.lines != -1)
cmdmode = 'l';
}
if ((create_tag_object || force) && (cmdmode != 0)) if ((create_tag_object || force) && (cmdmode != 0))
usage_with_options(git_tag_usage, options); usage_with_options(git_tag_usage, options);
@ -485,13 +491,13 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
return ret; return ret;
} }
if (filter.lines != -1) if (filter.lines != -1)
die(_("-n option is only allowed with -l.")); die(_("-n option is only allowed in list mode"));
if (filter.with_commit) if (filter.with_commit)
die(_("--contains option is only allowed with -l.")); die(_("--contains option is only allowed in list mode"));
if (filter.points_at.nr) if (filter.points_at.nr)
die(_("--points-at option is only allowed with -l.")); die(_("--points-at option is only allowed in list mode"));
if (filter.merge_commit) if (filter.merge_commit)
die(_("--merged and --no-merged option are only allowed with -l")); die(_("--merged and --no-merged options are only allowed in list mode"));
if (cmdmode == 'd') if (cmdmode == 'd')
return for_each_tag_name(argv, delete_tag, NULL); return for_each_tag_name(argv, delete_tag, NULL);
if (cmdmode == 'v') { if (cmdmode == 'v') {

Просмотреть файл

@ -643,6 +643,11 @@ test_expect_success \
git tag -n0 -l tag-one-line >actual && git tag -n0 -l tag-one-line >actual &&
test_cmp expect actual && test_cmp expect actual &&
git tag -n0 | grep "^tag-one-line" >actual &&
test_cmp expect actual &&
git tag -n0 tag-one-line >actual &&
test_cmp expect actual &&
echo "tag-one-line A msg" >expect && echo "tag-one-line A msg" >expect &&
git tag -n1 -l | grep "^tag-one-line" >actual && git tag -n1 -l | grep "^tag-one-line" >actual &&
test_cmp expect actual && test_cmp expect actual &&
@ -656,6 +661,17 @@ test_expect_success \
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'The -n 100 invocation means -n --list 100, not -n100' '
>expect &&
git tag -n 100 >actual &&
test_cmp expect actual &&
git tag -m "A msg" 100 &&
echo "100 A msg" >expect &&
git tag -n 100 >actual &&
test_cmp expect actual
'
test_expect_success \ test_expect_success \
'listing the zero-lines message of a non-signed tag should succeed' ' 'listing the zero-lines message of a non-signed tag should succeed' '
git tag -m "" tag-zero-lines && git tag -m "" tag-zero-lines &&
@ -1476,6 +1492,11 @@ test_expect_success 'checking that initial commit is in all tags' "
test_cmp expected actual test_cmp expected actual
" "
test_expect_success 'checking that --contains can be used in non-list mode' '
git tag --contains $hash1 v* >actual &&
test_cmp expected actual
'
# mixing modes and options: # mixing modes and options:
test_expect_success 'mixing incompatibles modes and options is forbidden' ' test_expect_success 'mixing incompatibles modes and options is forbidden' '
@ -1496,7 +1517,6 @@ test_expect_success 'mixing incompatibles modes and options is forbidden' '
test_must_fail git tag -l -v && test_must_fail git tag -l -v &&
test_must_fail git tag -l -d && test_must_fail git tag -l -d &&
test_must_fail git tag -l -v -d && test_must_fail git tag -l -v -d &&
test_must_fail git tag -n 100 &&
test_must_fail git tag -n 100 -v && test_must_fail git tag -n 100 -v &&
test_must_fail git tag -l -m msg && test_must_fail git tag -l -m msg &&
test_must_fail git tag -l -F some file && test_must_fail git tag -l -F some file &&
@ -1505,10 +1525,25 @@ test_expect_success 'mixing incompatibles modes and options is forbidden' '
test_must_fail git tag --contains tag-blob test_must_fail git tag --contains tag-blob
' '
for option in --contains --merged --no-merged --points-at
do
test_expect_success "mixing incompatible modes with $option is forbidden" "
test_must_fail git tag -d $option HEAD &&
test_must_fail git tag -d $option HEAD some-tag &&
test_must_fail git tag -v $option HEAD
"
test_expect_success "Doing 'git tag --list-like $option <commit> <pattern> is permitted" "
git tag -n $option HEAD HEAD &&
git tag $option HEAD HEAD
"
done
# check points-at # check points-at
test_expect_success '--points-at cannot be used in non-list mode' ' test_expect_success '--points-at can be used in non-list mode' '
test_must_fail git tag --points-at=v4.0 foo echo v4.0 >expect &&
git tag --points-at=v4.0 "v*" >actual &&
test_cmp expect actual
' '
test_expect_success '--points-at finds lightweight tags' ' test_expect_success '--points-at finds lightweight tags' '
@ -1785,8 +1820,13 @@ test_expect_success 'setup --merged test tags' '
git tag mergetest-3 HEAD git tag mergetest-3 HEAD
' '
test_expect_success '--merged cannot be used in non-list mode' ' test_expect_success '--merged can be used in non-list mode' '
test_must_fail git tag --merged=mergetest-2 foo cat >expect <<-\EOF &&
mergetest-1
mergetest-2
EOF
git tag --merged=mergetest-2 "mergetest*" >actual &&
test_cmp expect actual
' '
test_expect_success '--merged is incompatible with --no-merged' ' test_expect_success '--merged is incompatible with --no-merged' '
@ -1810,6 +1850,11 @@ test_expect_success '--no-merged show unmerged tags' '
test_cmp expect actual test_cmp expect actual
' '
test_expect_success '--no-merged can be used in non-list mode' '
git tag --no-merged=mergetest-2 mergetest-* >actual &&
test_cmp expect actual
'
test_expect_success 'ambiguous branch/tags not marked' ' test_expect_success 'ambiguous branch/tags not marked' '
git tag ambiguous && git tag ambiguous &&
git branch ambiguous && git branch ambiguous &&