git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] sha1_name: allow to add @{...} alias via config
@ 2010-09-08  4:04 Nguyễn Thái Ngọc Duy
  2010-09-08  9:45 ` Santi Béjar
  0 siblings, 1 reply; 5+ messages in thread
From: Nguyễn Thái Ngọc Duy @ 2010-09-08  4:04 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

This allows users to add new @{..} alias via ref-at.* config
variables. The rewrite rule is printf-alike.

My itch is I usually work on a topic and only want to see commits in
that topic. So I make a tag to the topic's base, then do

git log base/my-topic..

That is a lot of keystrokes, and my mind is small enough sometimes I
don't even remember the topic name, stucking at "base/  what?"

Now I have "ref-at.base = base/%(tip)" in my gitconfig and I only need
to do "git log @{base}..".

This is probably not the best way to do though. Any advice?

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 cache.h     |    3 ++
 config.c    |    3 ++
 sha1_name.c |  100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 101 insertions(+), 5 deletions(-)

diff --git a/cache.h b/cache.h
index be02a42..bad577d 100644
--- a/cache.h
+++ b/cache.h
@@ -1112,4 +1112,7 @@ extern struct startup_info *startup_info;
 /* builtin/merge.c */
 int checkout_fast_forward(const unsigned char *from, const unsigned char *to);
 
+/* sha1_name.c */
+extern int git_ref_at_config(const char *var, const char *value);
+
 #endif /* CACHE_H */
diff --git a/config.c b/config.c
index cdcf583..b560f51 100644
--- a/config.c
+++ b/config.c
@@ -720,6 +720,9 @@ int git_default_config(const char *var, const char *value, void *dummy)
 	if (!prefixcmp(var, "advice."))
 		return git_default_advice_config(var, value);
 
+	if (!strncmp(var, "ref-at.", 7))
+		return git_ref_at_config(var, value);
+
 	if (!strcmp(var, "pager.color") || !strcmp(var, "color.pager")) {
 		pager_use_color = git_config_bool(var,value);
 		return 0;
diff --git a/sha1_name.c b/sha1_name.c
index 7b7e617..c9987f4 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -7,6 +7,84 @@
 #include "refs.h"
 #include "remote.h"
 
+struct ref_at {
+	const char *mark;
+	const char *format;
+};
+
+static struct ref_at *ref_at;
+static int ref_at_nr;
+
+int git_ref_at_config(const char *var, const char *value)
+{
+	ref_at_nr++;
+	ref_at = xrealloc(ref_at, sizeof(*ref_at)*ref_at_nr);
+	ref_at[ref_at_nr-1].mark = xstrdup(var+7); /* ref-at. */
+	ref_at[ref_at_nr-1].format = xstrdup(value);
+	return 0;
+}
+
+static int substitute_ref_at(struct strbuf *sb, const char *name)
+{
+	int i;
+	const char *at = strchr(name, '@');
+	const char *p, *p2;
+
+	if (!at || at[1] != '{')
+		return -1;
+	for (i = 0; i < ref_at_nr; i++) {
+		int len = strlen(ref_at[i].mark);
+		if (!(at[len+2] == '}' && !strncmp(at+2, ref_at[i].mark, len)))
+			continue;
+
+		p = ref_at[i].format;
+		while (*p) {
+			if (*p != '%') {
+				strbuf_addch(sb, *p);
+				p++;
+				continue;
+			}
+			if (p[1] == '%') {
+				strbuf_addch(sb, '%');
+				p += 2;
+				continue;
+			}
+			if (p[1] != '(') {
+				error("ref-at.%s: '%%%c' not supported", ref_at[i].mark, p[1]);
+				return -1;
+			}
+			p += 2;
+			p2 = strchr(p, ')');
+			if (!p2)
+				return -1;
+			if (!strncmp(p, "branch", p2-p)) {
+				strbuf_add(sb, name, at-name);
+				p = p2+1;
+				continue;
+			}
+			if (!strncmp(p, "tip", p2-p)) {
+				if (at == name || !strncmp(name, "HEAD", at-name)) {
+					unsigned char sha1[20];
+					int flag;
+					const char *real_ref = resolve_ref("HEAD", sha1, 0, &flag);
+					if (!strncmp(real_ref, "refs/heads/", 11))
+						strbuf_addstr(sb, real_ref+11);
+					else
+						strbuf_addstr(sb, real_ref);
+				}
+				else
+					strbuf_add(sb, name, p2-p);
+				p = p2+1;
+				continue;
+			}
+			error("ref-at.%s: '%%(%.*s)' is not supported", ref_at[i].mark, p2-p, p);
+			return -1;
+		}
+		return 1;
+	}
+	return 0;
+}
+
 static int find_short_object_filename(int len, const char *name, unsigned char *sha1)
 {
 	struct alternate_object_database *alt;
@@ -346,6 +424,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 	char *real_ref = NULL;
 	int refs_found = 0;
 	int at, reflog_len;
+	struct strbuf new_str = STRBUF_INIT;
 
 	if (len == 40 && !get_sha1_hex(str, sha1))
 		return 0;
@@ -355,6 +434,11 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 	if (len && str[len-1] == '}') {
 		for (at = len-2; at >= 0; at--) {
 			if (str[at] == '@' && str[at+1] == '{') {
+				if (substitute_ref_at(&new_str, str) >= 0) {
+					str = new_str.buf;
+					len = new_str.len;
+					break;
+				}
 				if (!upstream_mark(str + at, len - at)) {
 					reflog_len = (len-1) - (at+2);
 					len = at;
@@ -366,7 +450,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 
 	/* Accept only unambiguous ref paths. */
 	if (len && ambiguous_path(str, len))
-		return -1;
+		goto failed;
 
 	if (!len && reflog_len) {
 		struct strbuf buf = STRBUF_INIT;
@@ -374,10 +458,11 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 		/* try the @{-N} syntax for n-th checkout */
 		ret = interpret_branch_name(str+at, &buf);
 		if (ret > 0) {
+			strbuf_release(&new_str);
 			/* substitute this branch name and restart */
 			return get_sha1_1(buf.buf, buf.len, sha1);
 		} else if (ret == 0) {
-			return -1;
+			goto failed;
 		}
 		/* allow "@{...}" to mean the current branch reflog */
 		refs_found = dwim_ref("HEAD", 4, sha1, &real_ref);
@@ -387,7 +472,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 		refs_found = dwim_ref(str, len, sha1, &real_ref);
 
 	if (!refs_found)
-		return -1;
+		goto failed;
 
 	if (warn_ambiguous_refs && refs_found > 1)
 		warning(warn_msg, len, str);
@@ -400,7 +485,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 
 		/* a @{-N} placed anywhere except the start is an error */
 		if (str[at+2] == '-')
-			return -1;
+			goto failed;
 
 		/* Is it asking for N-th entry, or approxidate? */
 		for (i = nth = 0; 0 <= nth && i < reflog_len; i++) {
@@ -421,7 +506,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 			at_time = approxidate_careful(tmp, &errors);
 			free(tmp);
 			if (errors)
-				return -1;
+				goto failed;
 		}
 		if (read_ref_at(real_ref, at_time, nth, sha1, NULL,
 				&co_time, &co_tz, &co_cnt)) {
@@ -438,7 +523,12 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 	}
 
 	free(real_ref);
+	strbuf_release(&new_str);
 	return 0;
+
+failed:
+	strbuf_release(&new_str);
+	return -1;
 }
 
 static int get_parent(const char *name, int len,
-- 
1.7.1.rc1.69.g24c2f7

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] sha1_name: allow to add @{...} alias via config
  2010-09-08  4:04 [PATCH] sha1_name: allow to add @{...} alias via config Nguyễn Thái Ngọc Duy
@ 2010-09-08  9:45 ` Santi Béjar
  2010-09-08  9:53   ` Santi Béjar
  2010-09-08 10:11   ` Nguyen Thai Ngoc Duy
  0 siblings, 2 replies; 5+ messages in thread
