author | Junio C Hamano <gitster@pobox.com> | |
Mon, 13 Feb 2012 19:42:15 +0000 (11:42 -0800) | ||
committer | Junio 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
parse_date(): '@' prefix forces git-timestamp
parse_date(): allow ancient git-timestamp
builtin/commit.c | patch | blob | history | |
date.c | patch | blob | history | |
git-sh-setup.sh | patch | blob | history | |
t/t3400-rebase.sh | patch | blob | history |
diff --git a/builtin/commit.c b/builtin/commit.c
index eba1377eb32c02e57c46364c381df940afa66048..2deccb54447d7f66213414914225a97e79049f74 100644 (file)
--- a/builtin/commit.c
+++ b/builtin/commit.c
if (author_message) {
const char *a, *lb, *rb, *eol;
+ size_t len;
a = strstr(author_message_buffer, "\nauthor ");
if (!a)
(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) {
index 353e0a5e53f13c36549e65452931f254de3423c4..a5055ca09dc1fafce2b9434c4fda02ad4f8e117f 100644 (file)
--- a/date.c
+++ b/date.c
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)
*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;
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index 1fba6c2de0b78ddb5aa1495c9c519c26b48eebc2..5d8e4e6c89f0471567a7aa1f07b054d8ac502e15 100644 (file)
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
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 c3555332366d687d04bfbc031b1be808f3caa802..e647272a01f3ac89e1d08e6b1ffa36a3a543e655 100755 (executable)
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
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