git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 12/16] tag: implicitly supply --list given another list-like option

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Mar 23, 2017, 13:05 UTC
Message-ID
<20170323130529.11361-13-avarab@gmail.com>
In-Reply-To
<20170323130529.11361-1-avarab@gmail.com>

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>
---
 Documentation/git-tag.txt | 17 +++++++++------
 builtin/tag.c             | 18 ++++++++++------
 t/t7004-tag.sh            | 55 ++++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 73 insertions(+), 17 deletions(-)
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 2640c6955c..491dba065c 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -82,10 +82,11 @@ OPTIONS
 
 -n<num>::
 	<num> specifies how many lines from the annotation, if any,
-	are printed when using -l.
-	The default is not to print any annotation lines.
-	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.
+	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.
+If the tag is not annotated, the commit message is displayed instead.
 
 -l::
 --list::
@@ -96,6 +97,10 @@ OPTIONS
 Running "git tag" without arguments also lists all tags. The pattern
 is a shell wildcard (i.e., matched using fnmatch(3)). Multiple
 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 based on the key given.  Prefix `-` to sort in
@@ -124,7 +129,7 @@ This option is only applicable when listing tags without annotation lines.
 
 --contains [<commit>]::
 	Only list tags which contain the specified commit (HEAD if not
-	specified).
+	specified). Implies `--list`.
 
 --merged [<commit>]::
 	Only list tags whose commits are reachable from the specified
@@ -135,7 +140,7 @@ This option is only applicable when listing tags without annotation lines.
 	commit (`HEAD` if not specified), incompatible with `--merged`.
 
 --points-at <object>::
-	Only list tags of the given object.
+	Only list tags of the given object. Implies `--list`.
 
 -m <msg>::
 --message=<msg>::
diff --git a/builtin/tag.c b/builtin/tag.c
index ad29be6923..3c686961db 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -454,8 +454,14 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	}
 	create_tag_object = (opt.sign || annotate || msg.given || msgfile);
 
-	if (argc == 0 && !cmdmode)
-		cmdmode = 'l';
+	if (!cmdmode) {
+		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))
 		usage_with_options(git_tag_usage, options);
@@ -485,13 +491,13 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 		return ret;
 	}
 	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)
-		die(_("--contains option is only allowed with -l."));
+		die(_("--contains option is only allowed in list mode"));
 	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)
-		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')
 		return for_each_tag_name(argv, delete_tag, NULL);
 	if (cmdmode == 'v') {
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 75681b2cad..5823de16aa 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -643,6 +643,11 @@ test_expect_success \
 	git tag -n0 -l tag-one-line >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 &&
 	git tag -n1 -l | grep "^tag-one-line" >actual &&
 	test_cmp expect actual &&
@@ -656,6 +661,17 @@ test_expect_success \
 	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 \
 	'listing the zero-lines message of a non-signed tag should succeed' '
 	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_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:
 
 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 -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 -l -m msg &&
 	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
 '
 
+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
 
-test_expect_success '--points-at cannot be used in non-list mode' '
-	test_must_fail git tag --points-at=v4.0 foo
+test_expect_success '--points-at can be used in non-list mode' '
+	echo v4.0 >expect &&
+	git tag --points-at=v4.0 "v*" >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success '--points-at finds lightweight tags' '
@@ -1785,8 +1820,13 @@ test_expect_success 'setup --merged test tags' '
 	git tag mergetest-3 HEAD
 '
 
-test_expect_success '--merged cannot be used in non-list mode' '
-	test_must_fail git tag --merged=mergetest-2 foo
+test_expect_success '--merged can be used in non-list mode' '
+	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' '
@@ -1810,6 +1850,11 @@ test_expect_success '--no-merged show unmerged tags' '
 	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' '
 	git tag ambiguous &&
 	git branch ambiguous &&
-- 
2.11.0
Previous: Ævar Arnfjörð BjarmasonNext: Junio C Hamano
Message 13 of 25 in “Various changes to the "tag" command & related”
  1. 00/16 Various changes to the "tag" command & relatedÆvar Arnfjörð Bjarmason, Mar 23, 2017
  2. 01/16 tag doc: move the description of --[no-]merged earlierÆvar Arnfjörð Bjarmason, Mar 23, 2017
  3. 02/16 tag doc: split up the --[no-]merged documentationÆvar Arnfjörð Bjarmason, Mar 23, 2017
  4. 03/16 tag doc: reword --[no-]merged to talk about commits, not tipsÆvar Arnfjörð Bjarmason, Mar 23, 2017
  5. 04/16 ref-filter: make combining --merged & --no-merged an errorÆvar Arnfjörð Bjarmason, Mar 23, 2017
  6. 05/16 ref-filter: add test for --contains on a non-commitÆvar Arnfjörð Bjarmason, Mar 23, 2017
  7. 06/16 tag: remove a TODO item from the test suiteÆvar Arnfjörð Bjarmason, Mar 23, 2017
  8. 08/16 for-each-ref: partly change <object> to <commit> in helpÆvar Arnfjörð Bjarmason, Mar 23, 2017
  9. 07/16 tag tests: fix a typo in a test descriptionÆvar Arnfjörð Bjarmason, Mar 23, 2017
  10. 11/16 tag: change misleading --list <pattern> documentationÆvar Arnfjörð Bjarmason, Mar 23, 2017
  11. Junio C HamanoMar 23, 2017
  12. 13/16 tag: change --point-at to default to HEADÆvar Arnfjörð Bjarmason, Mar 23, 2017
  13. 12/16 tag: implicitly supply --list given another list-like optionÆvar Arnfjörð Bjarmason, Mar 23, 2017
  14. Junio C HamanoMar 23, 2017
  15. Ævar Arnfjörð BjarmasonMar 23, 2017
  16. Junio C HamanoMar 23, 2017
  17. 14/16 ref-filter: add --no-contains option to tag/branch/for-each-refÆvar Arnfjörð Bjarmason, Mar 23, 2017
  18. 15/16 ref-filter: reflow recently changed branch/tag/for-each-ref docsÆvar Arnfjörð Bjarmason, Mar 23, 2017
  19. 10/16 parse-options: add OPT_NONEG to the "contains" optionÆvar Arnfjörð Bjarmason, Mar 23, 2017
  20. 16/16 tag: add tests for --with and --withoutÆvar Arnfjörð Bjarmason, Mar 23, 2017
  21. 09/16 tag: add more incompatibles mode testsÆvar Arnfjörð Bjarmason, Mar 23, 2017
  22. Junio C HamanoMar 23, 2017
  23. Ævar Arnfjörð BjarmasonMar 23, 2017
  24. Junio C HamanoMar 23, 2017
  25. Ævar Arnfjörð BjarmasonMar 23, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.