pack-objects: reuse on-disk deltas for thin "have" objects
[gitweb.git] / pack-bitmap.c
index 70465b8bf5a5e2716ad5c878b56746a32cf7c0a3..c3231ef9ef2d57ce21ebe8db64401af95a0bb6e6 100644 (file)
@@ -66,7 +66,7 @@ struct bitmap_index {
        /* Number of bitmapped commits */
        uint32_t entry_count;
 
-       /* Name-hash cache (or NULL if not present). */
+       /* If not NULL, this is a name-hash cache pointing into map. */
        uint32_t *hashes;
 
        /*
@@ -86,6 +86,9 @@ struct bitmap_index {
        /* Bitmap result of the last performed walk */
        struct bitmap *result;
 
+       /* "have" bitmap from the last performed walk */
+       struct bitmap *haves;
+
        /* Version of the bitmap index */
        unsigned int version;
 
@@ -350,6 +353,7 @@ struct bitmap_index *prepare_bitmap_git(void)
        if (!open_pack_bitmap(bitmap_git) && !load_pack_bitmap(bitmap_git))
                return bitmap_git;
 
+       free_bitmap_index(bitmap_git);
        return NULL;
 }
 
@@ -690,7 +694,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs)
        /* try to open a bitmapped pack, but don't parse it yet
         * because we may not need to use it */
        if (open_pack_bitmap(bitmap_git) < 0)
-               return NULL;
+               goto cleanup;
 
        for (i = 0; i < revs->pending.nr; ++i) {
                struct object *object = revs->pending.objects[i].item;
@@ -723,11 +727,11 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs)
         * optimize here
         */
        if (haves && !in_bitmapped_pack(bitmap_git, haves))
-               return NULL;
+               goto cleanup;
 
        /* if we don't want anything, we're done here */
        if (!wants)
-               return NULL;
+               goto cleanup;
 
        /*
         * now we're going to use bitmaps, so load the actual bitmap entries
@@ -735,7 +739,7 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs)
         * becomes invalidated and we must perform the revwalk through bitmaps
         */
        if (!bitmap_git->loaded && load_pack_bitmap(bitmap_git) < 0)
-               return NULL;
+               goto cleanup;
 
        object_array_clear(&revs->pending);
 
@@ -758,9 +762,13 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs)
                bitmap_and_not(wants_bitmap, haves_bitmap);
 
        bitmap_git->result = wants_bitmap;
+       bitmap_git->haves = haves_bitmap;
 
-       bitmap_free(haves_bitmap);
        return bitmap_git;
+
+cleanup:
+       free_bitmap_index(bitmap_git);
+       return NULL;
 }
 
 int reuse_partial_packfile_from_bitmap(struct bitmap_index *bitmap_git,
@@ -1001,7 +1009,7 @@ void test_bitmap_walk(struct rev_info *revs)
        else
                fprintf(stderr, "Mismatch!\n");
 
-       bitmap_free(result);
+       free_bitmap_index(bitmap_git);
 }
 
 static int rebuild_bitmap(uint32_t *reposition,
@@ -1093,3 +1101,41 @@ int rebuild_existing_bitmaps(struct bitmap_index *bitmap_git,
        bitmap_free(rebuild);
        return 0;
 }
+
+void free_bitmap_index(struct bitmap_index *b)
+{
+       if (!b)
+               return;
+
+       if (b->map)
+               munmap(b->map, b->map_size);
+       ewah_pool_free(b->commits);
+       ewah_pool_free(b->trees);
+       ewah_pool_free(b->blobs);
+       ewah_pool_free(b->tags);
+       kh_destroy_sha1(b->bitmaps);
+       free(b->ext_index.objects);
+       free(b->ext_index.hashes);
+       bitmap_free(b->result);
+       bitmap_free(b->haves);
+       free(b);
+}
+
+int bitmap_has_sha1_in_uninteresting(struct bitmap_index *bitmap_git,
+                                    const unsigned char *sha1)
+{
+       int pos;
+
+       if (!bitmap_git)
+               return 0; /* no bitmap loaded */
+       if (!bitmap_git->result)
+               BUG("failed to perform bitmap walk before querying");
+       if (!bitmap_git->haves)
+               return 0; /* walk had no "haves" */
+
+       pos = bitmap_position_packfile(bitmap_git, sha1);
+       if (pos < 0)
+               return 0;
+
+       return bitmap_get(bitmap_git->haves, pos);
+}