35
struct llist *all_objects;
36
} *local_packs = NULL, *altodb_packs = NULL;
37
38
-struct pll {
39
- struct pll *next;
40
- struct pack_list *pl;
41
-};
42
-
38
static struct llist_item *free_nodes;
39
40
static inline void llist_item_put(struct llist_item *item)
58
return new_item;
59
}
60
66
-static void llist_free(struct llist *list)
67
-{
68
- while ((list->back = list->front)) {
69
- list->front = list->front->next;
70
- llist_item_put(list->back);
71
- }
72
- free(list);
73
-}
74
-
61
static inline void llist_init(struct llist **list)
62
{
63
*list = xmalloc(sizeof(struct llist));
276
}
277
}
278
293
-static void pll_free(struct pll *l)
294
-{
295
- struct pll *old;
296
- struct pack_list *opl;
297
-
298
- while (l) {
299
- old = l;
300
- while (l->pl) {
301
- opl = l->pl;
302
- l->pl = opl->next;
303
- free(opl);
304
- }
305
- l = l->next;
306
- free(old);
307
- }
308
-}
309
-
310
-/* all the permutations have to be free()d at the same time,
311
- * since they refer to each other
312
- */
313
-static struct pll * get_permutations(struct pack_list *list, int n)
314
-{
315
- struct pll *subset, *ret = NULL, *new_pll = NULL;
316
-
317
- if (list == NULL || pack_list_size(list) < n || n == 0)
318
- return NULL;
319
-
320
- if (n == 1) {
321
- while (list) {
322
- new_pll = xmalloc(sizeof(*new_pll));
323
- new_pll->pl = NULL;
324
- pack_list_insert(&new_pll->pl, list);
325
- new_pll->next = ret;
326
- ret = new_pll;
327
- list = list->next;
328
- }
329
- return ret;
330
- }
331
-
332
- while (list->next) {
333
- subset = get_permutations(list->next, n - 1);
334
- while (subset) {
335
- new_pll = xmalloc(sizeof(*new_pll));
336
- new_pll->pl = subset->pl;
337
- pack_list_insert(&new_pll->pl, list);
338
- new_pll->next = ret;
339
- ret = new_pll;
340
- subset = subset->next;
341
- }
342
- list = list->next;
343
- }
344
- return ret;
345
-}
346
-
347
-static int is_superset(struct pack_list *pl, struct llist *list)
348
-{
349
- struct llist *diff;
350
-
351
- diff = llist_copy(list);
352
-
353
- while (pl) {
354
- llist_sorted_difference_inplace(diff, pl->all_objects);
355
- if (diff->size == 0) { /* we're done */
356
- llist_free(diff);
357
- return 1;
358
- }
359
- pl = pl->next;
360
- }
361
- llist_free(diff);
362
- return 0;
363
-}
364
-
279
static size_t sizeof_union(struct packed_git *p1, struct packed_git *p2)
280
{
281
size_t ret = 0;
340
return ret;
341
}
342
343
+static int cmp_pack_list_reverse(const void *a, const void *b)
344
+{
345
+ struct pack_list *pl_a = *((struct pack_list **)a);
346
+ struct pack_list *pl_b = *((struct pack_list **)b);
347
+ size_t sz_a = pl_a->all_objects->size;
348
+ size_t sz_b = pl_b->all_objects->size;
349
+
350
+ if (sz_a == sz_b)
351
+ return 0;
352
+ else if (sz_a < sz_b)
353
+ return 1;
354
+ else
355
+ return -1;
356
+}
357
+
358
+/* Sort pack_list, greater size of all_objects first */
359
+static void sort_pack_list(struct pack_list **pl)
360
+{
361
+ struct pack_list **ary, *p;
362
+ int i;
363
+ size_t n = pack_list_size(*pl);
364
+
365
+ if (n < 2)
366
+ return;
367
+
368
+ /* prepare an array of packed_list for easier sorting */
369
+ ary = xcalloc(n, sizeof(struct pack_list *));
370
+ for (n = 0, p = *pl; p; p = p->next)
371
+ ary[n++] = p;
372
+
373
+ QSORT(ary, n, cmp_pack_list_reverse);
374
+
375
+ /* link them back again */
376
+ for (i = 0; i < n - 1; i++)
377
+ ary[i]->next = ary[i + 1];
378
+ ary[n - 1]->next = NULL;
379
+ *pl = ary[0];
380
+
381
+ free(ary);
382
+}
383
+
384
+
385
static void minimize(struct pack_list **min)
386
{
431
- struct pack_list *pl, *unique = NULL,
432
- *non_unique = NULL, *min_perm = NULL;
433
- struct pll *perm, *perm_all, *perm_ok = NULL, *new_perm;
434
- struct llist *missing;
435
- off_t min_perm_size = 0, perm_size;
436
- int n;
387
+ struct pack_list *pl, *unique = NULL, *non_unique = NULL;
388
+ struct llist *missing, *unique_pack_objects;
389
390
pl = local_packs;
391
while (pl) {
403
pl = pl->next;
404
}
405
406
+ *min = unique;
407
+
408
/* return if there are no objects missing from the unique set */
409
if (missing->size == 0) {
456
- *min = unique;
410
free(missing);
411
return;
412
}
413
461
- /* find the permutations which contain all missing objects */
462
- for (n = 1; n <= pack_list_size(non_unique) && !perm_ok; n++) {
463
- perm_all = perm = get_permutations(non_unique, n);
464
- while (perm) {
465
- if (is_superset(perm->pl, missing)) {
466
- new_perm = xmalloc(sizeof(struct pll));
467
- memcpy(new_perm, perm, sizeof(struct pll));
468
- new_perm->next = perm_ok;
469
- perm_ok = new_perm;
470
- }
471
- perm = perm->next;
472
- }
473
- if (perm_ok)
474
- break;
475
- pll_free(perm_all);
476
- }
477
- if (perm_ok == NULL)
478
- die("Internal error: No complete sets found!");
479
-
480
- /* find the permutation with the smallest size */
481
- perm = perm_ok;
482
- while (perm) {
483
- perm_size = pack_set_bytecount(perm->pl);
484
- if (!min_perm_size || min_perm_size > perm_size) {
485
- min_perm_size = perm_size;
486
- min_perm = perm->pl;
487
- }
488
- perm = perm->next;
489
- }
490
- *min = min_perm;
491
- /* add the unique packs to the list */
492
- pl = unique;
414
+ unique_pack_objects = llist_copy(all_objects);
415
+ llist_sorted_difference_inplace(unique_pack_objects, missing);
416
+
417
+ /* remove unique pack objects from the non_unique packs */
418
+ pl = non_unique;
419
while (pl) {
494
- pack_list_insert(min, pl);
420
+ llist_sorted_difference_inplace(pl->all_objects, unique_pack_objects);
421
pl = pl->next;
422
}
423
+
424
+ while (non_unique) {
425
+ /* sort the non_unique packs, greater size of all_objects first */
426
+ sort_pack_list(&non_unique);
427
+ if (non_unique->all_objects->size == 0)
428
+ break;
429
+
430
+ pack_list_insert(min, non_unique);
431
+
432
+ for (pl = non_unique->next; pl && pl->all_objects->size > 0; pl = pl->next)
433
+ llist_sorted_difference_inplace(pl->all_objects, non_unique->all_objects);
434
+
435
+ non_unique = non_unique->next;
436
+ }
437
}
438
439
static void load_all_objects(void)
546
int cmd_pack_redundant(int argc, const char **argv, const char *prefix)
547
{
548
int i;
609
- struct pack_list *min, *red, *pl;
549
+ struct pack_list *min = NULL, *red, *pl;
550
struct llist *ignore;
551
struct object_id *oid;
552
char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */