Code

Merge branch 'jc/parse-date-raw' into maint
authorJunio C Hamano <gitster@pobox.com>
Mon, 13 Feb 2012 19:42:15 +0000 (11:42 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 13 Feb 2012 19:42:15 +0000 (11:42 -0800)
* jc/parse-date-raw:
  parse_date(): '@' prefix forces git-timestamp
  parse_date(): allow ancient git-timestamp

builtin/commit.c
date.c
git-sh-setup.sh
t/t3400-rebase.sh

index eba1377eb32c02e57c46364c381df940afa66048..2deccb54447d7f66213414914225a97e79049f74 100644 (file)
@@ -543,6 +543,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)
@@ -563,6 +564,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 353e0a5e53f13c36549e65452931f254de3423c4..a5055ca09dc1fafce2b9434c4fda02ad4f8e117f 100644 (file)
--- a/date.c
+++ b/date.c
@@ -597,6 +597,33 @@ static int date_string(unsigned long date, int offset, char *buf, int len)
        return snprintf(buf, len, "%lu %c%02d%02d", date, sign, offset / 60, offset % 60);
 }
 
+/*
+ * Parse a string like "0 +0000" as ancient timestamp near epoch, but
+ * only when it appears not as part of any other string.
+ */
+static int match_object_header_date(const char *date, unsigned long *timestamp, int *offset)
+{
+       char *end;
+       unsigned long stamp;
+       int ofs;
+
+       if (*date < '0' || '9' <= *date)
+               return -1;
+       stamp = strtoul(date, &end, 10);
+       if (*end != ' ' || stamp == ULONG_MAX || (end[1] != '+' && end[1] != '-'))
+               return -1;
+       date = end + 2;
+       ofs = strtol(date, &end, 10);
+       if ((*end != '\0' && (*end != '\n')) || end != date + 4)
+               return -1;
+       ofs = (ofs / 100) * 60 + (ofs % 100);
+       if (date[-1] == '-')
+               ofs = -ofs;
+       *timestamp = stamp;
+       *offset = ofs;
+       return 0;
+}
+
 /* Gr. strptime is crap for this; it doesn't have a way to require RFC2822
    (i.e. English) day/month names, and it doesn't work correctly with %z. */
 int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
@@ -622,6 +649,9 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
        *offset = -1;
        tm_gmt = 0;
 
+       if (*date == '@' &&
+           !match_object_header_date(date + 1, timestamp, offset))
+               return 0; /* success */
        for (;;) {
                int match = 0;
                unsigned char c = *date;
index 1fba6c2de0b78ddb5aa1495c9c519c26b48eebc2..5d8e4e6c89f0471567a7aa1f07b054d8ac502e15 100644 (file)
@@ -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
index c3555332366d687d04bfbc031b1be808f3caa802..e647272a01f3ac89e1d08e6b1ffa36a3a543e655 100755 (executable)
@@ -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