fast-import: introduce 'done' command

Add a 'done' command that causes fast-import to stop reading from the
stream and exit.

If the new --done command line flag was passed on the command line
(or a "feature done" declaration included at the start of the stream),
make the 'done' command mandatory.  So "git fast-import --done"'s
input format will be prefix-free, making errors easier to detect when
they show up as early termination at some convenient time of the
upstream of a pipe writing to fast-import.

Another possible application of the 'done' command would to be allow a
fast-import stream that is only a small part of a larger encapsulating
stream to be easily parsed, leaving the file offset after the "done\n"
so the other application can pick up from there.  This patch does not
teach fast-import to do that --- fast-import still uses buffered input
(stdio).

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
Acked-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Sverre Rabbelier 2011-07-16 15:03:32 +02:00 коммит произвёл Junio C Hamano
Родитель 460d10262d
Коммит be56862f19
3 изменённых файлов: 75 добавлений и 0 удалений

Просмотреть файл

@ -101,6 +101,12 @@ OPTIONS
when the `cat-blob` command is encountered in the stream. when the `cat-blob` command is encountered in the stream.
The default behaviour is to write to `stdout`. The default behaviour is to write to `stdout`.
--done::
Require a `done` command at the end of the stream.
This option might be useful for detecting errors that
cause the frontend to terminate before it has started to
write a stream.
--export-pack-edges=<file>:: --export-pack-edges=<file>::
After creating a packfile, print a line of data to After creating a packfile, print a line of data to
<file> listing the filename of the packfile and the last <file> listing the filename of the packfile and the last
@ -330,6 +336,11 @@ and control the current import process. More detailed discussion
standard output. This command is optional and is not needed standard output. This command is optional and is not needed
to perform an import. to perform an import.
`done`::
Marks the end of the stream. This command is optional
unless the `done` feature was requested using the
`--done` command line option or `feature done` command.
`cat-blob`:: `cat-blob`::
Causes fast-import to print a blob in 'cat-file --batch' Causes fast-import to print a blob in 'cat-file --batch'
format to the file descriptor set with `--cat-blob-fd` or format to the file descriptor set with `--cat-blob-fd` or
@ -1015,6 +1026,11 @@ notes::
Versions of fast-import not supporting notes will exit Versions of fast-import not supporting notes will exit
with a message indicating so. with a message indicating so.
done::
Error out if the stream ends without a 'done' command.
Without this feature, errors causing the frontend to end
abruptly at a convenient point in the stream can go
undetected.
`option` `option`
~~~~~~~~ ~~~~~~~~
@ -1044,6 +1060,15 @@ not be passed as option:
* cat-blob-fd * cat-blob-fd
* force * force
`done`
~~~~~~
If the `done` feature is not in use, treated as if EOF was read.
This can be used to tell fast-import to finish early.
If the `--done` command line option or `feature done` command is
in use, the `done` command is mandatory and marks the end of the
stream.
Crash Reports Crash Reports
------------- -------------
If fast-import is supplied invalid input it will terminate with a If fast-import is supplied invalid input it will terminate with a

Просмотреть файл

@ -354,6 +354,7 @@ static unsigned int cmd_save = 100;
static uintmax_t next_mark; static uintmax_t next_mark;
static struct strbuf new_data = STRBUF_INIT; static struct strbuf new_data = STRBUF_INIT;
static int seen_data_command; static int seen_data_command;
static int require_explicit_termination;
/* Signal handling */ /* Signal handling */
static volatile sig_atomic_t checkpoint_requested; static volatile sig_atomic_t checkpoint_requested;
@ -3139,6 +3140,8 @@ static int parse_one_feature(const char *feature, int from_stream)
relative_marks_paths = 1; relative_marks_paths = 1;
} else if (!strcmp(feature, "no-relative-marks")) { } else if (!strcmp(feature, "no-relative-marks")) {
relative_marks_paths = 0; relative_marks_paths = 0;
} else if (!strcmp(feature, "done")) {
require_explicit_termination = 1;
} else if (!strcmp(feature, "force")) { } else if (!strcmp(feature, "force")) {
force_update = 1; force_update = 1;
} else if (!strcmp(feature, "notes") || !strcmp(feature, "ls")) { } else if (!strcmp(feature, "notes") || !strcmp(feature, "ls")) {
@ -3288,6 +3291,8 @@ int main(int argc, const char **argv)
parse_reset_branch(); parse_reset_branch();
else if (!strcmp("checkpoint", command_buf.buf)) else if (!strcmp("checkpoint", command_buf.buf))
parse_checkpoint(); parse_checkpoint();
else if (!strcmp("done", command_buf.buf))
break;
else if (!prefixcmp(command_buf.buf, "progress ")) else if (!prefixcmp(command_buf.buf, "progress "))
parse_progress(); parse_progress();
else if (!prefixcmp(command_buf.buf, "feature ")) else if (!prefixcmp(command_buf.buf, "feature "))
@ -3307,6 +3312,9 @@ int main(int argc, const char **argv)
if (!seen_data_command) if (!seen_data_command)
parse_argv(); parse_argv();
if (require_explicit_termination && feof(stdin))
die("stream ends early");
end_packfile(); end_packfile();
dump_branches(); dump_branches();

Просмотреть файл

@ -2197,6 +2197,48 @@ test_expect_success 'R: quiet option results in no stats being output' '
test_cmp empty output test_cmp empty output
' '
test_expect_success 'R: feature done means terminating "done" is mandatory' '
echo feature done | test_must_fail git fast-import &&
test_must_fail git fast-import --done </dev/null
'
test_expect_success 'R: terminating "done" with trailing gibberish is ok' '
git fast-import <<-\EOF &&
feature done
done
trailing gibberish
EOF
git fast-import <<-\EOF
done
more trailing gibberish
EOF
'
test_expect_success 'R: terminating "done" within commit' '
cat >expect <<-\EOF &&
OBJID
:000000 100644 OBJID OBJID A hello.c
:000000 100644 OBJID OBJID A hello2.c
EOF
git fast-import <<-EOF &&
commit refs/heads/done-ends
committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
data <<EOT
Commit terminated by "done" command
EOT
M 100644 inline hello.c
data <<EOT
Hello, world.
EOT
C hello.c hello2.c
done
EOF
git rev-list done-ends |
git diff-tree -r --stdin --root --always |
sed -e "s/$_x40/OBJID/g" >actual &&
test_cmp expect actual
'
cat >input <<EOF cat >input <<EOF
option git non-existing-option option git non-existing-option
EOF EOF