threads / discuss / 6555

finding earliest tags descended from a given commit

Subject: finding earliest tags descended from a given commit

## tl;dr

22 messages between Jan 27, 2007 and Feb 18, 2007.

replies: 21people: 6as markdown or json

J. Bruce Fields· Jan 27, 2007, 04:06 UTC · lore

Just curious: every now and then somebody will ask me what kernel version they need to upgrade to to get some given fix. I can find the commit with the given fix easily enough. How do I then find the earliest tagged version containing that fix?

More generally, given a commit, is there a quick way to find the set of tags which tag commits descended from the given commit? Or to get the subset of such tags which are earliest (in the sense that they're not descendants of any of the others)?

I usually just do
	git-describe <commit>
to make a guess, then
	git log <tag>..<commit>

to verify, but perhaps there's something more clever, or something that would work better in a project where the tags aren't necessarily all in a straight line.

--b.
Shawn O. Pearce· Jan 27, 2007, 04:22 UTC · re: J. Bruce Fields · lore

Re: finding earliest tags descended from a given commit

"J. Bruce Fields" <bfields@fieldses.org> wrote:
> Just curious: every now and then somebody will ask me what kernel
> version they need to upgrade to to get some given fix.  I can find the
> commit with the given fix easily enough.  How do I then find the
> earliest tagged version containing that fix?
git-name-rev commit?

It should give you not only the tag, but how many commits before that tag the fix was made.

-- 
Shawn.
Linus Torvalds· Jan 27, 2007, 04:34 UTC · re: J. Bruce Fields · lore

Re: finding earliest tags descended from a given commit

On Fri, 26 Jan 2007, J. Bruce Fields wrote:
Show 5 quoted lines
>
> Just curious: every now and then somebody will ask me what kernel
> version they need to upgrade to to get some given fix.  I can find the
> commit with the given fix easily enough.  How do I then find the
> earliest tagged version containing that fix?
You can name any revision based on the set of tags you have with:
	git name-rev --tags <sha1-of-commit>

which will try to find the "simplest" way to name something by following one of your tags.

If no tag can be found that reaches that commit, it will say
	<sha1> undefined
but otherwise you will get something like this:
	[torvalds@woody linux]$ git name-rev --tags 7658cc28
	7658cc28 tags/v2.6.20-rc3^0~58

(That's the "VM: Fix nasty and subtle race in shared mmap'ed page writeback commit").

So that basically tells you that it's the 58'th parent of v2.6.20-rc3, ie it was in -rc3, but not in -rc2.

Show 7 quoted lines
> I usually just do
> 
> 	git-describe <commit>
> 
> to make a guess, then
> 
> 	git log <tag>..<commit>

Yeah. That mostly works too, and kind of for the right reason: it's a related operation. But as you can tell, git-describe tells you which version somethign is *based* on, not when it was merged, so while it gives you a starting point for your search, it's not what you want.

Basically 'git descibe' goes the "other way": it walks backwards from the commit to the nearest tag that can be found, while 'git name-rev --tags' walks the history backwards from the tags, and tries to find the commit.

NOTE! 'git name-rev' can in theory be quite expensive, although if you have a packed repository you'll probably never even notice it.

		Linus
J. Bruce Fields· Jan 27, 2007, 04:42 UTC · re: Linus Torvalds · lore

Re: finding earliest tags descended from a given commit

On Fri, Jan 26, 2007 at 08:34:15PM -0800, Linus Torvalds wrote:
Show 13 quoted lines
> On Fri, 26 Jan 2007, J. Bruce Fields wrote:
> >
> > Just curious: every now and then somebody will ask me what kernel
> > version they need to upgrade to to get some given fix.  I can find the
> > commit with the given fix easily enough.  How do I then find the
> > earliest tagged version containing that fix?
> 
> You can name any revision based on the set of tags you have with:
> 
> 	git name-rev --tags <sha1-of-commit>
> 
> which will try to find the "simplest" way to name something by following 
> one of your tags.

That's interesting, I hadn't noticed name-rev before you and Shawn mentioned it.

It only finds one name, though. When I tried it just now on my repository what it found was a tag I'd created for an experimental version, which probably wouldn't be what I wanted. (Though it might be, in some situations.)

--b.
Shawn O. Pearce· Jan 27, 2007, 04:55 UTC · re: J. Bruce Fields · lore

Re: finding earliest tags descended from a given commit

"J. Bruce Fields" <bfields@fieldses.org> wrote:
Show 7 quoted lines
> That's interesting, I hadn't noticed name-rev before you and Shawn
> mentioned it.
> 
> It only finds one name, though. When I tried it just now on my
> repository what it found was a tag I'd created for an experimental
> version, which probably wouldn't be what I wanted.  (Though it might be,
> in some situations.)

Yea. Hmm. Maybe name-rev needs to learn a few more tricks, like favoring annotated tags over non-annotated ones/heads, and being able to print the top n nearest matches (e.g. 10), by displaying only one line of output per tag (or ref).

Right now I'm trying to educate describe some more. Although similar, describe has a much easier job as its very easy for it to say "that's the best name we have for the input". Part of that is because it is favoring annotated tags all of the time, and part of that is because it does this distance computation thing now and always favors the tag with the shortest distance between the tag and the input.

In the case of name-rev I'm thinking maybe its actually the longest distance annotated tag that makes sense. That is, prefer to name the input using the annotated tag which has the shortest distance between the tag and the input, but where the tag is the farthest back in history you can go when compared to any other possible tag, and yet stills contains the input in its ancestry.

-- 
Shawn.
Junio C Hamano· Jan 27, 2007, 05:23 UTC · re: Shawn O. Pearce · lore

Re: finding earliest tags descended from a given commit

"Shawn O. Pearce" <spearce@spearce.org> writes:
Show 13 quoted lines
> "J. Bruce Fields" <bfields@fieldses.org> wrote:
>> That's interesting, I hadn't noticed name-rev before you and Shawn
>> mentioned it.
>> 
>> It only finds one name, though. When I tried it just now on my
>> repository what it found was a tag I'd created for an experimental
>> version, which probably wouldn't be what I wanted.  (Though it might be,
>> in some situations.)
>
> Yea. Hmm.  Maybe name-rev needs to learn a few more tricks, like
> favoring annotated tags over non-annotated ones/heads, and being
> able to print the top n nearest matches (e.g. 10), by displaying
> only one line of output per tag (or ref).

