It can be tedious to wait for a multi-million-revision import. Unfortunately it is hard to spy on the import because fast-import works by continuously streaming out objects, without updating the pack index or refs until a checkpoint command or the end of the stream. So allow the impatient operator to request checkpoints by sending a signal, like so: killall -USR1 git-fast-import When receiving such a signal, fast-import would schedule a checkpoint to take place after the current top-level command (usually a "commit" or "blob" request) finishes. Caveats: just like ordinary checkpoint commands, such requests slow down the import. Switching to a new pack at a suboptimal moment is also likely to result in a less dense initial collection of packs. That's the price. Signed-off-by: Jonathan Nieder <jrnieder@xxxxxxxxx> --- Thoughts? Documentation/git-fast-import.txt | 8 +++++++ fast-import.c | 42 ++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletions(-) diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 5d0c245..526670a 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -1233,6 +1233,14 @@ and lazy loading of subtrees, allows fast-import to efficiently import projects with 2,000+ branches and 45,114+ files in a very limited memory footprint (less than 2.7 MiB per active branch). +Signals +------- +Sending *SIGUSR1* to the 'git fast-import' process ends the current +packfile early, simulating a `checkpoint` command. The impatient +operator can use this facility to peek at the objects and refs from an +import in progress, at the cost of some added running time and worse +compression. + Author ------ diff --git a/fast-import.c b/fast-import.c index 77549eb..4779e3a 100644 --- a/fast-import.c +++ b/fast-import.c @@ -361,6 +361,9 @@ static uintmax_t next_mark; static struct strbuf new_data = STRBUF_INIT; static int seen_data_command; +/* Signal handling */ +static volatile sig_atomic_t checkpoint_requested; + static void parse_argv(void); static void write_branch_report(FILE *rpt, struct branch *b) @@ -500,6 +503,33 @@ static NORETURN void die_nicely(const char *err, va_list params) exit(128); } +#ifndef SIGUSR1 /* Windows, for example */ + +static void set_checkpoint_signal(void) +{ + /* nothing */ +} + +#else + +static void checkpoint_signal(int signo) +{ + checkpoint_requested = 1; +} + +static void set_checkpoint_signal(void) +{ + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = checkpoint_signal; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sigaction(SIGUSR1, &sa, NULL); +} + +#endif + static void alloc_objects(unsigned int cnt) { struct object_entry_pool *b; @@ -2689,14 +2719,20 @@ static void parse_reset_branch(void) unread_command_buf = 1; } -static void parse_checkpoint(void) +static void do_checkpoint(void) { + checkpoint_requested = 0; if (object_count) { cycle_packfile(); dump_branches(); dump_tags(); dump_marks(); } +} + +static void parse_checkpoint(void) +{ + do_checkpoint(); skip_optional_lf(); } @@ -2953,6 +2989,7 @@ int main(int argc, const char **argv) prepare_packed_git(); start_packfile(); set_die_routine(die_nicely); + set_checkpoint_signal(); while (read_next_command() != EOF) { if (!strcmp("blob", command_buf.buf)) parse_new_blob(); @@ -2974,6 +3011,9 @@ int main(int argc, const char **argv) /* ignore non-git options*/; else die("Unsupported command: %s", command_buf.buf); + + if (checkpoint_requested) + do_checkpoint(); } /* argv hasn't been parsed yet, do so */ -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html