mirror of
https://github.com/git/git.git
synced 2024-11-24 10:26:17 +08:00
show-branch: allow glob pattern to name branches to show.
With this, you can say "git-show-branch topic/* master" to show all the topic branches you have under .git/refs/heads/topic/ and your master branch. Another example is "git-show-branch --list v1.0*" to show all the v1.0 tags. You can disambiguate by saying "heads/topic/*" to show only topic branches if you have tags under .git/refs/tags/topic/ as well. Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
7b9b4c452c
commit
287f860054
@ -7,18 +7,29 @@ git-show-branch - Show branches and their commits.
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-show-branch [--all] [--heads] [--tags] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] <reference>...'
|
||||
'git-show-branch [--all] [--heads] [--tags] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] [<rev> | <glob>]...'
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Shows the head commits from the named <reference> (or all refs under
|
||||
$GIT_DIR/refs/heads), and displays concise list of commit logs
|
||||
to show their relationship semi-visually.
|
||||
|
||||
Shows the commit ancestry graph starting from the commits named
|
||||
with <rev>s or <globs>s (or all refs under $GIT_DIR/refs/heads
|
||||
and/or $GIT_DIR/refs/tags) semi-visually.
|
||||
|
||||
It cannot show more than 29 branches and commits at a time.
|
||||
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
<reference>::
|
||||
Name of the reference under $GIT_DIR/refs/.
|
||||
<rev>::
|
||||
Arbitrary extended SHA1 expression (see `git-rev-parse`)
|
||||
that typically names a branch HEAD or a tag.
|
||||
|
||||
<glob>::
|
||||
A glob pattern that matches branch or tag names under
|
||||
$GIT_DIR/refs. For example, if you have many topic
|
||||
branches under $GIT_DIR/refs/heads/topic, giving
|
||||
`topic/*` would show all of them.
|
||||
|
||||
--all --heads --tags::
|
||||
Show all refs under $GIT_DIR/refs, $GIT_DIR/refs/heads,
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <stdlib.h>
|
||||
#include <fnmatch.h>
|
||||
#include "cache.h"
|
||||
#include "commit.h"
|
||||
#include "refs.h"
|
||||
@ -332,6 +333,39 @@ static int append_tag_ref(const char *refname, const unsigned char *sha1)
|
||||
return append_ref(refname + 5, sha1);
|
||||
}
|
||||
|
||||
static const char *match_ref_pattern = NULL;
|
||||
static int match_ref_slash = 0;
|
||||
static int count_slash(const char *s)
|
||||
{
|
||||
int cnt = 0;
|
||||
while (*s)
|
||||
if (*s++ == '/')
|
||||
cnt++;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static int append_matching_ref(const char *refname, const unsigned char *sha1)
|
||||
{
|
||||
/* we want to allow pattern hold/<asterisk> to show all
|
||||
* branches under refs/heads/hold/, and v0.99.9? to show
|
||||
* refs/tags/v0.99.9a and friends.
|
||||
*/
|
||||
const char *tail;
|
||||
int slash = count_slash(refname);
|
||||
for (tail = refname; *tail && match_ref_slash < slash; )
|
||||
if (*tail++ == '/')
|
||||
slash--;
|
||||
if (!*tail)
|
||||
return 0;
|
||||
if (fnmatch(match_ref_pattern, tail, 0))
|
||||
return 0;
|
||||
if (!strncmp("refs/heads/", refname, 11))
|
||||
return append_head_ref(refname, sha1);
|
||||
if (!strncmp("refs/tags/", refname, 10))
|
||||
return append_tag_ref(refname, sha1);
|
||||
return append_ref(refname, sha1);
|
||||
}
|
||||
|
||||
static void snarf_refs(int head, int tag)
|
||||
{
|
||||
if (head) {
|
||||
@ -400,6 +434,27 @@ static int show_independent(struct commit **rev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void append_one_rev(const char *av)
|
||||
{
|
||||
unsigned char revkey[20];
|
||||
if (!get_sha1(av, revkey)) {
|
||||
append_ref(av, revkey);
|
||||
return;
|
||||
}
|
||||
if (strchr(av, '*') || strchr(av, '?')) {
|
||||
/* glob style match */
|
||||
int saved_matches = ref_name_cnt;
|
||||
match_ref_pattern = av;
|
||||
match_ref_slash = count_slash(av);
|
||||
for_each_ref(append_matching_ref);
|
||||
if (saved_matches == ref_name_cnt &&
|
||||
ref_name_cnt < MAX_REVS)
|
||||
error("no matching refs with %s", av);
|
||||
return;
|
||||
}
|
||||
die("bad sha1 reference %s", av);
|
||||
}
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
struct commit *rev[MAX_REVS], *commit;
|
||||
@ -458,17 +513,20 @@ int main(int ac, char **av)
|
||||
if (all_heads + all_tags)
|
||||
snarf_refs(all_heads, all_tags);
|
||||
|
||||
while (0 < ac) {
|
||||
unsigned char revkey[20];
|
||||
if (get_sha1(*av, revkey))
|
||||
die("bad sha1 reference %s", *av);
|
||||
append_ref(*av, revkey);
|
||||
ac--; av++;
|
||||
if (ac) {
|
||||
while (0 < ac) {
|
||||
append_one_rev(*av);
|
||||
ac--; av++;
|
||||
}
|
||||
}
|
||||
|
||||
/* If still no revs, then add heads */
|
||||
if (!ref_name_cnt)
|
||||
else {
|
||||
/* If no revs given, then add heads */
|
||||
snarf_refs(1, 0);
|
||||
}
|
||||
if (!ref_name_cnt) {
|
||||
fprintf(stderr, "No revs to be shown.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
for (num_rev = 0; ref_name[num_rev]; num_rev++) {
|
||||
unsigned char revkey[20];
|
||||
|
Loading…
Reference in New Issue
Block a user