Skip to content

Commit 9ce7875

Browse files
committed
Merge branch 'jn/gc-auto' into pu
"gc --auto" ended up calling exit(-1) upon error, which has been corrected to use exit(1). Also the error reporting behaviour when daemonized has been updated to exit with zero status when stopping due to a previously discovered error (which implies there is no point running gc to improve the situation); we used to exit with failure in such a case. Under discussion. cf. <[email protected]> * jn/gc-auto: gc: do not return error for prior errors in daemonized mode gc: exit with status 128 on failure gc: improve handling of errors reading gc.log
2 parents 235b9b5 + 3029970 commit 9ce7875

File tree

3 files changed

+40
-22
lines changed

3 files changed

+40
-22
lines changed

Documentation/config.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1697,7 +1697,8 @@ will be repacked. After this the number of packs should go below
16971697
gc.autoPackLimit and gc.bigPackThreshold should be respected again.
16981698

16991699
gc.logExpiry::
1700-
If the file gc.log exists, then `git gc --auto` won't run
1700+
If the file gc.log exists, then `git gc --auto` will print
1701+
its content and exit with status zero instead of running
17011702
unless that file is more than 'gc.logExpiry' old. Default is
17021703
"1.day". See `gc.pruneExpire` for more ways to specify its
17031704
value.

builtin/gc.c

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -442,50 +442,64 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
442442
return NULL;
443443
}
444444

445+
/*
446+
* Returns 0 if there was no previous error and gc can proceed, 1 if
447+
* gc should not proceed due to an error in the last run. Prints a
448+
* message and returns -1 if an error occured while reading gc.log
449+
*/
445450
static int report_last_gc_error(void)
446451
{
447452
struct strbuf sb = STRBUF_INIT;
448453
int ret = 0;
454+
ssize_t len;
449455
struct stat st;
450456
char *gc_log_path = git_pathdup("gc.log");
451457

452458
if (stat(gc_log_path, &st)) {
453459
if (errno == ENOENT)
454460
goto done;
455461

456-
ret = error_errno(_("Can't stat %s"), gc_log_path);
462+
ret = error_errno(_("cannot stat '%s'"), gc_log_path);
457463
goto done;
458464
}
459465

460466
if (st.st_mtime < gc_log_expire_time)
461467
goto done;
462468

463-
ret = strbuf_read_file(&sb, gc_log_path, 0);
464-
if (ret > 0)
465-
ret = error(_("The last gc run reported the following. "
469+
len = strbuf_read_file(&sb, gc_log_path, 0);
470+
if (len < 0)
471+
ret = error_errno(_("cannot read '%s'"), gc_log_path);
472+
else if (len > 0) {
473+
/*
474+
* A previous gc failed. Report the error, and don't
475+
* bother with an automatic gc run since it is likely
476+
* to fail in the same way.
477+
*/
478+
warning(_("The last gc run reported the following. "
466479
"Please correct the root cause\n"
467480
"and remove %s.\n"
468481
"Automatic cleanup will not be performed "
469482
"until the file is removed.\n\n"
470483
"%s"),
471484
gc_log_path, sb.buf);
485+
ret = 1;
486+
}
472487
strbuf_release(&sb);
473488
done:
474489
free(gc_log_path);
475490
return ret;
476491
}
477492

478-
static int gc_before_repack(void)
493+
static void gc_before_repack(void)
479494
{
480495
if (pack_refs && run_command_v_opt(pack_refs_cmd.argv, RUN_GIT_CMD))
481-
return error(FAILED_RUN, pack_refs_cmd.argv[0]);
496+
die(FAILED_RUN, pack_refs_cmd.argv[0]);
482497

483498
if (prune_reflogs && run_command_v_opt(reflog.argv, RUN_GIT_CMD))
484-
return error(FAILED_RUN, reflog.argv[0]);
499+
die(FAILED_RUN, reflog.argv[0]);
485500

486501
pack_refs = 0;
487502
prune_reflogs = 0;
488-
return 0;
489503
}
490504

491505
int cmd_gc(int argc, const char **argv, const char *prefix)
@@ -566,13 +580,17 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
566580
fprintf(stderr, _("See \"git help gc\" for manual housekeeping.\n"));
567581
}
568582
if (detach_auto) {
569-
if (report_last_gc_error())
570-
return -1;
583+
int ret = report_last_gc_error();
584+
if (ret < 0)
585+
/* an I/O error occured, already reported */
586+
exit(128);
587+
if (ret == 1)
588+
/* Last gc --auto failed. Skip this one. */
589+
return 0;
571590

572591
if (lock_repo_for_gc(force, &pid))
573592
return 0;
574-
if (gc_before_repack())
575-
return -1;
593+
gc_before_repack(); /* dies on failure */
576594
delete_tempfile(&pidfile);
577595

578596
/*
@@ -612,13 +630,12 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
612630
atexit(process_log_file_at_exit);
613631
}
614632

615-
if (gc_before_repack())
616-
return -1;
633+
gc_before_repack();
617634

618635
if (!repository_format_precious_objects) {
619636
close_all_packs(the_repository->objects);
620637
if (run_command_v_opt(repack.argv, RUN_GIT_CMD))
621-
return error(FAILED_RUN, repack.argv[0]);
638+
die(FAILED_RUN, repack.argv[0]);
622639

623640
if (prune_expire) {
624641
argv_array_push(&prune, prune_expire);
@@ -628,18 +645,18 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
628645
argv_array_push(&prune,
629646
"--exclude-promisor-objects");
630647
if (run_command_v_opt(prune.argv, RUN_GIT_CMD))
631-
return error(FAILED_RUN, prune.argv[0]);
648+
die(FAILED_RUN, prune.argv[0]);
632649
}
633650
}
634651

635652
if (prune_worktrees_expire) {
636653
argv_array_push(&prune_worktrees, prune_worktrees_expire);
637654
if (run_command_v_opt(prune_worktrees.argv, RUN_GIT_CMD))
638-
return error(FAILED_RUN, prune_worktrees.argv[0]);
655+
die(FAILED_RUN, prune_worktrees.argv[0]);
639656
}
640657

641658
if (run_command_v_opt(rerere.argv, RUN_GIT_CMD))
642-
return error(FAILED_RUN, rerere.argv[0]);
659+
die(FAILED_RUN, rerere.argv[0]);
643660

644661
report_garbage = report_pack_garbage;
645662
reprepare_packed_git(the_repository);

t/t6500-gc.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,11 @@ test_expect_success 'background auto gc does not run if gc.log is present and re
116116
test_config gc.autopacklimit 1 &&
117117
test_config gc.autodetach true &&
118118
echo fleem >.git/gc.log &&
119-
test_must_fail git gc --auto 2>err &&
120-
test_i18ngrep "^error:" err &&
119+
git gc --auto 2>err &&
120+
test_i18ngrep "^warning:" err &&
121121
test_config gc.logexpiry 5.days &&
122122
test-tool chmtime =-345600 .git/gc.log &&
123-
test_must_fail git gc --auto &&
123+
git gc --auto &&
124124
test_config gc.logexpiry 2.days &&
125125
run_and_wait_for_auto_gc &&
126126
ls .git/objects/pack/pack-*.pack >packs &&

0 commit comments

Comments
 (0)