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>
This commit is contained in:
Michael J Gruber 2011-08-28 16:54:32 +02:00 committed by Junio C Hamano
parent cddd127b9a
commit d8d33736b5
3 changed files with 46 additions and 5 deletions

View File

@ -10,7 +10,7 @@ SYNOPSIS
[verse] [verse]
'git branch' [--color[=<when>] | --no-color] [-r | -a] 'git branch' [--color[=<when>] | --no-color] [-r | -a]
[--list] [-v [--abbrev=<length> | --no-abbrev]] [--list] [-v [--abbrev=<length> | --no-abbrev]]
[(--merged | --no-merged | --contains) [<commit>]] [(--merged | --no-merged | --contains) [<commit>]] [<pattern>...]
'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>] 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
'git branch' (-m | -M) [<oldbranch>] <newbranch> 'git branch' (-m | -M) [<oldbranch>] <newbranch>
'git branch' (-d | -D) [-r] <branchname>... 'git branch' (-d | -D) [-r] <branchname>...
@ -22,6 +22,9 @@ With no arguments, existing branches are listed and the current branch will
be highlighted with an asterisk. Option `-r` causes the remote-tracking be highlighted with an asterisk. Option `-r` causes the remote-tracking
branches to be listed, and option `-a` shows both. This list mode is also branches to be listed, and option `-a` shows both. This list mode is also
activated by the `--list` and `-v` options (see below). activated by the `--list` and `-v` options (see below).
<pattern> restricts the output to matching branches, 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.
With `--contains`, shows only the branches that contain the named commit With `--contains`, shows only the branches that contain the named commit
(in other words, the branches whose tip commits are descendants of the (in other words, the branches whose tip commits are descendants of the
@ -112,7 +115,8 @@ OPTIONS
List both remote-tracking branches and local branches. List both remote-tracking branches and local branches.
--list:: --list::
Activate the list mode. Activate the list mode. `git branch <pattern>` would try to create a branch,
use `git branch --list <pattern>` to list matching branches.
-v:: -v::
--verbose:: --verbose::

View File

@ -260,9 +260,22 @@ static char *resolve_symref(const char *src, const char *prefix)
struct append_ref_cb { struct append_ref_cb {
struct ref_list *ref_list; struct ref_list *ref_list;
const char **pattern;
int ret; int ret;
}; };
static int match_patterns(const char **pattern, const char *refname)
{
if (!*pattern)
return 1; /* no pattern always matches */
while (*pattern) {
if (!fnmatch(*pattern, refname, 0))
return 1;
pattern++;
}
return 0;
}
static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data) static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
{ {
struct append_ref_cb *cb = (struct append_ref_cb *)(cb_data); 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,
if ((kind & ref_list->kinds) == 0) if ((kind & ref_list->kinds) == 0)
return 0; return 0;
if (!match_patterns(cb->pattern, refname))
return 0;
commit = NULL; commit = NULL;
if (ref_list->verbose || ref_list->with_commit || merge_filter != NO_FILTER) { if (ref_list->verbose || ref_list->with_commit || merge_filter != NO_FILTER) {
commit = lookup_commit_reference_gently(sha1, 1); commit = lookup_commit_reference_gently(sha1, 1);
@ -492,7 +508,7 @@ static void show_detached(struct ref_list *ref_list)
} }
} }
static int print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit) static int print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit, const char **pattern)
{ {
int i; int i;
struct append_ref_cb cb; struct append_ref_cb cb;
@ -506,6 +522,7 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru
if (merge_filter != NO_FILTER) if (merge_filter != NO_FILTER)
init_revisions(&ref_list.revs, NULL); init_revisions(&ref_list.revs, NULL);
cb.ref_list = &ref_list; cb.ref_list = &ref_list;
cb.pattern = pattern;
cb.ret = 0; cb.ret = 0;
for_each_rawref(append_ref, &cb); for_each_rawref(append_ref, &cb);
if (merge_filter != NO_FILTER) { if (merge_filter != NO_FILTER) {
@ -523,7 +540,7 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru
qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp); qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);
detached = (detached && (kinds & REF_LOCAL_BRANCH)); detached = (detached && (kinds & REF_LOCAL_BRANCH));
if (detached) if (detached && match_patterns(pattern, "HEAD"))
show_detached(&ref_list); show_detached(&ref_list);
for (i = 0; i < ref_list.index; i++) { for (i = 0; i < ref_list.index; i++) {
@ -708,7 +725,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if (delete) if (delete)
return delete_branches(argc, argv, delete > 1, kinds); return delete_branches(argc, argv, delete > 1, kinds);
else if (list) else if (list)
return print_ref_list(kinds, detached, verbose, abbrev, with_commit); return print_ref_list(kinds, detached, verbose, abbrev,
with_commit, argv);
else if (rename && (argc == 1)) else if (rename && (argc == 1))
rename_branch(head, argv[0], rename > 1); rename_branch(head, argv[0], rename > 1);
else if (rename && (argc == 2)) else if (rename && (argc == 2))

View File

@ -37,6 +37,15 @@ test_expect_success 'git branch --list shows local branches' '
test_cmp expect actual test_cmp expect actual
' '
cat >expect <<'EOF'
branch-one
branch-two
EOF
test_expect_success 'git branch --list pattern shows matching local branches' '
git branch --list branch* >actual &&
test_cmp expect actual
'
cat >expect <<'EOF' cat >expect <<'EOF'
origin/HEAD -> origin/branch-one origin/HEAD -> origin/branch-one
origin/branch-one origin/branch-one
@ -71,6 +80,16 @@ test_expect_success 'git branch -v shows branch summaries' '
test_cmp expect actual test_cmp expect actual
' '
cat >expect <<'EOF'
two
one
EOF
test_expect_success 'git branch -v pattern shows branch summaries' '
git branch -v branch* >tmp &&
awk "{print \$NF}" <tmp >actual &&
test_cmp expect actual
'
cat >expect <<'EOF' cat >expect <<'EOF'
* (no branch) * (no branch)
branch-one branch-one