Various changes to the "tag" command & related
v2 cover Various changes to the "tag" command & related
This series is now 2x the size of v1. The reason is that the discussion for v1 brought up lots of related side-points that I fixed while I was at it. Most if this *could* be split off, but since a lot of it's modifying the same bits of code doing that would result in merge conflict galore, so I think it's easier to bundle it up.
Comments on individual patches below:
Ævar Arnfjörð Bjarmason (16):
tag doc: move the description of --[no-]merged earlier tag doc: split up the --[no-]merged documentation tag doc: reword --[no-]merged to talk about commits, not tips
NEW: Document that --merged & --no-merged operate on commits, not objects. Split up the docs to document each option indepenently for ease of subsequent changes.
ref-filter: make combining --merged & --no-merged an error
NEW: Currently "--merged HEAD --no-merged HEAD" is just silently equivalent to "--no-merged HEAD". Make the former an "incompatible options" error.
ref-filter: add test for --contains on a non-commit
NEW: Jeff suggested we should test for this. Make it so.
tag: remove a TODO item from the test suite
No changes.
tag tests: fix a typo in a test description
NEW: Fix a tag test typo.
for-each-ref: partly change <object> to <commit> in help
NEW: Clarify the for-each-ref --help output.
tag: add more incompatibles mode tests
CHANGED: I dropped the "tag: Refactor the options handling code to be less bizarro" patch, but these are the tests that came along with it.
tag: change misleading --list <pattern> documentation
No changes.
tag: implicitly supply --list given another list-like option
Changed: Typo fixes in commit message, argc == 0 && !cmdmode logic changes, code reflow, better error messages etc.
tag: change --point-at to default to HEAD
Changed: Fixed up an ">expect" at the start of the test.
ref-filter: add --no-contains option to tag/branch/for-each-ref
Changed: Typos/grammar in commit message, get rid of needless "else", tests for tree/tag blobs.
ref-filter: reflow recently changed branch/tag/for-each-ref docs
NEW: Split off reflowing of documentation paragraphs from the above for ease of reading.
tag: implicitly supply --list given the -n option
Re-arranged: I still want this included, but the consensus on the list wasn't as strong, so it's moved later in the series so it can be dropped without conflicts.
tag: add tests for --with and --without
No changes.
Documentation/git-branch.txt | 33 +++-- Documentation/git-for-each-ref.txt | 12 +- Documentation/git-tag.txt | 60 ++++++--- builtin/branch.c | 5 +- builtin/for-each-ref.c | 5 +- builtin/tag.c | 27 ++-- contrib/completion/git-completion.bash | 4 +- parse-options.h | 4 +- ref-filter.c | 30 ++++- ref-filter.h | 1 + t/t3200-branch.sh | 4 + t/t3201-branch-contains.sh | 61 ++++++++- t/t6302-for-each-ref-filter.sh | 20 +++ t/t7004-tag.sh | 237 +++++++++++++++++++++++++++++++-- 14 files changed, 432 insertions(+), 71 deletions(-)
Signature · 1 line
2.11.0
PATCH v2 1/16 tag doc: move the description of --[no-]merged earlier
Move the documentation for the --merged & --no-merged options earlier in the documentation, to sit along the other switches, and right next to the similar --contains and --points-at switches.
It makes more sense to group the options together, not have some options after the like of <tagname>, <object>, <format> etc.
This was originally put there when the --merged & --no-merged options were introduced in 5242860f54 ("tag.c: implement '--merged' and '--no-merged' options", 2015-09-10). It's not apparent from that commit that the documentation is being placed apart from other options, rather than along with them, so this was likely missed in the initial review.
--- Documentation/git-tag.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
Documentation/git-tag.txt +5 -5
@@ -124,6 +124,11 @@ This option is only applicable when listing tags without annotation lines. Only list tags which contain the specified commit (HEAD if not specified). +--[no-]merged [<commit>]:: + Only list tags whose tips are reachable, or not reachable + if `--no-merged` is used, from the specified commit (`HEAD` + if not specified). + --points-at <object>:: Only list tags of the given object.
@@ -173,11 +178,6 @@ This option is only applicable when listing tags without annotation lines. that of linkgit:git-for-each-ref[1]. When unspecified, defaults to `%(refname:strip=2)`. ---[no-]merged [<commit>]:: - Only list tags whose tips are reachable, or not reachable - if `--no-merged` is used, from the specified commit (`HEAD` - if not specified). - CONFIGURATION ------------- By default, 'git tag' in sign-with-default mode (-s) will use your
Signature · 1 line
2.11.0
Re: [PATCH v2 01/16] tag doc: move the description of --[no-]merged earlier
Makes sense.
PATCH v2 2/16 tag doc: split up the --[no-]merged documentation
In reply to Ævar Arnfjörð BjarmasonSplit up the --[no-]merged documentation into documentation that documents each option independently. This is in line with how "branch" and "for-each-ref" are documented, and makes subsequent changes to discuss the limits & caveats of each option easier to read.
--- Documentation/git-tag.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
Documentation/git-tag.txt +7 -4
@@ -124,10 +124,13 @@ This option is only applicable when listing tags without annotation lines. Only list tags which contain the specified commit (HEAD if not specified). ---[no-]merged [<commit>]:: - Only list tags whose tips are reachable, or not reachable - if `--no-merged` is used, from the specified commit (`HEAD` - if not specified). +--merged [<commit>]:: + Only list tags whose tips are reachable from the specified commit + (`HEAD` if not specified). + +--no-merged [<commit>]:: + Only list tags whose tips are not reachable from the specified + commit (`HEAD` if not specified). --points-at <object>:: Only list tags of the given object.
Signature · 1 line
2.11.0
Re: [PATCH v2 02/16] tag doc: split up the --[no-]merged documentation
Quoted 7 lines · Ævar Arnfjörð Bjarmason
Split up the --[no-]merged documentation into documentation that documents each option independently. This is in line with how "branch" and "for-each-ref" are documented, and makes subsequent changes to discuss the limits & caveats of each option easier to read.
Signed-off-by Ævar Arnfjörð Bjarmason <[email protected]>---
This is consistent with a possible future (i.e. you do not have to be the one to realize it) where "--merged A --no-merged B" can be given together. Makes sense.
Quoted 25 lines
Documentation/git-tag.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)Documentation/git-tag.txt +7
-4@@ -124,10 +124,13 @@ This option is only applicable when listing tags without annotation lines. Only list tags which contain the specified commit (HEAD if not specified). ---[no-]merged [<commit>]:: - Only list tags whose tips are reachable, or not reachable - if `--no-merged` is used, from the specified commit (`HEAD` - if not specified). +--merged [<commit>]:: + Only list tags whose tips are reachable from the specified commit + (`HEAD` if not specified). + +--no-merged [<commit>]:: + Only list tags whose tips are not reachable from the specified + commit (`HEAD` if not specified). --points-at <object>:: Only list tags of the given object.
PATCH v2 3/16 tag doc: reword --[no-]merged to talk about commits, not tips
In reply to Ævar Arnfjörð BjarmasonChange the wording for the --merged and --no-merged options to talk about "commits" instead of "tips".
This phrasing was copied from the "branch" documentation in commit 5242860f54 ("tag.c: implement '--merged' and '--no-merged' options", 2015-09-10). Talking about the "tip" is branch nomenclature, not something usually associated with tags.
This phrasing might lead the reader to believe that these options might find tags pointing to trees or blobs, let's instead be explicit and only talk about commits.
--- Documentation/git-tag.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
Documentation/git-tag.txt +3 -3
@@ -125,11 +125,11 @@ This option is only applicable when listing tags without annotation lines. specified). --merged [<commit>]:: - Only list tags whose tips are reachable from the specified commit - (`HEAD` if not specified). + Only list tags whose commits are reachable from the specified + commit (`HEAD` if not specified). --no-merged [<commit>]:: - Only list tags whose tips are not reachable from the specified + Only list tags whose commits are not reachable from the specified commit (`HEAD` if not specified). --points-at <object>::
Signature · 1 line
2.11.0
PATCH v2 4/16 ref-filter: make combining --merged & --no-merged an error
In reply to Ævar Arnfjörð BjarmasonChange the behavior of specifying --merged & --no-merged to be an error, instead of silently picking the option that was provided last.
Subsequent changes of mine add a --no-contains option in addition to the existing --contains. Providing both of those isn't an error, and has actual meaning.
Making its cousins have different behavior in this regard would be confusing to the user, especially since we'd be silently disregarding some of their command-line input.
--- Documentation/git-branch.txt | 6 ++++-- Documentation/git-for-each-ref.txt | 6 ++++-- Documentation/git-tag.txt | 4 ++-- ref-filter.c | 11 ++++++++++- t/t3200-branch.sh | 4 ++++ t/t6302-for-each-ref-filter.sh | 4 ++++ t/t7004-tag.sh | 4 ++++ 7 files changed, 32 insertions(+), 7 deletions(-)
Documentation/git-branch.txt +4 -2
@@ -215,11 +215,13 @@ start-point is either a local or remote-tracking branch. --merged [<commit>]:: Only list branches whose tips are reachable from the - specified commit (HEAD if not specified). Implies `--list`. + specified commit (HEAD if not specified). Implies `--list`, + incompatible with `--no-merged`. --no-merged [<commit>]:: Only list branches whose tips are not reachable from the - specified commit (HEAD if not specified). Implies `--list`. + specified commit (HEAD if not specified). Implies `--list`, + incompatible with `--merged`. <branchname>:: The name of the branch to create or delete.
Documentation/git-for-each-ref.txt +4 -2
@@ -69,11 +69,13 @@ OPTIONS --merged [<object>]:: Only list refs whose tips are reachable from the - specified commit (HEAD if not specified). + specified commit (HEAD if not specified), + incompatible with `--no-merged`. --no-merged [<object>]:: Only list refs whose tips are not reachable from the - specified commit (HEAD if not specified). + specified commit (HEAD if not specified), + incompatible with `--merged`. --contains [<object>]:: Only list refs which contain the specified commit (HEAD if not
Documentation/git-tag.txt +2 -2
@@ -126,11 +126,11 @@ This option is only applicable when listing tags without annotation lines. --merged [<commit>]:: Only list tags whose commits are reachable from the specified - commit (`HEAD` if not specified). + commit (`HEAD` if not specified), incompatible with `--no-merged`. --no-merged [<commit>]:: Only list tags whose commits are not reachable from the specified - commit (`HEAD` if not specified). + commit (`HEAD` if not specified), incompatible with `--merged`. --points-at <object>:: Only list tags of the given object.
ref-filter.c +10 -1
@@ -2084,8 +2084,17 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset) {struct ref_filter *rf = opt->value;unsigned char sha1[20 ]; +int no_merged =starts_with (opt->long_name,"no" ); - rf->merge =starts_with (opt->long_name,"no" ) +if (rf->merge) { +if (no_merged) { +return opterror (opt,"is incompatible with --merged" ,0 ); + }else { +return opterror (opt,"is incompatible with --no-merged" ,0 ); + } + } + + rf->merge = no_merged ?REF_FILTER_MERGED_OMIT :REF_FILTER_MERGED_INCLUDE ;
t/t3200-branch.sh +4 -0
@@ -978,6 +978,10 @@ test_expect_success '--merged catches invalid object names' ' test_must_fail git branch --merged 0000000000000000000000000000000000000000 ' +test_expect_success '--merged is incompatible with --no-merged' ' + test_must_fail git branch --merged HEAD --no-merged HEAD +' + test_expect_success 'tracking with unexpected .fetch refspec' ' rm -rf a b c d && git init a &&
t/t6302-for-each-ref-filter.sh +4 -0
@@ -421,4 +421,8 @@ test_expect_success 'check %(if:notequals=<string>)' ' test_cmp expect actual ' +test_expect_success '--merged is incompatible with --no-merged' ' + test_must_fail git for-each-ref --merged HEAD --no-merged HEAD +' + test_done
t/t7004-tag.sh +4 -0
@@ -1748,6 +1748,10 @@ test_expect_success '--merged cannot be used in non-list mode' ' test_must_fail git tag --merged=mergetest-2 foo ' +test_expect_success '--merged is incompatible with --no-merged' ' + test_must_fail git tag --merged HEAD --no-merged HEAD +' + test_expect_success '--merged shows merged tags' ' cat >expect <<-\EOF && mergetest-1
Signature · 1 line
2.11.0
PATCH v2 5/16 ref-filter: add test for --contains on a non-commit
In reply to Ævar Arnfjörð BjarmasonChange the tag test suite to test for --contains on a tree & blob, it only accepts commits and will spew out "<object> is a tree, not a commit".
It's sufficient to test this just for the "tag" and "branch" commands, because it covers all the machinery is shared between "branch" and "for-each-ref".
--- t/t3201-branch-contains.sh | 9 +++++++++ t/t7004-tag.sh | 4 +++- 2 files changed, 12 insertions(+), 1 deletion(-)
t/t3201-branch-contains.sh +9 -0
@@ -130,6 +130,15 @@ test_expect_success 'implicit --list conflicts with modification options' ' ' +test_expect_success 'Assert that --contains only works on commits, not trees & blobs' ' + test_must_fail git branch --contains master^{tree} && + blob=$(git hash-object -w --stdin <<-\EOF + Some blob + EOF + ) && + test_must_fail git branch --contains $blob +' + # We want to set up a case where the walk for the tracking info # of one branch crosses the tip of another branch (and make sure # that the latter walk does not mess up our flag to see if it was
t/t7004-tag.sh +3 -1
@@ -1461,7 +1461,9 @@ test_expect_success 'mixing incompatibles modes and options is forbidden' ' test_must_fail git tag -n 100 && test_must_fail git tag -l -m msg && test_must_fail git tag -l -F some file && - test_must_fail git tag -v -s + test_must_fail git tag -v -s && + test_must_fail git tag --contains tag-tree && + test_must_fail git tag --contains tag-blob ' # check points-at
Signature · 1 line
2.11.0
Re: [PATCH v2 05/16] ref-filter: add test for --contains on a non-commit
Quoted 1 line · Ævar Arnfjörð Bjarmason
Change the tag test suite to test for --contains on a tree & blob, it
Either s/, it/. It/ or s/, it/; it/.
Quoted 5 lines
only accepts commits and will spew out "<object> is a tree, not a commit".
It's sufficient to test this just for the "tag" and "branch" commands, because it covers all the machinery is shared between "branch" and
Either s/is shared/shared/ or s/is shared/that is shared/.
Quoted 4 lines
"for-each-ref".
Signed-off-by Ævar Arnfjörð Bjarmason <[email protected]>---
The patch itself looks good.
Thanks.
PATCH v2 6/16 tag: remove a TODO item from the test suite
In reply to Ævar Arnfjörð BjarmasonChange the test for "git tag -l" to not have an associated TODO comment saying that it should return non-zero if there's no tags.
This was added in commit ef5a6fb597 ("Add test-script for git-tag", 2007-06-28) when the tests for "tag" were initially added, but at this point changing this would be inconsistent with how "git tag" is a synonym for "git tag -l", and would needlessly break external code that relies on this porcelain command.
--- t/t7004-tag.sh | 2 -- 1 file changed, 2 deletions(-)
t/t7004-tag.sh +0 -2
@@ -16,7 +16,6 @@ tag_exists () { git show-ref --quiet --verify refs/tags/"$1" } -# todo: git tag -l now returns always zero, when fixed, change this test test_expect_success 'listing all tags in an empty tree should succeed' ' git tag -l && git tag
@@ -136,7 +135,6 @@ test_expect_success \ 'listing a tag using a matching pattern should output that tag' \ 'test $(git tag -l mytag) = mytag' -# todo: git tag -l now returns always zero, when fixed, change this test test_expect_success \ 'listing tags using a non-matching pattern should suceed' \ 'git tag -l xxx'
Signature · 1 line
2.11.0
PATCH v2 7/16 tag tests: fix a typo in a test description
In reply to Ævar Arnfjörð BjarmasonChange "suceed" to "succeed" in a test description. The typo has been here since the code was originally added in commit ef5a6fb597 ("Add test-script for git-tag", 2007-06-28).
--- t/t7004-tag.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
t/t7004-tag.sh +1 -1
@@ -136,7 +136,7 @@ test_expect_success \ 'test $(git tag -l mytag) = mytag' test_expect_success \ - 'listing tags using a non-matching pattern should suceed' \ + 'listing tags using a non-matching pattern should succeed' \ 'git tag -l xxx' test_expect_success \
Signature · 1 line
2.11.0
PATCH v2 8/16 for-each-ref: partly change <object> to <commit> in help
In reply to Ævar Arnfjörð BjarmasonChange mentions of <object> to <commit> in the help output of for-each-ref as appropriate.
Both --[no-]merged and --contains only take commits, but --points-at can take any object, such as a tag pointing to a tree or blob.
--- builtin/for-each-ref.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
builtin/for-each-ref.c +2 -2
@@ -8,8 +8,8 @@static char const *const for_each_ref_usage[] = {N_ ("git for-each-ref [<options>] [<pattern>]" ),N_ ("git for-each-ref [--points-at <object>]" ), -N_ ("git for-each-ref [(--merged | --no-merged) [<object>]]" ), -N_ ("git for-each-ref [--contains [<object>]]" ), +N_ ("git for-each-ref [(--merged | --no-merged) [<commit>]]" ), +N_ ("git for-each-ref [--contains [<commit>]]" ),NULL };
Signature · 1 line
2.11.0
Re: [PATCH v2 08/16] for-each-ref: partly change <object> to <commit> in help
Quoted 8 lines · Ævar Arnfjörð Bjarmason
Change mentions of <object> to <commit> in the help output of for-each-ref as appropriate.
Both --[no-]merged and --contains only take commits, but --points-at can take any object, such as a tag pointing to a tree or blob.
Signed-off-by Ævar Arnfjörð Bjarmason <[email protected]>---
This definitely is a correction worth doing.
Do these strictly require commit, or does any commit-ish also do?
Quoted 17 lines
builtin/for-each-ref.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)builtin/for-each-ref.c +2
-2@@ -8,8 +8,8 @@static char const *const for_each_ref_usage[] = {N_ ("git for-each-ref [<options>] [<pattern>]" ),N_ ("git for-each-ref [--points-at <object>]" ), -N_ ("git for-each-ref [(--merged | --no-merged) [<object>]]" ), -N_ ("git for-each-ref [--contains [<object>]]" ), +N_ ("git for-each-ref [(--merged | --no-merged) [<commit>]]" ), +N_ ("git for-each-ref [--contains [<commit>]]" ),NULL };
Re: [PATCH v2 08/16] for-each-ref: partly change <object> to <commit> in help
Quoted 8 lines · Junio C Hamano
Quoted 6 lines · Ævar Arnfjörð Bjarmason
Change mentions of <object> to <commit> in the help output of for-each-ref as appropriate.
Both --[no-]merged and --contains only take commits, but --points-at can take any object, such as a tag pointing to a tree or blob.
Quoted 6 lines
Quoted 2 lines
Signed-off-by Ævar Arnfjörð Bjarmason <[email protected]>---
This definitely is a correction worth doing.
Do these strictly require commit, or does any commit-ish also do?
commit-ish, but that's a good point, and could be the subject of a future follow-up patch. Right now most of the things that say <commit> really mean <commit-ish>:
$ git grep '<commit>' -- builtin|wc -l
18
$ git grep '<commit.*ish>' -- builtin|wc -l
3Quoted 17 lines
Quoted 17 lines
builtin/for-each-ref.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)builtin/for-each-ref.c +2
-2@@ -8,8 +8,8 @@static char const *const for_each_ref_usage[] = {N_ ("git for-each-ref [<options>] [<pattern>]" ),N_ ("git for-each-ref [--points-at <object>]" ), -N_ ("git for-each-ref [(--merged | --no-merged) [<object>]]" ), -N_ ("git for-each-ref [--contains [<object>]]" ), +N_ ("git for-each-ref [(--merged | --no-merged) [<commit>]]" ), +N_ ("git for-each-ref [--contains [<commit>]]" ),NULL };
Re: [PATCH v2 08/16] for-each-ref: partly change <object> to <commit> in help
Quoted 4 lines · Ævar Arnfjörð Bjarmason
Quoted 1 line · Junio C Hamano
Do these strictly require commit, or does any commit-ish also do?
Quoted 8 lines
commit-ish, but that's a good point, and could be the subject of a future follow-up patch. Right now most of the things that say <commit> really mean <commit-ish>:
$ git grep '<commit>' -- builtin|wc -l 18 $ git grep '<commit.*ish>' -- builtin|wc -l 3
My gut feeling is that anywhere we say a <commit> for Porcelain commands, we should be also accepting a <commit-ish>, and it is not worth repeating to users that these command accept commit-ish. So I think it is better to leave these as <commit>, and to add special note to places where the commands insist taking <commit> and not <commit-ish>. They should be minorities, at least for Porcelain commands. The same for <tree> vs <tree-ish>.
Thanks.
PATCH v2 9/16 tag: add more incompatibles mode tests
In reply to Ævar Arnfjörð BjarmasonAmend the test suite to test for more invalid uses like "-l -a" etc. This mainly tests the (argc == 0 && !cmdmode) -> ((create_tag_object || force) && (cmdmode != 0)) code path in builtin/tag.c.
--- t/t7004-tag.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+)
t/t7004-tag.sh +13 -0
@@ -1455,6 +1455,19 @@ test_expect_success 'checking that initial commit is in all tags' " test_expect_success 'mixing incompatibles modes and options is forbidden' ' test_must_fail git tag -a && + test_must_fail git tag -a -l && + test_must_fail git tag -s && + test_must_fail git tag -s -l && + test_must_fail git tag -m && + test_must_fail git tag -m -l && + test_must_fail git tag -m "hlagh" && + test_must_fail git tag -m "hlagh" -l && + test_must_fail git tag -F && + test_must_fail git tag -F -l && + test_must_fail git tag -f && + test_must_fail git tag -f -l && + test_must_fail git tag -a -s -m -F && + test_must_fail git tag -a -s -m -F -l && test_must_fail git tag -l -v && test_must_fail git tag -n 100 && test_must_fail git tag -l -m msg &&
Signature · 1 line
2.11.0
Re: [PATCH v2 09/16] tag: add more incompatibles mode tests
Quoted 4 lines · Ævar Arnfjörð Bjarmason
Amend the test suite to test for more invalid uses like "-l -a" etc. This mainly tests the
(argc == 0 && !cmdmode)->((create_tag_object || force) && (cmdmode != 0))code path inbuiltin/tag.c.
The second sentence is now stale, isn't it?
Quoted 30 lines
Signed-off-by Ævar Arnfjörð Bjarmason <[email protected]>--- t/t7004-tag.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+)t/t7004-tag.sh +13
-0@@ -1455,6 +1455,19 @@ test_expect_success 'checking that initial commit is in all tags' " test_expect_success 'mixing incompatibles modes and options is forbidden' ' test_must_fail git tag -a && + test_must_fail git tag -a -l && + test_must_fail git tag -s && + test_must_fail git tag -s -l && + test_must_fail git tag -m && + test_must_fail git tag -m -l && + test_must_fail git tag -m "hlagh" && + test_must_fail git tag -m "hlagh" -l && + test_must_fail git tag -F && + test_must_fail git tag -F -l && + test_must_fail git tag -f && + test_must_fail git tag -f -l && + test_must_fail git tag -a -s -m -F && + test_must_fail git tag -a -s -m -F -l && test_must_fail git tag -l -v && test_must_fail git tag -n 100 && test_must_fail git tag -l -m msg &&
Re: [PATCH v2 09/16] tag: add more incompatibles mode tests
Quoted 8 lines · Junio C Hamano
Quoted 4 lines · Ævar Arnfjörð Bjarmason
Amend the test suite to test for more invalid uses like "-l -a" etc. This mainly tests the
(argc == 0 && !cmdmode)->((create_tag_object || force) && (cmdmode != 0))code path inbuiltin/tag.c.The second sentence is now stale, isn't it?
I've reworded this in WIP v3 to split out the code from the text, making this less confusing.
Quoted 30 lines
Quoted 30 lines
Signed-off-by Ævar Arnfjörð Bjarmason <[email protected]>--- t/t7004-tag.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+)t/t7004-tag.sh +13
-0@@ -1455,6 +1455,19 @@ test_expect_success 'checking that initial commit is in all tags' " test_expect_success 'mixing incompatibles modes and options is forbidden' ' test_must_fail git tag -a && + test_must_fail git tag -a -l && + test_must_fail git tag -s && + test_must_fail git tag -s -l && + test_must_fail git tag -m && + test_must_fail git tag -m -l && + test_must_fail git tag -m "hlagh" && + test_must_fail git tag -m "hlagh" -l && + test_must_fail git tag -F && + test_must_fail git tag -F -l && + test_must_fail git tag -f && + test_must_fail git tag -f -l && + test_must_fail git tag -a -s -m -F && + test_must_fail git tag -a -s -m -F -l && test_must_fail git tag -l -v && test_must_fail git tag -n 100 && test_must_fail git tag -l -m msg &&
PATCH v2 10/16 tag: change misleading --list <pattern> documentation
In reply to Ævar Arnfjörð BjarmasonChange the documentation for --list so that it's described as a toggle, not as an option that takes a <pattern> as an argument.
Junio initially documented this in b867c7c23a ("git-tag: -l to list tags (usability).", 2006-02-17), but later Jeff King changed "tag" to accept multiple patterns in 588d0e834b ("tag: accept multiple patterns for --list", 2011-06-20).
However, documenting this as "-l <pattern>" was never correct, as these both worked before Jeff's change:
git tag -l 'v*'
git tag 'v*' -lOne would expect an option that was documented like that to only accept:
git tag --list
git tag --list 'v*rc*'And after Jeff's change, one that took multiple patterns:
git tag --list 'v*rc*' --list '*2.8*'
But since it's actually a toggle all of these work as well, and produce identical output to the last example above:
git tag --list 'v*rc*' '*2.8*'
git tag --list 'v*rc*' '*2.8*' --list --list --list
git tag --list 'v*rc*' '*2.8*' --list -l --list -l --listNow the documentation is more in tune with how the "branch" command describes its --list option since commit cddd127b9a ("branch:
introduce --list option", 2011-08-28).
Change the test suite to assert that these invocations work for the cases that weren't already being tested for.
--- Documentation/git-tag.txt | 16 +++++++++------- t/t7004-tag.sh | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 7 deletions(-)
Documentation/git-tag.txt +9 -7
@@ -87,13 +87,15 @@ OPTIONS 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 <pattern>:: ---list <pattern>:: - List tags with names that match the given pattern (or all if no - pattern is given). 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. +-l:: +--list:: + Activate the list mode. `git tag <pattern>` would try to create a + tag, use `git tag --list <pattern>` to list matching branches, (or + all if no pattern is given). ++ +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. --sort=<key>:: Sort based on the key given. Prefix `-` to sort in
t/t7004-tag.sh +21 -0
@@ -118,6 +118,18 @@ test_expect_success 'listing all tags if one exists should succeed' ' git tag ' +cat >expect <<EOF +mytag +EOF +test_expect_success 'Multiple -l or --list options are equivalent to one -l option' ' + git tag -l -l >actual && + test_cmp expect actual && + git tag --list --list >actual && + test_cmp expect actual && + git tag --list -l --list >actual && + test_cmp expect actual +' + test_expect_success 'listing all tags if one exists should output that tag' ' test $(git tag -l) = mytag && test $(git tag) = mytag
@@ -336,6 +348,15 @@ test_expect_success 'tag -l can accept multiple patterns' ' test_cmp expect actual ' +test_expect_success 'tag -l can accept multiple patterns interleaved with -l or --list options' ' + git tag -l "v1*" "v0*" >actual && + test_cmp expect actual && + git tag -l "v1*" --list "v0*" >actual && + test_cmp expect actual && + git tag -l "v1*" "v0*" -l --list >actual && + test_cmp expect actual +' + test_expect_success 'listing tags in column' ' COLUMNS=40 git tag -l --column=row >actual && cat >expected <<\EOF &&
Signature · 1 line
2.11.0
Re: [PATCH v2 10/16] tag: change misleading --list <pattern> documentation
Quoted 3 lines · Ævar Arnfjörð Bjarmason
And after Jeff's change, one that took multiple patterns:
git tag --list 'v*rc*' --list '*2.8*'
I do not think this is a correct depiction of the evolution, and is a confusing description. It should say
git tag --list 'v*rc*' '*2.8*'
instead.
When the logic was still in scripted Porcelain, <pattern> _was_ an optional argument to the "-l" option (see b867c7c2 ("git-tag: -l to list tags (usability).", 2006-02-17) you quoted earlier). But way before Jeff's change, when the command was reimplemented in C and started using parse_options(), <pattern> stopped being an argument to the "-l" option. What Jeff's change did was that the original code that only took
git tag -l 'v*rc*'
to also take
git tag -l 'v*rc*' '*2.8*'
i.e. multiple patterns. Yes, thanks to parse_options, you could have -l twice on the command line, but "multiple patterns" does not have anything to do with having to (or allowing to) use '-l' multiple times.
Quoted 6 lines
But since it's actually a toggle all of these work as well, and produce identical output to the last example above:
git tag --list 'v*rc*' '*2.8*' git tag --list 'v*rc*' '*2.8*' --list --list --list git tag --list 'v*rc*' '*2.8*' --list -l --list -l --list
So citing Jeff's change is irrelevant to explain these. I doubt you even need to show these variations.
Quoted 6 lines
Now the documentation is more in tune with how the "branch" command describes its --list option since commit
cddd127b9a("branch:
introduce --list option", 2011-08-28).Change the test suite to assert that these invocations work for the cases that weren't already being tested for.
These two paragraphs are relevant.
Documentation/git-tag.txt OPTIONS · line 92
Quoted 10 lines
--l <pattern>::
---list <pattern>::Documentation/git-tag.txt +3
-5- List tags with names that match the given pattern (or all if no - pattern is given). 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. +-l:: +--list:: + Activate the list mode. `git tag <pattern>` would try to create a
Dont say <pattern> on this line. It is git tag <name>.
Documentation/git-tag.txt OPTIONS · line 93
Quoted 1 line
Documentation/git-tag.txt +1
-0+ tag, use `git tag --list <pattern>` to list matching branches, (or
Perhaps <pattern>... instead to signal that you can give multiple patterns?
Quoted 9 lines
t/t7004-tag.sh +1
-0@@ -118,6 +118,18 @@ test_expect_success 'listing all tags if one exists should succeed' ' git tag ' +cat >expect <<EOF
t/t7004-tag.sh test_expect_success 'listing all tags if one exists should succeed' ' · line 131
Quoted 10 lines
t/t7004-tag.sh +10
-0+mytag +EOF +test_expect_success 'Multiple -l or --list options are equivalent to one -l option' ' + git tag -l -l >actual && + test_cmp expect actual && + git tag --list --list >actual && + test_cmp expect actual && + git tag --list -l --list >actual && + test_cmp expect actual +'
The "-l/-d/-v" options follow the last-one-wins rule, no? Perhaps also show how this one works in this test (while retitling it)?
git tag -d -v -l
t/t7004-tag.sh test_expect_success 'tag -l can accept multiple patterns' ' · line 351
Quoted 5 lines
t/t7004-tag.sh +1
-0@@ -336,6 +348,15 @@ test_expect_success 'tag -l can accept multiple patterns' ' test_cmp expect actual ' +test_expect_success 'tag -l can accept multiple patterns interleaved with -l or --list options' '
Please drop "interleaved", as we are not encouraging GNUism. We just tolerate it but do not guarantee to keep them working.
Quoted 11 lines
t/t7004-tag.sh +8
-0+ git tag -l "v1*" "v0*" >actual && + test_cmp expect actual && + git tag -l "v1*" --list "v0*" >actual && + test_cmp expect actual && + git tag -l "v1*" "v0*" -l --list >actual && + test_cmp expect actual +' + test_expect_success 'listing tags in column' ' COLUMNS=40 git tag -l --column=row >actual && cat >expected <<\EOF &&
Re: [PATCH v2 10/16] tag: change misleading --list <pattern> documentation
Quoted 4 lines · Junio C Hamano
Quoted 2 lines · Ævar Arnfjörð Bjarmason
And after Jeff's change, one that took multiple patterns:
Quoted 8 lines
Quoted 1 line
git tag --list 'v*rc*' --list '*2.8*'I do not think this is a correct depiction of the evolution, and is a confusing description. It should say
git tag --list 'v*rc*' '*2.8*'instead.
Changing this from "--list <pattern> --list <pattern>" to "--list <pattern> <pattern>" wouldn't make any sense, because it's in the middle of a sentence explaining not how the tooling worked, but before this change, how it was documented to work. I.e. read up a few lines to "One would expect an option that was documented like that..." for the context.
Quoted 10 lines
When the logic was still in scripted Porcelain, <pattern> _was_ an optional argument to the "-l" option (see
b867c7c2("git-tag: -l to list tags (usability).", 2006-02-17) you quoted earlier). But way before Jeff's change, when the command was reimplemented in C and started usingparse_options(), <pattern> stopped being an argument to the "-l" option. What Jeff's change did was that the original code that only tookgit tag -l 'v*rc*'
Quoted 8 lines
to also take
git tag -l 'v*rc*' '*2.8*'i.e. multiple patterns. Yes, thanks to
parse_options, you could have -l twice on the command line, but "multiple patterns" does not have anything to do with having to (or allowing to) use '-l' multiple times.
Yes, all of this is correct, but not relevant to what I'm describing in the commit message, because I'm making a documentation change and describing how you *would* expect git to work if you read the *documentation*, not if you read the code.
If you read the documentation after Jeff's 588d0e834b, since -l was still documented as taking a <pattern> you'd expect "tag -l 'v*rc*' -l '*2.8*'" to be how it worked, and for "tag -l 'v*rc*' '*2.8*'" to be an error.
Quoted 9 lines
Quoted 6 lines
But since it's actually a toggle all of these work as well, and produce identical output to the last example above:
git tag --list 'v*rc*' '*2.8*' git tag --list 'v*rc*' '*2.8*' --list --list --list git tag --list 'v*rc*' '*2.8*' --list -l --list -l --listSo citing Jeff's change is irrelevant to explain these. I doubt you even need to show these variations.
Jeff's change isn't being cited to explain these, everything before the "But since it's actually" is describing how the documentation was phrased to give you the impression that it worked, including after Jeff's change where we started accepting multiple patterns. But at this point I'm starting to describe how the code actually parsed the --list option.
Regardless of that, I'll try to rephrase this somehow to make it clearer, but I'd like to keep the general gist of "before this change, if you read the docs, here's how you'd expect the -l option to work, but it actually worked like so-and-so, and now that's what we document instead".
Quoted 20 lines
Quoted 6 lines
Now the documentation is more in tune with how the "branch" command describes its --list option since commit
cddd127b9a("branch:
introduce --list option", 2011-08-28).Change the test suite to assert that these invocations work for the cases that weren't already being tested for.
These two paragraphs are relevant.
Documentation/git-tag.txt OPTIONS · line 92
Quoted 10 lines
--l <pattern>::
---list <pattern>::Documentation/git-tag.txt +3
-5- List tags with names that match the given pattern (or all if no - pattern is given). 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. +-l:: +--list:: + Activate the list mode. `git tag <pattern>` would try to create a
Quoted 1 line
Dont say <pattern> on this line. It is
git tag <name>.
Makes sense, but this is something I copied as-is from git-branch.txt, which then has the same issue, so v3 will have yet another related patch...
Quoted 4 lines
Quoted 1 line
+ tag, use
git tag --list <pattern>to list matching branches, (orPerhaps <pattern>... instead to signal that you can give multiple patterns?
Makes sense.
Quoted 23 lines
Quoted 9 lines
t/t7004-tag.sh +1
-0@@ -118,6 +118,18 @@ test_expect_success 'listing all tags if one exists should succeed' ' git tag ' +cat >expect <<EOFt/t7004-tag.sh test_expect_success 'listing all tags if one exists should succeed' ' · line 131
Quoted 10 lines
t/t7004-tag.sh +10
-0+mytag +EOF +test_expect_success 'Multiple -l or --list options are equivalent to one -l option' ' + git tag -l -l >actual && + test_cmp expect actual && + git tag --list --list >actual && + test_cmp expect actual && + git tag --list -l --list >actual && + test_cmp expect actual +'The "-l/-d/-v" options follow the last-one-wins rule, no? Perhaps also show how this one works in this test (while retitling it)?
Quoted 1 line
git tag -d -v -l
This will fail as tested for in "tag: add more incompatibles mode tests". We weren't testing "-d" with "-l", or this combination, I'll add both to the tests.
Quoted 8 lines
t/t7004-tag.sh test_expect_success 'tag -l can accept multiple patterns' ' · line 351
Quoted 5 lines
t/t7004-tag.sh +1
-0@@ -336,6 +348,15 @@ test_expect_success 'tag -l can accept multiple patterns' ' test_cmp expect actual ' +test_expect_success 'tag -l can accept multiple patterns interleaved with -l or --list options' 'Please drop "interleaved", as we are not encouraging GNUism. We just tolerate it but do not guarantee to keep them working.
This brings up the same point you made in <[email protected]>, I replied to in <CACBZZX5LN8nhs85K18XVg4Y9_qb9zKGBoFnnQHSsRZVOP=OkDw@mail.gmail.com>, and that you didn't get back to me about.
Rather than split the discussion or me copy/pasting large parts of that E-Mail could you please reply to me over in that thread?
Quoted 11 lines
Quoted 11 lines
t/t7004-tag.sh +8
-0+ git tag -l "v1*" "v0*" >actual && + test_cmp expect actual && + git tag -l "v1*" --list "v0*" >actual && + test_cmp expect actual && + git tag -l "v1*" "v0*" -l --list >actual && + test_cmp expect actual +' + test_expect_success 'listing tags in column' ' COLUMNS=40 git tag -l --column=row >actual && cat >expected <<\EOF &&
Re: [PATCH v2 10/16] tag: change misleading --list <pattern> documentation
Quoted 10 lines · Ævar Arnfjörð Bjarmason
Quoted 2 lines
Please drop "interleaved", as we are not encouraging GNUism. We just tolerate it but do not guarantee to keep them working.
This brings up the same point you made in <[email protected]>, I replied to in <CACBZZX5LN8nhs85K18XVg4Y9_qb9zKGBoFnnQHSsRZVOP=OkDw@mail.gmail.com>, and that you didn't get back to me about.
Rather than split the discussion or me copy/pasting large parts of that E-Mail could you please reply to me over in that thread?
There is nothing to reply. We know some people favor GNUism, but we do not actively encourage it, period.
Re: [PATCH v2 10/16] tag: change misleading --list <pattern> documentation
Quoted 10 lines · Junio C Hamano
Quoted 8 lines · Ævar Arnfjörð Bjarmason
Quoted 2 lines
Please drop "interleaved", as we are not encouraging GNUism. We just tolerate it but do not guarantee to keep them working.
This brings up the same point you made in <[email protected]>, I replied to in <CACBZZX5LN8nhs85K18XVg4Y9_qb9zKGBoFnnQHSsRZVOP=OkDw@mail.gmail.com>, and that you didn't get back to me about.
Quoted 5 lines
Quoted 2 lines
Rather than split the discussion or me copy/pasting large parts of that E-Mail could you please reply to me over in that thread?
There is nothing to reply. We know some people favor GNUism, but we do not actively encourage it, period.
I'd understand the objection to encouraging if I was proposing to include mentions of "--list <pattern> --list <pattern>" in the documentation, but what this patch is about (and this wasn't clear enough from the beginning, I'll reword it), is essentially:
"So for the last 5 years of Git releases if you'd read the git-tag docs you'd think --list <pat> --list <pat> was the blessed way of supplying multiple patterns. That's not actually needed, or encouraged, so here's a change to the docs & a test addition to make sure we know if we break this long-documented pattern in the future".
You'd like the doc change but not the regression test. If so I'm fine with that. The reason I'm asking you follow-up questions about it is because I'd like to know in general, for future submissions, what sort of things you think we should be putting in the test suite. I.e. should the tests be:
a) Only be a collection of invocations of git we'd be comfortable showing to someone as "this works, and this is how you should do it", or things that explicitly fail marked with test_must_fail.
b) or a) && also various surprising combinations of things we don't necessarily want to encourage or even support in the future, but which are in there so if we change them, we at least know our change changed something that worked before.
Now. I think the policy should be "b". The main reason is that as I noted in [1] people do write scripts against the porcelain. There's doubtless scripted invocations out there that use multiple GNU-like "-l <pattern>" options, and it's worthwhile for us to know if we make a change that breaks that.
But if you think it should be "a" obviously that's the project policy, but then I'd like to know that it's "a", both because it'll save me time authoring future patches, and I'd like to submit some change to SubmittingPatches or t/README describing to others what sort of tests are acceptable for inclusion.
The reason I brought up a hypothetical "test_might_get_deprecated" feature in my original message [2] is that even if you think we should only do "a" now and not "b", I think that perhaps that's only because of some limitation of the current test suite. I.e.:
1) Maybe we shouldn't run these ("b" && !"a") tests by default unless some flag is provided, so that someone who's working on an otherwise worthwhile new feature isn't dissuaded by some failing test that's checking for an obscure and historically unintended feature of git.
2) Or we could run them, but e.g. turn them into TODO's for failure to mark them as things we'd like to deprecate.
1. <CACBZZX59KXPOEjiUKtZLN6zjO_xpiWve7Xga6q-53J2LwvfZyw@mail.gmail.com>
2. <CACBZZX5LN8nhs85K18XVg4Y9_qb9zKGBoFnnQHSsRZVOP=OkDw@mail.gmail.com>,
Re: [PATCH v2 10/16] tag: change misleading --list <pattern> documentation
Quoted 11 lines · Ævar Arnfjörð Bjarmason
of things you think we should be putting in the test suite. I.e. should the tests be:
a) Only be a collection of invocations of git we'd be comfortable showing to someone as "this works, and this is how you should do it", or things that explicitly fail marked with
test_must_fail.b) or a) && also various surprising combinations of things we don't necessarily want to encourage or even support in the future, but which are in there so if we change them, we at least know our change changed something that worked before.
I am strongly inclined to (a). If we cannot decide when we designed the feature, and we anticipate that we may want to change it later, then documenting the choice in a test or two may be a way to remind the choice we happened to have made, but in general I do not think we want to promise (to ourselves) more than what we are willing to commit to.
Re: [PATCH v2 10/16] tag: change misleading --list <pattern> documentation
Quoted 14 lines · Junio C Hamano
Quoted 11 lines · Ævar Arnfjörð Bjarmason
of things you think we should be putting in the test suite. I.e. should the tests be:
a) Only be a collection of invocations of git we'd be comfortable showing to someone as "this works, and this is how you should do it", or things that explicitly fail marked with
test_must_fail.b) or a) && also various surprising combinations of things we don't necessarily want to encourage or even support in the future, but which are in there so if we change them, we at least know our change changed something that worked before.
Quoted 6 lines
I am strongly inclined to (a). If we cannot decide when we designed the feature, and we anticipate that we may want to change it later, then documenting the choice in a test or two may be a way to remind the choice we happened to have made, but in general I do not think we want to promise (to ourselves) more than what we are willing to commit to.
I've occasionally[1] added tests that are "what we happen to produce now", but I almost always mark them with a comment either in the test script or in the commit message. What I'm _most_ concerned about is a developer later breaking the test, but being unsure if they were breaking some real-world case (and not being able to find clues in the history).
A secondary concern would be people using the test snippets as guidance on what is normal or encouraged.
So I could live with these patches, but I'd prefer to see a comment somewhere. And I think I'd have a slight inclination to just stick to
(a) in the first place, unless there is a really good reason to cover the test (like that we do not care between behaviors X and Y, but we need to check that it does one of them, and not Z).
-Peff
[1] E.g., see the comment in t3204 from a356e8e2a (t3204: test
git-branch @-expansion corner cases, 2017-03-02).
Re: [PATCH v2 10/16] tag: change misleading --list <pattern> documentation
Quoted 30 lines · Jeff King
Quoted 14 lines · Junio C Hamano
Quoted 11 lines · Ævar Arnfjörð Bjarmason
of things you think we should be putting in the test suite. I.e. should the tests be:
a) Only be a collection of invocations of git we'd be comfortable showing to someone as "this works, and this is how you should do it", or things that explicitly fail marked with
test_must_fail.b) or a) && also various surprising combinations of things we don't necessarily want to encourage or even support in the future, but which are in there so if we change them, we at least know our change changed something that worked before.
Quoted 6 lines
I am strongly inclined to (a). If we cannot decide when we designed the feature, and we anticipate that we may want to change it later, then documenting the choice in a test or two may be a way to remind the choice we happened to have made, but in general I do not think we want to promise (to ourselves) more than what we are willing to commit to.
I've occasionally[1] added tests that are "what we happen to produce now", but I almost always mark them with a comment either in the test script or in the commit message. What I'm _most_ concerned about is a developer later breaking the test, but being unsure if they were breaking some real-world case (and not being able to find clues in the history).
Quoted 8 lines
A secondary concern would be people using the test snippets as guidance on what is normal or encouraged.
So I could live with these patches, but I'd prefer to see a comment somewhere. And I think I'd have a slight inclination to just stick to
(a) in the first place, unless there is a really good reason to cover the test (like that we do not care between behaviors X and Y, but we need to check that it does one of them, and not Z).
Right, or in this case something where we're testing for behavior we documented for a long time, but never really intended to support. Junio would you be fine with just this on top:
t/README +18 -0
@@ -379,2 +379,5 @@ Do: + - Include tests which assert that the desired & recommended behavior + of commands is preserved. + - Put all code inside test_expect_success and other assertions.
@@ -424,2 +427,17 @@ Don't: + - Include tests which exhaustively test for various edge cases or + unintended emergent behavior which we're not interested in + supporting in the future. + + An exception to this is are cases where we don't care about + different behaviors X and Y, but we need to check that it does one + of them, and not Z. + + Another exception are cases where our documentation might + unintentionally stated or implied that something was supported or + recommended, but we'd like to discourage its use going forward. + + In both of the above cases please prominently comment the test + indicating that you're testing for one of these two cases. + - exit() within a <script> part.
t/t7004-tag.sh +4 -0
@@ -350,2 +350,6 @@ test_expect_success 'tag -l can accept multiple patterns' ' +# Between around v1.7.6.1 & v2.13.0 the documentation unintentionally +# implied that --list was what took the <pattern>, not that patterns +# should be clustered at the very end. This test should not imply that +# this is a sane thing to support. test_expect_success 'tag -l can accept multiple patterns interleaved
with -l or --list options' '
Or do you think the "long documented but unintentional" argument isn't worth a test, in which case squash this:
t/README +2 -6
@@ -433,12 +433,8 @@ Don't: different behaviors X and Y, but we need to check that it does one of them, and not Z. - Another exception are cases where our documentation might - unintentionally stated or implied that something was supported or - recommended, but we'd like to discourage its use going forward. - - In both of the above cases please prominently comment the test - indicating that you're testing for one of these two cases. + In that case please prominently comment the test indicating that + you're testing for one of these two cases. - exit() within a <script> part.
t/t7004-tag.sh +0 -5
@@ -348,19 +348,6 @@ test_expect_success 'tag -l can accept multiple patterns' ' test_cmp expect actual ' -# Between around v1.7.6.1 & v2.13.0 the documentation unintentionally -# implied that --list was what took the <pattern>, not that patterns -# should be clustered at the very end. This test should not imply that -# this is a sane thing to support. -test_expect_success 'tag -l can accept multiple patterns interleaved
with -l or --list options' '
- git tag -l "v1*" "v0*" >actual &&
- test_cmp expect actual &&
- git tag -l "v1*" --list "v0*" >actual &&
- test_cmp expect actual &&
- git tag -l "v1*" "v0*" -l --list >actual &&
- test_cmp expect actual
-'
-
test_expect_success 'listing tags in column' '
COLUMNS=40 git tag -l --column=row >actual &&
cat >expected <<\EOF &&Re: [PATCH v2 10/16] tag: change misleading --list <pattern> documentation
Quoted 20 lines · Ævar Arnfjörð Bjarmason
Junio would you be fine with just this on top:
t/README +9
-0@@ -379,2 +379,5 @@ Do: + - Include tests which assert that the desired & recommended behavior + of commands is preserved. + - Put all code inside test_expect_success and other assertions.@@ -424,2 +427,17 @@ Don't: + - Include tests which exhaustively test for various edge cases or + unintended emergent behavior which we're not interested in + supporting in the future. + + An exception to this is are cases where we don't care about + different behaviors X and Y, but we need to check that it does one
t/README Don't: · line 443
Quoted 10 lines
t/README +9
-0+ of them, and not Z. + + Another exception are cases where our documentation might + unintentionally stated or implied that something was supported or + recommended, but we'd like to discourage its use going forward. + + In both of the above cases please prominently comment the test + indicating that you're testing for one of these two cases. + - exit() within a <script> part.
This would probably be part of your other three-patch series for t/README? With a quick read-through I spotted nothing questionable, but I am not 100% sure about the value of going into that level of details, especially with the latter one about "discourage and wean off of".
Quoted 13 lines
t/t7004-tag.sh +4
-0@@ -350,2 +350,6 @@ test_expect_success 'tag -l can accept multiple patterns' ' +# Between around v1.7.6.1 & v2.13.0 the documentation unintentionally +# implied that --list was what took the <pattern>, not that patterns +# should be clustered at the very end. This test should not imply that +# this is a sane thing to support. test_expect_success 'tag -l can accept multiple patterns interleavedwith -l or --list options' '
Quoted 2 lines
Or do you think the "long documented but unintentional" argument isn't worth a test, in which case squash this:
Oh, I didn't know I was given two choices and the second one does address the "I am not 100% sure" above ;-).
Quoted 8 lines
t/README +0
-0@@ -433,12 +433,8 @@ Don't: different behaviors X and Y, but we need to check that it does one of them, and not Z.
t/README Don't: · line 439
Quoted 10 lines
t/README +2
-6- Another exception are cases where our documentation might - unintentionally stated or implied that something was supported or - recommended, but we'd like to discourage its use going forward. - - In both of the above cases please prominently comment the test - indicating that you're testing for one of these two cases. + In that case please prominently comment the test indicating that + you're testing for one of these two cases. - exit() within a <script> part.
So for the doc part, I can go with either, but prefer the latter between the two.
Quoted 14 lines
t/t7004-tag.sh +0
-5@@ -348,19 +348,6 @@ test_expect_success 'tag -l can accept multiple patterns' ' test_cmp expect actual ' -# Between around v1.7.6.1 & v2.13.0 the documentation unintentionally -# implied that --list was what took the <pattern>, not that patterns -# should be clustered at the very end. This test should not imply that -# this is a sane thing to support. -test_expect_success 'tag -l can accept multiple patterns interleavedwith -l or --list options' '
t/t7004-tag.sh
Quoted 2 lines
t/t7004-tag.sh +0
-2- git tag -l "v1*" "v0*" >actual && - test_cmp expect actual &&
I'd actually think "multiple patterns" should be kept, as that is really what we want to support forever.
Acceptance of multiple and redundant "--list", e.g.
git tag -l --list "v1*" "v0*" >actual && test_cmp expect actual &&
immediately after the above may also be something worth protecting, but that is how OPT_CMDMODE works in general, so it may not be necessary to test it specifically in a test for "tag -l".
Acceptance of multiple and redundant "--list" that are given after a <pattern> is already given on the command line is not something we want to actively deprecate (it is not worth our time or effort) but it is not something we want to encourage, either. So I have a preference for dropping the ones below.
Quoted 9 lines
t/t7004-tag.sh +0
-6- git tag -l "v1*" --list "v0*" >actual && - test_cmp expect actual && - git tag -l "v1*" "v0*" -l --list >actual && - test_cmp expect actual -' - test_expect_success 'listing tags in column' ' COLUMNS=40 git tag -l --column=row >actual && cat >expected <<\EOF &&
Re: [PATCH v2 10/16] tag: change misleading --list <pattern> documentation
In reply to Ævar Arnfjörð BjarmasonQuoted 4 lines · Ævar Arnfjörð Bjarmason
Yes, all of this is correct, but not relevant to what I'm describing in the commit message, because I'm making a documentation change and describing how you *would* expect git to work if you read the *documentation*, not if you read the code.
OK.
Quoted 9 lines
Quoted 5 lines
Quoted 3 lines
+-l:: +--list:: + Activate the list mode. `git tag <pattern>` would try to create aDont say <pattern> on this line. It is
git tag <name>.Makes sense, but this is something I copied as-is from git-branch.txt, which then has the same issue, so v3 will have yet another related patch...
I think you'd rather want to make it a single patch to be applied and merged independently, as a fix to a documentation bug we somehow noticed that is unrelated to the main theme of what we were working to perfect ;-)
Quoted 8 lines
Quoted 4 lines
The "-l/-d/-v" options follow the last-one-wins rule, no? Perhaps also show how this one works in this test (while retitling it)?
git tag -d -v -l
This will fail as tested for in "tag: add more incompatibles mode tests". We weren't testing "-d" with "-l", or this combination, I'll add both to the tests.
Thanks.
PATCH v2 11/16 tag: implicitly supply --list given another list-like option
In reply to Ævar Arnfjörð BjarmasonChange 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.
This change does not consider "-n" a list-like option, even though that might be logical. Permitting it would allow:
git tag -n 100
As a synonym for:
git tag -n --list 100
Which, while not technically ambiguous as the option must already be provided as -n<num> rather than -n <num>, would be confusing.
--- Documentation/git-tag.txt | 8 ++++++-- builtin/tag.c | 17 +++++++++++------ t/t7004-tag.sh | 39 +++++++++++++++++++++++++++++++++++---- 3 files changed, 52 insertions(+), 12 deletions(-)
Documentation/git-tag.txt +6 -2
@@ -96,6 +96,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 +128,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 +139,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>::
builtin/tag.c +11 -6
@@ -454,8 +454,13 @@ 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) + cmdmode ='l' ; + }if ((create_tag_object || force) && (cmdmode !=0 ))usage_with_options (git_tag_usage, options);
@@ -485,13 +490,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' ) {
t/t7004-tag.sh +35 -4
@@ -1472,6 +1472,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' '
@@ -1491,6 +1496,7 @@ test_expect_success 'mixing incompatibles modes and options is forbidden' ' test_must_fail git tag -a -s -m -F -l && test_must_fail git tag -l -v && 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 && test_must_fail git tag -v -s &&
@@ -1498,10 +1504,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' '
@@ -1778,8 +1799,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' '
@@ -1803,6 +1829,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 &&
Signature · 1 line
2.11.0
Re: [PATCH v2 11/16] tag: implicitly supply --list given another list-like option
Quoted 7 lines · Ævar Arnfjörð Bjarmason
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
s/,././
Quoted 2 lines
subsequent list-like options that were added copied its pattern of making this usage an error.
Good digging, and I do agree that this is a good change.
Thanks.
PATCH v2 12/16 tag: change --point-at to default to HEAD
In reply to Ævar Arnfjörð BjarmasonChange the --points-at option to default to HEAD for consistency with its siblings --contains, --merged etc. which default to HEAD. Previously we'd get:
$ git tag --points-at 2>&1 | head -n 1
error: option `points-at' requires a valueThis changes behavior added in commit ae7706b9ac (tag: add --points-at list option, 2012-02-08).
--- Documentation/git-tag.txt | 3 ++- builtin/tag.c | 3 ++- t/t7004-tag.sh | 9 ++++++++- 3 files changed, 12 insertions(+), 3 deletions(-)
Documentation/git-tag.txt +2 -1
@@ -139,7 +139,8 @@ 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. Implies `--list`. + Only list tags of the given object (HEAD if not + specified). Implies `--list`. -m <msg>:: --message=<msg>::
builtin/tag.c +2 -1
@@ -431,7 +431,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix) N_("field name to sort on"), &parse_opt_ref_sorting), {OPTION_CALLBACK ,0 ,"points-at" , &filter.points_at,N_ ("object" ), -N_ ("print only tags of the object" ),0 , parse_opt_object_name +N_ ("print only tags of the object" ),PARSE_OPT_LASTARG_DEFAULT , + parse_opt_object_name, (intptr_t )"HEAD" },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")),
t/t7004-tag.sh +8 -1
@@ -1513,7 +1513,8 @@ do " test_expect_success "Doing 'git tag --list-like $option <commit> <pattern> is permitted" " git tag -n $option HEAD HEAD && - git tag $option HEAD HEAD + git tag $option HEAD HEAD && + git tag $option " done
@@ -1525,6 +1526,12 @@ test_expect_success '--points-at can be used in non-list mode' ' test_cmp expect actual ' +test_expect_success '--points-at is a synonym for --points-at HEAD' ' + echo v4.0 >expect && + git tag --points-at >actual && + test_cmp expect actual +' + test_expect_success '--points-at finds lightweight tags' ' echo v4.0 >expect && git tag --points-at v4.0 >actual &&
Signature · 1 line
2.11.0
Re: [PATCH v2 12/16] tag: change --point-at to default to HEAD
Makes sense. Thanks.
PATCH v2 13/16 ref-filter: add --no-contains option to tag/branch/for-each-ref
In reply to Ævar Arnfjörð BjarmasonChange the tag, branch & for-each-ref commands to have a --no-contains option in addition to their longstanding --contains options.
This allows for finding the last-good rollout tag given a known-bad <commit>. Given a hypothetically bad commit cf5c7253e0, the git version to revert to can be found with this hacky two-liner:
(git tag -l 'v[0-9]*'; git tag -l --contains cf5c7253e0 'v[0-9]*') |
sort | uniq -c | grep -E '^ *1 ' | awk '{print $2}' | tail -n 10With this new --no-contains option the same can be achieved with:
git tag -l --no-contains cf5c7253e0 'v[0-9]*' | sort | tail -n 10
As the filtering machinery is shared between the tag, branch & for-each-ref commands, implement this for those commands too. A practical use for this with "branch" is e.g. finding branches which were branched off between v2.8.0 and v2.10.0:
git branch --contains v2.8.0 --no-contains v2.10.0
The "describe" command also has a --contains option, but its semantics are unrelated to what tag/branch/for-each-ref use --contains for. A --no-contains option for "describe" wouldn't make any sense, other than being exactly equivalent to not supplying --contains at all, which would be confusing at best.
Add a --without option to "tag" as an alias for --no-contains, for consistency with --with and --contains. The --with option is undocumented, and possibly the only user of it is
Junio (<[email protected]>). But it's trivial to support, so let's do that.
The additions to the the test suite are inverse copies of the corresponding --contains tests. With this change --no-contains for tag, branch & for-each-ref is just as well tested as the existing --contains option.
In addition to those tests, add a test for "tag" which asserts that --no-contains won't find tree/blob tags, which is slightly unintuitive, but consistent with how --contains works & is documented.
--- Documentation/git-branch.txt | 16 +++- Documentation/git-for-each-ref.txt | 6 +- Documentation/git-tag.txt | 6 +- builtin/branch.c | 5 +- builtin/for-each-ref.c | 3 +- builtin/tag.c | 8 +- contrib/completion/git-completion.bash | 4 +- parse-options.h | 4 +- ref-filter.c | 19 +++-- ref-filter.h | 1 + t/t3201-branch-contains.sh | 54 +++++++++++++- t/t6302-for-each-ref-filter.sh | 16 ++++ t/t7004-tag.sh | 130 ++++++++++++++++++++++++++++++++- 13 files changed, 246 insertions(+), 26 deletions(-)
Documentation/git-branch.txt +12 -4
@@ -11,7 +11,8 @@ SYNOPSIS 'git branch' [--color[=<when>] | --no-color] [-r | -a] [--list] [-v [--abbrev=<length> | --no-abbrev]] [--column[=<options>] | --no-column] - [(--merged | --no-merged | --contains) [<commit>]] [--sort=<key>] + [(--merged | --no-merged) [<commit>]] + [--contains [<commit]] [--no-contains [<commit>]] [--sort=<key>] [--points-at <object>] [--format=<format>] [<pattern>...] 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>] 'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]
@@ -35,7 +36,7 @@ as branch creation. With `--contains`, shows only the branches that contain the named commit (in other words, the branches whose tip commits are descendants of the -named commit). With `--merged`, only branches merged into the named +named commit), `--no-contains` inverts it. With `--merged`, only branches merged into the named commit (i.e. the branches whose tip commits are reachable from the named commit) will be listed. With `--no-merged` only branches not merged into the named commit will be listed. If the <commit> argument is missing it
@@ -213,6 +214,10 @@ start-point is either a local or remote-tracking branch. Only list branches which contain the specified commit (HEAD if not specified). Implies `--list`. +--no-contains [<commit>]:: + Only list branches which don't contain the specified commit + (HEAD if not specified). Implies `--list`. + --merged [<commit>]:: Only list branches whose tips are reachable from the specified commit (HEAD if not specified). Implies `--list`,
@@ -298,13 +303,16 @@ If you are creating a branch that you want to checkout immediately, it is easier to use the git checkout command with its `-b` option to create a branch and check it out with a single command. -The options `--contains`, `--merged` and `--no-merged` serve three related -but different purposes: +The options `--contains`, `--no-contains`, `--merged` and `--no-merged` +serve four related but different purposes: - `--contains <commit>` is used to find all branches which will need special attention if <commit> were to be rebased or amended, since those branches contain the specified <commit>. +- `--no-contains <commit>` is the inverse of that, i.e. branches that don't + contain the specified <commit>. + - `--merged` is used to find all branches which can be safely deleted, since those branches are fully contained by HEAD.
Documentation/git-for-each-ref.txt +5 -1
@@ -11,7 +11,7 @@ SYNOPSIS 'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl] [(--sort=<key>)...] [--format=<format>] [<pattern>...] [--points-at <object>] [(--merged | --no-merged) [<object>]] - [--contains [<object>]] + [--contains [<object>]] [--no-contains [<object>]] DESCRIPTION -----------
@@ -81,6 +81,10 @@ OPTIONS Only list refs which contain the specified commit (HEAD if not specified). +--no-contains [<object>]:: + Only list refs which don't contain the specified commit (HEAD + if not specified). + --ignore-case:: Sorting and filtering refs are case insensitive.
Documentation/git-tag.txt +5 -1
@@ -12,7 +12,7 @@ SYNOPSIS 'git tag' [-a | -s | -u <keyid>] [-f] [-m <msg> | -F <file>] <tagname> [<commit> | <object>] 'git tag' -d <tagname>... -'git tag' [-n[<num>]] -l [--contains <commit>] [--points-at <object>] +'git tag' [-n[<num>]] -l [--contains <commit>] [--contains <commit>] [--points-at <object>] [--column[=<options>] | --no-column] [--create-reflog] [--sort=<key>] [--format=<format>] [--[no-]merged [<commit>]] [<pattern>...] 'git tag' -v [--format=<format>] <tagname>...
@@ -130,6 +130,10 @@ This option is only applicable when listing tags without annotation lines. Only list tags which contain the specified commit (HEAD if not specified). Implies `--list`. +--no-contains [<commit>]:: + Only list tags which don't contain the specified commit (HEAD if + not specified). Implies `--list`. + --merged [<commit>]:: Only list tags whose commits are reachable from the specified commit (`HEAD` if not specified), incompatible with `--no-merged`.
builtin/branch.c +4 -1
@@ -562,7 +562,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)OPT_SET_INT ('r' ,"remotes" , &filter.kind,N_ ("act on remote-tracking branches" ),FILTER_REFS_REMOTES ),OPT_CONTAINS (&filter.with_commit,N_ ("print only branches that contain the commit" )), +OPT_NO_CONTAINS (&filter.no_commit,N_ ("print only branches that don't contain the commit" )),OPT_WITH (&filter.with_commit,N_ ("print only branches that contain the commit" )), +OPT_WITHOUT (&filter.no_commit,N_ ("print only branches that don't contain the commit" )),OPT__ABBREV (&filter.abbrev), OPT_GROUP(N_("Specific git-branch actions:")),
@@ -618,7 +620,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)if (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc ==0 ) list =1 ; -if (filter.with_commit || filter.merge !=REF_FILTER_MERGED_NONE || filter.points_at.nr) +if (filter.with_commit || filter.merge !=REF_FILTER_MERGED_NONE || filter.points_at.nr || + filter.no_commit) list =1 ; if (!!delete + !!rename + !!new_upstream +
builtin/for-each-ref.c +2 -1
@@ -9,7 +9,7 @@ static char const * const for_each_ref_usage[] = {N_ ("git for-each-ref [<options>] [<pattern>]" ),N_ ("git for-each-ref [--points-at <object>]" ),N_ ("git for-each-ref [(--merged | --no-merged) [<commit>]]" ), -N_ ("git for-each-ref [--contains [<commit>]]" ), +N_ ("git for-each-ref [--contains [<commit>]] [--no-contains [<commit>]]" ), NULL };
@@ -43,6 +43,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)OPT_MERGED (&filter,N_ ("print only refs that are merged" )),OPT_NO_MERGED (&filter,N_ ("print only refs that are not merged" )),OPT_CONTAINS (&filter.with_commit,N_ ("print only refs which contain the commit" )), +OPT_NO_CONTAINS (&filter.no_commit,N_ ("print only refs which don't contain the commit" )),OPT_BOOL (0 ,"ignore-case" , &icase,N_ ("sorting and filtering are case insensitive" )), OPT_END(), };
builtin/tag.c +6 -2
@@ -22,7 +22,7 @@static const char *const git_tag_usage[] = {N_ ("git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] <tagname> [<head>]" ),N_ ("git tag -d <tagname>..." ), -N_ ("git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>]" +N_ ("git tag -l [-n[<num>]] [--contains <commit>] [--no-contains <commit>] [--points-at <object>]" "\n\t\t[--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]" ),N_ ("git tag -v [--format=<format>] <tagname>..." ),NULL
@@ -424,7 +424,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)OPT_GROUP (N_ ("Tag listing options" )),OPT_COLUMN (0 ,"column" , &colopts,N_ ("show tag list in columns" )),OPT_CONTAINS (&filter.with_commit,N_ ("print only tags that contain the commit" )), +OPT_NO_CONTAINS (&filter.no_commit,N_ ("print only tags that don't contain the commit" )),OPT_WITH (&filter.with_commit,N_ ("print only tags that contain the commit" )), +OPT_WITHOUT (&filter.no_commit,N_ ("print only tags that don't contain the commit" )),OPT_MERGED (&filter,N_ ("print only tags that are merged" )),OPT_NO_MERGED (&filter,N_ ("print only tags that are not merged" )), OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"),
@@ -458,7 +460,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)if (!cmdmode) {if (argc ==0 ) cmdmode ='l' ; -else if (filter.with_commit || +else if (filter.with_commit || filter.no_commit || filter.points_at.nr || filter.merge_commit) cmdmode ='l' ; }
@@ -494,6 +496,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)die (_ ("-n option is only allowed in list mode" ));if (filter.with_commit)die (_ ("--contains option is only allowed in list mode" )); +if (filter.no_commit) +die (_ ("--no-contains option is only allowed in list mode" ));if (filter.points_at.nr)die (_ ("--points-at option is only allowed in list mode" ));if (filter.merge_commit)
contrib/completion/git-completion.bash +2 -2
@@ -1093,7 +1093,7 @@ _git_branch () --*) __gitcomp " --color --no-color --verbose --abbrev= --no-abbrev - --track --no-track --contains --merged --no-merged + --track --no-track --contains --no-contains --merged --no-merged --set-upstream-to= --edit-description --list --unset-upstream --delete --move --remotes --column --no-column --sort= --points-at
@@ -2862,7 +2862,7 @@ _git_tag () __gitcomp " --list --delete --verify --annotate --message --file --sign --cleanup --local-user --force --column --sort= - --contains --points-at --merged --no-merged --create-reflog + --contains --no-contains --points-at --merged --no-merged --create-reflog " ;; esac
parse-options.h +3 -1
@@ -258,7 +258,9 @@ extern int parse_opt_passthru_argv(const struct option *, const char *, int); PARSE_OPT_LASTARG_DEFAULT | flag, \ parse_opt_commits, (intptr_t) "HEAD" \ } -#define OPT_CONTAINS (v, h) _OPT_CONTAINS_OR_WITH("contains", v, h, 0) +#define OPT_CONTAINS (v, h) _OPT_CONTAINS_OR_WITH("contains", v, h, PARSE_OPT_NONEG) +#define OPT_NO_CONTAINS (v, h) _OPT_CONTAINS_OR_WITH("no-contains", v, h, PARSE_OPT_NONEG)#define OPT_WITH (v, h) _OPT_CONTAINS_OR_WITH("with", v, h, PARSE_OPT_HIDDEN) +#define OPT_WITHOUT (v, h) _OPT_CONTAINS_OR_WITH("without", v, h, PARSE_OPT_HIDDEN)#endif
ref-filter.c +13 -6
@@ -1487,6 +1487,7 @@ struct ref_filter_cbdata {struct ref_array *array;struct ref_filter *filter;struct contains_cache contains_cache; +struct contains_cache no_contains_cache; };/*
@@ -1586,11 +1587,11 @@ static enum contains_result contains_tag_algo(struct commit *candidate, }static int commit_contains (struct ref_filter *filter,struct commit *commit, -struct contains_cache *cache) +struct commit_list *list,struct contains_cache *cache) {if (filter->with_commit_tag_algo) -return contains_tag_algo (commit, filter->with_commit, cache) ==CONTAINS_YES ; -return is_descendant_of (commit, filter->with_commit); +return contains_tag_algo (commit, list, cache) ==CONTAINS_YES ; +return is_descendant_of (commit, list); }/*
@@ -1780,13 +1781,17 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,* obtain the commit using the 'oid' available and discard all * non-commits early. The actual filtering is done later. */ -if (filter->merge_commit || filter->with_commit || filter->verbose) { +if (filter->merge_commit || filter->with_commit || filter->no_commit || filter->verbose) { commit =lookup_commit_reference_gently (oid->hash,1 );if (!commit)return 0 ; -/* We perform the filtering for the '--contains' option */ +/* We perform the filtering for the '--contains' option... */ if (filter->with_commit && - !commit_contains (filter, commit, &ref_cbdata->contains_cache)) + !commit_contains (filter, commit, filter->with_commit, &ref_cbdata->contains_cache)) +return 0 ; +/* ...or for the `--no-contains' option */ +if (filter->no_commit && +commit_contains (filter, commit, filter->no_commit, &ref_cbdata->no_contains_cache))return 0 ; }
@@ -1887,6 +1892,7 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int filter->kind = type &FILTER_REFS_KIND_MASK ;init_contains_cache (&ref_cbdata.contains_cache); +init_contains_cache (&ref_cbdata.no_contains_cache);/* Simple per-ref filtering */ if (!filter->kind)
@@ -1911,6 +1917,7 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int }clear_contains_cache (&ref_cbdata.contains_cache); +clear_contains_cache (&ref_cbdata.no_contains_cache);/* Filters that need revision walking */ if (filter->merge_commit)
ref-filter.h +1 -0
@@ -53,6 +53,7 @@ struct ref_filter {const char **name_patterns;struct sha1_array points_at;struct commit_list *with_commit; +struct commit_list *no_commit;enum {REF_FILTER_MERGED_NONE =0 ,
t/t3201-branch-contains.sh +51 -3
93 lines not on this page · raw message
t/t6302-for-each-ref-filter.sh +16 -0
@@ -93,6 +93,22 @@ test_expect_success 'filtering with --contains' ' test_cmp expect actual ' +test_expect_success 'filtering with --no-contains' ' + cat >expect <<-\EOF && + refs/tags/one + EOF + git for-each-ref --format="%(refname)" --no-contains=two >actual && + test_cmp expect actual +' + +test_expect_success 'filtering with --contains and --no-contains' ' + cat >expect <<-\EOF && + refs/tags/two + EOF + git for-each-ref --format="%(refname)" --contains=two --no-contains=three >actual && + test_cmp expect actual +' + test_expect_success '%(color) must fail' ' test_must_fail git for-each-ref --format="%(color)%(refname)" '
t/t7004-tag.sh +126 -4
190 lines not on this page · raw message
Signature · 1 line
2.11.0
Re: [PATCH v2 13/16] ref-filter: add --no-contains option to tag/branch/for-each-ref
Quoted 19 lines · Ævar Arnfjörð Bjarmason
Change the tag, branch & for-each-ref commands to have a --no-contains option in addition to their longstanding --contains options.
This allows for finding the last-good rollout tag given a known-bad <commit>. Given a hypothetically bad commit
cf5c7253e0, the git version to revert to can be found with this hacky two-liner:(git tag -l 'v[0-9]*'; git tag -l --contains cf5c7253e0 'v[0-9]*') | sort | uniq -c | grep -E '^ *1 ' | awk '{print $2}' | tail -n 10With this new --no-contains option the same can be achieved with:
git tag -l --no-contains cf5c7253e0 'v[0-9]*' | sort | tail -n 10As the filtering machinery is shared between the tag, branch & for-each-ref commands, implement this for those commands too. A practical use for this with "branch" is e.g. finding branches which were branched off between v2.8.0 and v2.10.0:
Quoted 7 lines
git branch --contains v2.8.0 --no-contains v2.10.0The "describe" command also has a --contains option, but its semantics are unrelated to what tag/branch/for-each-ref use --contains for. A --no-contains option for "describe" wouldn't make any sense, other than being exactly equivalent to not supplying --contains at all, which would be confusing at best.
Nicely explained. Thanks.
parse-options.h extern int parse_opt_passthru_argv(const struct option *, const char *, int); · line 264
Quoted 13 lines
parse-options.h +3
-1@@ -258,7 +258,9 @@ extern int parse_opt_passthru_argv(const struct option *, const char *, int);PARSE_OPT_LASTARG_DEFAULT | flag, \ parse_opt_commits, (intptr_t) "HEAD" \ } -#define OPT_CONTAINS (v, h) _OPT_CONTAINS_OR_WITH("contains", v, h, 0) +#define OPT_CONTAINS (v, h) _OPT_CONTAINS_OR_WITH("contains", v, h, PARSE_OPT_NONEG) +#define OPT_NO_CONTAINS (v, h) _OPT_CONTAINS_OR_WITH("no-contains", v, h, PARSE_OPT_NONEG)#define OPT_WITH (v, h) _OPT_CONTAINS_OR_WITH("with", v, h, PARSE_OPT_HIDDEN) +#define OPT_WITHOUT (v, h) _OPT_CONTAINS_OR_WITH("without", v, h, PARSE_OPT_HIDDEN)
Doesn't OPT_WITHOUT() need PARSE_OPT_NONEG (in addition to HIDDEN), just like OPT_NO_CONTAINS() uses one to reject "--no-no-contains"? Does the code do a sensible thing when --no-without is given?
Re: [PATCH v2 13/16] ref-filter: add --no-contains option to tag/branch/for-each-ref
Quoted 40 lines · Junio C Hamano
Quoted 19 lines · Ævar Arnfjörð Bjarmason
Change the tag, branch & for-each-ref commands to have a --no-contains option in addition to their longstanding --contains options.
This allows for finding the last-good rollout tag given a known-bad <commit>. Given a hypothetically bad commit
cf5c7253e0, the git version to revert to can be found with this hacky two-liner:(git tag -l 'v[0-9]*'; git tag -l --contains cf5c7253e0 'v[0-9]*') | sort | uniq -c | grep -E '^ *1 ' | awk '{print $2}' | tail -n 10With this new --no-contains option the same can be achieved with:
git tag -l --no-contains cf5c7253e0 'v[0-9]*' | sort | tail -n 10As the filtering machinery is shared between the tag, branch & for-each-ref commands, implement this for those commands too. A practical use for this with "branch" is e.g. finding branches which were branched off between v2.8.0 and v2.10.0:
Quoted 7 lines
git branch --contains v2.8.0 --no-contains v2.10.0The "describe" command also has a --contains option, but its semantics are unrelated to what tag/branch/for-each-ref use --contains for. A --no-contains option for "describe" wouldn't make any sense, other than being exactly equivalent to not supplying --contains at all, which would be confusing at best.
Nicely explained. Thanks.
Quoted 9 lines
parse-options.h +0
-1@@ -258,7 +258,9 @@ extern int parse_opt_passthru_argv(const struct option *, const char *, int);PARSE_OPT_LASTARG_DEFAULT | flag, \ parse_opt_commits, (intptr_t) "HEAD" \ } -#define OPT_CONTAINS (v, h) _OPT_CONTAINS_OR_WITH("contains", v, h, 0)
Quoted 8 lines
parse-options.h extern int parse_opt_passthru_argv(const struct option *, const char *, int); · line 264
Quoted 4 lines
parse-options.h +3
-0+#define OPT_CONTAINS (v, h) _OPT_CONTAINS_OR_WITH("contains", v, h, PARSE_OPT_NONEG) +#define OPT_NO_CONTAINS (v, h) _OPT_CONTAINS_OR_WITH("no-contains", v, h, PARSE_OPT_NONEG)#define OPT_WITH (v, h) _OPT_CONTAINS_OR_WITH("with", v, h, PARSE_OPT_HIDDEN) +#define OPT_WITHOUT (v, h) _OPT_CONTAINS_OR_WITH("without", v, h, PARSE_OPT_HIDDEN)Doesn't
OPT_WITHOUT()needPARSE_OPT_NONEG(in addition to HIDDEN), just likeOPT_NO_CONTAINS()uses one to reject "--no-no-contains"? Does the code do a sensible thing when --no-without is given?
Yes, you'd mentioned this before but fixing this got lost in my note taking process for v1->v2. Will fix for v3.
PATCH v2 14/16 ref-filter: reflow recently changed branch/tag/for-each-ref docs
In reply to Ævar Arnfjörð BjarmasonReflow the recently changed branch/tag-for-each-ref documentation. This change shows no changes under --word-diff, except the innocuous change of moving git-tag.txt's "[--sort=<key>]" around slightly.
--- Documentation/git-branch.txt | 15 ++++++++------- Documentation/git-tag.txt | 7 ++++--- 2 files changed, 12 insertions(+), 10 deletions(-)
Documentation/git-branch.txt +8 -7
@@ -10,9 +10,9 @@ SYNOPSIS [verse] 'git branch' [--color[=<when>] | --no-color] [-r | -a] [--list] [-v [--abbrev=<length> | --no-abbrev]] - [--column[=<options>] | --no-column] + [--column[=<options>] | --no-column] [--sort=<key>] [(--merged | --no-merged) [<commit>]] - [--contains [<commit]] [--no-contains [<commit>]] [--sort=<key>] + [--contains [<commit]] [--no-contains [<commit>]] [--points-at <object>] [--format=<format>] [<pattern>...] 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>] 'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]
@@ -36,11 +36,12 @@ as branch creation. With `--contains`, shows only the branches that contain the named commit (in other words, the branches whose tip commits are descendants of the -named commit), `--no-contains` inverts it. With `--merged`, only branches merged into the named -commit (i.e. the branches whose tip commits are reachable from the named -commit) will be listed. With `--no-merged` only branches not merged into -the named commit will be listed. If the <commit> argument is missing it -defaults to `HEAD` (i.e. the tip of the current branch). +named commit), `--no-contains` inverts it. With `--merged`, only branches +merged into the named commit (i.e. the branches whose tip commits are +reachable from the named commit) will be listed. With `--no-merged` only +branches not merged into the named commit will be listed. If the <commit> +argument is missing it defaults to `HEAD` (i.e. the tip of the current +branch). The command's second form creates a new branch head named <branchname> which points to the current `HEAD`, or <start-point> if given.
Documentation/git-tag.txt +4 -3
@@ -12,9 +12,10 @@ SYNOPSIS 'git tag' [-a | -s | -u <keyid>] [-f] [-m <msg> | -F <file>] <tagname> [<commit> | <object>] 'git tag' -d <tagname>... -'git tag' [-n[<num>]] -l [--contains <commit>] [--contains <commit>] [--points-at <object>] - [--column[=<options>] | --no-column] [--create-reflog] [--sort=<key>] - [--format=<format>] [--[no-]merged [<commit>]] [<pattern>...] +'git tag' [-n[<num>]] -l [--contains <commit>] [--contains <commit>] + [--points-at <object>] [--column[=<options>] | --no-column] + [--create-reflog] [--sort=<key>] [--format=<format>] + [--[no-]merged [<commit>]] [<pattern>...] 'git tag' -v [--format=<format>] <tagname>... DESCRIPTION
Signature · 1 line
2.11.0
Re: [PATCH v2 14/16] ref-filter: reflow recently changed branch/tag/for-each-ref docs
Quoted 5 lines · Ævar Arnfjörð Bjarmason
Reflow the recently changed branch/tag-for-each-ref documentation. This change shows no changes under --word-diff, except the innocuous change of moving git-tag.txt's "[--sort=<key>]" around slightly.
---
Thanks.
Needs sign-off (I could just add it back in if you tell me so ;)
Re: [PATCH v2 14/16] ref-filter: reflow recently changed branch/tag/for-each-ref docs
Quoted 11 lines · Junio C Hamano
Quoted 5 lines · Ævar Arnfjörð Bjarmason
Reflow the recently changed branch/tag-for-each-ref documentation. This change shows no changes under --word-diff, except the innocuous change of moving git-tag.txt's "[--sort=<key>]" around slightly.
---Thanks.
Needs sign-off (I could just add it back in if you tell me so ;)
Oops, will fix for v3.
PATCH v2 15/16 tag: implicitly supply --list given the -n option
In reply to Ævar Arnfjörð BjarmasonChange the "tag" command to treat the "-n" invocation as a list-like option in addition to --contains, --points-at etc.
Most of the work for this was done in my earlier "tag: Implicitly supply --list given another list-like option" commit, but I've split off this patch since it's more contentious. Now these will be synonymous:
git tag -n 100
git tag -n --list 100Whereas before the former would die. This doesn't technically introduce any more ambiguity than the aforementioned change applied to th other list-like options, but it does introduce the possibility for more confusion, since instead of the latter of these dying:
git tag -n100
git tag -n 100It now works entirely differently, i.e. invokes list mode with a filter for "100" as a pattern. I.e. it's synonymous with:
git tag -n --list 100
--- Documentation/git-tag.txt | 9 +++++---- builtin/tag.c | 3 ++- t/t7004-tag.sh | 17 ++++++++++++++++- 3 files changed, 23 insertions(+), 6 deletions(-)
Documentation/git-tag.txt +5 -4
@@ -83,10 +83,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::
builtin/tag.c +2 -1
@@ -461,7 +461,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)if (argc ==0 ) cmdmode ='l' ;else if (filter.with_commit || filter.no_commit || - filter.points_at.nr || filter.merge_commit) + filter.points_at.nr || filter.merge_commit || + filter.lines !=-1 ) cmdmode ='l' ; }
t/t7004-tag.sh +16 -1
@@ -639,6 +639,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 &&
@@ -652,6 +657,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 &&
@@ -1569,7 +1585,6 @@ test_expect_success 'mixing incompatibles modes and options is forbidden' ' test_must_fail git tag -a -s -m -F && test_must_fail git tag -a -s -m -F -l && test_must_fail git tag -l -v && - 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 &&
Signature · 1 line
2.11.0
Re: [PATCH v2 15/16] tag: implicitly supply --list given the -n option
Quoted 10 lines · Ævar Arnfjörð Bjarmason
Change the "tag" command to treat the "-n" invocation as a list-like option in addition to --contains, --points-at etc.
Most of the work for this was done in my earlier "tag: Implicitly supply --list given another list-like option" commit, but I've split off this patch since it's more contentious. Now these will be synonymous:
git tag -n 100 git tag -n --list 100
Hmph. I would understand if these meant the same thing:
git tag -l -n 100
git tag -l -n=100
git tag -l -n100with or without "-l". And accepting any of the above three without "-l" instead of rejecting is a very good change, I would think.
I however do not understand how accepting this:
git tag -n --list 100
would be a good thing, as "100" an optional parameter to the "-n" option.
Quoted 5 lines
Whereas before the former would die. This doesn't technically introduce any more ambiguity than the aforementioned change applied to th other list-like options, but it does introduce the possibility for more confusion, since instead of the latter of these dying:
Quoted 7 lines
git tag -n100 git tag -n 100It now works entirely differently, i.e. invokes list mode with a filter for "100" as a pattern. I.e. it's synonymous with:
git tag -n --list 100
Ahhh, yuck. OK, so in "git tag -n --list 100", 100 does not have anything to do with the -n option. It is a pattern and -n specifies "just one line" by default.
Oh, boy, that is confusing. While it is very logical.
Still I think it is OK as I can see why people who wanted to have '-n' in the first place may want
git tag -n -l <pattern>
Thanks.
Re: [PATCH v2 15/16] tag: implicitly supply --list given the -n option
Quoted 46 lines · Junio C Hamano
Quoted 10 lines · Ævar Arnfjörð Bjarmason
Change the "tag" command to treat the "-n" invocation as a list-like option in addition to --contains, --points-at etc.
Most of the work for this was done in my earlier "tag: Implicitly supply --list given another list-like option" commit, but I've split off this patch since it's more contentious. Now these will be synonymous:
git tag -n 100 git tag -n --list 100Hmph. I would understand if these meant the same thing:
git tag -l -n 100 git tag -l -n=100 git tag -l -n100with or without "-l". And accepting any of the above three without "-l" instead of rejecting is a very good change, I would think.
I however do not understand how accepting this:
git tag -n --list 100would be a good thing, as "100" an optional parameter to the "-n" option.
Quoted 5 lines
Whereas before the former would die. This doesn't technically introduce any more ambiguity than the aforementioned change applied to th other list-like options, but it does introduce the possibility for more confusion, since instead of the latter of these dying:
Quoted 7 lines
git tag -n100 git tag -n 100It now works entirely differently, i.e. invokes list mode with a filter for "100" as a pattern. I.e. it's synonymous with:
git tag -n --list 100Ahhh, yuck. OK, so in "git tag -n --list 100", 100 does not have anything to do with the -n option. It is a pattern and -n specifies "just one line" by default.
Quoted 6 lines
Oh, boy, that is confusing. While it is very logical.
Still I think it is OK as I can see why people who wanted to have '-n' in the first place may want
git tag -n -l <pattern>
Yeah I see now that this is rather badly explained. I'll fix this up for v3. All of this worked already:
$ ./git tag 100
$ ./git tag -n -l 100
100 tag: add tests for --with and --without
$ ./git tag -l -n 100
100 tag: add tests for --with and --withoutSo actually thinking about it again it doesn't add any more ambiguity than we had before. The change is just strictly getting rid of the need for -l for consistency with --contains, --points-at etc.
I see now that the whole thing that led me down this golden path was that I was removing the failing "git tag -n 100" test, so while I was still wrapping my mind around this I thought I was introducing some *more* confusion, but really that test was just testing that it didn't work, as opposed to "git tag -l -n 100".
I'm just going to squash this into the "tag: implicitly supply --list given another list-like option" patch for v3 unless you have objections, I think there's no reason to split this off any more than splitting off e.g. --points-at etc.
Re: [PATCH v2 15/16] tag: implicitly supply --list given the -n option
Quoted 9 lines · Ævar Arnfjörð Bjarmason
Yeah I see now that this is rather badly explained. I'll fix this up for v3. All of this worked already:
$ ./git tag 100 $ ./git tag -n -l 100 100 tag: add tests for --with and --without $ ./git tag -l -n 100 100 tag: add tests for --with and --without
Quoted 6 lines
So actually thinking about it again it doesn't add any more ambiguity than we had before. The change is just strictly getting rid of the need for -l for consistency with --contains, --points-at etc.
I see now that the whole thing that led me down this golden path was that I was removing the failing "git tag -n 100" test,...
Wait a minute. I do not think I would agree with the behaviour of the last one, if "tag -l -n 100" is taking 100 as a pattern, not a numerical argument to "-n". That sounds utterly broken.
Is it because we use it OPT_OPTARG, which requires it to be spelled as "-n100" or "-n=100" or somesuch?
In any case, it is not a new confusion this series introduces, so let's include it in the series, but I'd prefer to see it kept as a separate patch, at least for now. Maybe somebody else have an idea to resolve this apparent confusion in a cleaner way.
Thanks.
Re: [PATCH v2 15/16] tag: implicitly supply --list given the -n option
Quoted 22 lines · Junio C Hamano
Quoted 9 lines · Ævar Arnfjörð Bjarmason
Yeah I see now that this is rather badly explained. I'll fix this up for v3. All of this worked already:
$ ./git tag 100 $ ./git tag -n -l 100 100 tag: add tests for --with and --without $ ./git tag -l -n 100 100 tag: add tests for --with and --withoutQuoted 6 lines
So actually thinking about it again it doesn't add any more ambiguity than we had before. The change is just strictly getting rid of the need for -l for consistency with --contains, --points-at etc.
I see now that the whole thing that led me down this golden path was that I was removing the failing "git tag -n 100" test,...
Wait a minute. I do not think I would agree with the behaviour of the last one, if "tag -l -n 100" is taking 100 as a pattern, not a numerical argument to "-n". That sounds utterly broken.
Quoted 7 lines
Is it because we use it
OPT_OPTARG, which requires it to be spelled as "-n100" or "-n=100" or somesuch?In any case, it is not a new confusion this series introduces, so let's include it in the series, but I'd prefer to see it kept as a separate patch, at least for now. Maybe somebody else have an idea to resolve this apparent confusion in a cleaner way.
Yup, that's why. This:
builtin/tag.c +1 -1
@@ -403,7 +403,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)OPT_CMDMODE ('l' ,"list" , &cmdmode,N_ ("list tag names" ),'l' ), { OPTION_INTEGER, 'n', NULL, &filter.lines, N_("n"),N_ ("print <n> lines of each tag message" ), - PARSE_OPT_OPTARG, NULL, 1 }, + 0, NULL, 1 },OPT_CMDMODE ('d' ,"delete" , &cmdmode,N_ ("delete tags" ),'d' ), OPT_CMDMODE('v', "verify", &cmdmode, N_("verify tags"), 'v'),
Changes it so that "git tag -n 100 '*1.6.6*rc*'" does what "git tag -n100 '*1.6.6*rc*'" does. But that breaks a bunch of tests / possibly some scripts in the wild, especially because "git tag -n '*1.6.6*rc*'" now becomes an error, i.e. we'll try to treat the pattern as the numeric argument.
PATCH v2 16/16 tag: add tests for --with and --without
In reply to Ævar Arnfjörð BjarmasonChange the test suite to test for these synonyms for --contains and --no-contains, respectively.
Before this change there were no tests for them at all. This doesn't exhaustively test for them as well as their --contains and --no-contains synonyms, but at least it's something.
--- t/t7004-tag.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
t/t7004-tag.sh +1 -1
@@ -1596,7 +1596,7 @@ test_expect_success 'mixing incompatibles modes and options is forbidden' ' test_must_fail git tag --contains --no-contains ' -for option in --contains --no-contains --merged --no-merged --points-at +for option in --contains --with --no-contains --without --merged --no-merged --points-at do test_expect_success "mixing incompatible modes with $option is forbidden" " test_must_fail git tag -d $option HEAD &&
Signature · 1 line
2.11.0
Quoted 5 lines · Ævar Arnfjörð Bjarmason
This series is now 2x the size of v1. The reason is that the discussion for v1 brought up lots of related side-points that I fixed while I was at it. Most if this *could* be split off, but since a lot of it's modifying the same bits of code doing that would result in merge conflict galore, so I think it's easier to bundle it up.
Whew. v1 was already a tad larger than v0 and now this ;-)
Thanks for a well-written and concise summary below. Makes it much more pleasant to review than without them.