From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH] sha1_name: allow to add @{...} alias via config
Date: Wed, 8 Sep 2010 14:04:01 +1000 [thread overview]
Message-ID: <1283918641-3662-1-git-send-email-pclouds@gmail.com> (raw)
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
next reply other threads:[~2010-09-08 4:04 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-09-08 4:04 Nguyễn Thái Ngọc Duy [this message]
2010-09-08 9:45 ` [PATCH] sha1_name: allow to add @{...} alias via config 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1283918641-3662-1-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).