1015
strbuf_release(&buf);
1016
}
1017
1018
-static bool midx_needs_update(struct write_midx_context *ctx)
1018
+static bool midx_needs_update(struct multi_pack_index *midx, struct write_midx_context *ctx)
1019
{
1020
- struct multi_pack_index *midx = ctx->m;
1020
+ struct strset packs = STRSET_INIT;
1021
+ struct strbuf buf = STRBUF_INIT;
1022
bool needed = true;
1023
1024
/*
1029
if (ctx->incremental)
1030
goto out;
1031
1031
- /*
1032
- * If there is no MIDX then either it doesn't exist, or we're doing a
1033
- * geometric repack. We cannot (yet) determine whether we need to
1034
- * update the multi-pack index in the second case.
1035
- */
1036
- if (!midx)
1037
- goto out;
1038
-
1032
/*
1033
* Otherwise, we need to verify that the packs covered by the existing
1041
- * MIDX match the packs that we already have. This test is somewhat
1042
- * lenient and will be fixed.
1034
+ * MIDX match the packs that we already have. The logic to do so is way
1035
+ * more complicated than it has any right to be. This is because:
1036
+ *
1037
+ * - We cannot assume any ordering.
1038
+ *
1039
+ * - The MIDX packs may not be loaded at all, and loading them would
1040
+ * be wasteful. So we need to use the pack names tracked by the
1041
+ * MIDX itself.
1042
+ *
1043
+ * - The MIDX pack names are tracking the ".idx" files, whereas the
1044
+ * packs themselves are tracking the ".pack" files. So we need to
1045
+ * strip suffixes.
1046
*/
1047
if (ctx->nr != midx->num_packs + midx->num_packs_in_base)
1048
goto out;
1049
1050
+ for (uint32_t i = 0; i < ctx->nr; i++) {
1051
+ strbuf_reset(&buf);
1052
+ strbuf_addstr(&buf, pack_basename(ctx->info[i].p));
1053
+ strbuf_strip_suffix(&buf, ".pack");
1054
+
1055
+ if (!strset_add(&packs, buf.buf))
1056
+ BUG("same pack added twice?");
1057
+ }
1058
+
1059
+ for (uint32_t i = 0; i < ctx->nr; i++) {
1060
+ strbuf_reset(&buf);
1061
+ strbuf_addstr(&buf, midx->pack_names[i]);
1062
+ strbuf_strip_suffix(&buf, ".idx");
1063
+
1064
+ if (!strset_contains(&packs, buf.buf))
1065
+ goto out;
1066
+ strset_remove(&packs, buf.buf);
1067
+ }
1068
+
1069
needed = false;
1070
1071
out:
1072
+ strbuf_release(&buf);
1073
+ strset_clear(&packs);
1074
return needed;
1075
}
1076
1091
struct write_midx_context ctx = {
1092
.preferred_pack_idx = NO_PREFERRED_PACK,
1093
};
1094
+ struct multi_pack_index *midx_to_free = NULL;
1095
int bitmapped_packs_concat_len = 0;
1096
int pack_name_concat_len = 0;
1097
int dropped_packs = 0;
1172
for_each_file_in_pack_dir(source->path, add_pack_to_midx, &ctx);
1173
stop_progress(&ctx.progress);
1174
1150
- if (!packs_to_include && !packs_to_drop && !midx_needs_update(&ctx)) {
1151
- struct bitmap_index *bitmap_git;
1152
- int bitmap_exists;
1153
- int want_bitmap = flags & MIDX_WRITE_BITMAP;
1154
-
1155
- bitmap_git = prepare_midx_bitmap_git(ctx.m);
1156
- bitmap_exists = bitmap_git && bitmap_is_midx(bitmap_git);
1157
- free_bitmap_index(bitmap_git);
1158
-
1159
- if (bitmap_exists || !want_bitmap) {
1160
- /*
1161
- * The correct MIDX already exists, and so does a
1162
- * corresponding bitmap (or one wasn't requested).
1163
- */
1164
- if (!want_bitmap)
1165
- clear_midx_files_ext(source, "bitmap", NULL);
1166
- result = 0;
1167
- goto cleanup;
1175
+ if (!packs_to_drop) {
1176
+ /*
1177
+ * If there is no MIDX then either it doesn't exist, or we're
1178
+ * doing a geometric repack. Try to load it from the source to
1179
+ * tell these two cases apart.
1180
+ */
1181
+ struct multi_pack_index *midx = ctx.m;
1182
+ if (!midx)
1183
+ midx = midx_to_free = load_multi_pack_index(ctx.source);
1184
+
1185
+ if (midx && !midx_needs_update(midx, &ctx)) {
1186
+ struct bitmap_index *bitmap_git;
1187
+ int bitmap_exists;
1188
+ int want_bitmap = flags & MIDX_WRITE_BITMAP;
1189
+
1190
+ bitmap_git = prepare_midx_bitmap_git(midx);
1191
+ bitmap_exists = bitmap_git && bitmap_is_midx(bitmap_git);
1192
+ free_bitmap_index(bitmap_git);
1193
+
1194
+ if (bitmap_exists || !want_bitmap) {
1195
+ /*
1196
+ * The correct MIDX already exists, and so does a
1197
+ * corresponding bitmap (or one wasn't requested).
1198
+ */
1199
+ if (!want_bitmap)
1200
+ clear_midx_files_ext(source, "bitmap", NULL);
1201
+ result = 0;
1202
+ goto cleanup;
1203
+ }
1204
}
1205
+
1206
+ close_midx(midx_to_free);
1207
+ midx_to_free = NULL;
1208
}
1209
1210
if (ctx.incremental && !ctx.nr) {
1560
free(keep_hashes);
1561
}
1562
strbuf_release(&midx_name);
1563
+ close_midx(midx_to_free);
1564
1565
trace2_region_leave("midx", "write_midx_internal", r);
1566