- logm 'debug', "housekeeping: subdirs $subdir: touched recently";
- next;
- }
- if (!lockfile \*LOCK, $lock, LOCK_EX|LOCK_NB) {
- logm 'info', "housekeeping: subdirs $subdir: lock busy, skipping";
- next;
- }
- logm 'info', "housekeeping: subdirs $subdir: cleaning";
- eval {
- foreach my $suffix (qw(tmp git)) {
- my $dir = "${subdir}\\.$suffix";
- my $tdir = "${subdir}\\.tmp";
- if ($dir ne $tdir) {
- if (!rename $dir,$tdir) {
- next if $! == ENOENT;
- die "$dir: cannot rename to $tdir: $!\n";
+ my $gccheck = sub {
+ if (!lstat "$gcdone") {
+ $! == ENOENT or hkfail "$gcdone: lstat: $!";
+ return 1, "touched recently, never gc'd!";
+ } elsif (-M _ <= $gcintervaldays) {
+ return 0, "touched recently, gc'd recently";
+ } else {
+ return 1, "touched recently, needs gc";
+ }
+ };
+ my ($needsgc, $gcmsg) = $gccheck->();
+ logm 'debug', "housekeeping: subdirs $subdir: $gcmsg";
+ next unless $needsgc;
+ $mode_what = 'garbage collecting';
+ $mode_locknb = 0;
+ $mode_action = sub {
+ my ($needsgc, $gcmsg) = $gccheck->();
+ if (!$needsgc) {
+ logm 'info',
+ "housekeeping: subdirs $subdir: someone else has gc'd";
+ return;
+ }
+ logm 'debug', "housekeeping: subdirs $subdir: $gcmsg (2)";
+ my $gclog = "$subdir/gc.log";
+ unlink $gclog or $!==ENOENT or hkfail "remove $gclog: $!";
+ my $child = fork // hkfail "fork (for $subdir): $!";
+ if (!$child) {
+ if (!chdir "$subdir\\.git") {
+ exit 0 if $!==ENOENT;
+ die "for gc: chdir $subdir: $!\n";