write_pack_file() now also sets up and sorts written_list for each pack; modify write_one() to update this and write_index_file() to use it. --- builtin-pack-objects.c | 147 ++++++++++++++++++++++++++++++++++-------------- 1 files changed, 105 insertions(+), 42 deletions(-) -- Dana L. How danahow@xxxxxxxxx +1 650 804 5991 cell
From cc6808e18fbeb2049e1d705eb7c7f6f9b83b3441 Mon Sep 17 00:00:00 2001 From: Dana How <how@xxxxxxxxxxxxxxxxxxxxxxx> Date: Thu, 5 Apr 2007 14:43:33 -0700 Subject: [PATCH 12/13] rewrite write_pack_file() to write multiple packs write_pack_file() now also sets up and sorts written_list for each pack; modify write_one() to update this and write_index_file() to use it. --- builtin-pack-objects.c | 147 ++++++++++++++++++++++++++++++++++-------------- 1 files changed, 105 insertions(+), 42 deletions(-) diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index ac643dd..3229df8 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -534,14 +534,17 @@ static off_t write_one(struct sha1file *f, * Ensure the packfile size never exceeds or matches offset_limit. * The "20" is for the final SHA1. */ - if ((unsigned long)offset < (unsigned long)(offset_limit - 20)) + if ((unsigned long)offset < (unsigned long)(offset_limit - 20)) { + *written_list++ = e; return offset; + } written = save_written, written_delta = save_written_delta; reused = save_reused, reused_delta = save_reused_delta; sha1undo(f, &posn, offset, e->offset); e->offset = 0; return 0; } + *written_list++ = e; return offset + write_object(f, e); } @@ -597,52 +600,112 @@ static void write_index_file(void); static void write_pack_file(void) { - uint32_t i; + uint32_t i, j; struct sha1file *f; off_t offset; struct pack_header hdr; unsigned last_percent = 999; - int do_progress = progress; + int do_progress = progress >> !base_name; + char oldname[PATH_MAX]; + int pack_fd; + struct object_entry **list; + SHA_CTX ctx; + uint32_t nr_actual = nr_result - nr_skipped; - if (!base_name) { - f = sha1fd(1, "<stdout>"); - do_progress >>= 1; - } - else - f = sha1create("%s-%s.%s", base_name, - sha1_to_hex(object_list_sha1), "pack"); if (do_progress) - fprintf(stderr, "Writing %u objects.\n", nr_result); - - hdr.hdr_signature = htonl(PACK_SIGNATURE); - hdr.hdr_version = htonl(PACK_VERSION); - hdr.hdr_entries = htonl(nr_result); - sha1write(f, &hdr, sizeof(hdr)); - offset = sizeof(hdr); - if (!nr_result) - goto done; - for (i = 0; i < nr_objects; i++) { - offset = write_one(f, objects + i, offset); - if (do_progress) { - unsigned percent = written * 100 / nr_result; - if (progress_update || percent != last_percent) { - fprintf(stderr, "%4u%% (%u/%u) done\r", - percent, written, nr_result); - progress_update = 0; - last_percent = percent; + fprintf(stderr, "Writing %u objects.\n", nr_actual); + written_list = list = xmalloc(nr_objects * sizeof(struct object_entry *)); + + for (i = 0; i < nr_objects;) { + if (!base_name) { + f = sha1fd(pack_fd = 1, "<stdout>"); + } + else { + int len = snprintf(oldname, sizeof oldname, "%s-XXXXXX", base_name); + if (len >= PATH_MAX) + die("excessive pathname length for initial packfile name"); + pack_fd = mkstemp(oldname); + if (pack_fd < 0) + die("can't create %s: %s", oldname, strerror(errno)); + f = sha1fd(pack_fd, oldname); + } + + hdr.hdr_signature = htonl(PACK_SIGNATURE); + hdr.hdr_version = htonl(PACK_VERSION); + hdr.hdr_entries = htonl(!base_name && offset_limit ? 0 : nr_actual); + sha1write(f, &hdr, sizeof(hdr)); + offset = sizeof(hdr); + for (; i < nr_objects; i++) { + off_t offset_one = write_one(f, objects + i, offset); + if (!offset_one) + break; + offset = offset_one; + if (do_progress) { + unsigned percent = written * 100 / nr_actual; + if (progress_update || percent != last_percent) { + fprintf(stderr, "%4u%% (%u/%u) done\r", + percent, written, nr_actual); + progress_update = 0; + last_percent = percent; + } } } + nr_written = written_list - list; + written_list = list; + + /* + * Write terminator record here if desired: + * type=OBJ_NONE, len=0; this is a zero byte. + */ + + /* + * Did we write the wrong # entries in the header? + * If so, rewrite it like in fast-import (gackk). + */ + if ( !base_name || nr_written == nr_actual ) { + sha1close(f, pack_file_sha1, 1); + } else { + sha1close(f, pack_file_sha1, -1); + fixup_header_footer(pack_fd, pack_file_sha1, oldname, nr_written); + } + + /* + * compute object_list_sha1 of sorted sha's we just wrote out; + * we also mark these objects as written + */ + current_sort = sha1_sort; + qsort(list, nr_written, sizeof(struct object_entry *), sort_comparator); + SHA1_Init(&ctx); + for (j = 0; j < nr_written; j++) { + struct object_entry *entry = *list++; + entry->no_write = 1; + SHA1_Update(&ctx, entry->sha1, 20); + } + SHA1_Final(object_list_sha1, &ctx); + list = written_list; + /* + * now we can rename the pack correctly and write the index file + */ + if (base_name) { + char newname[PATH_MAX]; + int len = snprintf(newname, sizeof newname, "%s-%s.%s", + base_name, sha1_to_hex(object_list_sha1), "pack"); + if (len >= PATH_MAX) + die("excessive pathname length for final packfile name"); + if (rename(oldname, newname) < 0) + die("could not rename the pack file"); + } + if (!pack_to_stdout) { + write_index_file(); + puts(sha1_to_hex(object_list_sha1)); + } } - if (do_progress) + + free(written_list); + if (nr_actual && do_progress) fputc('\n', stderr); - done: - if (written != nr_result) - die("wrote %u objects while expecting %u", written, nr_result); - sha1close(f, pack_file_sha1, 1); - if (!pack_to_stdout) { - write_index_file(); - puts(sha1_to_hex(object_list_sha1)); - } + if (written != nr_actual) + die("wrote %u objects while expecting %u", written, nr_actual); } static void write_index_file(void) @@ -650,8 +713,8 @@ static void write_index_file(void) uint32_t i; struct sha1file *f = sha1create("%s-%s.%s", base_name, sha1_to_hex(object_list_sha1), "idx"); - struct object_entry **list = sorted_by_sha; - struct object_entry **last = list + nr_result; + struct object_entry **list = written_list; + struct object_entry **last = list + nr_written; uint32_t array[256]; /* @@ -667,7 +730,7 @@ static void write_index_file(void) break; next++; } - array[i] = htonl(next - sorted_by_sha); + array[i] = htonl(next - written_list); list = next; } sha1write(f, array, 256 * 4); @@ -675,8 +738,8 @@ static void write_index_file(void) /* * Write the actual SHA1 entries.. */ - list = sorted_by_sha; - for (i = 0; i < nr_result; i++) { + list = written_list; + for (i = 0; i < nr_written; i++) { struct object_entry *entry = *list++; uint32_t offset = htonl(entry->offset); sha1write(f, &offset, 4); -- 1.5.1.rc2.18.g9c88-dirty