branch: allow pattern arguments

Allow pattern arguments for the list mode just like for git tag -l. Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael J Gruber committed Aug 28, 2011 at 16:54 UTC d8d33736b53fb0bef68ca30a64bf7f9ecd872115
3 files changed +46 -5
Documentation/git-branch.txt
+6 -2
@@ -10,7 +10,7 @@ SYNOPSIS
10 [verse]
11 'git branch' [--color[=<when>] | --no-color] [-r | -a]
12 [--list] [-v [--abbrev=<length> | --no-abbrev]]
13 - [(--merged | --no-merged | --contains) [<commit>]]
13 + [(--merged | --no-merged | --contains) [<commit>]] [<pattern>...]
14 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
15 'git branch' (-m | -M) [<oldbranch>] <newbranch>
16 'git branch' (-d | -D) [-r] <branchname>...
@@ -22,6 +22,9 @@ With no arguments, existing branches are listed and the current branch will
22 be highlighted with an asterisk. Option `-r` causes the remote-tracking
23 branches to be listed, and option `-a` shows both. This list mode is also
24 activated by the `--list` and `-v` options (see below).
25 +<pattern> restricts the output to matching branches, the pattern is a shell
26 +wildcard (i.e., matched using fnmatch(3))
27 +Multiple patterns may be given; if any of them matches, the tag is shown.
28
29 With `--contains`, shows only the branches that contain the named commit
30 (in other words, the branches whose tip commits are descendants of the
@@ -112,7 +115,8 @@ OPTIONS
115 List both remote-tracking branches and local branches.
116
117 --list::
115 - Activate the list mode.
118 + Activate the list mode. `git branch <pattern>` would try to create a branch,
119 + use `git branch --list <pattern>` to list matching branches.
120
121 -v::
122 --verbose::
builtin/branch.c
+21 -3
@@ -260,9 +260,22 @@ static char *resolve_symref(const char *src, const char *prefix)
260
261 struct append_ref_cb {
262 struct ref_list *ref_list;
263 + const char **pattern;
264 int ret;
265 };
266
267 +static int match_patterns(const char **pattern, const char *refname)
268 +{
269 + if (!*pattern)
270 + return 1; /* no pattern always matches */
271 + while (*pattern) {
272 + if (!fnmatch(*pattern, refname, 0))
273 + return 1;
274 + pattern++;
275 + }
276 + return 0;
277 +}
278 +
279 static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
280 {
281 struct append_ref_cb *cb = (struct append_ref_cb *)(cb_data);
@@ -297,6 +310,9 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags,
310 if ((kind & ref_list->kinds) == 0)
311 return 0;
312
313 + if (!match_patterns(cb->pattern, refname))
314 + return 0;
315 +
316 commit = NULL;
317 if (ref_list->verbose || ref_list->with_commit || merge_filter != NO_FILTER) {
318 commit = lookup_commit_reference_gently(sha1, 1);
@@ -492,7 +508,7 @@ static void show_detached(struct ref_list *ref_list)
508 }
509 }
510
495 -static int print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit)
511 +static int print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit, const char **pattern)
512 {
513 int i;
514 struct append_ref_cb cb;
@@ -506,6 +522,7 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru
522 if (merge_filter != NO_FILTER)
523 init_revisions(&ref_list.revs, NULL);
524 cb.ref_list = &ref_list;
525 + cb.pattern = pattern;
526 cb.ret = 0;
527 for_each_rawref(append_ref, &cb);
528 if (merge_filter != NO_FILTER) {
@@ -523,7 +540,7 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru
540 qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);
541
542 detached = (detached && (kinds & REF_LOCAL_BRANCH));
526 - if (detached)
543 + if (detached && match_patterns(pattern, "HEAD"))
544 show_detached(&ref_list);
545
546 for (i = 0; i < ref_list.index; i++) {
@@ -708,7 +725,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
725 if (delete)
726 return delete_branches(argc, argv, delete > 1, kinds);
727 else if (list)
711 - return print_ref_list(kinds, detached, verbose, abbrev, with_commit);
728 + return print_ref_list(kinds, detached, verbose, abbrev,
729 + with_commit, argv);
730 else if (rename && (argc == 1))
731 rename_branch(head, argv[0], rename > 1);
732 else if (rename && (argc == 2))
t/t3203-branch-output.sh
+19
@@ -37,6 +37,15 @@ test_expect_success 'git branch --list shows local branches' '
37 test_cmp expect actual
38 '
39
40 +cat >expect <<'EOF'
41 + branch-one
42 + branch-two
43 +EOF
44 +test_expect_success 'git branch --list pattern shows matching local branches' '
45 + git branch --list branch* >actual &&
46 + test_cmp expect actual
47 +'
48 +
49 cat >expect <<'EOF'
50 origin/HEAD -> origin/branch-one
51 origin/branch-one
@@ -71,6 +80,16 @@ test_expect_success 'git branch -v shows branch summaries' '
80 test_cmp expect actual
81 '
82
83 +cat >expect <<'EOF'
84 +two
85 +one
86 +EOF
87 +test_expect_success 'git branch -v pattern shows branch summaries' '
88 + git branch -v branch* >tmp &&
89 + awk "{print \$NF}" <tmp >actual &&
90 + test_cmp expect actual
91 +'
92 +
93 cat >expect <<'EOF'
94 * (no branch)
95 branch-one