]> git.ipfire.org Git - thirdparty/git.git/blobdiff - midx.c
Merge branch 'es/worktree-repair'
[thirdparty/git.git] / midx.c
diff --git a/midx.c b/midx.c
index a5fb797edeeae46b76f8f926d4b9d40b2236878d..cc19b6615281475f25cc4119ff2246e2961497fa 100644 (file)
--- a/midx.c
+++ b/midx.c
@@ -17,7 +17,6 @@
 #define MIDX_BYTE_HASH_VERSION 5
 #define MIDX_BYTE_NUM_CHUNKS 6
 #define MIDX_BYTE_NUM_PACKS 8
-#define MIDX_HASH_VERSION 1
 #define MIDX_HEADER_SIZE 12
 #define MIDX_MIN_SIZE (MIDX_HEADER_SIZE + the_hash_algo->rawsz)
 
 
 #define PACK_EXPIRED UINT_MAX
 
+static uint8_t oid_version(void)
+{
+       switch (hash_algo_by_ptr(the_hash_algo)) {
+       case GIT_HASH_SHA1:
+               return 1;
+       case GIT_HASH_SHA256:
+               return 2;
+       default:
+               die(_("invalid hash version"));
+       }
+}
+
 static char *get_midx_filename(const char *object_dir)
 {
        return xstrfmt("%s/pack/multi-pack-index", object_dir);
@@ -90,8 +101,11 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
                      m->version);
 
        hash_version = m->data[MIDX_BYTE_HASH_VERSION];
-       if (hash_version != MIDX_HASH_VERSION)
-               die(_("hash version %u does not match"), hash_version);
+       if (hash_version != oid_version()) {
+               error(_("multi-pack-index hash version %u does not match version %u"),
+                     hash_version, oid_version());
+               goto cleanup_fail;
+       }
        m->hash_len = the_hash_algo->rawsz;
 
        m->num_chunks = m->data[MIDX_BYTE_NUM_CHUNKS];
@@ -402,8 +416,12 @@ int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, i
        m = load_multi_pack_index(object_dir, local);
 
        if (m) {
-               m->next = r->objects->multi_pack_index;
-               r->objects->multi_pack_index = m;
+               struct multi_pack_index *mp = r->objects->multi_pack_index;
+               if (mp) {
+                       m->next = mp->next;
+                       mp->next = m;
+               } else
+                       r->objects->multi_pack_index = m;
                return 1;
        }
 
@@ -418,7 +436,7 @@ static size_t write_midx_header(struct hashfile *f,
 
        hashwrite_be32(f, MIDX_SIGNATURE);
        byte_values[0] = MIDX_VERSION;
-       byte_values[1] = MIDX_HASH_VERSION;
+       byte_values[1] = oid_version();
        byte_values[2] = num_chunks;
        byte_values[3] = 0; /* unused */
        hashwrite(f, byte_values, sizeof(byte_values));
@@ -807,11 +825,9 @@ static int write_midx_internal(const char *object_dir, struct multi_pack_index *
        int result = 0;
 
        midx_name = get_midx_filename(object_dir);
-       if (safe_create_leading_directories(midx_name)) {
-               UNLEAK(midx_name);
+       if (safe_create_leading_directories(midx_name))
                die_errno(_("unable to create leading directories of %s"),
                          midx_name);
-       }
 
        if (m)
                packs.m = m;
@@ -1051,10 +1067,8 @@ void clear_midx_file(struct repository *r)
                r->objects->multi_pack_index = NULL;
        }
 
-       if (remove_path(midx)) {
-               UNLEAK(midx);
+       if (remove_path(midx))
                die(_("failed to clear multi-pack-index at %s"), midx);
-       }
 
        free(midx);
 }
@@ -1105,8 +1119,17 @@ int verify_midx_file(struct repository *r, const char *object_dir, unsigned flag
        struct multi_pack_index *m = load_multi_pack_index(object_dir, 1);
        verify_midx_error = 0;
 
-       if (!m)
-               return 0;
+       if (!m) {
+               int result = 0;
+               struct stat sb;
+               char *filename = get_midx_filename(object_dir);
+               if (!stat(filename, &sb)) {
+                       error(_("multi-pack-index file exists, but failed to parse"));
+                       result = 1;
+               }
+               free(filename);
+               return result;
+       }
 
        if (flags & MIDX_PROGRESS)
                progress = start_progress(_("Looking for referenced packfiles"),
@@ -1371,7 +1394,7 @@ static int fill_included_packs_batch(struct repository *r,
 
        free(pack_info);
 
-       if (total_size < batch_size || packs_to_repack < 2)
+       if (packs_to_repack < 2)
                return 1;
 
        return 0;
@@ -1383,6 +1406,7 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size,
        uint32_t i;
        unsigned char *include_pack;
        struct child_process cmd = CHILD_PROCESS_INIT;
+       FILE *cmd_in;
        struct strbuf base_name = STRBUF_INIT;
        struct multi_pack_index *m = load_multi_pack_index(object_dir, 1);
 
@@ -1435,6 +1459,8 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size,
                goto cleanup;
        }
 
+       cmd_in = xfdopen(cmd.in, "w");
+
        for (i = 0; i < m->num_objects; i++) {
                struct object_id oid;
                uint32_t pack_int_id = nth_midxed_pack_int_id(m, i);
@@ -1443,10 +1469,9 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size,
                        continue;
 
                nth_midxed_object_oid(&oid, m, i);
-               xwrite(cmd.in, oid_to_hex(&oid), the_hash_algo->hexsz);
-               xwrite(cmd.in, "\n", 1);
+               fprintf(cmd_in, "%s\n", oid_to_hex(&oid));
        }
-       close(cmd.in);
+       fclose(cmd_in);
 
        if (finish_command(&cmd)) {
                error(_("could not finish pack-objects"));