Skip to content

Commit dae82ec

Browse files
committed
Merge branch 'en/fast-import-parsing-fix'
"git fast-import" update. * en/fast-import-parsing-fix: fast-import: fix erroneous handling of get-mark with empty orphan commits fast-import: only allow cat-blob requests where it makes sense fast-import: check most prominent commands first git-fast-import.txt: fix wording about where ls command can appear t9300: demonstrate bug with get-mark and empty orphan commits
2 parents 732ce7a + cf7b857 commit dae82ec

File tree

3 files changed

+66
-24
lines changed

3 files changed

+66
-24
lines changed

Documentation/git-fast-import.txt

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,12 @@ However it is recommended that a `filedeleteall` command precede
422422
all `filemodify`, `filecopy`, `filerename` and `notemodify` commands in
423423
the same commit, as `filedeleteall` wipes the branch clean (see below).
424424

425-
The `LF` after the command is optional (it used to be required).
425+
The `LF` after the command is optional (it used to be required). Note
426+
that for reasons of backward compatibility, if the commit ends with a
427+
`data` command (i.e. it has has no `from`, `merge`, `filemodify`,
428+
`filedelete`, `filecopy`, `filerename`, `filedeleteall` or
429+
`notemodify` commands) then two `LF` commands may appear at the end of
430+
the command instead of just one.
426431

427432
`author`
428433
^^^^^^^^
@@ -966,10 +971,6 @@ might want to refer to in their commit messages.
966971
'get-mark' SP ':' <idnum> LF
967972
....
968973

969-
This command can be used anywhere in the stream that comments are
970-
accepted. In particular, the `get-mark` command can be used in the
971-
middle of a commit but not in the middle of a `data` command.
972-
973974
See ``Responses To Commands'' below for details about how to read
974975
this output safely.
975976

@@ -996,9 +997,10 @@ Output uses the same format as `git cat-file --batch`:
996997
<contents> LF
997998
====
998999

999-
This command can be used anywhere in the stream that comments are
1000-
accepted. In particular, the `cat-blob` command can be used in the
1001-
middle of a commit but not in the middle of a `data` command.
1000+
This command can be used where a `filemodify` directive can appear,
1001+
allowing it to be used in the middle of a commit. For a `filemodify`
1002+
using an inline directive, it can also appear right before the `data`
1003+
directive.
10021004

10031005
See ``Responses To Commands'' below for details about how to read
10041006
this output safely.
@@ -1011,8 +1013,8 @@ printing a blob from the active commit (with `cat-blob`) or copying a
10111013
blob or tree from a previous commit for use in the current one (with
10121014
`filemodify`).
10131015

1014-
The `ls` command can be used anywhere in the stream that comments are
1015-
accepted, including the middle of a commit.
1016+
The `ls` command can also be used where a `filemodify` directive can
1017+
appear, allowing it to be used in the middle of a commit.
10161018

10171019
Reading from the active commit::
10181020
This form can only be used in the middle of a `commit`.

fast-import.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1748,8 +1748,6 @@ static int read_next_command(void)
17481748
}
17491749

