39
static int use_delta_islands;
40
static int run_update_server_info = 1;
41
static char *packdir, *packtmp_name, *packtmp;
42
+static int midx_must_contain_cruft = 1;
43
44
static const char *const git_repack_usage[] = {
45
N_("git repack [-a] [-A] [-d] [-f] [-F] [-l] [-n] [-q] [-b] [-m]\n"
109
free(cruft_po_args->threads);
110
return git_config_string(&cruft_po_args->threads, var, value);
111
}
112
+ if (!strcmp(var, "repack.midxmustcontaincruft")) {
113
+ midx_must_contain_cruft = git_config_bool(var, value);
114
+ return 0;
115
+ }
116
return git_default_config(var, value, ctx, cb);
117
}
118
695
free(geometry->pack);
696
}
697
698
+static int midx_has_unknown_packs(char **midx_pack_names,
699
+ size_t midx_pack_names_nr,
700
+ struct string_list *include,
701
+ struct pack_geometry *geometry,
702
+ struct existing_packs *existing)
703
+{
704
+ size_t i;
705
+
706
+ string_list_sort(include);
707
+
708
+ for (i = 0; i < midx_pack_names_nr; i++) {
709
+ const char *pack_name = midx_pack_names[i];
710
+
711
+ /*
712
+ * Determine whether or not each MIDX'd pack from the existing
713
+ * MIDX (if any) is represented in the new MIDX. For each pack
714
+ * in the MIDX, it must either be:
715
+ *
716
+ * - In the "include" list of packs to be included in the new
717
+ * MIDX. Note this function is called before the include
718
+ * list is populated with any cruft pack(s).
719
+ *
720
+ * - Below the geometric split line (if using pack geometry),
721
+ * indicating that the pack won't be included in the new
722
+ * MIDX, but its contents were rolled up as part of the
723
+ * geometric repack.
724
+ *
725
+ * - In the existing non-kept packs list (if not using pack
726
+ * geometry), and marked as non-deleted.
727
+ */
728
+ if (string_list_has_string(include, pack_name)) {
729
+ continue;
730
+ } else if (geometry) {
731
+ struct strbuf buf = STRBUF_INIT;
732
+ uint32_t j;
733
+
734
+ for (j = 0; j < geometry->split; j++) {
735
+ strbuf_reset(&buf);
736
+ strbuf_addstr(&buf, pack_basename(geometry->pack[j]));
737
+ strbuf_strip_suffix(&buf, ".pack");
738
+ strbuf_addstr(&buf, ".idx");
739
+
740
+ if (!strcmp(pack_name, buf.buf)) {
741
+ strbuf_release(&buf);
742
+ break;
743
+ }
744
+ }
745
+
746
+ strbuf_release(&buf);
747
+
748
+ if (j < geometry->split)
749
+ continue;
750
+ } else {
751
+ struct string_list_item *item;
752
+
753
+ item = string_list_lookup(&existing->non_kept_packs,
754
+ pack_name);
755
+ if (item && !pack_is_marked_for_deletion(item))
756
+ continue;
757
+ }
758
+
759
+ /*
760
+ * If we got to this point, the MIDX includes some pack that we
761
+ * don't know about.
762
+ */
763
+ return 1;
764
+ }
765
+
766
+ return 0;
767
+}
768
+
769
struct midx_snapshot_ref_data {
770
struct tempfile *f;
771
struct oidset seen;
834
835
static void midx_included_packs(struct string_list *include,
836
struct existing_packs *existing,
837
+ char **midx_pack_names,
838
+ size_t midx_pack_names_nr,
839
struct string_list *names,
840
struct pack_geometry *geometry)
841
{
889
}
890
}
891
814
- for_each_string_list_item(item, &existing->cruft_packs) {
892
+ if (midx_must_contain_cruft ||
893
+ midx_has_unknown_packs(midx_pack_names, midx_pack_names_nr,
894
+ include, geometry, existing)) {
895
/*
816
- * When doing a --geometric repack, there is no need to check
817
- * for deleted packs, since we're by definition not doing an
818
- * ALL_INTO_ONE repack (hence no packs will be deleted).
819
- * Otherwise we must check for and exclude any packs which are
820
- * enqueued for deletion.
896
+ * If there are one or more unknown pack(s) present (see
897
+ * midx_has_unknown_packs() for what makes a pack
898
+ * "unknown") in the MIDX before the repack, keep them
899
+ * as they may be required to form a reachability
900
+ * closure if the MIDX is bitmapped.
901
*
822
- * So we could omit the conditional below in the --geometric
823
- * case, but doing so is unnecessary since no packs are marked
824
- * as pending deletion (since we only call
825
- * `mark_packs_for_deletion()` when doing an all-into-one
826
- * repack).
902
+ * For example, a cruft pack can be required to form a
903
+ * reachability closure if the MIDX is bitmapped and one
904
+ * or more of the bitmap's selected commits reaches a
905
+ * once-cruft object that was later made reachable.
906
*/
828
- if (pack_is_marked_for_deletion(item))
829
- continue;
907
+ for_each_string_list_item(item, &existing->cruft_packs) {
908
+ /*
909
+ * When doing a --geometric repack, there is no
910
+ * need to check for deleted packs, since we're
911
+ * by definition not doing an ALL_INTO_ONE
912
+ * repack (hence no packs will be deleted).
913
+ * Otherwise we must check for and exclude any
914
+ * packs which are enqueued for deletion.
915
+ *
916
+ * So we could omit the conditional below in the
917
+ * --geometric case, but doing so is unnecessary
918
+ * since no packs are marked as pending
919
+ * deletion (since we only call
920
+ * `mark_packs_for_deletion()` when doing an
921
+ * all-into-one repack).
922
+ */
923
+ if (pack_is_marked_for_deletion(item))
924
+ continue;
925
831
- strbuf_reset(&buf);
832
- strbuf_addf(&buf, "%s.idx", item->string);
833
- string_list_insert(include, buf.buf);
926
+ strbuf_reset(&buf);
927
+ strbuf_addf(&buf, "%s.idx", item->string);
928
+ string_list_insert(include, buf.buf);
929
+ }
930
+ } else {
931
+ /*
932
+ * Modern versions of Git (with the appropriate
933
+ * configuration setting) will write new copies of
934
+ * once-cruft objects when doing a --geometric repack.
935
+ *
936
+ * If the MIDX has no cruft pack, new packs written
937
+ * during a --geometric repack will not rely on the
938
+ * cruft pack to form a reachability closure, so we can
939
+ * avoid including them in the MIDX in that case.
940
+ */
941
+ ;
942
}
943
944
strbuf_release(&buf);
1253
struct tempfile *refs_snapshot = NULL;
1254
int i, ext, ret;
1255
int show_progress;
1256
+ char **midx_pack_names = NULL;
1257
+ size_t midx_pack_names_nr = 0;
1258
1259
/* variables to be filled by option parsing */
1260
int delete_redundant = 0;
1471
!(pack_everything & PACK_CRUFT))
1472
strvec_push(&cmd.args, "--pack-loose-unreachable");
1473
} else if (geometry.split_factor) {
1364
- strvec_push(&cmd.args, "--stdin-packs");
1474
+ if (midx_must_contain_cruft)
1475
+ strvec_push(&cmd.args, "--stdin-packs");
1476
+ else
1477
+ strvec_push(&cmd.args, "--stdin-packs=follow");
1478
strvec_push(&cmd.args, "--unpacked");
1479
} else {
1480
strvec_push(&cmd.args, "--unpacked");
1514
if (ret)
1515
goto cleanup;
1516
1404
- if (!names.nr && !po_args.quiet)
1405
- printf_ln(_("Nothing new to pack."));
1517
+ if (!names.nr) {
1518
+ if (!po_args.quiet)
1519
+ printf_ln(_("Nothing new to pack."));
1520
+ /*
1521
+ * If we didn't write any new packs, the non-cruft packs
1522
+ * may refer to once-unreachable objects in the cruft
1523
+ * pack(s).
1524
+ *
1525
+ * If there isn't already a MIDX, the one we write
1526
+ * must include the cruft pack(s), in case the
1527
+ * non-cruft pack(s) refer to once-cruft objects.
1528
+ *
1529
+ * If there is already a MIDX, we can punt here, since
1530
+ * midx_has_unknown_packs() will make the decision for
1531
+ * us.
1532
+ */
1533
+ if (!get_local_multi_pack_index(the_repository))
1534
+ midx_must_contain_cruft = 1;
1535
+ }
1536
1537
if (pack_everything & PACK_CRUFT) {
1538
const char *pack_prefix = find_pack_prefix(packdir, packtmp);
1613
1614
string_list_sort(&names);
1615
1616
+ if (get_local_multi_pack_index(the_repository)) {
1617
+ struct multi_pack_index *m =
1618
+ get_local_multi_pack_index(the_repository);
1619
+
1620
+ ALLOC_ARRAY(midx_pack_names,
1621
+ m->num_packs + m->num_packs_in_base);
1622
+
1623
+ for (; m; m = m->base_midx)
1624
+ for (uint32_t i = 0; i < m->num_packs; i++)
1625
+ midx_pack_names[midx_pack_names_nr++] =
1626
+ xstrdup(m->pack_names[i]);
1627
+ }
1628
+
1629
close_object_store(the_repository->objects);
1630
1631
/*
1667
1668
if (write_midx) {
1669
struct string_list include = STRING_LIST_INIT_DUP;
1527
- midx_included_packs(&include, &existing, &names, &geometry);
1670
+ midx_included_packs(&include, &existing, midx_pack_names,
1671
+ midx_pack_names_nr, &names, &geometry);
1672
1673
ret = write_midx_included_packs(&include, &geometry, &names,
1674
refs_snapshot ? get_tempfile_path(refs_snapshot) : NULL,
1719
string_list_clear(&names, 1);
1720
existing_packs_release(&existing);
1721
free_pack_geometry(&geometry);
1722
+ for (size_t i = 0; i < midx_pack_names_nr; i++)
1723
+ free(midx_pack_names[i]);
1724
+ free(midx_pack_names);
1725
pack_objects_args_release(&po_args);
1726
pack_objects_args_release(&cruft_po_args);
1727