{"thread":{"id":"7541","subject":"[PATCH 12/13] rewrite write_pack_file() to write multiple packs","startedAt":"2007-04-05T22:41:06Z","lastAt":"2007-04-05T22:41:06Z","messageCount":1,"participants":["Dana How"],"isPatch":true,"patchVersion":1,"patchTotal":13},"messages":[{"id":"38753","messageId":"56b7f5510704051541s524480cfgbb73f077e5753168@mail.gmail.com","threadId":"7541","inReplyTo":null,"subject":"[PATCH 12/13] rewrite write_pack_file() to write multiple packs","fromName":"Dana How","fromEmail":"danahow@gmail.com","sentAt":"2007-04-05T22:41:06Z","receivedAt":"2007-04-05T22:41:06Z","isPatch":true,"sender":{"key":"danahow@gmail.com","avatar":null},"body":"write_pack_file() now also sets up and sorts written_list\nfor each pack;  modify write_one() to update this and\nwrite_index_file() to use it.\n---\n builtin-pack-objects.c |  147 ++++++++++++++++++++++++++++++++++--------------\n 1 files changed, 105 insertions(+), 42 deletions(-)\n\n-- \nDana L. How  danahow@gmail.com  +1 650 804 5991 cell\n\n\nFrom cc6808e18fbeb2049e1d705eb7c7f6f9b83b3441 Mon Sep 17 00:00:00 2001\nFrom: Dana How <how@deathvalley.cswitch.com>\nDate: Thu, 5 Apr 2007 14:43:33 -0700\nSubject: [PATCH 12/13] rewrite write_pack_file() to write multiple packs\n\nwrite_pack_file() now also sets up and sorts written_list\nfor each pack;  modify write_one() to update this and\nwrite_index_file() to use it.\n---\n builtin-pack-objects.c |  147 ++++++++++++++++++++++++++++++++++--------------\n 1 files changed, 105 insertions(+), 42 deletions(-)\n\ndiff --git a/builtin-pack-objects.c b/builtin-pack-objects.c\nindex ac643dd..3229df8 100644\n--- a/builtin-pack-objects.c\n+++ b/builtin-pack-objects.c\n@@ -534,14 +534,17 @@ static off_t write_one(struct sha1file *f,\n \t\t * Ensure the packfile size never exceeds or matches offset_limit.\n \t\t * The \"20\" is for the final SHA1.\n \t\t */\n-\t\tif ((unsigned long)offset < (unsigned long)(offset_limit - 20))\n+\t\tif ((unsigned long)offset < (unsigned long)(offset_limit - 20)) {\n+\t\t\t*written_list++ = e;\n \t\t\treturn offset;\n+\t\t}\n \t\twritten = save_written, written_delta = save_written_delta;\n \t\treused = save_reused, reused_delta = save_reused_delta;\n \t\tsha1undo(f, &posn, offset, e->offset);\n \t\te->offset = 0;\n \t\treturn 0;\n \t}\n+\t*written_list++ = e;\n \treturn offset + write_object(f, e);\n }\n \n@@ -597,52 +600,112 @@ static void write_index_file(void);\n \n static void write_pack_file(void)\n {\n-\tuint32_t i;\n+\tuint32_t i, j;\n \tstruct sha1file *f;\n \toff_t offset;\n \tstruct pack_header hdr;\n \tunsigned last_percent = 999;\n-\tint do_progress = progress;\n+\tint do_progress = progress >> !base_name;\n+\tchar oldname[PATH_MAX];\n+\tint pack_fd;\n+\tstruct object_entry **list;\n+\tSHA_CTX ctx;\n+\tuint32_t nr_actual = nr_result - nr_skipped;\n \n-\tif (!base_name) {\n-\t\tf = sha1fd(1, \"<stdout>\");\n-\t\tdo_progress >>= 1;\n-\t}\n-\telse\n-\t\tf = sha1create(\"%s-%s.%s\", base_name,\n-\t\t\t       sha1_to_hex(object_list_sha1), \"pack\");\n \tif (do_progress)\n-\t\tfprintf(stderr, \"Writing %u objects.\\n\", nr_result);\n-\n-\thdr.hdr_signature = htonl(PACK_SIGNATURE);\n-\thdr.hdr_version = htonl(PACK_VERSION);\n-\thdr.hdr_entries = htonl(nr_result);\n-\tsha1write(f, &hdr, sizeof(hdr));\n-\toffset = sizeof(hdr);\n-\tif (!nr_result)\n-\t\tgoto done;\n-\tfor (i = 0; i < nr_objects; i++) {\n-\t\toffset = write_one(f, objects + i, offset);\n-\t\tif (do_progress) {\n-\t\t\tunsigned percent = written * 100 / nr_result;\n-\t\t\tif (progress_update || percent != last_percent) {\n-\t\t\t\tfprintf(stderr, \"%4u%% (%u/%u) done\\r\",\n-\t\t\t\t\tpercent, written, nr_result);\n-\t\t\t\tprogress_update = 0;\n-\t\t\t\tlast_percent = percent;\n+\t\tfprintf(stderr, \"Writing %u objects.\\n\", nr_actual);\n+\twritten_list = list = xmalloc(nr_objects * sizeof(struct object_entry *));\n+\n+\tfor (i = 0; i < nr_objects;) {\n+\t\tif (!base_name) {\n+\t\t\tf = sha1fd(pack_fd = 1, \"<stdout>\");\n+\t\t}\n+\t\telse {\n+\t\t\tint len = snprintf(oldname, sizeof oldname, \"%s-XXXXXX\", base_name);\n+\t\t\tif (len >= PATH_MAX)\n+\t\t\t\tdie(\"excessive pathname length for initial packfile name\");\n+\t\t\tpack_fd = mkstemp(oldname);\n+\t\t\tif (pack_fd < 0)\n+\t\t\t\tdie(\"can't create %s: %s\", oldname, strerror(errno));\n+\t\t\tf = sha1fd(pack_fd, oldname);\n+\t\t}\n+\n+\t\thdr.hdr_signature = htonl(PACK_SIGNATURE);\n+\t\thdr.hdr_version = htonl(PACK_VERSION);\n+\t\thdr.hdr_entries = htonl(!base_name && offset_limit ? 0 : nr_actual);\n+\t\tsha1write(f, &hdr, sizeof(hdr));\n+\t\toffset = sizeof(hdr);\n+\t\tfor (; i < nr_objects; i++) {\n+\t\t\toff_t offset_one = write_one(f, objects + i, offset);\n+\t\t\tif (!offset_one)\n+\t\t\t\tbreak;\n+\t\t\toffset = offset_one;\n+\t\t\tif (do_progress) {\n+\t\t\t\tunsigned percent = written * 100 / nr_actual;\n+\t\t\t\tif (progress_update || percent != last_percent) {\n+\t\t\t\t\tfprintf(stderr, \"%4u%% (%u/%u) done\\r\",\n+\t\t\t\t\t\tpercent, written, nr_actual);\n+\t\t\t\t\tprogress_update = 0;\n+\t\t\t\t\tlast_percent = percent;\n+\t\t\t\t}\n \t\t\t}\n \t\t}\n+\t\tnr_written = written_list - list;\n+\t\twritten_list = list;\n+\n+\t\t/*\n+\t\t * Write terminator record here if desired:\n+\t\t * type=OBJ_NONE, len=0;  this is a zero byte.\n+\t\t */\n+\n+\t\t/*\n+\t\t * Did we write the wrong # entries in the header?\n+\t\t * If so, rewrite it like in fast-import (gackk).\n+\t\t */\n+\t\tif ( !base_name || nr_written == nr_actual ) {\n+\t\t\tsha1close(f, pack_file_sha1, 1);\n+\t\t} else {\n+\t\t\tsha1close(f, pack_file_sha1, -1);\n+\t\t\tfixup_header_footer(pack_fd, pack_file_sha1, oldname, nr_written);\n+\t\t}\n+\n+\t\t/*\n+\t\t * compute object_list_sha1 of sorted sha's we just wrote out;\n+\t\t * we also mark these objects as written\n+\t\t */\n+\t\tcurrent_sort = sha1_sort;\n+\t\tqsort(list, nr_written, sizeof(struct object_entry *), sort_comparator);\n+\t\tSHA1_Init(&ctx);\n+\t\tfor (j = 0; j < nr_written; j++) {\n+\t\t\tstruct object_entry *entry = *list++;\n+\t\t\tentry->no_write = 1;\n+\t\t\tSHA1_Update(&ctx, entry->sha1, 20);\n+\t\t}\n+\t\tSHA1_Final(object_list_sha1, &ctx);\n+\t\tlist = written_list;\n+\t\t/*\n+\t\t * now we can rename the pack correctly and write the index file\n+\t\t */\n+\t\tif (base_name) {\n+\t\t\tchar newname[PATH_MAX];\n+\t\t\tint len = snprintf(newname, sizeof newname, \"%s-%s.%s\",\n+\t\t\t\t\t\tbase_name, sha1_to_hex(object_list_sha1), \"pack\");\n+\t\t\tif (len >= PATH_MAX)\n+\t\t\t\tdie(\"excessive pathname length for final packfile name\");\n+\t\t\tif (rename(oldname, newname) < 0)\n+\t\t\t\tdie(\"could not rename the pack file\");\n+\t\t}\n+\t\tif (!pack_to_stdout) {\n+\t\t\twrite_index_file();\n+\t\t\tputs(sha1_to_hex(object_list_sha1));\n+\t\t}\n \t}\n-\tif (do_progress)\n+\n+\tfree(written_list);\n+\tif (nr_actual && do_progress)\n \t\tfputc('\\n', stderr);\n- done:\n-\tif (written != nr_result)\n-\t\tdie(\"wrote %u objects while expecting %u\", written, nr_result);\n-\tsha1close(f, pack_file_sha1, 1);\n-\tif (!pack_to_stdout) {\n-\t\twrite_index_file();\n-\t\tputs(sha1_to_hex(object_list_sha1));\n-\t}\n+\tif (written != nr_actual)\n+\t\tdie(\"wrote %u objects while expecting %u\", written, nr_actual);\n }\n \n static void write_index_file(void)\n@@ -650,8 +713,8 @@ static void write_index_file(void)\n \tuint32_t i;\n \tstruct sha1file *f = sha1create(\"%s-%s.%s\", base_name,\n \t\t\t\t\tsha1_to_hex(object_list_sha1), \"idx\");\n-\tstruct object_entry **list = sorted_by_sha;\n-\tstruct object_entry **last = list + nr_result;\n+\tstruct object_entry **list = written_list;\n+\tstruct object_entry **last = list + nr_written;\n \tuint32_t array[256];\n \n \t/*\n@@ -667,7 +730,7 @@ static void write_index_file(void)\n \t\t\t\tbreak;\n \t\t\tnext++;\n \t\t}\n-\t\tarray[i] = htonl(next - sorted_by_sha);\n+\t\tarray[i] = htonl(next - written_list);\n \t\tlist = next;\n \t}\n \tsha1write(f, array, 256 * 4);\n@@ -675,8 +738,8 @@ static void write_index_file(void)\n \t/*\n \t * Write the actual SHA1 entries..\n \t */\n-\tlist = sorted_by_sha;\n-\tfor (i = 0; i < nr_result; i++) {\n+\tlist = written_list;\n+\tfor (i = 0; i < nr_written; i++) {\n \t\tstruct object_entry *entry = *list++;\n \t\tuint32_t offset = htonl(entry->offset);\n \t\tsha1write(f, &offset, 4);\n-- \n1.5.1.rc2.18.g9c88-dirty\n\n"}]}