fast-import: Allow cat-blob requests at arbitrary points in stream
The new rule: a "cat-blob" can be inserted wherever a comment is allowed, which means at the start of any line except in the middle of a "data" command. This saves frontends from having to loop over everything they want to commit in the next commit and cat-ing the necessary objects in advance. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: David Barr <david.barr@cordelta.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
85c62395b1
commit
777f80d742
@ -912,6 +912,10 @@ output uses the same format as `git cat-file --batch`:
|
|||||||
<contents> LF
|
<contents> 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.
|
||||||
|
|
||||||
`feature`
|
`feature`
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
Require that fast-import supports the specified feature, or abort if
|
Require that fast-import supports the specified feature, or abort if
|
||||||
|
@ -55,8 +55,6 @@ Format of STDIN stream:
|
|||||||
('from' sp committish lf)?
|
('from' sp committish lf)?
|
||||||
lf?;
|
lf?;
|
||||||
|
|
||||||
cat_blob ::= 'cat-blob' sp (hexsha1 | idnum) lf;
|
|
||||||
|
|
||||||
checkpoint ::= 'checkpoint' lf
|
checkpoint ::= 'checkpoint' lf
|
||||||
lf?;
|
lf?;
|
||||||
|
|
||||||
@ -134,14 +132,17 @@ Format of STDIN stream:
|
|||||||
ts ::= # time since the epoch in seconds, ascii base10 notation;
|
ts ::= # time since the epoch in seconds, ascii base10 notation;
|
||||||
tz ::= # GIT style timezone;
|
tz ::= # GIT style timezone;
|
||||||
|
|
||||||
# note: comments may appear anywhere in the input, except
|
# note: comments and cat requests may appear anywhere
|
||||||
# within a data command. Any form of the data command
|
# in the input, except within a data command. Any form
|
||||||
# always escapes the related input from comment processing.
|
# of the data command always escapes the related input
|
||||||
|
# from comment processing.
|
||||||
#
|
#
|
||||||
# In case it is not clear, the '#' that starts the comment
|
# In case it is not clear, the '#' that starts the comment
|
||||||
# must be the first character on that line (an lf
|
# must be the first character on that line (an lf
|
||||||
# preceded it).
|
# preceded it).
|
||||||
#
|
#
|
||||||
|
cat_blob ::= 'cat-blob' sp (hexsha1 | idnum) lf;
|
||||||
|
|
||||||
comment ::= '#' not_lf* lf;
|
comment ::= '#' not_lf* lf;
|
||||||
not_lf ::= # Any byte that is not ASCII newline (LF);
|
not_lf ::= # Any byte that is not ASCII newline (LF);
|
||||||
*/
|
*/
|
||||||
@ -367,6 +368,7 @@ static int seen_data_command;
|
|||||||
static int cat_blob_fd = STDOUT_FILENO;
|
static int cat_blob_fd = STDOUT_FILENO;
|
||||||
|
|
||||||
static void parse_argv(void);
|
static void parse_argv(void);
|
||||||
|
static void parse_cat_blob(void);
|
||||||
|
|
||||||
static void write_branch_report(FILE *rpt, struct branch *b)
|
static void write_branch_report(FILE *rpt, struct branch *b)
|
||||||
{
|
{
|
||||||
@ -1785,7 +1787,6 @@ static void read_marks(void)
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int read_next_command(void)
|
static int read_next_command(void)
|
||||||
{
|
{
|
||||||
static int stdin_eof = 0;
|
static int stdin_eof = 0;
|
||||||
@ -1795,7 +1796,7 @@ static int read_next_command(void)
|
|||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
for (;;) {
|
||||||
if (unread_command_buf) {
|
if (unread_command_buf) {
|
||||||
unread_command_buf = 0;
|
unread_command_buf = 0;
|
||||||
} else {
|
} else {
|
||||||
@ -1828,9 +1829,14 @@ static int read_next_command(void)
|
|||||||
rc->prev->next = rc;
|
rc->prev->next = rc;
|
||||||
cmd_tail = rc;
|
cmd_tail = rc;
|
||||||
}
|
}
|
||||||
} while (command_buf.buf[0] == '#');
|
if (!prefixcmp(command_buf.buf, "cat-blob ")) {
|
||||||
|
parse_cat_blob();
|
||||||
return 0;
|
continue;
|
||||||
|
}
|
||||||
|
if (command_buf.buf[0] == '#')
|
||||||
|
continue;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void skip_optional_lf(void)
|
static void skip_optional_lf(void)
|
||||||
@ -3066,8 +3072,6 @@ int main(int argc, const char **argv)
|
|||||||
parse_new_tag();
|
parse_new_tag();
|
||||||
else if (!prefixcmp(command_buf.buf, "reset "))
|
else if (!prefixcmp(command_buf.buf, "reset "))
|
||||||
parse_reset_branch();
|
parse_reset_branch();
|
||||||
else if (!prefixcmp(command_buf.buf, "cat-blob "))
|
|
||||||
parse_cat_blob();
|
|
||||||
else if (!strcmp("checkpoint", command_buf.buf))
|
else if (!strcmp("checkpoint", command_buf.buf))
|
||||||
parse_checkpoint();
|
parse_checkpoint();
|
||||||
else if (!prefixcmp(command_buf.buf, "progress "))
|
else if (!prefixcmp(command_buf.buf, "progress "))
|
||||||
|
@ -1823,6 +1823,72 @@ test_expect_success PIPE 'R: copy using cat-file' '
|
|||||||
test_cmp big actual
|
test_cmp big actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success PIPE 'R: print blob mid-commit' '
|
||||||
|
rm -f blobs &&
|
||||||
|
echo "A blob from _before_ the commit." >expect &&
|
||||||
|
mkfifo blobs &&
|
||||||
|
(
|
||||||
|
exec 3<blobs &&
|
||||||
|
cat <<-EOF &&
|
||||||
|
feature cat-blob
|
||||||
|
blob
|
||||||
|
mark :1
|
||||||
|
data <<BLOB
|
||||||
|
A blob from _before_ the commit.
|
||||||
|
BLOB
|
||||||
|
commit refs/heads/temporary
|
||||||
|
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||||
|
data <<COMMIT
|
||||||
|
Empty commit
|
||||||
|
COMMIT
|
||||||
|
cat-blob :1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
read blob_id type size <&3 &&
|
||||||
|
dd if=/dev/stdin of=actual bs=$size count=1 <&3 &&
|
||||||
|
read newline <&3 &&
|
||||||
|
|
||||||
|
echo
|
||||||
|
) |
|
||||||
|
git fast-import --cat-blob-fd=3 3>blobs &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success PIPE 'R: print staged blob within commit' '
|
||||||
|
rm -f blobs &&
|
||||||
|
echo "A blob from _within_ the commit." >expect &&
|
||||||
|
mkfifo blobs &&
|
||||||
|
(
|
||||||
|
exec 3<blobs &&
|
||||||
|
cat <<-EOF &&
|
||||||
|
feature cat-blob
|
||||||
|
commit refs/heads/within
|
||||||
|
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||||
|
data <<COMMIT
|
||||||
|
Empty commit
|
||||||
|
COMMIT
|
||||||
|
M 644 inline within
|
||||||
|
data <<BLOB
|
||||||
|
A blob from _within_ the commit.
|
||||||
|
BLOB
|
||||||
|
EOF
|
||||||
|
|
||||||
|
to_get=$(
|
||||||
|
echo "A blob from _within_ the commit." |
|
||||||
|
git hash-object --stdin
|
||||||
|
) &&
|
||||||
|
echo "cat-blob $to_get" &&
|
||||||
|
|
||||||
|
read blob_id type size <&3 &&
|
||||||
|
dd if=/dev/stdin of=actual bs=$size count=1 <&3 &&
|
||||||
|
read newline <&3 &&
|
||||||
|
|
||||||
|
echo deleteall
|
||||||
|
) |
|
||||||
|
git fast-import --cat-blob-fd=3 3>blobs &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
cat >input << EOF
|
cat >input << EOF
|
||||||
option git quiet
|
option git quiet
|
||||||
blob
|
blob
|
||||||
|
Loading…
Reference in New Issue
Block a user