Browse Source

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>
maint
Junio C Hamano 13 years ago
parent
commit
2c733fb24c
  1. 6
      builtin/commit.c
  2. 3
      date.c
  3. 2
      git-sh-setup.sh
  4. 23
      t/t3400-rebase.sh

6
builtin/commit.c

@ -534,6 +534,7 @@ static void determine_author_info(struct strbuf *author_ident) @@ -534,6 +534,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)
@ -554,6 +555,11 @@ static void determine_author_info(struct strbuf *author_ident) @@ -554,6 +555,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) {

3
date.c

@ -637,7 +637,8 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset) @@ -637,7 +637,8 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
*offset = -1;
tm_gmt = 0;

if (!match_object_header_date(date, timestamp, offset))
if (*date == '@' &&
!match_object_header_date(date + 1, timestamp, offset))
return 0; /* success */
for (;;) {
int match = 0;

2
git-sh-setup.sh

@ -200,7 +200,7 @@ get_author_ident_from_commit () { @@ -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

23
t/t3400-rebase.sh

@ -218,4 +218,27 @@ test_expect_success 'rebase -m can copy notes' ' @@ -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

Loading…
Cancel
Save