difftool: allow running outside Git worktrees with --no-index
[gitweb.git] / builtin / pack-redundant.c
index d6d9a66e46cdc2a975153ad39ab79ae3214e937f..68c1e547c244e09f6447c361b9c665efbb27192d 100644 (file)
@@ -32,7 +32,8 @@ static struct pack_list {
        struct pack_list *next;
        struct packed_git *pack;
        struct llist *unique_objects;
-       struct llist *all_objects;
+       struct llist *remaining_objects;
+       size_t all_objects_size;
 } *local_packs = NULL, *altodb_packs = NULL;
 
 static struct llist_item *free_nodes;
@@ -152,7 +153,7 @@ static inline struct llist_item * llist_sorted_remove(struct llist *list, const
        l = (hint == NULL) ? list->front : hint;
        prev = NULL;
        while (l) {
-               int cmp = oidcmp(l->oid, oid);
+               const int cmp = oidcmp(l->oid, oid);
                if (cmp > 0) /* not in list, since sorted */
                        return prev;
                if (!cmp) { /* found */
@@ -241,9 +242,9 @@ static void cmp_two_packs(struct pack_list *p1, struct pack_list *p2)
        const unsigned int hashsz = the_hash_algo->rawsz;
 
        if (!p1->unique_objects)
-               p1->unique_objects = llist_copy(p1->all_objects);
+               p1->unique_objects = llist_copy(p1->remaining_objects);
        if (!p2->unique_objects)
-               p2->unique_objects = llist_copy(p2->all_objects);
+               p2->unique_objects = llist_copy(p2->remaining_objects);
 
        p1_base = p1->pack->index_data;
        p2_base = p2->pack->index_data;
@@ -255,7 +256,7 @@ static void cmp_two_packs(struct pack_list *p1, struct pack_list *p2)
        while (p1_off < p1->pack->num_objects * p1_step &&
               p2_off < p2->pack->num_objects * p2_step)
        {
-               int cmp = hashcmp(p1_base + p1_off, p2_base + p2_off);
+               const int cmp = hashcmp(p1_base + p1_off, p2_base + p2_off);
                /* cmp ~ p1 - p2 */
                if (cmp == 0) {
                        p1_hint = llist_sorted_remove(p1->unique_objects,
@@ -340,22 +341,28 @@ static inline off_t pack_set_bytecount(struct pack_list *pl)
        return ret;
 }
 
-static int cmp_pack_list_reverse(const void *a, const void *b)
+static int cmp_remaining_objects(const void *a, const void *b)
 {
        struct pack_list *pl_a = *((struct pack_list **)a);
        struct pack_list *pl_b = *((struct pack_list **)b);
-       size_t sz_a = pl_a->all_objects->size;
-       size_t sz_b = pl_b->all_objects->size;
 
-       if (sz_a == sz_b)
-               return 0;
-       else if (sz_a < sz_b)
+       if (pl_a->remaining_objects->size == pl_b->remaining_objects->size) {
+               /* have the same remaining_objects, big pack first */
+               if (pl_a->all_objects_size == pl_b->all_objects_size)
+                       return 0;
+               else if (pl_a->all_objects_size < pl_b->all_objects_size)
+                       return 1;
+               else
+                       return -1;
+       } else if (pl_a->remaining_objects->size < pl_b->remaining_objects->size) {
+               /* sort by remaining objects, more objects first */
                return 1;
-       else
+       } else {
                return -1;
+       }
 }
 
-/* Sort pack_list, greater size of all_objects first */
+/* Sort pack_list, greater size of remaining_objects first */
 static void sort_pack_list(struct pack_list **pl)
 {
        struct pack_list **ary, *p;
@@ -370,7 +377,7 @@ static void sort_pack_list(struct pack_list **pl)
        for (n = 0, p = *pl; p; p = p->next)
                ary[n++] = p;
 
-       QSORT(ary, n, cmp_pack_list_reverse);
+       QSORT(ary, n, cmp_remaining_objects);
 
        /* link them back again */
        for (i = 0; i < n - 1; i++)
@@ -399,7 +406,7 @@ static void minimize(struct pack_list **min)
        missing = llist_copy(all_objects);
        pl = unique;
        while (pl) {
-               llist_sorted_difference_inplace(missing, pl->all_objects);
+               llist_sorted_difference_inplace(missing, pl->remaining_objects);
                pl = pl->next;
        }
 
@@ -417,20 +424,20 @@ static void minimize(struct pack_list **min)
        /* remove unique pack objects from the non_unique packs */
        pl = non_unique;
        while (pl) {
-               llist_sorted_difference_inplace(pl->all_objects, unique_pack_objects);
+               llist_sorted_difference_inplace(pl->remaining_objects, unique_pack_objects);
                pl = pl->next;
        }
 
        while (non_unique) {
-               /* sort the non_unique packs, greater size of all_objects first */
+               /* sort the non_unique packs, greater size of remaining_objects first */
                sort_pack_list(&non_unique);
-               if (non_unique->all_objects->size == 0)
+               if (non_unique->remaining_objects->size == 0)
                        break;
 
                pack_list_insert(min, non_unique);
 
-               for (pl = non_unique->next; pl && pl->all_objects->size > 0;  pl = pl->next)
-                       llist_sorted_difference_inplace(pl->all_objects, non_unique->all_objects);
+               for (pl = non_unique->next; pl && pl->remaining_objects->size > 0;  pl = pl->next)
+                       llist_sorted_difference_inplace(pl->remaining_objects, non_unique->remaining_objects);
 
                non_unique = non_unique->next;
        }
@@ -445,7 +452,7 @@ static void load_all_objects(void)
 
        while (pl) {
                hint = NULL;
-               l = pl->all_objects->front;
+               l = pl->remaining_objects->front;
                while (l) {
                        hint = llist_insert_sorted_unique(all_objects,
                                                          l->oid, hint);
@@ -456,7 +463,7 @@ static void load_all_objects(void)
        /* remove objects present in remote packs */
        pl = altodb_packs;
        while (pl) {
-               llist_sorted_difference_inplace(all_objects, pl->all_objects);
+               llist_sorted_difference_inplace(all_objects, pl->remaining_objects);
                pl = pl->next;
        }
 }
@@ -481,8 +488,8 @@ static void scan_alt_odb_packs(void)
        while (alt) {
                local = local_packs;
                while (local) {
-                       llist_sorted_difference_inplace(local->all_objects,
-                                                       alt->all_objects);
+                       llist_sorted_difference_inplace(local->remaining_objects,
+                                                       alt->remaining_objects);
                        local = local->next;
                }
                alt = alt->next;
@@ -499,7 +506,7 @@ static struct pack_list * add_pack(struct packed_git *p)
                return NULL;
 
        l.pack = p;
-       llist_init(&l.all_objects);
+       llist_init(&l.remaining_objects);
 
        if (open_pack_index(p))
                return NULL;
@@ -508,9 +515,10 @@ static struct pack_list * add_pack(struct packed_git *p)
        base += 256 * 4 + ((p->index_version < 2) ? 4 : 8);
        step = the_hash_algo->rawsz + ((p->index_version < 2) ? 4 : 0);
        while (off < p->num_objects * step) {
-               llist_insert_back(l.all_objects, (const struct object_id *)(base + off));
+               llist_insert_back(l.remaining_objects, (const struct object_id *)(base + off));
                off += step;
        }
+       l.all_objects_size = l.remaining_objects->size;
        l.unique_objects = NULL;
        if (p->pack_local)
                return pack_list_insert(&local_packs, &l);
@@ -605,7 +613,7 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix)
        llist_sorted_difference_inplace(all_objects, ignore);
        pl = local_packs;
        while (pl) {
-               llist_sorted_difference_inplace(pl->all_objects, ignore);
+               llist_sorted_difference_inplace(pl->remaining_objects, ignore);
                pl = pl->next;
        }