Skip to content

Commit 3d8bc74

Browse files
committed
Merge branch 'jc/parse-date-raw'
* jc/parse-date-raw: parse_date(): '@' prefix forces git-timestamp parse_date(): allow ancient git-timestamp
2 parents fd6abd0 + 2c733fb commit 3d8bc74

File tree

4 files changed

+60
-1
lines changed

4 files changed

+60
-1
lines changed

builtin/commit.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ static void determine_author_info(struct strbuf *author_ident)
543543

544544
if (author_message) {
545545
const char *a, *lb, *rb, *eol;
546+
size_t len;
546547

547548
a = strstr(author_message_buffer, "\nauthor ");
548549
if (!a)
@@ -563,6 +564,11 @@ static void determine_author_info(struct strbuf *author_ident)
563564
(a + strlen("\nauthor "))));
564565
email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
565566
date = xmemdupz(rb + strlen("> "), eol - (rb + strlen("> ")));
567+
len = eol - (rb + strlen("> "));
568+
date = xmalloc(len + 2);
569+
*date = '@';
570+
memcpy(date + 1, rb + strlen("> "), len);
571+
date[len + 1] = '\0';
566572
}
567573

568574
if (force_author) {

date.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,33 @@ static int date_string(unsigned long date, int offset, char *buf, int len)
597597
return snprintf(buf, len, "%lu %c%02d%02d", date, sign, offset / 60, offset % 60);
598598
}
599599

600+
/*
601+
* Parse a string like "0 +0000" as ancient timestamp near epoch, but
602+
* only when it appears not as part of any other string.
603+
*/
604+
static int match_object_header_date(const char *date, unsigned long *timestamp, int *offset)
605+
{
606+
char *end;
607+
unsigned long stamp;
608+
int ofs;
609+
610+
if (*date < '0' || '9' <= *date)
611+
return -1;
612+
stamp = strtoul(date, &end, 10);
613+
if (*end != ' ' || stamp == ULONG_MAX || (end[1] != '+' && end[1] != '-'))
614+
return -1;
615+
date = end + 2;
616+
ofs = strtol(date, &end, 10);
617+
if ((*end != '\0' && (*end != '\n')) || end != date + 4)
618+
return -1;
619+
ofs = (ofs / 100) * 60 + (ofs % 100);
620+
if (date[-1] == '-')
621+
ofs = -ofs;
622+
*timestamp = stamp;
623+
*offset = ofs;
624+
return 0;
625+
}
626+
600627
/* Gr. strptime is crap for this; it doesn't have a way to require RFC2822
601628
(i.e. English) day/month names, and it doesn't work correctly with %z. */
602629
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)
622649
*offset = -1;
623650
tm_gmt = 0;
624651

652+
if (*date == '@' &&
653+
!match_object_header_date(date + 1, timestamp, offset))
654+
return 0; /* success */
625655
for (;;) {
626656
int match = 0;
627657
unsigned char c = *date;

git-sh-setup.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ get_author_ident_from_commit () {
200200
s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
201201
202202
g
203-
s/^author [^<]* <[^>]*> \(.*\)$/\1/
203+
s/^author [^<]* <[^>]*> \(.*\)$/@\1/
204204
s/.*/GIT_AUTHOR_DATE='\''&'\''/p
205205
206206
q

t/t3400-rebase.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,4 +218,27 @@ test_expect_success 'rebase -m can copy notes' '
218218
test "a note" = "$(git notes show HEAD)"
219219
'
220220

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+
221244
test_done

0 commit comments

Comments
 (0)