Yeah, I found name-rev to be mostly useless since it almost always names relative to my unannotated "anchor" tag that I use to keep track of 'master' I sent the last "What's in" message for.

I think doing parallel merge-base computation that is in show-branch and the updated describe would be a sensible approach. When somebody says such and such does not work yet in his version, after identifying the commit that introduced that feature, I would run "show-branch $that_rev 'tags/v1.*'" to see which tag(s) contain that revision.

Johannes Schindelin· Jan 27, 2007, 12:39 UTC · re: Junio C Hamano · lore

[PATCH] name-rev: introduce the --ref-filter=<regex> option

Instead of (or, in addition to) --tags, to use only tags for naming, you can now use --ref-filter=<regex> to specify which refs are used for naming.

Example:
	$ git name-rev --ref-filter='/v1' 33db5f4d
	33db5f4d tags/v1.0rc1^0~1593
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
	On Fri, 26 Jan 2007, Junio C Hamano wrote:
	> Yeah, I found name-rev to be mostly useless since it almost
	> always names relative to my unannotated "anchor" tag that I use
	> to keep track of 'master' I sent the last "What's in" message
	> for.
	How about this?
	Though I think you'd use --ref-filter='tags/v[0-9]'. Or you would 
	alias it:
		git-repo-config alias.findver \
			"name-rev --ref-filter='tags/v[0-9]'"
 Documentation/git-name-rev.txt |   14 ++++++++++++--
 builtin-name-rev.c             |   27 +++++++++++++++++++++------
 2 files changed, 33 insertions(+), 8 deletions(-)
diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.txt
index 37fbf66..7de4bea 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 | --ref-filter=<regex>] ( --all | --stdin | <committish>... )
 
 DESCRIPTION
 -----------
@@ -22,6 +22,9 @@ OPTIONS
 --tags::
 	Do not use branch names, but only tags to name the commits
 
+--ref-filter=<regex>::
+	Only use refs for naming which match the regexp
+
 --all::
 	List all commits reachable from all refs
 
@@ -29,7 +32,7 @@ OPTIONS
 	Read from stdin, append "(<rev_name>)" to all sha1's of nameable
 	commits, and pass to stdout
 
-EXAMPLE
+EXAMPLES
 -------
 
 Given a commit, find out where it is relative to the local refs. Say somebody
@@ -52,6 +55,13 @@ Another nice thing you can do is:
 % git log | git name-rev --stdin
 ------------
 
+If you want to name a revision only by a subset of the refs you have, use
+a regular expression to specify the subset:
+
+------------
+$ git name-rev --ref-filter='/v1' 33db5f4d
+33db5f4d tags/v1.0rc1^0~1593
+------------
 
 Author
 ------
diff --git a/builtin-name-rev.c b/builtin-name-rev.c
index b4f15cc..89ea95d 100644
--- a/builtin-name-rev.c
+++ b/builtin-name-rev.c
@@ -3,9 +3,10 @@
 #include "commit.h"
 #include "tag.h"
 #include "refs.h"
+#include <regex.h>
 
 static const char name_rev_usage[] =
-	"git-name-rev [--tags] ( --all | --stdin | committish [committish...] )\n";
+	"git-name-rev [--tags | --ref-filter=<regexp>] ( --all | --stdin | committish [committish...] )\n";
 
 typedef struct rev_name {
 	const char *tip_name;
@@ -74,13 +75,21 @@ copy_data:
 	}
 }
 