From: Santi Béjar @ 2010-09-08  9:45 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git

2010/9/8 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>:
> This allows users to add new @{..} alias via ref-at.* config
> variables. The rewrite rule is printf-alike.
>
> My itch is I usually work on a topic and only want to see commits in
> that topic. So I make a tag to the topic's base, then do
>
> git log base/my-topic..
>
> That is a lot of keystrokes, and my mind is small enough sometimes I
> don't even remember the topic name, stucking at "base/  what?"
>
> Now I have "ref-at.base = base/%(tip)" in my gitconfig and I only need
> to do "git log @{base}..".

I like the idea, but I would like something more generic, a ref
transformation or expression (ref-exp?). Currently you can't say
%(tip)@{1}, neither %(tip)^, nor origin/master..origin/%(tip).

Another issue is that it can shadow builtin @{}s, like @{upstream}.

Why %(tip) and not %(branchname), in line with other %() modifiers.

In particular I have a use case for this @{name}. I would like something like:

ref-exp.last = %(tip)@{1}..%(tip)@{0}

so I could do:

git log @{last}
git log origin/master@{last}

Although another way to get it could be:

git log @{1..0}
git log origin/master@{1..0}

Thanks,
Santi

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] sha1_name: allow to add @{...} alias via config
  2010-09-08  9:45 ` Santi Béjar
@ 2010-09-08  9:53   ` Santi Béjar
  2010-09-08 10:12     ` Nguyen Thai Ngoc Duy
  2010-09-08 10:11   ` Nguyen Thai Ngoc Duy
  1 sibling, 1 reply; 5+ messages in thread
