summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2013-09-09 20:58:05 +0700
committerNicolas Pitre <nico@fluxnic.net>2013-09-13 21:00:29 -0400
commit99e842643417dfe238f40c19c50c7eaffb8c0e4d (patch)
treefb8af69d8661642e14bbe0b7424f0117c246eb63
parentfa7e4e65ff84dae1da69a633126f062999431875 (diff)
downloadgit-99e842643417dfe238f40c19c50c7eaffb8c0e4d.tar.gz
pack v4: support "end-of-pack" indicator in index-pack and pack-objects
In v2, the number of objects in the pack header indicates how many objects are sent. In v4 this is no longer true, that number includes the base objects ommitted by pack-objects. An "end-of-pack" is inserted just before the final SHA-1 to let index-pack knows when to stop. The EOP is zero (in variable length encoding it means type zero, OBJ_NONE, and size zero) Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Nicolas Pitre <nico@fluxnic.net>
-rw-r--r--builtin/index-pack.c29
-rw-r--r--builtin/pack-objects.c15
2 files changed, 36 insertions, 8 deletions
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 059fe3db21..c97c051a80 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1494,7 +1494,7 @@ static void parse_dictionaries(void)
*/
static void parse_pack_objects(unsigned char *sha1)
{
- int i, nr_delays = 0;
+ int i, nr_delays = 0, eop = 0;
struct stat st;
if (verbose)
@@ -1503,7 +1503,28 @@ static void parse_pack_objects(unsigned char *sha1)
nr_objects);
for (i = 0; i < nr_objects; i++) {
struct object_entry *obj = &objects[i];
- void *data = unpack_raw_entry(obj, obj->idx.sha1);
+ void *data;
+
+ if (packv4) {
+ unsigned char *eop_byte;
+ flush();
+ /* Got End-of-Pack signal? */
+ eop_byte = fill(1);
+ if (*eop_byte == 0) {
+ git_SHA1_Update(&input_ctx, eop_byte, 1);
+ use(1);
+ /*
+ * consumed by is used to mark the end
+ * of the object right after this
+ * loop. Undo use() effect.
+ */
+ consumed_bytes--;
+ eop = 1; /* so we don't flush() again */
+ break;
+ }
+ }
+
+ data = unpack_raw_entry(obj, obj->idx.sha1);
if (is_delta_type(obj->type) || is_delta_tree(obj)) {
/* delay sha1_object() until second pass */
} else if (!data) {
@@ -1522,8 +1543,8 @@ static void parse_pack_objects(unsigned char *sha1)
objects[i].idx.offset = consumed_bytes;
stop_progress(&progress);
- /* Check pack integrity */
- flush();
+ if (!eop)
+ flush(); /* Check pack integrity */
git_SHA1_Final(sha1, &input_ctx);
if (hashcmp(fill(20), sha1))
die(_("pack is corrupted (SHA1 mismatch)"));
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 1e118660c7..39d1e088fb 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -866,15 +866,22 @@ static void write_pack_file(void)
display_progress(progress_state, written);
}
- /*
- * Did we write the wrong # entries in the header?
- * If so, rewrite it like in fast-import
- */
if (pack_to_stdout) {
+ unsigned char type_zero = 0;
+ /*
+ * Pack v4 thin pack is terminated by a "type
+ * 0, size 0" in variable length encoding
+ */
+ if (pack_version == 4 && nr_written < v4.all_objs_nr)
+ sha1write(f, &type_zero, 1);
sha1close(f, sha1, CSUM_CLOSE);
} else if (nr_written == nr_remaining) {
sha1close(f, sha1, CSUM_FSYNC);
} else {
+ /*
+ * Did we write the wrong # entries in the header?
+ * If so, rewrite it like in fast-import
+ */
int fd = sha1close(f, sha1, 0);
fixup_pack_header_footer(fd, sha1, pack_tmp_name,
nr_written, sha1, offset);