checkout: add simple check for 'git checkout -b'
[gitweb.git] / packfile.c
index 17f993b5bfec64b2c747bd5f8daa7f8628cfa374..16bcb75262d918fc7b88cc5141213e951be145cc 100644 (file)
@@ -80,10 +80,8 @@ void pack_report(void)
 static int check_packed_git_idx(const char *path, struct packed_git *p)
 {
        void *idx_map;
-       struct pack_idx_header *hdr;
        size_t idx_size;
-       uint32_t version, nr, i, *index;
-       int fd = git_open(path);
+       int fd = git_open(path), ret;
        struct stat st;
        const unsigned int hashsz = the_hash_algo->rawsz;
 
@@ -101,16 +99,32 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)
        idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0);
        close(fd);
 
-       hdr = idx_map;
+       ret = load_idx(path, hashsz, idx_map, idx_size, p);
+
+       if (ret)
+               munmap(idx_map, idx_size);
+
+       return ret;
+}
+
+int load_idx(const char *path, const unsigned int hashsz, void *idx_map,
+            size_t idx_size, struct packed_git *p)
+{
+       struct pack_idx_header *hdr = idx_map;
+       uint32_t version, nr, i, *index;
+
+       if (idx_size < 4 * 256 + hashsz + hashsz)
+               return error("index file %s is too small", path);
+       if (idx_map == NULL)
+               return error("empty data");
+
        if (hdr->idx_signature == htonl(PACK_IDX_SIGNATURE)) {
                version = ntohl(hdr->idx_version);
-               if (version < 2 || version > 2) {
-                       munmap(idx_map, idx_size);
+               if (version < 2 || version > 2)
                        return error("index file %s is version %"PRIu32
                                     " and is not supported by this binary"
                                     " (try upgrading GIT to a newer version)",
                                     path, version);
-               }
        } else
                version = 1;
 
@@ -120,10 +134,8 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)
                index += 2;  /* skip index header */
        for (i = 0; i < 256; i++) {
                uint32_t n = ntohl(index[i]);
-               if (n < nr) {
-                       munmap(idx_map, idx_size);
+               if (n < nr)
                        return error("non-monotonic index %s", path);
-               }
                nr = n;
        }
 
@@ -135,10 +147,8 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)
                 *  - hash of the packfile
                 *  - file checksum
                 */
-               if (idx_size != 4*256 + nr * (hashsz + 4) + hashsz + hashsz) {
-                       munmap(idx_map, idx_size);
+               if (idx_size != 4 * 256 + nr * (hashsz + 4) + hashsz + hashsz)
                        return error("wrong index v1 file size in %s", path);
-               }
        } else if (version == 2) {
                /*
                 * Minimum size:
@@ -157,20 +167,16 @@ static int check_packed_git_idx(const char *path, struct packed_git *p)
                unsigned long max_size = min_size;
                if (nr)
                        max_size += (nr - 1)*8;
-               if (idx_size < min_size || idx_size > max_size) {
-                       munmap(idx_map, idx_size);
+               if (idx_size < min_size || idx_size > max_size)
                        return error("wrong index v2 file size in %s", path);
-               }
                if (idx_size != min_size &&
                    /*
                     * make sure we can deal with large pack offsets.
                     * 31-bit signed offset won't be enough, neither
                     * 32-bit unsigned one will be.
                     */
-                   (sizeof(off_t) <= 4)) {
-                       munmap(idx_map, idx_size);
+                   (sizeof(off_t) <= 4))
                        return error("pack too large for current definition of off_t in %s", path);
-               }
        }
 
        p->index_version = version;
@@ -339,6 +345,11 @@ void close_all_packs(struct raw_object_store *o)
                        BUG("want to close pack marked 'do-not-close'");
                else
                        close_pack(p);
+
+       if (o->multi_pack_index) {
+               close_midx(o->multi_pack_index);
+               o->multi_pack_index = NULL;
+       }
 }
 
 /*
@@ -960,16 +971,16 @@ static void prepare_packed_git_mru(struct repository *r)
 
 static void prepare_packed_git(struct repository *r)
 {
-       struct alternate_object_database *alt;
+       struct object_directory *odb;
 
        if (r->objects->packed_git_initialized)
                return;
-       prepare_multi_pack_index_one(r, r->objects->objectdir, 1);
-       prepare_packed_git_one(r, r->objects->objectdir, 1);
+
        prepare_alt_odb(r);
-       for (alt = r->objects->alt_odb_list; alt; alt = alt->next) {
-               prepare_multi_pack_index_one(r, alt->path, 0);
-               prepare_packed_git_one(r, alt->path, 0);
+       for (odb = r->objects->odb; odb; odb = odb->next) {
+               int local = (odb == r->objects->odb);
+               prepare_multi_pack_index_one(r, odb->path, local);
+               prepare_packed_git_one(r, odb->path, local);
        }
        rearrange_packed_git(r);
 
@@ -981,6 +992,11 @@ static void prepare_packed_git(struct repository *r)
 
 void reprepare_packed_git(struct repository *r)
 {
+       struct object_directory *odb;
+
+       for (odb = r->objects->odb; odb; odb = odb->next)
+               odb_clear_loose_cache(odb);
+
        r->objects->approximate_object_count_valid = 0;
        r->objects->packed_git_initialized = 0;
        prepare_packed_git(r);
@@ -1132,12 +1148,13 @@ void mark_bad_packed_object(struct packed_git *p, const unsigned char *sha1)
        p->num_bad_objects++;
 }
 
-const struct packed_git *has_packed_and_bad(const unsigned char *sha1)
+const struct packed_git *has_packed_and_bad(struct repository *r,
+                                           const unsigned char *sha1)
 {
        struct packed_git *p;
        unsigned i;
 
-       for (p = the_repository->objects->packed_git; p; p = p->next)
+       for (p = r->objects->packed_git; p; p = p->next)
                for (i = 0; i < p->num_bad_objects; i++)
                        if (hasheq(sha1,
                                   p->bad_object_sha1 + the_hash_algo->rawsz * i))
@@ -2081,7 +2098,7 @@ static int add_promisor_object(const struct object_id *oid,
                         */
                        return 0;
                while (tree_entry_gently(&desc, &entry))
-                       oidset_insert(set, entry.oid);
+                       oidset_insert(set, &entry.oid);
        } else if (obj->type == OBJ_COMMIT) {
                struct commit *commit = (struct commit *) obj;
                struct commit_list *parents = commit->parents;