From: Santi Béjar @ 2010-09-08  9:53 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy; +Cc: git

2010/9/8 Santi Béjar <santi@agolina.net>:
> 2010/9/8 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>:
>> This allows users to add new @{..} alias via ref-at.* config
>> variables. The rewrite rule is printf-alike.
>
> Another issue is that it can shadow builtin @{}s, like @{upstream}.

In fact this patch breaks @{upstream}.

Santi

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] sha1_name: allow to add @{...} alias via config
  2010-09-08  9:45 ` Santi Béjar
  2010-09-08  9:53   ` Santi Béjar
@ 2010-09-08 10:11   ` Nguyen Thai Ngoc Duy
  1 sibling, 0 replies; 5+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2010-09-08 10:11 UTC (permalink / raw)
  To: Santi Béjar; +Cc: git

2010/9/8 Santi Béjar <santi@agolina.net>:
> 2010/9/8 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>:
>> This allows users to add new @{..} alias via ref-at.* config
>> variables. The rewrite rule is printf-alike.
>>
>> My itch is I usually work on a topic and only want to see commits in
>> that topic. So I make a tag to the topic's base, then do
>>
>> git log base/my-topic..
>>
>> That is a lot of keystrokes, and my mind is small enough sometimes I
>> don't even remember the topic name, stucking at "base/  what?"
>>
>> Now I have "ref-at.base = base/%(tip)" in my gitconfig and I only need
>> to do "git log @{base}..".
>
> I like the idea, but I would like something more generic, a ref
> transformation or expression (ref-exp?). Currently you can't say
> %(tip)@{1}, neither %(tip)^, nor origin/master..origin/%(tip).

The idea is to nail down what kind of expression that should be used.
Then implement it. My first thought was to use a hook, but I thought
it was overkill for ref transformation.

Something like bash variable substitution is probably enough.

> Another issue is that it can shadow builtin @{}s, like @{upstream}.

Yes. I think @{upstream} can be put in to ref-transformation list at
startup. That way it always gets precedence.

> Why %(tip) and not %(branchname), in line with other %() modifiers.

Oh.. I picked whatever name I had in my mind. @(branchname) of @(branch)
sounds good.

> In particular I have a use case for this @{name}. I would like something like:
>
> ref-exp.last = %(tip)@{1}..%(tip)@{0}

Yeah I was tempted too after writing the patch. It's a revision range,
not a reference anymore. But from user perspective it's pretty much
the same. And transformation rule would be the same. Hmm.. tempting.
-- 
Duy

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] sha1_name: allow to add @{...} alias via config
  2010-09-08  9:53   ` Santi Béjar
@ 2010-09-08 10:12     ` Nguyen Thai Ngoc Duy
  0 siblings, 0 replies; 5+ messages in thread
From: Nguyen Thai Ngoc Duy @ 2010-09-08 10:12 UTC (permalink / raw)
  To: Santi Béjar; +Cc: git

2010/9/8 Santi Béjar <santi@agolina.net>:
> 2010/9/8 Santi Béjar <santi@agolina.net>:
>> 2010/9/8 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>:
>>> This allows users to add new @{..} alias via ref-at.* config
>>> variables. The rewrite rule is printf-alike.
>>
>> Another issue is that it can shadow builtin @{}s, like @{upstream}.
>
> In fact this patch breaks @{upstream}.

My fault. There should not be an equal in

if (substitute_ref_at(&new_str, str) >= 0)
-- 
Duy

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-09-08 10:16 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-08  4:04 [PATCH] sha1_name: allow to add @{...} alias via config Nguyễn Thái Ngọc Duy
2010-09-08  9:45 ` Santi Béjar
2010-09-08  9:53   ` Santi Béjar
2010-09-08 10:12     ` Nguyen Thai Ngoc Duy
2010-09-08 10:11   ` Nguyen Thai Ngoc Duy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).