builtin/repack.c: factor out "generated_pack_install"

Once all new packs are known to exist, 'repack' installs their contents from their temporary location into their permanent one. This is a semi-involved procedure for each pack, since for each extension (e.g., ".idx", ".pack", ".mtimes", and so on) we have to either: - adjust the filemode of the temporary file before renaming it into place, or - die() if we are missing a non-optional extension, or - unlink() any existing file for extensions that we did not generate (e.g., if a non-cruft pack we generated was identical to, say, a cruft pack which existed at the beginning of the process, we have to remove the ".mtimes" file). Extract this procedure into its own function, and call it "generated_pack_install"(). This will set us up for pulling this function out of the builtin entirely and making it part of the repack.h API, which will be done in a future commit. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed Oct 15, 2025 at 18:28 UTC c0427692cb0fe03eb32fffc5bd06fad4ee434561
1 file changed +35 -30
builtin/repack.c
+35 -30
@@ -183,6 +183,38 @@ static int generated_pack_has_ext(const struct generated_pack *pack,
183 BUG("unknown pack extension: '%s'", ext);
184 }
185
186 +static void generated_pack_install(struct generated_pack *pack,
187 + const char *name)
188 +{
189 + int ext;
190 + for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
191 + char *fname;
192 +
193 + fname = mkpathdup("%s/pack-%s%s", packdir, name,
194 + exts[ext].name);
195 +
196 + if (pack->tempfiles[ext]) {
197 + const char *fname_old = get_tempfile_path(pack->tempfiles[ext]);
198 + struct stat statbuffer;
199 +
200 + if (!stat(fname_old, &statbuffer)) {
201 + statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
202 + chmod(fname_old, statbuffer.st_mode);
203 + }
204 +
205 + if (rename_tempfile(&pack->tempfiles[ext], fname))
206 + die_errno(_("renaming pack to '%s' failed"),
207 + fname);
208 + } else if (!exts[ext].optional)
209 + die(_("pack-objects did not write a '%s' file for pack %s-%s"),
210 + exts[ext].name, packtmp, name);
211 + else if (unlink(fname) < 0 && errno != ENOENT)
212 + die_errno(_("could not unlink: %s"), fname);
213 +
214 + free(fname);
215 + }
216 +}
217 +
218 static void repack_promisor_objects(struct repository *repo,
219 const struct pack_objects_args *args,
220 struct string_list *names)
@@ -1045,7 +1077,7 @@ int cmd_repack(int argc,
1077 struct existing_packs existing = EXISTING_PACKS_INIT;
1078 struct pack_geometry geometry = { 0 };
1079 struct tempfile *refs_snapshot = NULL;
1048 - int i, ext, ret;
1080 + int i, ret;
1081 int show_progress;
1082 char **midx_pack_names = NULL;
1083 size_t midx_pack_names_nr = 0;
@@ -1434,35 +1466,8 @@ int cmd_repack(int argc,
1466 /*
1467 * Ok we have prepared all new packfiles.
1468 */
1437 - for_each_string_list_item(item, &names) {
1438 - struct generated_pack *pack = item->util;
1439 -
1440 - for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
1441 - char *fname;
1442 -
1443 - fname = mkpathdup("%s/pack-%s%s",
1444 - packdir, item->string, exts[ext].name);
1445 -
1446 - if (pack->tempfiles[ext]) {
1447 - const char *fname_old = get_tempfile_path(pack->tempfiles[ext]);
1448 - struct stat statbuffer;
1449 -
1450 - if (!stat(fname_old, &statbuffer)) {
1451 - statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
1452 - chmod(fname_old, statbuffer.st_mode);
1453 - }
1454 -
1455 - if (rename_tempfile(&pack->tempfiles[ext], fname))
1456 - die_errno(_("renaming pack to '%s' failed"), fname);
1457 - } else if (!exts[ext].optional)
1458 - die(_("pack-objects did not write a '%s' file for pack %s-%s"),
1459 - exts[ext].name, packtmp, item->string);
1460 - else if (unlink(fname) < 0 && errno != ENOENT)
1461 - die_errno(_("could not unlink: %s"), fname);
1462 -
1463 - free(fname);
1464 - }
1465 - }
1469 + for_each_string_list_item(item, &names)
1470 + generated_pack_install(item->util, item->string);
1471 /* End of pack replacement. */
1472
1473 if (delete_redundant && pack_everything & ALL_INTO_ONE)