17501750
for (;;) {
1751-
const char *p;
1752-
17531751
if (unread_command_buf) {
17541752
unread_command_buf = 0;
17551753
} else {
@@ -1782,14 +1780,6 @@ static int read_next_command(void)
17821780
rc->prev->next = rc;
17831781
cmd_tail = rc;
17841782
}
1785-
if (skip_prefix(command_buf.buf, "get-mark ", &p)) {
1786-
parse_get_mark(p);
1787-
continue;
1788-
}
1789-
if (skip_prefix(command_buf.buf, "cat-blob ", &p)) {
1790-
parse_cat_blob(p);
1791-
continue;
1792-
}
17931783
if (command_buf.buf[0] == '#')
17941784
continue;
17951785
return 0;
@@ -2254,8 +2244,15 @@ static void file_change_m(const char *p, struct branch *b)
22542244
strbuf_addstr(&uq, p);
22552245
p = uq.buf;
22562246
}
2257-
read_next_command();
2258-
parse_and_store_blob(&last_blob, &oid, 0);
2247+
while (read_next_command() != EOF) {
2248+
const char *v;
2249+
if (skip_prefix(command_buf.buf, "cat-blob ", &v))
2250+
parse_cat_blob(v);
2251+
else {
2252+
parse_and_store_blob(&last_blob, &oid, 0);
2253+
break;
2254+
}
2255+
}
22592256
} else {
22602257
enum object_type expected = S_ISDIR(mode) ?
22612258
OBJ_TREE: OBJ_BLOB;
@@ -2627,6 +2624,8 @@ static void parse_new_commit(const char *arg)
26272624
file_change_deleteall(b);
26282625
else if (skip_prefix(command_buf.buf, "ls ", &v))
26292626
parse_ls(v, b);
2627+
else if (skip_prefix(command_buf.buf, "cat-blob ", &v))
2628+
parse_cat_blob(v);
26302629
else {
26312630
unread_command_buf = 1;
26322631
break;
@@ -3303,14 +3302,18 @@ int cmd_main(int argc, const char **argv)
33033302
const char *v;
33043303
if (!strcmp("blob", command_buf.buf))
33053304
parse_new_blob();
3306-
else if (skip_prefix(command_buf.buf, "ls ", &v))
3307-
parse_ls(v, NULL);
33083305
else if (skip_prefix(command_buf.buf, "commit ", &v))
33093306
parse_new_commit(v);
33103307
else if (skip_prefix(command_buf.buf, "tag ", &v))
33113308
parse_new_tag(v);
33123309
else if (skip_prefix(command_buf.buf, "reset ", &v))
33133310
parse_reset_branch(v);
3311+
else if (skip_prefix(command_buf.buf, "ls ", &v))
3312+
parse_ls(v, NULL);
3313+
else if (skip_prefix(command_buf.buf, "cat-blob ", &v))
3314+
parse_cat_blob(v);
3315+
else if (skip_prefix(command_buf.buf, "get-mark ", &v))
3316+
parse_get_mark(v);
33143317
else if (!strcmp("checkpoint", command_buf.buf))
33153318
parse_checkpoint();
33163319
else if (!strcmp("done", command_buf.buf))

t/t9300-fast-import.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3262,4 +3262,41 @@ test_expect_success PIPE 'V: checkpoint updates tags after tag' '
32623262
background_import_still_running
32633263
'
32643264

3265+
###
3266+
### series W (get-mark and empty orphan commits)
3267+
###
3268+
3269+
cat >>W-input <<-W_INPUT_END
3270+
commit refs/heads/W-branch
3271+
mark :1
3272+
author Full Name <[email protected]> 1000000000 +0100
3273+
committer Full Name <[email protected]> 1000000000 +0100
3274+
data 27
3275+
Intentionally empty commit
3276+
LFsget-mark :1
3277+
W_INPUT_END
3278+
3279+
test_expect_success !MINGW 'W: get-mark & empty orphan commit with no newlines' '
3280+
sed -e s/LFs// W-input | tr L "\n" | git fast-import
3281+
'
3282+
3283+
test_expect_success !MINGW 'W: get-mark & empty orphan commit with one newline' '
3284+
sed -e s/LFs/L/ W-input | tr L "\n" | git fast-import
3285+
'
3286+
3287+
test_expect_success !MINGW 'W: get-mark & empty orphan commit with ugly second newline' '
3288+
# Technically, this should fail as it has too many linefeeds
3289+
# according to the grammar in fast-import.txt. But, for whatever
3290+
# reason, it works. Since using the correct number of newlines
3291+
# does not work with older (pre-2.22) versions of git, allow apps
3292+
# that used this second-newline workaround to keep working by
3293+
# checking it with this test...
3294+
sed -e s/LFs/LL/ W-input | tr L "\n" | git fast-import
3295+
'
3296+
3297+
test_expect_success !MINGW 'W: get-mark & empty orphan commit with erroneous third newline' '
3298+
# ...but do NOT allow more empty lines than that (see previous test).
3299+
sed -e s/LFs/LLL/ W-input | tr L "\n" | test_must_fail git fast-import
3300+
'
3301+
32653302
test_done

0 commit comments

Comments
 (0)