+struct name_ref_data {
+	int tags_only;
+	regex_t *ref_filter;
+};
+
 static int name_ref(const char *path, const unsigned char *sha1, int flags, void *cb_data)
 {
 	struct object *o = parse_object(sha1);
-	int tags_only = *(int*)cb_data;
+	struct name_ref_data *data = cb_data;
 	int deref = 0;
 
-	if (tags_only && strncmp(path, "refs/tags/", 10))
+	if (data->tags_only && strncmp(path, "refs/tags/", 10))
+		return 0;
+
+	if (data->ref_filter && regexec(data->ref_filter, path, 0, NULL, 0))
 		return 0;
 
 	while (o && o->type == OBJ_TAG) {
@@ -129,7 +138,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
 {
 	struct object_array revs = { 0, 0, NULL };
 	int as_is = 0, all = 0, transform_stdin = 0;
-	int tags_only = 0;
+	struct name_ref_data data = { 0, NULL };
 
 	git_config(git_default_config);
 
@@ -146,7 +155,13 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
 				as_is = 1;
 				continue;
 			} else if (!strcmp(*argv, "--tags")) {
-				tags_only = 1;
+				data.tags_only = 1;
+				continue;
+			} else  if (!strncmp(*argv, "--ref-filter=", 13)) {
+				data.ref_filter = xmalloc(sizeof(regex_t));
+				if (regcomp(data.ref_filter, *argv + 13,
+							REG_EXTENDED))
+					die ("invalid regexp: %s", *argv + 13);
 				continue;
 			} else if (!strcmp(*argv, "--all")) {
 				if (argc > 1)
@@ -185,7 +200,7 @@ 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);
+	for_each_ref(name_ref, &data);
 
 	if (transform_stdin) {
 		char buffer[2048];
-- 
1.5.0.rc2.g324a-dirty
Johannes Schindelin· Feb 17, 2007, 14:02 UTC · re: Johannes Schindelin · lore

Re: [PATCH] name-rev: introduce the --ref-filter=<regex> option

Hi,
On Sat, 27 Jan 2007, Johannes Schindelin wrote:
Show 8 quoted lines
> Instead of (or, in addition to) --tags, to use only tags for naming,
> you can now use --ref-filter=<regex> to specify which refs are
> used for naming.
> 
> Example:
> 
> 	$ git name-rev --ref-filter='/v1' 33db5f4d
> 	33db5f4d tags/v1.0rc1^0~1593
Likes, dislikes?

Ciao, Dscho

Jeff King· Feb 17, 2007, 14:59 UTC · re: Johannes Schindelin · lore

Re: [PATCH] name-rev: introduce the --ref-filter=<regex> option

On Sat, Feb 17, 2007 at 03:02:36PM +0100, Johannes Schindelin wrote:
Show 10 quoted lines
> > Instead of (or, in addition to) --tags, to use only tags for naming,
> > you can now use --ref-filter=<regex> to specify which refs are
> > used for naming.
> > 
> > Example:
> > 
> > 	$ git name-rev --ref-filter='/v1' 33db5f4d
> > 	33db5f4d tags/v1.0rc1^0~1593
> 
> Likes, dislikes?

It's a neat idea, but I wonder if you could make it even more flexible by simply accepting a list of possible refs, and then you could filter using grep, or your own more complex selection algorithm. Unfortunately, --stdin is already taken, but something like:

git show-ref | grep tags/v1.4 | git name-rev --stdin-refs 33db5f4d

If the stdin ref format includes both the refname and the hash, you could even find 'fake' refs that don't exist in git (e.g., that you get from a foreign SCM; though why you wouldn't just make git tags for them, I don't know).

Or maybe this is just making the problem too complex, and nobody really wants to do it. I certainly don't have a use at this point, but if you're going to do ref filtering, it seems like making it as general as (painlessly) possible is useful.

-Peff
Johannes Schindelin· Feb 17, 2007, 17:50 UTC · re: Jeff King · lore

Re: [PATCH] name-rev: introduce the --ref-filter=<regex> option

Hi,
On Sat, 17 Feb 2007, Jeff King wrote:
Show 16 quoted lines
> On Sat, Feb 17, 2007 at 03:02:36PM +0100, Johannes Schindelin wrote:
> 
> > > Instead of (or, in addition to) --tags, to use only tags for naming,
> > > you can now use --ref-filter=<regex> to specify which refs are
> > > used for naming.
> > > 
> > > Example:
> > > 
> > > 	$ git name-rev --ref-filter='/v1' 33db5f4d
> > > 	33db5f4d tags/v1.0rc1^0~1593
> > 
> > Likes, dislikes?
> 
> It's a neat idea, but I wonder if you could make it even more flexible
> by simply accepting a list of possible refs, and then you could filter
> using grep, or your own more complex selection algorithm.

You can do that with regexps also. And you're right, my code was meant to be simple...

Ciao, Dscho

Junio C Hamano· Feb 17, 2007, 18:25 UTC · re: Jeff King · lore

Re: [PATCH] name-rev: introduce the --ref-filter=<regex> option

Jeff King <peff@peff.net> writes:
Show 19 quoted lines
> On Sat, Feb 17, 2007 at 03:02:36PM +0100, Johannes Schindelin wrote:
>
>> > Instead of (or, in addition to) --tags, to use only tags for naming,
>> > you can now use --ref-filter=<regex> to specify which refs are
>> > used for naming.
>> > 
>> > Example:
>> > 
>> > 	$ git name-rev --ref-filter='/v1' 33db5f4d
>> > 	33db5f4d tags/v1.0rc1^0~1593
>> 
>> Likes, dislikes?
>
> It's a neat idea, but I wonder if you could make it even more flexible
> by simply accepting a list of possible refs, and then you could filter
> using grep, or your own more complex selection algorithm.
> Unfortunately, --stdin is already taken, but something like:
>
> git show-ref | grep tags/v1.4 | git name-rev --stdin-refs 33db5f4d
FWIW, I like that.
Jeff King· Feb 17, 2007, 23:13 UTC · re: Junio C Hamano · lore

[PATCH] git-name-rev: accept list of refs from user

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@peff.net>
---
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
Jeff King· Feb 17, 2007, 23:19 UTC · re: Jeff King · lore

Re: [PATCH] git-name-rev: accept list of refs from user

On Sat, Feb 17, 2007 at 06:13:28PM -0500, Jeff King wrote:
>   git show-ref | grep /v1 | git name-rev --refs-from=- $commit

BTW, I think this should be in addition to, not instead of, Johannes' patch. I think for the simple filtering case, his syntax is much quicker and more natural.

Of course, there will be plenty of conflicts merging them. :) I can do the merge and resubmit after you publish Johannes' patch; just let me know.

-Peff
Junio C Hamano· Feb 17, 2007, 23:30 UTC · re: Jeff King · lore

Re: [PATCH] git-name-rev: accept list of refs from user

Jeff King <peff@peff.net> writes:
Show 11 quoted lines
> On Sat, Feb 17, 2007 at 06:13:28PM -0500, Jeff King wrote:
>
>>   git show-ref | grep /v1 | git name-rev --refs-from=- $commit
>
> BTW, I think this should be in addition to, not instead of, Johannes'
> patch. I think for the simple filtering case, his syntax is much quicker
> and more natural.
>
> Of course, there will be plenty of conflicts merging them. :) I can do
> the merge and resubmit after you publish Johannes' patch; just let me
> know.

I was hoping that everybody would be happy once Johannes's patch is extended to grok more than one --refs=<pattern> options.

Jeff King· Feb 17, 2007, 23:40 UTC · re: Junio C Hamano · lore

Re: [PATCH] git-name-rev: accept list of refs from user

On Sat, Feb 17, 2007 at 03:30:02PM -0800, Junio C Hamano wrote:
> I was hoping that everybody would be happy once Johannes's patch
> is extended to grok more than one --refs=<pattern> options.
I don't think just having text filters easily allows something like:
  git show-ref |
    perl -ne 'print if m#tags/v1\.(\d+)# && $1 > 3' |
    git name-rev --refs-from=- $commit

But I don't know how many people will want to do something that complex. I suppose you could mimic it with many --refs, but the syntax gets a bit painful.

-Peff
Johannes Schindelin· Feb 18, 2007, 00:02 UTC · re: Jeff King · lore

Re: [PATCH] git-name-rev: accept list of refs from user

Hi,
On Sat, 17 Feb 2007, Jeff King wrote:
Show 10 quoted lines
> On Sat, Feb 17, 2007 at 03:30:02PM -0800, Junio C Hamano wrote:
> 
> > I was hoping that everybody would be happy once Johannes's patch
> > is extended to grok more than one --refs=<pattern> options.
> 
> I don't think just having text filters easily allows something like:
> 
>   git show-ref |
>     perl -ne 'print if m#tags/v1\.(\d+)# && $1 > 3' |
>     git name-rev --refs-from=- $commit
Does
	git name-rev --refs='*v1.[4-]*' $commit
what you are trying to achieve?

However, another use case could be where you do not want to tag a certain commit, but want to label it with a certin name just for this call to name-rev. But I don't know how useful that is.

Ciao, Dscho

Junio C Hamano· Feb 17, 2007, 17:42 UTC · re: Johannes Schindelin · lore

Re: [PATCH] name-rev: introduce the --ref-filter=<regex> option

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 10 quoted lines
>> Instead of (or, in addition to) --tags, to use only tags for naming,
>> you can now use --ref-filter=<regex> to specify which refs are
>> used for naming.
>> 
>> Example:
>> 
>> 	$ git name-rev --ref-filter='/v1' 33db5f4d
>> 	33db5f4d tags/v1.0rc1^0~1593
>
> Likes, dislikes?

"Describe these objects in terms of these refs -- do not use any other random refs, even if they are closer" was sorely lacking for it to be usable for me, so I like what it does.

When we talk about path and path-like things including refs I think we consistently use fnmatch not regexp. At least I think we try to.

Johannes Schindelin· Feb 17, 2007, 18:01 UTC · re: Junio C Hamano · lore

Re: [PATCH] name-rev: introduce the --ref-filter=<regex> option

Hi,
On Sat, 17 Feb 2007, Junio C Hamano wrote:
Show 20 quoted lines
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> >> Instead of (or, in addition to) --tags, to use only tags for naming,
> >> you can now use --ref-filter=<regex> to specify which refs are
> >> used for naming.
> >> 
> >> Example:
> >> 
> >> 	$ git name-rev --ref-filter='/v1' 33db5f4d
> >> 	33db5f4d tags/v1.0rc1^0~1593
> >
> > Likes, dislikes?
> 
> "Describe these objects in terms of these refs -- do not use any
> other random refs, even if they are closer" was sorely lacking
> for it to be usable for me, so I like what it does.
> 
> When we talk about path and path-like things including refs
> I think we consistently use fnmatch not regexp.  At least I
> think we try to.
Okay. Will rework.

Ciao, Dscho

Johannes Schindelin· Feb 17, 2007, 18:22 UTC · re: Junio C Hamano · lore

[PATCH] name-rev: introduce the --ref-filter=<pattern> option

Instead of (or, in addition to) --tags, to use only tags for naming, you can now use --ref-filter=<patter> to specify a shell pattern which the refs must match to be used for naming.

Example:
	$ git name-rev --ref-filter=*v1* 33db5f4d
	33db5f4d tags/v1.0rc1^0~1593
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
	On Sat, 17 Feb 2007, Junio C Hamano wrote:
	> When we talk about path and path-like things including refs
	> I think we consistently use fnmatch not regexp.  At least I
	> think we try to.
	And this patch does exactly that.
 Documentation/git-name-rev.txt |    6 +++++-
 builtin-name-rev.c             |   23 +++++++++++++++++------
 2 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.txt
index 37fbf66..a99d60b 100644
--- a/Documentation/git-name-rev.txt
+++ b/Documentation/git-name-rev.txt
@@ -8,7 +8,8 @@ git-name-rev - Find symbolic names for given revs
 
 SYNOPSIS
 --------
-'git-name-rev' [--tags] ( --all | --stdin | <committish>... )
+'git-name-rev' [--tags] [--ref-filter=<pattern>]
+	       ( --all | --stdin | <committish>... )
 
 DESCRIPTION
 -----------
@@ -22,6 +23,9 @@ OPTIONS
 --tags::
 	Do not use branch names, but only tags to name the commits
 
+--ref-filter=<pattern>::
+	Only use refs whose names match a given shell pattern.
+
 --all::
 	List all commits reachable from all refs
 
diff --git a/builtin-name-rev.c b/builtin-name-rev.c
index b4f15cc..615af4b 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 | --ref-filter=<pattern>] ( --all | --stdin | committish [committish...] )\n";
 
 typedef struct rev_name {
 	const char *tip_name;
@@ -74,13 +74,21 @@ copy_data:
 	}
 }
 
