From ac053c02029d88c7ed4d7e92949a1586eb3f7704 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 1 Aug 2007 10:23:08 -0400 Subject: [PATCH] Allow frontends to bidirectionally communicate with fast-import The existing checkpoint command is very useful to force fast-import to dump the branches out to disk so that standard Git tools can access them and the objects they refer to. However there was not a way to know when fast-import had finished executing the checkpoint and it was safe to read those refs. The progress command can be used to make fast-import output any message of the frontend's choosing to standard out. The frontend can scan for these messages using select() or poll() to monitor a pipe connected to the standard output of fast-import. Signed-off-by: Shawn O. Pearce --- Documentation/git-fast-import.txt | 39 +++++++++++++++++++++++++++++++ fast-import.c | 14 +++++++++++ t/t9300-fast-import.sh | 31 ++++++++++++++++++++++++ 3 files changed, 84 insertions(+) diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 1644b90ce..0a019dd2e 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -298,6 +298,11 @@ and control the current import process. More detailed discussion This command is optional and is not needed to perform an import. +`progress`:: + Causes fast-import to echo the entire line to its own + standard output. This command is optional and is not needed + to perform an import. + `commit` ~~~~~~~~ Create or update a branch with a new commit, recording one logical @@ -775,6 +780,31 @@ explicit checkpointing may not be necessary. The `LF` after the command is optional (it used to be required). +`progress` +~~~~~~~~~~ +Causes fast-import to print the entire `progress` line unmodified to +its standard output channel (file descriptor 1) when the command is +processed from the input stream. The command otherwise has no impact +on the current import, or on any of fast-import's internal state. + +.... + 'progress' SP LF + LF? +.... + +The `` part of the command may contain any sequence of bytes +that does not contain `LF`. The `LF` after the command is optional. +Callers may wish to process the output through a tool such as sed to +remove the leading part of the line, for example: + +==== + frontend | git-fast-import | sed 's/^progress //' +==== + +Placing a `progress` command immediately after a `checkpoint` will +inform the reader when the `checkpoint` has been completed and it +can safely access the refs that fast-import updated. + Tips and Tricks --------------- The following tips and tricks have been collected from various @@ -867,6 +897,15 @@ This will take longer, but will also produce a smaller packfile. You only need to expend the effort once, and everyone using your project will benefit from the smaller repository. +Include Some Progress Messages +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Every once in a while have your frontend emit a `progress` message +to fast-import. The contents of the messages are entirely free-form, +so one suggestion would be to output the current month and year +each time the current commit date moves into the next month. +Your users will feel better knowing how much of the data stream +has been processed. + Packfile Optimization --------------------- diff --git a/fast-import.c b/fast-import.c index 4bc7f81bc..429ab491b 100644 --- a/fast-import.c +++ b/fast-import.c @@ -8,6 +8,7 @@ Format of STDIN stream: | new_tag | reset_branch | checkpoint + | progress ; new_blob ::= 'blob' lf @@ -53,6 +54,9 @@ Format of STDIN stream: checkpoint ::= 'checkpoint' lf lf?; + progress ::= 'progress' sp not_lf* lf + lf?; + # note: the first idnum in a stream should be 1 and subsequent # idnums should not have gaps between values as this will cause # the stream parser to reserve space for the gapped values. An @@ -2125,6 +2129,14 @@ static void cmd_checkpoint(void) skip_optional_lf(); } +static void cmd_progress(void) +{ + fwrite(command_buf.buf, 1, command_buf.len - 1, stdout); + fputc('\n', stdout); + fflush(stdout); + skip_optional_lf(); +} + static void import_marks(const char *input_file) { char line[512]; @@ -2235,6 +2247,8 @@ int main(int argc, const char **argv) cmd_reset_branch(); else if (!strcmp("checkpoint", command_buf.buf)) cmd_checkpoint(); + else if (!prefixcmp(command_buf.buf, "progress ")) + cmd_progress(); else die("Unsupported command: %s", command_buf.buf); } diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 5d82b0f1c..0595041af 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -885,4 +885,35 @@ test_expect_success \ git log --reverse --pretty=oneline O3 | sed s/^.*z// >actual && git diff expect actual' +cat >input < $GIT_COMMITTER_DATE +data < $GIT_COMMITTER_DATE +data < $GIT_COMMITTER_DATE +data < $GIT_COMMITTER_DATE +data <actual && + grep "progress " expect && + git diff expect actual' + test_done -- 2.30.2