diff options
author | Junio C Hamano <junkio@cox.net> | 2006-10-05 23:16:15 -0700 |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2006-10-05 23:17:11 -0700 |
commit | ab2a1a32ffa5a39aaf4204bd717562bce49e0a36 (patch) | |
tree | 21b6b7f63d6e74f023df5d338282b0a75df55c35 | |
parent | 422b4a0e03658d0933a7abc149f175735ea9c4b5 (diff) | |
download | git-ab2a1a32ffa5a39aaf4204bd717562bce49e0a36.tar.gz |
ref-log: allow ref@{count} syntax.
Often I find myself wanting to say 'tip of "next" before I
merged the last three topics'. Now I can say that with:
git log next@{3}..next
Since small integers alone are invalid input strings to
approxidate, there is no fear of confusion.
Signed-off-by: Junio C Hamano <junkio@cox.net>
-rw-r--r-- | refs.c | 6 | ||||
-rw-r--r-- | refs.h | 2 | ||||
-rw-r--r-- | sha1_name.c | 44 |
3 files changed, 32 insertions, 20 deletions
@@ -795,7 +795,7 @@ int write_ref_sha1(struct ref_lock *lock, return 0; } -int read_ref_at(const char *ref, unsigned long at_time, unsigned char *sha1) +int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1) { const char *logfile, *logdata, *logend, *rec, *lastgt, *lastrec; char *tz_c; @@ -828,7 +828,7 @@ int read_ref_at(const char *ref, unsigned long at_time, unsigned char *sha1) if (!lastgt) die("Log %s is corrupt.", logfile); date = strtoul(lastgt + 1, &tz_c, 10); - if (date <= at_time) { + if (date <= at_time || cnt == 0) { if (lastrec) { if (get_sha1_hex(lastrec, logged_sha1)) die("Log %s is corrupt.", logfile); @@ -859,6 +859,8 @@ int read_ref_at(const char *ref, unsigned long at_time, unsigned char *sha1) return 0; } lastrec = rec; + if (cnt > 0) + cnt--; } rec = logdata; @@ -39,7 +39,7 @@ extern void unlock_ref(struct ref_lock *lock); extern int write_ref_sha1(struct ref_lock *lock, const unsigned char *sha1, const char *msg); /** Reads log for the value of ref during at_time. **/ -extern int read_ref_at(const char *ref, unsigned long at_time, unsigned char *sha1); +extern int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1); /** Returns 0 if target has the right format for a ref. **/ extern int check_ref_format(const char *target); diff --git a/sha1_name.c b/sha1_name.c index ed711f2079..e5170336ff 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -249,24 +249,23 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) static const char *warning = "warning: refname '%.*s' is ambiguous.\n"; const char **p, *ref; char *real_ref = NULL; - int refs_found = 0, am; - unsigned long at_time = (unsigned long)-1; + int refs_found = 0; + int at, reflog_len; unsigned char *this_result; unsigned char sha1_from_ref[20]; if (len == 40 && !get_sha1_hex(str, sha1)) return 0; - /* At a given period of time? "@{2 hours ago}" */ - for (am = 1; am < len - 1; am++) { - if (str[am] == '@' && str[am+1] == '{' && str[len-1] == '}') { - int date_len = len - am - 3; - char *date_spec = xmalloc(date_len + 1); - strlcpy(date_spec, str + am + 2, date_len + 1); - at_time = approxidate(date_spec); - free(date_spec); - len = am; - break; + /* basic@{time or number} format to query ref-log */ + reflog_len = 0; + if (str[len-1] == '}') { + for (at = 1; at < len - 1; at++) { + if (str[at] == '@' && str[at+1] == '{') { + reflog_len = (len-1) - (at+2); + len = at; + break; + } } } @@ -291,11 +290,22 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1) if (warn_ambiguous_refs && refs_found > 1) fprintf(stderr, warning, len, str); - if (at_time != (unsigned long)-1) { - read_ref_at( - real_ref, - at_time, - sha1); + if (reflog_len) { + /* Is it asking for N-th entry, or approxidate? */ + int nth, i; + unsigned long at_time; + for (i = nth = 0; 0 <= nth && i < reflog_len; i++) { + char ch = str[at+2+i]; + if ('0' <= ch && ch <= '9') + nth = nth * 10 + ch - '0'; + else + nth = -1; + } + if (0 <= nth) + at_time = 0; + else + at_time = approxidate(str + at + 2); + read_ref_at(real_ref, at_time, nth, sha1); } free(real_ref); |