* [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).