+struct name_ref_data {
+	int tags_only;
+	const char *ref_filter;
+};
+
 static int name_ref(const char *path, const unsigned char *sha1, int flags, void *cb_data)
 {
 	struct object *o = parse_object(sha1);
-	int tags_only = *(int*)cb_data;
+	struct name_ref_data *data = cb_data;
 	int deref = 0;
 
-	if (tags_only && strncmp(path, "refs/tags/", 10))
+	if (data->tags_only && strncmp(path, "refs/tags/", 10))
+		return 0;
+
+	if (data->ref_filter && fnmatch(data->ref_filter, path, 0))
 		return 0;
 
 	while (o && o->type == OBJ_TAG) {
@@ -129,7 +137,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
 {
 	struct object_array revs = { 0, 0, NULL };
 	int as_is = 0, all = 0, transform_stdin = 0;
-	int tags_only = 0;
+	struct name_ref_data data = { 0, NULL };
 
 	git_config(git_default_config);
 
@@ -146,7 +154,10 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
 				as_is = 1;
 				continue;
 			} else if (!strcmp(*argv, "--tags")) {
-				tags_only = 1;
+				data.tags_only = 1;
+				continue;
+			} else  if (!strncmp(*argv, "--ref-filter=", 13)) {
+				data.ref_filter = *argv + 13;
 				continue;
 			} else if (!strcmp(*argv, "--all")) {
 				if (argc > 1)
@@ -185,7 +196,7 @@ 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);
+	for_each_ref(name_ref, &data);
 
 	if (transform_stdin) {
 		char buffer[2048];
-- 
1.5.0.2139.gdafc9-dirty
Junio C Hamano· Feb 17, 2007, 18:47 UTC · re: Johannes Schindelin · lore

Re: [PATCH] name-rev: introduce the --ref-filter=<pattern> option

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 8 quoted lines
> Instead of (or, in addition to) --tags, to use only tags for naming,
> you can now use --ref-filter=<patter> to specify a shell pattern
> which the refs must match to be used for naming.
>
> Example:
>
> 	$ git name-rev --ref-filter=*v1* 33db5f4d
> 	33db5f4d tags/v1.0rc1^0~1593

I am sorry I did not mention earlier, but doesn't --ref-filter sound too long? How about '--refs=*v1*'?

No need to resend, just Ack / Nack would do.
Johannes Schindelin· Feb 17, 2007, 23:55 UTC · re: Junio C Hamano · lore

Re: [PATCH] name-rev: introduce the --ref-filter=<pattern> option

Hi,
On Sat, 17 Feb 2007, Junio C Hamano wrote:
Show 15 quoted lines
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > Instead of (or, in addition to) --tags, to use only tags for naming,
> > you can now use --ref-filter=<patter> to specify a shell pattern
> > which the refs must match to be used for naming.
> >
> > Example:
> >
> > 	$ git name-rev --ref-filter=*v1* 33db5f4d
> > 	33db5f4d tags/v1.0rc1^0~1593
> 
> I am sorry I did not mention earlier, but doesn't --ref-filter
> sound too long?  How about '--refs=*v1*'?
> 
> No need to resend, just Ack / Nack would do.

Ack. I am okay with any change, since I will probably not use it anyway. name-rev is usable to me, but since you said it is not to you, I wanted to change _that_.

Ciao, Dscho

Junio C Hamano· Feb 17, 2007, 19:00 UTC · re: Johannes Schindelin · lore

Re: [PATCH] name-rev: introduce the --ref-filter=<pattern> option

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Show 10 quoted lines
> Instead of (or, in addition to) --tags, to use only tags for naming,
> you can now use --ref-filter=<patter> to specify a shell pattern
> which the refs must match to be used for naming.
>
> Example:
>
> 	$ git name-rev --ref-filter=*v1* 33db5f4d
> 	33db5f4d tags/v1.0rc1^0~1593
>
> Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>

Thanks. It's a bit counterintuitive that the first asterisk in your example "*v1*" matches something that contains a slash, but at least the patch makes it usable for me.

By the way, v1.0rc1^0~1593 is the same as v1.0rc1~1593. Technically, the latter loses the information that the starting ref is a tag, but I wonder if it is worth keeping that information at the expense of (slightly) uglier output.

← back to recent threads