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 <gitster@pobox.com>
Junio C Hamano committed
Feb 2, 2012 at 13:41 UTC
2c733fb24c10a9d7aacc51f956bf9b7881980870
4 files changed
+32
-2
builtin/commit.c
+6
@@ -534,6 +534,7 @@ static void determine_author_info(struct strbuf *author_ident)
534
535
if (author_message) {
536
const char *a, *lb, *rb, *eol;
537
+ size_t len;
538
539
a = strstr(author_message_buffer, "\nauthor ");
540
if (!a)
@@ -554,6 +555,11 @@ static void determine_author_info(struct strbuf *author_ident)
555
(a + strlen("\nauthor "))));
556
email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
557
date = xmemdupz(rb + strlen("> "), eol - (rb + strlen("> ")));
558
+ len = eol - (rb + strlen("> "));
559
+ date = xmalloc(len + 2);
560
+ *date = '@';
561
+ memcpy(date + 1, rb + strlen("> "), len);
562
+ date[len + 1] = '\0';
563
}
564
565
if (force_author) {
date.c
+2
-1
@@ -637,7 +637,8 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
637
*offset = -1;
638
tm_gmt = 0;
639
640
- if (!match_object_header_date(date, timestamp, offset))
640
+ if (*date == '@' &&
641
+ !match_object_header_date(date + 1, timestamp, offset))
642
return 0; /* success */
643
for (;;) {
644
int match = 0;
git-sh-setup.sh
+1
-1
@@ -200,7 +200,7 @@ get_author_ident_from_commit () {
200
s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
201
202
g
203
- s/^author [^<]* <[^>]*> \(.*\)$/\1/
203
+ s/^author [^<]* <[^>]*> \(.*\)$/@\1/
204
s/.*/GIT_AUTHOR_DATE='\''&'\''/p
205
206
q
t/t3400-rebase.sh
+23
@@ -218,4 +218,27 @@ test_expect_success 'rebase -m can copy notes' '
218
test "a note" = "$(git notes show HEAD)"
219
'
220
221
+test_expect_success 'rebase commit with an ancient timestamp' '
222
+ git reset --hard &&
223
+
224
+ >old.one && git add old.one && test_tick &&
225
+ git commit --date="@12345 +0400" -m "Old one" &&
226
+ >old.two && git add old.two && test_tick &&
227
+ git commit --date="@23456 +0500" -m "Old two" &&
228
+ >old.three && git add old.three && test_tick &&
229
+ git commit --date="@34567 +0600" -m "Old three" &&
230
+
231
+ git cat-file commit HEAD^^ >actual &&
232
+ grep "author .* 12345 +0400$" actual &&
233
+ git cat-file commit HEAD^ >actual &&
234
+ grep "author .* 23456 +0500$" actual &&
235
+ git cat-file commit HEAD >actual &&
236
+ grep "author .* 34567 +0600$" actual &&
237
+
238
+ git rebase --onto HEAD^^ HEAD^ &&
239
+
240
+ git cat-file commit HEAD >actual &&
241
+ grep "author .* 34567 +0600$" actual
242
+'
243
+
244
test_done