From: Junio C Hamano Date: Thu, 2 Feb 2012 21:41:43 +0000 (-0800) Subject: parse_date(): '@' prefix forces git-timestamp X-Git-Tag: v1.7.9.1~7^2 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=2c733fb24c10a9d7aacc51f956bf9b7881980870;p=git.git parse_date(): '@' prefix forces git-timestamp The only place that the issue this series addresses was observed where we read "cat-file commit" output and put it in GIT_AUTHOR_DATE in order to replay a commit with an ancient timestamp. With the previous patch alone, "git commit --date='20100917 +0900'" can be misinterpreted to mean an ancient timestamp, not September in year 2010. Guard this codepath by requring an extra '@' in front of the raw git timestamp on the parsing side. This of course needs to be compensated by updating get_author_ident_from_commit and the code for "git commit --amend" to prepend '@' to the string read from the existing commit in the GIT_AUTHOR_DATE environment variable. Signed-off-by: Junio C Hamano --- diff --git a/builtin/commit.c b/builtin/commit.c index cbc9613ec..bcb0db2db 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -534,6 +534,7 @@ static void determine_author_info(struct strbuf *author_ident) if (author_message) { const char *a, *lb, *rb, *eol; + size_t len; a = strstr(author_message_buffer, "\nauthor "); if (!a) @@ -554,6 +555,11 @@ static void determine_author_info(struct strbuf *author_ident) (a + strlen("\nauthor ")))); email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<"))); date = xmemdupz(rb + strlen("> "), eol - (rb + strlen("> "))); + len = eol - (rb + strlen("> ")); + date = xmalloc(len + 2); + *date = '@'; + memcpy(date + 1, rb + strlen("> "), len); + date[len + 1] = '\0'; } if (force_author) { diff --git a/date.c b/date.c index 099ddbe7f..bf8e088e6 100644 --- a/date.c +++ b/date.c @@ -637,7 +637,8 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset) *offset = -1; tm_gmt = 0; - if (!match_object_header_date(date, timestamp, offset)) + if (*date == '@' && + !match_object_header_date(date + 1, timestamp, offset)) return 0; /* success */ for (;;) { int match = 0; diff --git a/git-sh-setup.sh b/git-sh-setup.sh index 8e427dab3..015fe6e33 100644 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -200,7 +200,7 @@ get_author_ident_from_commit () { s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p g - s/^author [^<]* <[^>]*> \(.*\)$/\1/ + s/^author [^<]* <[^>]*> \(.*\)$/@\1/ s/.*/GIT_AUTHOR_DATE='\''&'\''/p q diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index 6eaecec90..e26e14dd5 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -218,4 +218,27 @@ test_expect_success 'rebase -m can copy notes' ' test "a note" = "$(git notes show HEAD)" ' +test_expect_success 'rebase commit with an ancient timestamp' ' + git reset --hard && + + >old.one && git add old.one && test_tick && + git commit --date="@12345 +0400" -m "Old one" && + >old.two && git add old.two && test_tick && + git commit --date="@23456 +0500" -m "Old two" && + >old.three && git add old.three && test_tick && + git commit --date="@34567 +0600" -m "Old three" && + + git cat-file commit HEAD^^ >actual && + grep "author .* 12345 +0400$" actual && + git cat-file commit HEAD^ >actual && + grep "author .* 23456 +0500$" actual && + git cat-file commit HEAD >actual && + grep "author .* 34567 +0600$" actual && + + git rebase --onto HEAD^^ HEAD^ && + + git cat-file commit HEAD >actual && + grep "author .* 34567 +0600$" actual +' + test_done