{"thread":{"id":"4205","subject":"[PATCH 5/5] Change 'master@noon' syntax to 'master@{noon}'.","startedAt":"2006-05-19T07:29:43Z","lastAt":"2006-05-19T07:29:43Z","messageCount":1,"participants":["Shawn Pearce"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"20276","messageId":"20060519072943.GF22257@spearce.org","threadId":"4205","inReplyTo":null,"subject":"[PATCH 5/5] Change 'master@noon' syntax to 'master@{noon}'.","fromName":"Shawn Pearce","fromEmail":"spearce@spearce.org","sentAt":"2006-05-19T07:29:43Z","receivedAt":"2006-05-19T07:29:43Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Its ambiguous to parse \"master@2006-05-17 18:30:foo\" when foo is\nmeant as a file name and \":30\" is meant as 30 minutes past 6 pm.\nTherefore all date specifications in a sha1 expression must now\nappear within brackets and the ':' splitter used for the path name\nin a sha1 expression ignores ':' appearing within brackets.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n\n---\n\n Documentation/git-rev-parse.txt |   11 ++++----\n sha1_name.c                     |   27 ++++++++++++-------\n t/t1400-update-ref.sh           |   55 ++++++++++++++++++++++++++++-----------\n 3 files changed, 62 insertions(+), 31 deletions(-)\n\neea4ae092b92129ef09e9caf6f6f2b523cd193cb\ndiff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt\nindex df308c3..b894694 100644\n--- a/Documentation/git-rev-parse.txt\n+++ b/Documentation/git-rev-parse.txt\n@@ -124,11 +124,12 @@ syntax.\n   happen to have both heads/master and tags/master, you can\n   explicitly say 'heads/master' to tell git which one you mean.\n \n-* A suffix '@' followed by a date specification such as 'yesterday'\n-  (24 hours ago) or '1 month 2 weeks 3 days 1 hour 1 second ago'\n-  to specify the value of the ref at a prior point in time.\n-  This suffix may only be used immediately following a ref name\n-  and the ref must have an existing log ($GIT_DIR/logs/<ref>).\n+* A suffix '@' followed by a date specification enclosed in a brace\n+  pair (e.g. '\\{yesterday\\}', '\\{1 month 2 weeks 3 days 1 hour 1\n+  second ago\\}' or '\\{1979-02-26 18:30:00\\}') to specify the value\n+  of the ref at a prior point in time.  This suffix may only be\n+  used immediately following a ref name and the ref must have an\n+  existing log ($GIT_DIR/logs/<ref>).\n \n * A suffix '{caret}' to a revision parameter means the first parent of\n   that commit object.  '{caret}<n>' means the <n>th parent (i.e.\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 4376cb3..fbbde1c 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -249,7 +249,7 @@ static int get_sha1_basic(const char *st\n \tstatic const char *warning = \"warning: refname '%.*s' is ambiguous.\\n\";\n \tconst char **p, *pathname;\n \tchar *real_path = NULL;\n-\tint refs_found = 0, at_mark;\n+\tint refs_found = 0, am;\n \tunsigned long at_time = (unsigned long)-1;\n \tunsigned char *this_result;\n \tunsigned char sha1_from_ref[20];\n@@ -257,16 +257,16 @@ static int get_sha1_basic(const char *st\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 (at_mark = 1; at_mark < len; at_mark++) {\n-\t\tif (str[at_mark] == '@') {\n-\t\t\tint date_len = len - at_mark - 1;\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\tstrncpy(date_spec, str + at_mark + 1, date_len);\n+\t\t\tstrncpy(date_spec, str + am + 2, date_len);\n \t\t\tdate_spec[date_len] = 0;\n \t\t\tat_time = approxidate(date_spec);\n \t\t\tfree(date_spec);\n-\t\t\tlen = at_mark;\n+\t\t\tlen = am;\n \t\t\tbreak;\n \t\t}\n \t}\n@@ -482,7 +482,7 @@ static int get_sha1_1(const char *name, \n  */\n int get_sha1(const char *name, unsigned char *sha1)\n {\n-\tint ret;\n+\tint ret, bracket_depth;\n \tunsigned unused;\n \tint namelen = strlen(name);\n \tconst char *cp;\n@@ -528,8 +528,15 @@ int get_sha1(const char *name, unsigned \n \t\t}\n \t\treturn -1;\n \t}\n-\tcp = strchr(name, ':');\n-\tif (cp) {\n+\tfor (cp = name, bracket_depth = 0; *cp; cp++) {\n+\t\tif (*cp == '{')\n+\t\t\tbracket_depth++;\n+\t\telse if (bracket_depth && *cp == '}')\n+\t\t\tbracket_depth--;\n+\t\telse if (!bracket_depth && *cp == ':')\n+\t\t\tbreak;\n+\t}\n+\tif (*cp == ':') {\n \t\tunsigned char tree_sha1[20];\n \t\tif (!get_sha1_1(name, cp-name, tree_sha1))\n \t\t\treturn get_tree_entry(tree_sha1, cp+1, sha1,\ndiff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh\nindex 7858d86..f6b076b 100755\n--- a/t/t1400-update-ref.sh\n+++ b/t/t1400-update-ref.sh\n@@ -125,52 +125,75 @@ ed=\"Thu, 26 May 2005 18:32:00 -0500\"\n gd=\"Thu, 26 May 2005 18:33:00 -0500\"\n ld=\"Thu, 26 May 2005 18:43:00 -0500\"\n test_expect_success \\\n-\t'Query \"master@May 25 2005\" (before history)' \\\n+\t'Query \"master@{May 25 2005}\" (before history)' \\\n \t'rm -f o e\n-\t git-rev-parse --verify \"master@May 25 2005\" >o 2>e &&\n+\t git-rev-parse --verify \"master@{May 25 2005}\" >o 2>e &&\n \t test $C = $(cat o) &&\n \t test \"warning: Log .git/logs/$m only goes back to $ed.\" = \"$(cat e)\"'\n test_expect_success \\\n-\t\"Query master@2005-05-25 (before history)\" \\\n+\t\"Query master@{2005-05-25} (before history)\" \\\n \t'rm -f o e\n-\t git-rev-parse --verify master@2005-05-25 >o 2>e &&\n+\t git-rev-parse --verify master@{2005-05-25} >o 2>e &&\n \t test $C = $(cat o) &&\n \t echo test \"warning: Log .git/logs/$m only goes back to $ed.\" = \"$(cat e)\"'\n test_expect_success \\\n-\t'Query \"master@May 26 2005 23:31:59\" (1 second before history)' \\\n+\t'Query \"master@{May 26 2005 23:31:59}\" (1 second before history)' \\\n \t'rm -f o e\n-\t git-rev-parse --verify \"master@May 26 2005 23:31:59\" >o 2>e &&\n+\t git-rev-parse --verify \"master@{May 26 2005 23:31:59}\" >o 2>e &&\n \t test $C = $(cat o) &&\n \t test \"warning: Log .git/logs/$m only goes back to $ed.\" = \"$(cat e)\"'\n test_expect_success \\\n-\t'Query \"master@May 26 2005 23:32:00\" (exactly history start)' \\\n+\t'Query \"master@{May 26 2005 23:32:00}\" (exactly history start)' \\\n \t'rm -f o e\n-\t git-rev-parse --verify \"master@May 26 2005 23:32:00\" >o 2>e &&\n+\t git-rev-parse --verify \"master@{May 26 2005 23:32:00}\" >o 2>e &&\n \t test $A = $(cat o) &&\n \t test \"\" = \"$(cat e)\"'\n test_expect_success \\\n-\t'Query \"master@2005-05-26 23:33:01\" (middle of history with gap)' \\\n+\t'Query \"master@{2005-05-26 23:33:01}\" (middle of history with gap)' \\\n \t'rm -f o e\n-\t git-rev-parse --verify \"master@2005-05-26 23:33:01\" >o 2>e &&\n+\t git-rev-parse --verify \"master@{2005-05-26 23:33:01}\" >o 2>e &&\n \t test $B = $(cat o) &&\n \t test \"warning: Log .git/logs/$m has gap after $gd.\" = \"$(cat e)\"'\n test_expect_success \\\n-\t'Query \"master@2005-05-26 23:33:01\" (middle of history)' \\\n+\t'Query \"master@{2005-05-26 23:38:00}\" (middle of history)' \\\n \t'rm -f o e\n-\t git-rev-parse --verify \"master@2005-05-26 23:38:00\" >o 2>e &&\n+\t git-rev-parse --verify \"master@{2005-05-26 23:38:00}\" >o 2>e &&\n \t test $Z = $(cat o) &&\n \t test \"\" = \"$(cat e)\"'\n test_expect_success \\\n-\t'Query \"master@2005-05-26 23:43:00\" (exact end of history)' \\\n+\t'Query \"master@{2005-05-26 23:43:00}\" (exact end of history)' \\\n \t'rm -f o e\n-\t git-rev-parse --verify \"master@2005-05-26 23:43:00\" >o 2>e &&\n+\t git-rev-parse --verify \"master@{2005-05-26 23:43:00}\" >o 2>e &&\n \t test $E = $(cat o) &&\n \t test \"\" = \"$(cat e)\"'\n test_expect_success \\\n-\t'Query \"master@2005-05-28\" (past end of history)' \\\n+\t'Query \"master@{2005-05-28}\" (past end of history)' \\\n \t'rm -f o e\n-\t git-rev-parse --verify \"master@2005-05-28\" >o 2>e &&\n+\t git-rev-parse --verify \"master@{2005-05-28}\" >o 2>e &&\n \t test $D = $(cat o) &&\n \t test \"warning: Log .git/logs/$m unexpectedly ended on $ld.\" = \"$(cat e)\"'\n \n+\n+rm -f .git/$m .git/logs/$m expect\n+\n+test_expect_success \\\n+    'creating initial files' \\\n+    'cp ../../COPYING COPYING &&\n+     git-add COPYING &&\n+\t GIT_COMMITTER_DATE=\"2005-05-26 23:30\" git-commit -m add -a &&\n+\t cp ../../Makefile COPYING &&\n+\t GIT_COMMITTER_DATE=\"2005-05-26 23:41\" git-commit -m change -a'\n+\n+test_expect_success \\\n+\t'git-cat-file blob master:COPYING (expect Makefile)' \\\n+\t'git-cat-file blob master:COPYING | diff - ../../Makefile'\n+test_expect_success \\\n+\t'git-cat-file blob master@{2005-05-26 23:30}:COPYING (expect COPYING)' \\\n+\t'git-cat-file blob \"master@{2005-05-26 23:30}:COPYING\" \\\n+\t  | diff - ../../COPYING'\n+test_expect_success \\\n+\t'git-cat-file blob master@{2005-05-26 23:42}:COPYING (expect Makefile)' \\\n+\t'git-cat-file blob \"master@{2005-05-26 23:42}:COPYING\" \\\n+\t  | diff - ../../Makefile'\n+\n test_done\n-- \n1.3.2.g7278\n"}]}