diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 43ab3b1637..33cce1e150 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -422,7 +422,12 @@ However it is recommended that a `filedeleteall` command precede all `filemodify`, `filecopy`, `filerename` and `notemodify` commands in the same commit, as `filedeleteall` wipes the branch clean (see below). -The `LF` after the command is optional (it used to be required). +The `LF` after the command is optional (it used to be required). Note +that for reasons of backward compatibility, if the commit ends with a +`data` command (i.e. it has has no `from`, `merge`, `filemodify`, +`filedelete`, `filecopy`, `filerename`, `filedeleteall` or +`notemodify` commands) then two `LF` commands may appear at the end of +the command instead of just one. `author` ^^^^^^^^ @@ -966,10 +971,6 @@ might want to refer to in their commit messages. 'get-mark' SP ':' LF .... -This command can be used anywhere in the stream that comments are -accepted. In particular, the `get-mark` command can be used in the -middle of a commit but not in the middle of a `data` command. - See ``Responses To Commands'' below for details about how to read this output safely. @@ -996,9 +997,10 @@ Output uses the same format as `git cat-file --batch`: LF ==== -This command can be used anywhere in the stream that comments are -accepted. In particular, the `cat-blob` command can be used in the -middle of a commit but not in the middle of a `data` command. +This command can be used where a `filemodify` directive can appear, +allowing it to be used in the middle of a commit. For a `filemodify` +using an inline directive, it can also appear right before the `data` +directive. See ``Responses To Commands'' below for details about how to read this output safely. @@ -1011,8 +1013,8 @@ printing a blob from the active commit (with `cat-blob`) or copying a blob or tree from a previous commit for use in the current one (with `filemodify`). -The `ls` command can be used anywhere in the stream that comments are -accepted, including the middle of a commit. +The `ls` command can also be used where a `filemodify` directive can +appear, allowing it to be used in the middle of a commit. Reading from the active commit:: This form can only be used in the middle of a `commit`. diff --git a/fast-import.c b/fast-import.c index b7ba755c2b..064c55e8be 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1748,8 +1748,6 @@ static int read_next_command(void) } for (;;) { - const char *p; - if (unread_command_buf) { unread_command_buf = 0; } else { @@ -1782,14 +1780,6 @@ static int read_next_command(void) rc->prev->next = rc; cmd_tail = rc; } - if (skip_prefix(command_buf.buf, "get-mark ", &p)) { - parse_get_mark(p); - continue; - } - if (skip_prefix(command_buf.buf, "cat-blob ", &p)) { - parse_cat_blob(p); - continue; - } if (command_buf.buf[0] == '#') continue; return 0; @@ -2254,8 +2244,15 @@ static void file_change_m(const char *p, struct branch *b) strbuf_addstr(&uq, p); p = uq.buf; } - read_next_command(); - parse_and_store_blob(&last_blob, &oid, 0); + while (read_next_command() != EOF) { + const char *v; + if (skip_prefix(command_buf.buf, "cat-blob ", &v)) + parse_cat_blob(v); + else { + parse_and_store_blob(&last_blob, &oid, 0); + break; + } + } } else { enum object_type expected = S_ISDIR(mode) ? OBJ_TREE: OBJ_BLOB; @@ -2627,6 +2624,8 @@ static void parse_new_commit(const char *arg) file_change_deleteall(b); else if (skip_prefix(command_buf.buf, "ls ", &v)) parse_ls(v, b); + else if (skip_prefix(command_buf.buf, "cat-blob ", &v)) + parse_cat_blob(v); else { unread_command_buf = 1; break; @@ -3303,14 +3302,18 @@ int cmd_main(int argc, const char **argv) const char *v; if (!strcmp("blob", command_buf.buf)) parse_new_blob(); - else if (skip_prefix(command_buf.buf, "ls ", &v)) - parse_ls(v, NULL); else if (skip_prefix(command_buf.buf, "commit ", &v)) parse_new_commit(v); else if (skip_prefix(command_buf.buf, "tag ", &v)) parse_new_tag(v); else if (skip_prefix(command_buf.buf, "reset ", &v)) parse_reset_branch(v); + else if (skip_prefix(command_buf.buf, "ls ", &v)) + parse_ls(v, NULL); + else if (skip_prefix(command_buf.buf, "cat-blob ", &v)) + parse_cat_blob(v); + else if (skip_prefix(command_buf.buf, "get-mark ", &v)) + parse_get_mark(v); else if (!strcmp("checkpoint", command_buf.buf)) parse_checkpoint(); else if (!strcmp("done", command_buf.buf)) diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 59a13b6a77..3668263c40 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -3262,4 +3262,41 @@ test_expect_success PIPE 'V: checkpoint updates tags after tag' ' background_import_still_running ' +### +### series W (get-mark and empty orphan commits) +### + +cat >>W-input <<-W_INPUT_END + commit refs/heads/W-branch + mark :1 + author Full Name 1000000000 +0100 + committer Full Name 1000000000 +0100 + data 27 + Intentionally empty commit + LFsget-mark :1 + W_INPUT_END + +test_expect_success !MINGW 'W: get-mark & empty orphan commit with no newlines' ' + sed -e s/LFs// W-input | tr L "\n" | git fast-import +' + +test_expect_success !MINGW 'W: get-mark & empty orphan commit with one newline' ' + sed -e s/LFs/L/ W-input | tr L "\n" | git fast-import +' + +test_expect_success !MINGW 'W: get-mark & empty orphan commit with ugly second newline' ' + # Technically, this should fail as it has too many linefeeds + # according to the grammar in fast-import.txt. But, for whatever + # reason, it works. Since using the correct number of newlines + # does not work with older (pre-2.22) versions of git, allow apps + # that used this second-newline workaround to keep working by + # checking it with this test... + sed -e s/LFs/LL/ W-input | tr L "\n" | git fast-import +' + +test_expect_success !MINGW 'W: get-mark & empty orphan commit with erroneous third newline' ' + # ...but do NOT allow more empty lines than that (see previous test). + sed -e s/LFs/LLL/ W-input | tr L "\n" | test_must_fail git fast-import +' + test_done