431
return strcmp(a->pack_name, b->pack_name);
432
}
433
434
+static int idx_or_pack_name_cmp(const void *_va, const void *_vb)
435
+{
436
+ const char *pack_name = _va;
437
+ const struct pack_info *compar = _vb;
438
+
439
+ return cmp_idx_or_pack_name(pack_name, compar->pack_name);
440
+}
441
+
442
struct write_midx_context {
443
struct pack_info *info;
444
uint32_t nr;
453
uint32_t *pack_perm;
454
unsigned large_offsets_needed:1;
455
uint32_t num_large_offsets;
456
+
457
+ int preferred_pack_idx;
458
};
459
460
static void add_pack_to_midx(const char *full_path, size_t full_path_len,
499
uint32_t pack_int_id;
500
time_t pack_mtime;
501
uint64_t offset;
502
+ unsigned preferred : 1;
503
};
504
505
static int midx_oid_compare(const void *_a, const void *_b)
511
if (cmp)
512
return cmp;
513
514
+ /* Sort objects in a preferred pack first when multiple copies exist. */
515
+ if (a->preferred > b->preferred)
516
+ return -1;
517
+ if (a->preferred < b->preferred)
518
+ return 1;
519
+
520
if (a->pack_mtime > b->pack_mtime)
521
return -1;
522
else if (a->pack_mtime < b->pack_mtime)
544
static void fill_pack_entry(uint32_t pack_int_id,
545
struct packed_git *p,
546
uint32_t cur_object,
530
- struct pack_midx_entry *entry)
547
+ struct pack_midx_entry *entry,
548
+ int preferred)
549
{
550
if (nth_packed_object_id(&entry->oid, p, cur_object) < 0)
551
die(_("failed to locate object %d in packfile"), cur_object);
554
entry->pack_mtime = p->mtime;
555
556
entry->offset = nth_packed_object_offset(p, cur_object);
557
+ entry->preferred = !!preferred;
558
}
559
560
/*
571
static struct pack_midx_entry *get_sorted_entries(struct multi_pack_index *m,
572
struct pack_info *info,
573
uint32_t nr_packs,
555
- uint32_t *nr_objects)
574
+ uint32_t *nr_objects,
575
+ int preferred_pack)
576
{
577
uint32_t cur_fanout, cur_pack, cur_object;
578
uint32_t alloc_fanout, alloc_objects, total_objects = 0;
609
nth_midxed_pack_midx_entry(m,
610
&entries_by_fanout[nr_fanout],
611
cur_object);
612
+ if (nth_midxed_pack_int_id(m, cur_object) == preferred_pack)
613
+ entries_by_fanout[nr_fanout].preferred = 1;
614
+ else
615
+ entries_by_fanout[nr_fanout].preferred = 0;
616
nr_fanout++;
617
}
618
}
619
620
for (cur_pack = start_pack; cur_pack < nr_packs; cur_pack++) {
621
uint32_t start = 0, end;
622
+ int preferred = cur_pack == preferred_pack;
623
624
if (cur_fanout)
625
start = get_pack_fanout(info[cur_pack].p, cur_fanout - 1);
627
628
for (cur_object = start; cur_object < end; cur_object++) {
629
ALLOC_GROW(entries_by_fanout, nr_fanout + 1, alloc_fanout);
605
- fill_pack_entry(cur_pack, info[cur_pack].p, cur_object, &entries_by_fanout[nr_fanout]);
630
+ fill_pack_entry(cur_pack,
631
+ info[cur_pack].p,
632
+ cur_object,
633
+ &entries_by_fanout[nr_fanout],
634
+ preferred);
635
nr_fanout++;
636
}
637
}
806
}
807
808
static int write_midx_internal(const char *object_dir, struct multi_pack_index *m,
780
- struct string_list *packs_to_drop, unsigned flags)
809
+ struct string_list *packs_to_drop,
810
+ const char *preferred_pack_name,
811
+ unsigned flags)
812
{
813
char *midx_name;
814
uint32_t i;
859
if (ctx.m && ctx.nr == ctx.m->num_packs && !packs_to_drop)
860
goto cleanup;
861
831
- ctx.entries = get_sorted_entries(ctx.m, ctx.info, ctx.nr, &ctx.entries_nr);
862
+ ctx.preferred_pack_idx = -1;
863
+ if (preferred_pack_name) {
864
+ for (i = 0; i < ctx.nr; i++) {
865
+ if (!cmp_idx_or_pack_name(preferred_pack_name,
866
+ ctx.info[i].pack_name)) {
867
+ ctx.preferred_pack_idx = i;
868
+ break;
869
+ }
870
+ }
871
+ }
872
+
873
+ ctx.entries = get_sorted_entries(ctx.m, ctx.info, ctx.nr, &ctx.entries_nr,
874
+ ctx.preferred_pack_idx);
875
876
ctx.large_offsets_needed = 0;
877
for (i = 0; i < ctx.entries_nr; i++) {
932
pack_name_concat_len += strlen(ctx.info[i].pack_name) + 1;
933
}
934
935
+ /* Check that the preferred pack wasn't expired (if given). */
936
+ if (preferred_pack_name) {
937
+ struct pack_info *preferred = bsearch(preferred_pack_name,
938
+ ctx.info, ctx.nr,
939
+ sizeof(*ctx.info),
940
+ idx_or_pack_name_cmp);
941
+
942
+ if (!preferred)
943
+ warning(_("unknown preferred pack: '%s'"),
944
+ preferred_pack_name);
945
+ else {
946
+ uint32_t perm = ctx.pack_perm[preferred->orig_pack_int_id];
947
+ if (perm == PACK_EXPIRED)
948
+ warning(_("preferred pack '%s' is expired"),
949
+ preferred_pack_name);
950
+ }
951
+ }
952
+
953
if (pack_name_concat_len % MIDX_CHUNK_ALIGNMENT)
954
pack_name_concat_len += MIDX_CHUNK_ALIGNMENT -
955
(pack_name_concat_len % MIDX_CHUNK_ALIGNMENT);
1008
return result;
1009
}
1010
950
-int write_midx_file(const char *object_dir, unsigned flags)
1011
+int write_midx_file(const char *object_dir,
1012
+ const char *preferred_pack_name,
1013
+ unsigned flags)
1014
{
952
- return write_midx_internal(object_dir, NULL, NULL, flags);
1015
+ return write_midx_internal(object_dir, NULL, NULL, preferred_pack_name,
1016
+ flags);
1017
}
1018
1019
void clear_midx_file(struct repository *r)
1248
free(count);
1249
1250
if (packs_to_drop.nr)
1187
- result = write_midx_internal(object_dir, m, &packs_to_drop, flags);
1251
+ result = write_midx_internal(object_dir, m, &packs_to_drop, NULL, flags);
1252
1253
string_list_clear(&packs_to_drop, 0);
1254
return result;
1437
goto cleanup;
1438
}
1439
1376
- result = write_midx_internal(object_dir, m, NULL, flags);
1440
+ result = write_midx_internal(object_dir, m, NULL, NULL, flags);
1441
m = NULL;
1442
1443
cleanup: