chiark / gitweb /
git-cache-proxy: Tolerate failure to write gc stamp
[chiark-utils.git] / scripts / git-cache-proxy
index 636ebfecb2adb51e0f0296ccd7a334c3e51ea89e..762cacb38830cc6c58b04591b9be7dd95662189e 100755 (executable)
@@ -307,8 +307,11 @@ sub readcommand () {
 sub update_gcstamp ($) {
     my ($gitdir) = (@_);
     my $gcdone = "$gitdir/cache-proxy-gc.stamp";
-    open GCSTAMP, '>', $gcdone or fail "create $gcdone: $!";
-    close GCSTAMP;
+    if (open GCSTAMP, '>', $gcdone) {
+       close GCSTAMP;
+    } else {
+       $!==ENOENT or fail "create $gcdone: $!";
+    }
 }
 
 sub clonefetch () {
@@ -430,29 +433,44 @@ sub housekeeping () {
        }
        my ($mode_what,$mode_locknb,$mode_action);
        if (-M _ <= $treeexpiredays) {
-           if (!lstat "$gcdone") {
-               $! == ENOENT or hkfail "$gcdone: lstat: $!";
-               logm 'debug',
- "housekeeping: subdirs $subdir: touched recently, never gc'd!";
-           } elsif (-M _ <= $gcintervaldays) {
-               logm 'debug',
- "housekeeping: subdirs $subdir: touched recently, gc'd recently";
-               next;
-           } else {
-               logm 'debug',
- "housekeeping: subdirs $subdir: touched recently, needs gc";
-           }
+           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 $r = system qw(sh -ec),
-                   'cd "$1"; shift; exec "$@"', 'x', "$subdir\\.git",
-                   qw(git gc --quiet);
-               if ($r) {
+               my $child = fork // hkfail "fork (for $subdir): $!";
+               if (!$child) {
+                   if (!chdir "$subdir\\.git") {
+                       exit 0 if $!==ENOENT;
+                       die "for gc: chdir $subdir: $!\n";
+                   }
+                   exec qw(git gc --quiet);
+                   die "exec git gc (for $subdir): $!\n";
+               }
+               waitpid($child, 0) == $child or hkfail "waitpid failed! $!";
+               if ($?) {
                    logm 'err',
                      "housekeeping: subdirs $subdir: gc failed (status $r)";
"housekeeping: subdirs $subdir: gc failed (wait status $?)";
                } else {
                    update_gcstamp("$subdir\\.git");
                    logm 'debug',