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 <pclo...@gmail.com>
---
 builtin/index-pack.c   | 29 +++++++++++++++++++++++++----
 builtin/pack-objects.c | 15 +++++++++++----
 2 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 88340b5..9036f3e 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1493,7 +1493,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)
@@ -1502,7 +1502,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) {
@@ -1521,8 +1542,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 12d9af4..1efb728 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -865,15 +865,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 < nr_objects)
+                               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);
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to