{"thread":{"id":"5831","subject":"[PATCH] ref-log: allow ref@{count} syntax.","startedAt":"2006-10-06T06:16:15Z","lastAt":"2006-10-06T16:05:21Z","messageCount":2,"participants":["Junio C Hamano","Shawn Pearce"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"28271","messageId":"7vsli20y1c.fsf@assigned-by-dhcp.cox.net","threadId":"5831","inReplyTo":null,"subject":"[PATCH] ref-log: allow ref@{count} syntax.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-10-06T06:16:15Z","receivedAt":"2006-10-06T06:16:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Often I find myself wanting to say 'tip of \"next\" before I\nmerged the last three topics'.  Now I can say that with:\n\n\tgit log next@{3}..next\n\nSince small integers alone are invalid input strings to\napproxidate, there is no fear of confusion.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n * The implementation is rather hacky but I think this is\n   mildly useful.  Likes, dislikes?\n\n refs.c      |    6 ++++--\n refs.h      |    2 +-\n sha1_name.c |   44 +++++++++++++++++++++++++++-----------------\n 3 files changed, 32 insertions(+), 20 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 305c1a9..d7f4aa5 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -795,7 +795,7 @@ int write_ref_sha1(struct ref_lock *lock\n \treturn 0;\n }\n \n-int read_ref_at(const char *ref, unsigned long at_time, unsigned char *sha1)\n+int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1)\n {\n \tconst char *logfile, *logdata, *logend, *rec, *lastgt, *lastrec;\n \tchar *tz_c;\n@@ -828,7 +828,7 @@ int read_ref_at(const char *ref, unsigne\n \t\tif (!lastgt)\n \t\t\tdie(\"Log %s is corrupt.\", logfile);\n \t\tdate = strtoul(lastgt + 1, &tz_c, 10);\n-\t\tif (date <= at_time) {\n+\t\tif (date <= at_time || cnt == 0) {\n \t\t\tif (lastrec) {\n \t\t\t\tif (get_sha1_hex(lastrec, logged_sha1))\n \t\t\t\t\tdie(\"Log %s is corrupt.\", logfile);\n@@ -859,6 +859,8 @@ int read_ref_at(const char *ref, unsigne\n \t\t\treturn 0;\n \t\t}\n \t\tlastrec = rec;\n+\t\tif (cnt > 0)\n+\t\t\tcnt--;\n \t}\n \n \trec = logdata;\ndiff --git a/refs.h b/refs.h\nindex 0d4d79e..a57d437 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -39,7 +39,7 @@ extern void unlock_ref(struct ref_lock *\n extern int write_ref_sha1(struct ref_lock *lock, const unsigned char *sha1, const char *msg);\n \n /** Reads log for the value of ref during at_time. **/\n-extern int read_ref_at(const char *ref, unsigned long at_time, unsigned char *sha1);\n+extern int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1);\n \n /** Returns 0 if target has the right format for a ref. **/\n extern int check_ref_format(const char *target);\ndiff --git a/sha1_name.c b/sha1_name.c\nindex ed711f2..e517033 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -249,24 +249,23 @@ static int get_sha1_basic(const char *st\n \tstatic const char *warning = \"warning: refname '%.*s' is ambiguous.\\n\";\n \tconst char **p, *ref;\n \tchar *real_ref = NULL;\n-\tint refs_found = 0, am;\n-\tunsigned long at_time = (unsigned long)-1;\n+\tint refs_found = 0;\n+\tint at, reflog_len;\n \tunsigned char *this_result;\n \tunsigned char sha1_from_ref[20];\n \n \tif (len == 40 && !get_sha1_hex(str, sha1))\n \t\treturn 0;\n \n-\t/* At a given period of time? \"@{2 hours ago}\" */\n-\tfor (am = 1; am < len - 1; am++) {\n-\t\tif (str[am] == '@' && str[am+1] == '{' && str[len-1] == '}') {\n-\t\t\tint date_len = len - am - 3;\n-\t\t\tchar *date_spec = xmalloc(date_len + 1);\n-\t\t\tstrlcpy(date_spec, str + am + 2, date_len + 1);\n-\t\t\tat_time = approxidate(date_spec);\n-\t\t\tfree(date_spec);\n-\t\t\tlen = am;\n-\t\t\tbreak;\n+\t/* basic@{time or number} format to query ref-log */\n+\treflog_len = 0;\n+\tif (str[len-1] == '}') {\n+\t\tfor (at = 1; at < len - 1; at++) {\n+\t\t\tif (str[at] == '@' && str[at+1] == '{') {\n+\t\t\t\treflog_len = (len-1) - (at+2);\n+\t\t\t\tlen = at;\n+\t\t\t\tbreak;\n+\t\t\t}\n \t\t}\n \t}\n \n@@ -291,11 +290,22 @@ static int get_sha1_basic(const char *st\n \tif (warn_ambiguous_refs && refs_found > 1)\n \t\tfprintf(stderr, warning, len, str);\n \n-\tif (at_time != (unsigned long)-1) {\n-\t\tread_ref_at(\n-\t\t\treal_ref,\n-\t\t\tat_time,\n-\t\t\tsha1);\n+\tif (reflog_len) {\n+\t\t/* Is it asking for N-th entry, or approxidate? */\n+\t\tint nth, i;\n+\t\tunsigned long at_time;\n+\t\tfor (i = nth = 0; 0 <= nth && i < reflog_len; i++) {\n+\t\t\tchar ch = str[at+2+i];\n+\t\t\tif ('0' <= ch && ch <= '9')\n+\t\t\t\tnth = nth * 10 + ch - '0';\n+\t\t\telse\n+\t\t\t\tnth = -1;\n+\t\t}\n+\t\tif (0 <= nth)\n+\t\t\tat_time = 0;\n+\t\telse\n+\t\t\tat_time = approxidate(str + at + 2);\n+\t\tread_ref_at(real_ref, at_time, nth, sha1);\n \t}\n \n \tfree(real_ref);\n-- \n1.4.2.3.gae59\n"},{"id":"28296","messageId":"20061006160521.GA20024@spearce.org","threadId":"5831","inReplyTo":"7vsli20y1c.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] ref-log: allow ref@{count} syntax.","fromName":"Shawn Pearce","fromEmail":"spearce@spearce.org","sentAt":"2006-10-06T16:05:21Z","receivedAt":"2006-10-06T16:05:21Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Junio C Hamano <junkio@cox.net> wrote:\n> Often I find myself wanting to say 'tip of \"next\" before I\n> merged the last three topics'.  Now I can say that with:\n> \n> \tgit log next@{3}..next\n> \n> Since small integers alone are invalid input strings to\n> approxidate, there is no fear of confusion.\n> \n> Signed-off-by: Junio C Hamano <junkio@cox.net>\n> ---\n> \n>  * The implementation is rather hacky but I think this is\n>    mildly useful.  Likes, dislikes?\n\nAck'd.\n\nIts a useful feature. Something I've been wanting myself for\nsome time.  I usually just guess with '@{5.minutes.ago}' or some\nnonsense until I find the right time.  But since I know it was X\noperations ago, '@{X}' will be very handy.  Thanks!\n\n-- \nShawn.\n"}]}