This lets you do things like git show-ref | grep /v1 | git name-rev --refs-from=- $commit or even git show-ref | ./some_complex_ref_filter >refs git name-rev --refs-from=refs --stdin <list_of_commits Signed-off-by: Jeff King <peff@xxxxxxxx> --- On Sat, Feb 17, 2007 at 10:25:00AM -0800, Junio C Hamano wrote: >> git show-ref | grep tags/v1.4 | git name-rev --stdin-refs 33db5f4d > FWIW, I like that. Here it is (I chose --refs-from= so you could use it with the existing --stdin flag). We might want to do the same for git-describe, I would think (they can probably share the for_each_ref_from_file code). The input format is "sha1 ref"; clearly it could also accept just "ref", and look up the sha1, but I expect most people will just be piping from git-show-ref anyway. Documentation/git-name-rev.txt | 16 +++++++++++- builtin-name-rev.c | 54 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.txt index 37fbf66..d2fb3bb 100644 --- a/Documentation/git-name-rev.txt +++ b/Documentation/git-name-rev.txt @@ -8,7 +8,7 @@ git-name-rev - Find symbolic names for given revs SYNOPSIS -------- -'git-name-rev' [--tags] ( --all | --stdin | <committish>... ) +'git-name-rev' [--tags] [--refs-from=<file>] ( --all | --stdin | <committish>... ) DESCRIPTION ----------- @@ -22,6 +22,13 @@ OPTIONS --tags:: Do not use branch names, but only tags to name the commits +--refs-from=<file>:: + Instead of choosing a name based on all refs, read refs from <file>, + one per line, in the form "sha1 ref". This is the same as the + default output generated by "git show-ref". If <file> is "-", + read from stdin. The --tags option is still respected when using + --refs-from. + --all:: List all commits reachable from all refs @@ -52,6 +59,13 @@ Another nice thing you can do is: % git log | git name-rev --stdin ------------ +You can filter the commits used to describe a commit using the --refs-from +option: + +------------ +% git show-ref | grep tags/v1 | git name-rev --refs-from=- 26cfcfbf +------------ + Author ------ diff --git a/builtin-name-rev.c b/builtin-name-rev.c index b4f15cc..c8480d2 100644 --- a/builtin-name-rev.c +++ b/builtin-name-rev.c @@ -5,7 +5,7 @@ #include "refs.h" static const char name_rev_usage[] = - "git-name-rev [--tags] ( --all | --stdin | committish [committish...] )\n"; +"git-name-rev [--tags] [--refs-from=<file>] ( --all | --stdin | committish ... )"; typedef struct rev_name { const char *tip_name; @@ -14,6 +14,7 @@ typedef struct rev_name { } rev_name; static long cutoff = LONG_MAX; +static const char *refs_from = NULL; static void name_rev(struct commit *commit, const char *tip_name, int merge_traversals, int generation, @@ -103,6 +104,46 @@ static int name_ref(const char *path, const unsigned char *sha1, int flags, void return 0; } +static void trim_trailing_whitespace(char *buf) +{ + int i = strlen(buf) - 1; + while(i >= 0 && isspace(buf[i])) + buf[i--] = '\0'; +} + +static void for_each_ref_from_file(const char *filename, each_ref_fn fn, void *data) +{ + FILE *fh; + char buf[PATH_MAX + 40 + 3]; /* "PATH SHA1\n\0" */ + unsigned char sha1[20]; + + if (!strcmp(filename, "-")) + fh = stdin; + else { + fh = fopen(filename, "r"); + if (!fh) + die("unable to open %s: %s", filename, strerror(errno)); + } + + while (fgets(buf, sizeof buf, fh)) { + char *name; + + trim_trailing_whitespace(buf); + + name = strchr(buf, ' '); + if (!name) + die("invalid input ref format: %s\n", buf); + *name++ = '\0'; + + if (get_sha1_hex(buf, sha1) < 0) + die("invalid sha1: %s\n", buf); + + name_ref(name, sha1, 0, data); + } + + fclose(fh); +} + /* returns a static buffer */ static const char* get_rev_name(struct object *o) { @@ -160,6 +201,9 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) transform_stdin = 1; cutoff = 0; continue; + } else if (!strncmp(*argv, "--refs-from=", 12)) { + refs_from = (*argv)+12; + continue; } usage(name_rev_usage); } @@ -185,7 +229,13 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix) add_object_array((struct object *)commit, *argv, &revs); } - for_each_ref(name_ref, &tags_only); + if (refs_from && !strcmp(refs_from, "-") && transform_stdin) + die("--refs-from=- and --stdin are incompatible!"); + + if (refs_from) + for_each_ref_from_file(refs_from, name_ref, &tags_only); + else + for_each_ref(name_ref, &tags_only); if (transform_stdin) { char buffer[2048]; -- 1.5.0.552.ge1b1c-dirty - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html