Skip to content

Commit 39d38a5

Browse files
committed
Merge branch 'tb/repack-simplify'
Simplify the logic to deal with a repack operation that ended up creating the same packfile. * tb/repack-simplify: builtin/repack.c: don't move existing packs out of the way builtin/repack.c: keep track of what pack-objects wrote repack: make "exts" array available outside cmd_repack()
2 parents c692e1b + 2fcb03b commit 39d38a5

File tree

1 file changed

+54
-99
lines changed

1 file changed

+54
-99
lines changed

builtin/repack.c

Lines changed: 54 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,37 @@ static int write_oid(const struct object_id *oid, struct packed_git *pack,
202202
return 0;
203203
}
204204

205+
static struct {
206+
const char *name;
207+
unsigned optional:1;
208+
} exts[] = {
209+
{".pack"},
210+
{".idx"},
211+
{".bitmap", 1},
212+
{".promisor", 1},
213+
};
214+
215+
static unsigned populate_pack_exts(char *name)
216+
{
217+
struct stat statbuf;
218+
struct strbuf path = STRBUF_INIT;
219+
unsigned ret = 0;
220+
int i;
221+
222+
for (i = 0; i < ARRAY_SIZE(exts); i++) {
223+
strbuf_reset(&path);
224+
strbuf_addf(&path, "%s-%s%s", packtmp, name, exts[i].name);
225+
226+
if (stat(path.buf, &statbuf))
227+
continue;
228+
229+
ret |= (1 << i);
230+
}
231+
232+
strbuf_release(&path);
233+
return ret;
234+
}
235+
205236
static void repack_promisor_objects(const struct pack_objects_args *args,
206237
struct string_list *names)
207238
{
@@ -230,11 +261,12 @@ static void repack_promisor_objects(const struct pack_objects_args *args,
230261

231262
out = xfdopen(cmd.out, "r");
232263
while (strbuf_getline_lf(&line, out) != EOF) {
264+
struct string_list_item *item;
233265
char *promisor_name;
234266
int fd;
235267
if (line.len != the_hash_algo->hexsz)
236268
die(_("repack: Expecting full hex object ID lines only from pack-objects."));
237-
string_list_append(names, line.buf);
269+
item = string_list_append(names, line.buf);
238270

239271
/*
240272
* pack-objects creates the .pack and .idx files, but not the
@@ -253,6 +285,9 @@ static void repack_promisor_objects(const struct pack_objects_args *args,
253285
if (fd < 0)
254286
die_errno(_("unable to create '%s'"), promisor_name);
255287
close(fd);
288+
289+
item->util = (void *)(uintptr_t)populate_pack_exts(item->string);
290+
256291
free(promisor_name);
257292
}
258293
fclose(out);
@@ -265,22 +300,13 @@ static void repack_promisor_objects(const struct pack_objects_args *args,
265300

266301
int cmd_repack(int argc, const char **argv, const char *prefix)
267302
{
268-
struct {
269-
const char *name;
270-
unsigned optional:1;
271-
} exts[] = {
272-
{".pack"},
273-
{".idx"},
274-
{".bitmap", 1},
275-
{".promisor", 1},
276-
};
277303
struct child_process cmd = CHILD_PROCESS_INIT;
278304
struct string_list_item *item;
279305
struct string_list names = STRING_LIST_INIT_DUP;
280306
struct string_list rollback = STRING_LIST_INIT_NODUP;
281307
struct string_list existing_packs = STRING_LIST_INIT_DUP;
282308
struct strbuf line = STRBUF_INIT;
283-
int i, ext, ret, failed;
309+
int i, ext, ret;
284310
FILE *out;
285311

286312
/* variables to be filled by option parsing */
@@ -429,113 +455,42 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
429455
if (!names.nr && !po_args.quiet)
430456
printf_ln(_("Nothing new to pack."));
431457

458+
for_each_string_list_item(item, &names) {
459+
item->util = (void *)(uintptr_t)populate_pack_exts(item->string);
460+
}
461+
432462
close_object_store(the_repository->objects);
433463

434464
/*
435465
* Ok we have prepared all new packfiles.
436-
* First see if there are packs of the same name and if so
437-
* if we can move them out of the way (this can happen if we
438-
* repacked immediately after packing fully.
439466
*/
440-
failed = 0;
441467
for_each_string_list_item(item, &names) {
442468
for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
443469
char *fname, *fname_old;
444470

445-
fname = mkpathdup("%s/pack-%s%s", packdir,
446-
item->string, exts[ext].name);
447-
if (!file_exists(fname)) {
448-
free(fname);
449-
continue;
450-
}
451-
452-
fname_old = mkpathdup("%s/old-%s%s", packdir,
453-
item->string, exts[ext].name);
454-
if (file_exists(fname_old))
455-
if (unlink(fname_old))
456-
failed = 1;
457-
458-
if (!failed && rename(fname, fname_old)) {
459-
free(fname);
460-
free(fname_old);
461-
failed = 1;
462-
break;
463-
} else {
464-
string_list_append(&rollback, fname);
465-
free(fname_old);
466-
}
467-
}
468-
if (failed)
469-
break;
470-
}
471-
if (failed) {
472-
struct string_list rollback_failure = STRING_LIST_INIT_DUP;
473-
for_each_string_list_item(item, &rollback) {
474-
char *fname, *fname_old;
475-
fname = mkpathdup("%s/%s", packdir, item->string);
476-
fname_old = mkpathdup("%s/old-%s", packdir, item->string);
477-
if (rename(fname_old, fname))
478-
string_list_append(&rollback_failure, fname);
479-
free(fname);
480-
free(fname_old);
481-
}
482-
483-
if (rollback_failure.nr) {
484-
int i;
485-
fprintf(stderr,
486-
_("WARNING: Some packs in use have been renamed by\n"
487-
"WARNING: prefixing old- to their name, in order to\n"
488-
"WARNING: replace them with the new version of the\n"
489-
"WARNING: file. But the operation failed, and the\n"
490-
"WARNING: attempt to rename them back to their\n"
491-
"WARNING: original names also failed.\n"
492-
"WARNING: Please rename them in %s manually:\n"), packdir);
493-
for (i = 0; i < rollback_failure.nr; i++)
494-
fprintf(stderr, "WARNING: old-%s -> %s\n",
495-
rollback_failure.items[i].string,
496-
rollback_failure.items[i].string);
497-
}
498-
exit(1);
499-
}
500-
501-
/* Now the ones with the same name are out of the way... */
502-
for_each_string_list_item(item, &names) {
503-
for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
504-
char *fname, *fname_old;
505-
struct stat statbuffer;
506-
int exists = 0;
507471
fname = mkpathdup("%s/pack-%s%s",
508472
packdir, item->string, exts[ext].name);
509473
fname_old = mkpathdup("%s-%s%s",
510474
packtmp, item->string, exts[ext].name);
511-
if (!stat(fname_old, &statbuffer)) {
512-
statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
513-
chmod(fname_old, statbuffer.st_mode);
514-
exists = 1;
515-
}
516-
if (exists || !exts[ext].optional) {
475+
476+
if (((uintptr_t)item->util) & (1 << ext)) {
477+
struct stat statbuffer;
478+
if (!stat(fname_old, &statbuffer)) {
479+
statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
480+
chmod(fname_old, statbuffer.st_mode);
481+
}
482+
517483
if (rename(fname_old, fname))
518484
die_errno(_("renaming '%s' failed"), fname_old);
519-
}
520-
free(fname);
521-
free(fname_old);
522-
}
523-
}
485+
} else if (!exts[ext].optional)
486+
die(_("missing required file: %s"), fname_old);
487+
else if (unlink(fname) < 0 && errno != ENOENT)
488+
die_errno(_("could not unlink: %s"), fname);
524489

525-
/* Remove the "old-" files */
526-
for_each_string_list_item(item, &names) {
527-
for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
528-
char *fname;
529-
fname = mkpathdup("%s/old-%s%s",
530-
packdir,
531-
item->string,
532-
exts[ext].name);
533-
if (remove_path(fname))
534-
warning(_("failed to remove '%s'"), fname);
535490
free(fname);
491+
free(fname_old);
536492
}
537493
}
538-
539494
/* End of pack replacement. */
540495

541496
reprepare_packed_git(the_repository);

0 commit comments

Comments
 (0)