From: Jonathan Nieder Date: Mon, 22 Nov 2010 08:16:02 +0000 (-0600) Subject: fast-import: treat SIGUSR1 as a request to access objects early X-Git-Tag: v1.7.4-rc0~41^2 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=dc01f59d21fca9ade97f1433ca4cee17b5ce59a7;p=git.git fast-import: treat SIGUSR1 as a request to access objects early 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 Signed-off-by: Junio C Hamano --- diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 5d0c245e3..9667e9aeb 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -1233,6 +1233,13 @@ 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 77549ebd6..b91470d7c 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,32 @@ static NORETURN void die_nicely(const char *err, va_list params) exit(128); } +#ifndef SIGUSR1 /* Windows, for example */ + +static void set_checkpoint_signal(void) +{ +} + +#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 +2718,20 @@ static void parse_reset_branch(void) unread_command_buf = 1; } -static void parse_checkpoint(void) +static void checkpoint(void) { + checkpoint_requested = 0; if (object_count) { cycle_packfile(); dump_branches(); dump_tags(); dump_marks(); } +} + +static void parse_checkpoint(void) +{ + checkpoint_requested = 1; skip_optional_lf(); } @@ -2953,6 +2988,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 +3010,9 @@ int main(int argc, const char **argv) /* ignore non-git options*/; else die("Unsupported command: %s", command_buf.buf); + + if (checkpoint_requested) + checkpoint(); } /* argv hasn't been parsed yet, do so */