Merge branch 'jc/parse-date-raw'
* jc/parse-date-raw: parse_date(): '@' prefix forces git-timestamp parse_date(): allow ancient git-timestamp
This commit is contained in:
commit
3d8bc74127
@ -543,6 +543,7 @@ static void determine_author_info(struct strbuf *author_ident)
|
|||||||
|
|
||||||
if (author_message) {
|
if (author_message) {
|
||||||
const char *a, *lb, *rb, *eol;
|
const char *a, *lb, *rb, *eol;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
a = strstr(author_message_buffer, "\nauthor ");
|
a = strstr(author_message_buffer, "\nauthor ");
|
||||||
if (!a)
|
if (!a)
|
||||||
@ -563,6 +564,11 @@ static void determine_author_info(struct strbuf *author_ident)
|
|||||||
(a + strlen("\nauthor "))));
|
(a + strlen("\nauthor "))));
|
||||||
email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
|
email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
|
||||||
date = xmemdupz(rb + strlen("> "), eol - (rb + 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) {
|
if (force_author) {
|
||||||
|
30
date.c
30
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);
|
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
|
/* 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. */
|
(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)
|
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;
|
*offset = -1;
|
||||||
tm_gmt = 0;
|
tm_gmt = 0;
|
||||||
|
|
||||||
|
if (*date == '@' &&
|
||||||
|
!match_object_header_date(date + 1, timestamp, offset))
|
||||||
|
return 0; /* success */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int match = 0;
|
int match = 0;
|
||||||
unsigned char c = *date;
|
unsigned char c = *date;
|
||||||
|
@ -200,7 +200,7 @@ get_author_ident_from_commit () {
|
|||||||
s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
|
s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
|
||||||
|
|
||||||
g
|
g
|
||||||
s/^author [^<]* <[^>]*> \(.*\)$/\1/
|
s/^author [^<]* <[^>]*> \(.*\)$/@\1/
|
||||||
s/.*/GIT_AUTHOR_DATE='\''&'\''/p
|
s/.*/GIT_AUTHOR_DATE='\''&'\''/p
|
||||||
|
|
||||||
q
|
q
|
||||||
|
@ -218,4 +218,27 @@ test_expect_success 'rebase -m can copy notes' '
|
|||||||
test "a note" = "$(git notes show HEAD)"
|
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
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user