tag: accept multiple patterns for --list
Until now, "git tag -l foo* bar*" would silently ignore the second argument, showing only refs starting with "foo". It's not just unfriendly not to take a second pattern; we actually generated subtly wrong results (from the user's perspective) because some of the requested tags were omitted. This patch allows an arbitrary number of patterns on the command line; if any of them matches, the ref is shown. While we're tweaking the documentation, let's also make it clear that the pattern is fnmatch. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
		
				
					committed by
					
						
						Junio C Hamano
					
				
			
			
				
	
			
			
			
						parent
						
							daab4eeafa
						
					
				
				
					commit
					588d0e834b
				
			@ -12,7 +12,7 @@ SYNOPSIS
 | 
				
			|||||||
'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]
 | 
					'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]
 | 
				
			||||||
	<tagname> [<commit> | <object>]
 | 
						<tagname> [<commit> | <object>]
 | 
				
			||||||
'git tag' -d <tagname>...
 | 
					'git tag' -d <tagname>...
 | 
				
			||||||
'git tag' [-n[<num>]] -l [--contains <commit>] [<pattern>]
 | 
					'git tag' [-n[<num>]] -l [--contains <commit>] [<pattern>...]
 | 
				
			||||||
'git tag' -v <tagname>...
 | 
					'git tag' -v <tagname>...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DESCRIPTION
 | 
					DESCRIPTION
 | 
				
			||||||
@ -69,8 +69,11 @@ OPTIONS
 | 
				
			|||||||
	If the tag is not annotated, the commit message is displayed instead.
 | 
						If the tag is not annotated, the commit message is displayed instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-l <pattern>::
 | 
					-l <pattern>::
 | 
				
			||||||
	List tags with names that match the given pattern (or all if no pattern is given).
 | 
						List tags with names that match the given pattern (or all if no
 | 
				
			||||||
	Typing "git tag" without arguments, also lists all tags.
 | 
						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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
--contains <commit>::
 | 
					--contains <commit>::
 | 
				
			||||||
	Only list tags which contain the specified commit.
 | 
						Only list tags which contain the specified commit.
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,7 @@
 | 
				
			|||||||
static const char * const git_tag_usage[] = {
 | 
					static const char * const git_tag_usage[] = {
 | 
				
			||||||
	"git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
 | 
						"git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
 | 
				
			||||||
	"git tag -d <tagname>...",
 | 
						"git tag -d <tagname>...",
 | 
				
			||||||
	"git tag -l [-n[<num>]] [<pattern>]",
 | 
						"git tag -l [-n[<num>]] [<pattern>...]",
 | 
				
			||||||
	"git tag -v <tagname>...",
 | 
						"git tag -v <tagname>...",
 | 
				
			||||||
	NULL
 | 
						NULL
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -24,17 +24,28 @@ static const char * const git_tag_usage[] = {
 | 
				
			|||||||
static char signingkey[1000];
 | 
					static char signingkey[1000];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct tag_filter {
 | 
					struct tag_filter {
 | 
				
			||||||
	const char *pattern;
 | 
						const char **patterns;
 | 
				
			||||||
	int lines;
 | 
						int lines;
 | 
				
			||||||
	struct commit_list *with_commit;
 | 
						struct commit_list *with_commit;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int match_pattern(const char **patterns, const char *ref)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						/* no pattern means match everything */
 | 
				
			||||||
 | 
						if (!*patterns)
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						for (; *patterns; patterns++)
 | 
				
			||||||
 | 
							if (!fnmatch(*patterns, ref, 0))
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int show_reference(const char *refname, const unsigned char *sha1,
 | 
					static int show_reference(const char *refname, const unsigned char *sha1,
 | 
				
			||||||
			  int flag, void *cb_data)
 | 
								  int flag, void *cb_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tag_filter *filter = cb_data;
 | 
						struct tag_filter *filter = cb_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!fnmatch(filter->pattern, refname, 0)) {
 | 
						if (match_pattern(filter->patterns, refname)) {
 | 
				
			||||||
		int i;
 | 
							int i;
 | 
				
			||||||
		unsigned long size;
 | 
							unsigned long size;
 | 
				
			||||||
		enum object_type type;
 | 
							enum object_type type;
 | 
				
			||||||
@ -88,15 +99,12 @@ static int show_reference(const char *refname, const unsigned char *sha1,
 | 
				
			|||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int list_tags(const char *pattern, int lines,
 | 
					static int list_tags(const char **patterns, int lines,
 | 
				
			||||||
			struct commit_list *with_commit)
 | 
								struct commit_list *with_commit)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tag_filter filter;
 | 
						struct tag_filter filter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pattern == NULL)
 | 
						filter.patterns = patterns;
 | 
				
			||||||
		pattern = "*";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	filter.pattern = pattern;
 | 
					 | 
				
			||||||
	filter.lines = lines;
 | 
						filter.lines = lines;
 | 
				
			||||||
	filter.with_commit = with_commit;
 | 
						filter.with_commit = with_commit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -414,7 +422,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 | 
				
			|||||||
	if (list + delete + verify > 1)
 | 
						if (list + delete + verify > 1)
 | 
				
			||||||
		usage_with_options(git_tag_usage, options);
 | 
							usage_with_options(git_tag_usage, options);
 | 
				
			||||||
	if (list)
 | 
						if (list)
 | 
				
			||||||
		return list_tags(argv[0], lines == -1 ? 0 : lines,
 | 
							return list_tags(argv, lines == -1 ? 0 : lines,
 | 
				
			||||||
				 with_commit);
 | 
									 with_commit);
 | 
				
			||||||
	if (lines != -1)
 | 
						if (lines != -1)
 | 
				
			||||||
		die(_("-n option is only allowed with -l."));
 | 
							die(_("-n option is only allowed with -l."));
 | 
				
			||||||
 | 
				
			|||||||
@ -257,6 +257,11 @@ test_expect_success \
 | 
				
			|||||||
	test_cmp expect actual
 | 
						test_cmp expect actual
 | 
				
			||||||
'
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_expect_success 'tag -l can accept multiple patterns' '
 | 
				
			||||||
 | 
						git tag -l "v1*" "v0*" >actual &&
 | 
				
			||||||
 | 
						test_cmp expect actual
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# creating and verifying lightweight tags:
 | 
					# creating and verifying lightweight tags:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test_expect_success \
 | 
					test_expect_success \
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user