{"thread":{"id":"43528","subject":"[PATCH 2/3] add progress status to index-pack","startedAt":"2006-10-26T03:32:59Z","lastAt":"2006-10-26T03:32:59Z","messageCount":1,"participants":["Nicolas Pitre"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"295291","messageId":"Pine.LNX.4.64.0610252332300.12418@xanadu.home","threadId":"43528","inReplyTo":null,"subject":"[PATCH 2/3] add progress status to index-pack","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2006-10-26T03:32:59Z","receivedAt":"2006-10-26T03:32:59Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"This is more interesting to look at when performing a big fetch.\n\nSigned-off-by: Nicolas Pitre <nico@cam.org>\n---\n Documentation/git-index-pack.txt |    7 +++-\n index-pack.c                     |   74 +++++++++++++++++++++++++++++++++++--\n 2 files changed, 75 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt\nindex c58287d..9fa4847 100644\n--- a/Documentation/git-index-pack.txt\n+++ b/Documentation/git-index-pack.txt\n@@ -8,8 +8,8 @@ git-index-pack - Build pack index file f\n \n SYNOPSIS\n --------\n-'git-index-pack' [-o <index-file>] <pack-file>\n-'git-index-pack' --stdin [--fix-thin] [-o <index-file>] [<pack-file>]\n+'git-index-pack' [-v] [-o <index-file>] <pack-file>\n+'git-index-pack' --stdin [--fix-thin] [-v] [-o <index-file>] [<pack-file>]\n \n \n DESCRIPTION\n@@ -22,6 +22,9 @@ objects/pack/ directory of a git reposit\n \n OPTIONS\n -------\n+-v::\n+\tBe verbose about what is going on, including progress status.\n+\n -o <index-file>::\n \tWrite the generated pack index into the specified\n \tfile.  Without this option the name of pack index\ndiff --git a/index-pack.c b/index-pack.c\nindex 9086bbf..2046b37 100644\n--- a/index-pack.c\n+++ b/index-pack.c\n@@ -6,9 +6,11 @@\n #include \"commit.h\"\n #include \"tag.h\"\n #include \"tree.h\"\n+#include <sys/time.h>\n+#include <signal.h>\n \n static const char index_pack_usage[] =\n-\"git-index-pack [-o <index-file>] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }\";\n+\"git-index-pack [-v] [-o <index-file>] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }\";\n \n struct object_entry\n {\n@@ -44,6 +46,42 @@ static int nr_deltas;\n static int nr_resolved_deltas;\n \n static int from_stdin;\n+static int verbose;\n+\n+static volatile sig_atomic_t progress_update;\n+\n+static void progress_interval(int signum)\n+{\n+\tprogress_update = 1;\n+}\n+\n+static void setup_progress_signal(void)\n+{\n+\tstruct sigaction sa;\n+\tstruct itimerval v;\n+\n+\tmemset(&sa, 0, sizeof(sa));\n+\tsa.sa_handler = progress_interval;\n+\tsigemptyset(&sa.sa_mask);\n+\tsa.sa_flags = SA_RESTART;\n+\tsigaction(SIGALRM, &sa, NULL);\n+\n+\tv.it_interval.tv_sec = 1;\n+\tv.it_interval.tv_usec = 0;\n+\tv.it_value = v.it_interval;\n+\tsetitimer(ITIMER_REAL, &v, NULL);\n+\n+}\n+\n+static unsigned display_progress(unsigned n, unsigned total, unsigned last_pc)\n+{\n+\tunsigned percent = n * 100 / total;\n+\tif (percent != last_pc || progress_update) {\n+\t\tfprintf(stderr, \"%4u%% (%u/%u) done\\r\", percent, n, total);\n+\t\tprogress_update = 0;\n+\t}\n+\treturn percent;\n+}\n \n /* We always read in 4kB chunks. */\n static unsigned char input_buffer[4096];\n@@ -135,7 +173,6 @@ static void parse_pack_header(void)\n \n \tnr_objects = ntohl(hdr->hdr_entries);\n \tuse(sizeof(struct pack_header));\n-\t/*fprintf(stderr, \"Indexing %d objects\\n\", nr_objects);*/\n }\n \n static void bad_object(unsigned long offset, const char *format,\n@@ -383,7 +420,7 @@ static int compare_delta_entry(const voi\n /* Parse all objects and return the pack content SHA1 hash */\n static void parse_pack_objects(unsigned char *sha1)\n {\n-\tint i;\n+\tint i, percent = -1;\n \tstruct delta_entry *delta = deltas;\n \tvoid *data;\n \tstruct stat st;\n@@ -394,6 +431,8 @@ static void parse_pack_objects(unsigned\n \t * - calculate SHA1 of all non-delta objects;\n \t * - remember base SHA1 for all deltas.\n \t */\n+\tif (verbose)\n+\t\tfprintf(stderr, \"Indexing %d objects.\\n\", nr_objects);\n \tfor (i = 0; i < nr_objects; i++) {\n \t\tstruct object_entry *obj = &objects[i];\n \t\tdata = unpack_raw_entry(obj, &delta->base);\n@@ -405,8 +444,12 @@ static void parse_pack_objects(unsigned\n \t\t} else\n \t\t\tsha1_object(data, obj->size, obj->type, obj->sha1);\n \t\tfree(data);\n+\t\tif (verbose)\n+\t\t\tpercent = display_progress(i+1, nr_objects, percent);\n \t}\n \tobjects[i].offset = consumed_bytes;\n+\tif (verbose)\n+\t\tfputc('\\n', stderr);\n \n \t/* Check pack integrity */\n \tflush();\n@@ -420,6 +463,9 @@ static void parse_pack_objects(unsigned\n \tif (S_ISREG(st.st_mode) && st.st_size != consumed_bytes + 20)\n \t\tdie(\"pack has junk at the end\");\n \n+\tif (!nr_deltas)\n+\t\treturn;\n+\n \t/* Sort deltas by base SHA1/offset for fast searching */\n \tqsort(deltas, nr_deltas, sizeof(struct delta_entry),\n \t      compare_delta_entry);\n@@ -432,6 +478,8 @@ static void parse_pack_objects(unsigned\n \t *   recursively checking if the resulting object is used as a base\n \t *   for some more deltas.\n \t */\n+\tif (verbose)\n+\t\tfprintf(stderr, \"Resolving %d deltas.\\n\", nr_deltas);\n \tfor (i = 0; i < nr_objects; i++) {\n \t\tstruct object_entry *obj = &objects[i];\n \t\tunion delta_base base;\n@@ -462,7 +510,12 @@ static void parse_pack_objects(unsigned\n \t\t\t\t\t\t      obj->size, obj->type);\n \t\t\t}\n \t\tfree(data);\n+\t\tif (verbose)\n+\t\t\tpercent = display_progress(nr_resolved_deltas,\n+\t\t\t\t\t\t   nr_deltas, percent);\n \t}\n+\tif (verbose && nr_resolved_deltas == nr_deltas)\n+\t\tfputc('\\n', stderr);\n }\n \n static int write_compressed(int fd, void *in, unsigned int size)\n@@ -521,7 +574,7 @@ static int delta_pos_compare(const void\n static void fix_unresolved_deltas(int nr_unresolved)\n {\n \tstruct delta_entry **sorted_by_pos;\n-\tint i, n = 0;\n+\tint i, n = 0, percent = -1;\n \n \t/*\n \t * Since many unresolved deltas may well be themselves base objects\n@@ -570,8 +623,13 @@ static void fix_unresolved_deltas(int nr\n \n \t\tappend_obj_to_pack(data, size, obj_type);\n \t\tfree(data);\n+\t\tif (verbose)\n+\t\t\tpercent = display_progress(nr_resolved_deltas,\n+\t\t\t\t\t\t   nr_deltas, percent);\n \t}\n \tfree(sorted_by_pos);\n+\tif (verbose)\n+\t\tfputc('\\n', stderr);\n }\n \n static void readjust_pack_header_and_sha1(unsigned char *sha1)\n@@ -747,6 +805,8 @@ int main(int argc, char **argv)\n \t\t\t\tfrom_stdin = 1;\n \t\t\t} else if (!strcmp(arg, \"--fix-thin\")) {\n \t\t\t\tfix_thin_pack = 1;\n+\t\t\t} else if (!strcmp(arg, \"-v\")) {\n+\t\t\t\tverbose = 1;\n \t\t\t} else if (!strcmp(arg, \"-o\")) {\n \t\t\t\tif (index_name || (i+1) >= argc)\n \t\t\t\t\tusage(index_pack_usage);\n@@ -780,16 +840,22 @@ int main(int argc, char **argv)\n \tparse_pack_header();\n \tobjects = xmalloc((nr_objects + 1) * sizeof(struct object_entry));\n \tdeltas = xmalloc(nr_objects * sizeof(struct delta_entry));\n+\tif (verbose)\n+\t\tsetup_progress_signal();\n \tparse_pack_objects(sha1);\n \tif (nr_deltas != nr_resolved_deltas) {\n \t\tif (fix_thin_pack) {\n \t\t\tint nr_unresolved = nr_deltas - nr_resolved_deltas;\n+\t\t\tint nr_objects_initial = nr_objects;\n \t\t\tif (nr_unresolved <= 0)\n \t\t\t\tdie(\"confusion beyond insanity\");\n \t\t\tobjects = xrealloc(objects,\n \t\t\t\t\t   (nr_objects + nr_unresolved + 1)\n \t\t\t\t\t   * sizeof(*objects));\n \t\t\tfix_unresolved_deltas(nr_unresolved);\n+\t\t\tif (verbose)\n+\t\t\t\tfprintf(stderr, \"%d objects were added to complete this thin pack.\\n\",\n+\t\t\t\t\tnr_objects - nr_objects_initial);\n \t\t\treadjust_pack_header_and_sha1(sha1);\n \t\t}\n \t\tif (nr_deltas != nr_resolved_deltas)\n-- \n1.4.3.3.g10cf-dirty\n"}]}