git-repack --max-pack-size: split packs as asked by write_object/write_one
PATCH 7/8 git-repack --max-pack-size: split packs as asked by write_object/write_one
Rewrite write_pack_file() to break to a new packfile whenever write_object/write_one request it, and correct the header's object count in the previous packfile. Change write_index_file() to write an index
for just the objects in the most recent packfile.
Signed-off-by Dana How <[email protected]>
--- builtin-pack-objects.c | 126 ++++++++++++++++++++++++++++++++++-------------- 1 files changed, 89 insertions(+), 37 deletions(-)
builtin-pack-objects.c +89 -37
@@ -572,6 +572,7 @@ static off_t write_one(struct sha1file *f, result =write_object (f, e, offset_limit && nr_written ? offset_limit - offset :0 );if (!result)return result; + written_list[nr_written++] = e; e->offset = offset;return offset + result; }
@@ -628,52 +629,103 @@ 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; +SHA_CTX ctx; -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); + written_list =xmalloc (nr_objects *sizeof (struct object_entry *)); - 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; +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 (nr_result); +sha1write (f, &hdr,sizeof (hdr)); + offset =sizeof (hdr); + nr_written =0 ; +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_result; +if (progress_update || percent != last_percent) { +fprintf (stderr,"%4u%% (%u/%u) done\r" , + percent, written, nr_result); + progress_update =0 ; + last_percent = percent; + } } } + +/* +* Did we write the wrong # entries in the header? +* If so, rewrite it like in fast-import (gackk). +*/ +if ( !base_name || nr_written == nr_result ) { +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 (written_list, nr_written,sizeof (struct object_entry *), sort_comparator); +SHA1_Init (&ctx); +for (j =0 ; j < nr_written; j++) { +struct object_entry *entry = written_list[j]; + entry->prev_pack =1 ; +SHA1_Update (&ctx, entry->sha1,20 ); + } +SHA1_Final (object_list_sha1, &ctx); +/* +* 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_result && 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)); - } }static void write_index_file (void )
@@ -681,8 +733,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 ];/*
@@ -698,7 +750,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 );
@@ -706,8 +758,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 );
Signature · 1 line
1.5.1.89.g8abf0