Skip to content

Commit

Permalink
Merge branch 'en/fast-import-looser-date'
Browse files Browse the repository at this point in the history
Some repositories in the wild have commits that record nonsense
committer timezone (e.g. rails.git); "git fast-import" learned an
option to pass these nonsense timestamps intact to allow recreating
existing repositories as-is.

* en/fast-import-looser-date:
  fast-import: add new --date-format=raw-permissive format
  • Loading branch information
gitster committed Jun 2, 2020
2 parents a0ba2bb + d42a2fb commit 5404183
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 5 deletions.
9 changes: 8 additions & 1 deletion Documentation/git-fast-import.txt
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,14 @@ by users who are located in the same location and time zone. In this
case a reasonable offset from UTC could be assumed.
+
Unlike the `rfc2822` format, this format is very strict. Any
variation in formatting will cause fast-import to reject the value.
variation in formatting will cause fast-import to reject the value,
and some sanity checks on the numeric values may also be performed.

`raw-permissive`::
This is the same as `raw` except that no sanity checks on
the numeric epoch and local offset are performed. This can
be useful when trying to filter or import an existing history
with e.g. bogus timezone values.

`rfc2822`::
This is the standard email format as described by RFC 2822.
Expand Down
25 changes: 21 additions & 4 deletions fast-import.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ struct hash_list {

typedef enum {
WHENSPEC_RAW = 1,
WHENSPEC_RAW_PERMISSIVE,
WHENSPEC_RFC2822,
WHENSPEC_NOW
} whenspec_type;
Expand Down Expand Up @@ -1911,7 +1912,7 @@ static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
return 1;
}

static int validate_raw_date(const char *src, struct strbuf *result)
static int validate_raw_date(const char *src, struct strbuf *result, int strict)
{
const char *orig_src = src;
char *endp;
Expand All @@ -1920,7 +1921,11 @@ static int validate_raw_date(const char *src, struct strbuf *result)
errno = 0;

num = strtoul(src, &endp, 10);
/* NEEDSWORK: perhaps check for reasonable values? */
/*
* NEEDSWORK: perhaps check for reasonable values? For example, we
* could error on values representing times more than a
* day in the future.
*/
if (errno || endp == src || *endp != ' ')
return -1;

Expand All @@ -1929,7 +1934,13 @@ static int validate_raw_date(const char *src, struct strbuf *result)
return -1;

num = strtoul(src + 1, &endp, 10);
if (errno || endp == src + 1 || *endp || 1400 < num)
/*
* NEEDSWORK: check for brokenness other than num > 1400, such as
* (num % 100) >= 60, or ((num % 100) % 15) != 0 ?
*/
if (errno || endp == src + 1 || *endp || /* did not parse */
(strict && (1400 < num)) /* parsed a broken timezone */
)
return -1;

strbuf_addstr(result, orig_src);
Expand Down Expand Up @@ -1963,7 +1974,11 @@ static char *parse_ident(const char *buf)

switch (whenspec) {
case WHENSPEC_RAW:
if (validate_raw_date(ltgt, &ident) < 0)
if (validate_raw_date(ltgt, &ident, 1) < 0)
die("Invalid raw date \"%s\" in ident: %s", ltgt, buf);
break;
case WHENSPEC_RAW_PERMISSIVE:
if (validate_raw_date(ltgt, &ident, 0) < 0)
die("Invalid raw date \"%s\" in ident: %s", ltgt, buf);
break;
case WHENSPEC_RFC2822:
Expand Down Expand Up @@ -3258,6 +3273,8 @@ static void option_date_format(const char *fmt)
{
if (!strcmp(fmt, "raw"))
whenspec = WHENSPEC_RAW;
else if (!strcmp(fmt, "raw-permissive"))
whenspec = WHENSPEC_RAW_PERMISSIVE;
else if (!strcmp(fmt, "rfc2822"))
whenspec = WHENSPEC_RFC2822;
else if (!strcmp(fmt, "now"))
Expand Down
28 changes: 28 additions & 0 deletions t/t9300-fast-import.sh
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,34 @@ test_expect_success 'B: accept empty committer' '
test -z "$out"
'

test_expect_success 'B: reject invalid timezone' '
cat >input <<-INPUT_END &&
commit refs/heads/invalid-timezone
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1234567890 +051800
data <<COMMIT
empty commit
COMMIT
INPUT_END
test_when_finished "git update-ref -d refs/heads/invalid-timezone" &&
test_must_fail git fast-import <input
'

test_expect_success 'B: accept invalid timezone with raw-permissive' '
cat >input <<-INPUT_END &&
commit refs/heads/invalid-timezone
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1234567890 +051800
data <<COMMIT
empty commit
COMMIT
INPUT_END
git init invalid-timezone &&
git -C invalid-timezone fast-import --date-format=raw-permissive <input &&
git -C invalid-timezone cat-file -p invalid-timezone >out &&
grep "1234567890 [+]051800" out
'

test_expect_success 'B: accept and fixup committer with no name' '
cat >input <<-INPUT_END &&
commit refs/heads/empty-committer-2
Expand Down

0 comments on commit 5404183

Please sign in to comment.