X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-utils.git;a=blobdiff_plain;f=scripts%2Fgit-cache-proxy;h=f797e74920cc36822141ad2422ad683d6f8e4281;hp=df522a0126238d40d97a0c342ea7e22910269bd5;hb=cb8ee35c18f491d1a9e0b334a0d0e165a52adfe1;hpb=18cb26fc56f3384564491dc155c104639695d550;ds=sidebyside diff --git a/scripts/git-cache-proxy b/scripts/git-cache-proxy index df522a0..f797e74 100755 --- a/scripts/git-cache-proxy +++ b/scripts/git-cache-proxy @@ -156,71 +156,76 @@ for (;;) { chdir $cachedir or fail "chdir $cachedir: $!"; -our ($service,$specpath,$spechost); - -$SIG{ALRM} = sub { fail "timeout" }; -alarm 30; +our ($service,$specpath,$spechost,$subdir); +our ($tmpd,$gitd,$lock); +our ($fetch,$url); sub xread { my $length = shift; my $buffer = ""; while ($length > length $buffer) { my $ret = sysread STDIN, $buffer, $length, length $buffer; - fail "Expected $length bytes, got ".length $buffer + fail "expected $length bytes, got ".length $buffer if defined $ret and $ret == 0; fail "read: $!" if not defined $ret and $! != EINTR and $! != EAGAIN; } return $buffer; } -my $hex_len = xread 4; -fail "Bad hex in packet length" unless $hex_len =~ m|^[0-9a-fA-F]{4}$|; -my $line = xread -4 + hex $hex_len; -unless (($service,$specpath,$spechost) = $line =~ - m|^(git-[a-z-]+) /*([!-~ ]+)\0host=([!-~]+)\0$|) { - $line =~ s|[^ -~]+| |g; - gitfail "unknown/unsupported instruction `$line'" -} -alarm 0; - -$service eq 'git-upload-pack' - or gitfail "unknown/unsupported service `$service'"; - -my $fetch = 2; # 0:don't; 1:try; 2:force -my $url = $specpath; - -while ($url =~ s#\s+(\[)([^][{}]+)\]$## || - $url =~ s#\s+(\{)([^][{}]+)\}$##) { - $_ = $2; - my $must = $1 eq '{'; - if (m/^fetch=try$/) { - $fetch = 1; - } elsif (m/^fetch=no$/) { - $fetch = 0; - } elsif (m/^fetch=must$/) { - $fetch = 2; # the default - } elsif (m/^timeout=(\d+)$/) { - $fetchtimeout = $1 <= $maxfetchtimeout ? $1 : $maxfetchtimeout; - } elsif ($must) { - gitfail "unknown/unsupported option `$_'"; +sub readcommand () { + $SIG{ALRM} = sub { fail "timeout" }; + alarm 30; + + my $hex_len = xread 4; + fail "Bad hex in packet length" unless $hex_len =~ m|^[0-9a-fA-F]{4}$|; + my $line = xread -4 + hex $hex_len; + unless (($service,$specpath,$spechost) = $line =~ + m|^(git-[a-z-]+) /*([!-~ ]+)\0host=([!-~]+)\0$|) { + $line =~ s|[^ -~]+| |g; + gitfail "unknown/unsupported instruction `$line'" } -} -$url =~ m{^(?:https?|git)://[-.0-9a-z]+/} - or gitfail "unknown/unsupported url scheme or format `$url'"; + alarm 0; + + $service eq 'git-upload-pack' + or gitfail "unknown/unsupported service `$service'"; + + $fetch = 2; # 0:don't; 1:try; 2:force + $url = $specpath; + + while ($url =~ s#\s+(\[)([^][{}]+)\]$## || + $url =~ s#\s+(\{)([^][{}]+)\}$##) { + $_ = $2; + my $must = $1 eq '{'; + if (m/^fetch=try$/) { + $fetch = 1; + } elsif (m/^fetch=no$/) { + $fetch = 0; + } elsif (m/^fetch=must$/) { + $fetch = 2; # the default + } elsif (m/^timeout=(\d+)$/) { + $fetchtimeout = $1 <= $maxfetchtimeout ? $1 : $maxfetchtimeout; + } elsif ($must) { + gitfail "unknown/unsupported option `$_'"; + } + } -our $subdir = $url; -$subdir =~ s|\\|\\\\|g; -$subdir =~ s|,|\\,|g; -$subdir =~ s|/|,|g; + $url =~ m{^(?:https?|git)://[-.0-9a-z]+/} + or gitfail "unknown/unsupported url scheme or format `$url'"; -logm 'info', "$specpath locking"; + $subdir = $url; + $subdir =~ s|\\|\\\\|g; + $subdir =~ s|,|\\,|g; + $subdir =~ s|/|,|g; -my $tmpd= "$subdir\\.tmp"; -my $gitd= "$subdir\\.git"; -my $lock = "$subdir\\.lock"; + logm 'info', "$specpath locking"; + + $tmpd= "$subdir\\.tmp"; + $gitd= "$subdir\\.git"; + $lock = "$subdir\\.lock"; +} -for (;;) { +sub clonefetch () { open LOCK, "+>", $lock or fail "open/create $lock: $!"; flock LOCK, LOCK_EX or fail "lock exclusive $lock: $!"; @@ -307,14 +312,25 @@ logm 'info', "timeout=$fetchtimeout"; # but it's best to be explicit if (chdir $gitd) { - last; + return 1; } $!==ENOENT or fail "chdir $gitd: $!"; # Well, err, someone must have taken the lock in between # and garbage collected it. How annoying. + return 0; +} + +sub runcommand () { + logm 'info', "$specpath servicing"; + exec qw(git-upload-pack --strict --timeout=1000 .) + or fail "exec git-upload-pack: $!"; +} + +sub daemonservice () { + readcommand(); + while (!clonefetch()) { } + runcommand(); } -logm 'info', "$specpath servicing"; -exec qw(git-upload-pack --strict --timeout=1000 .) - or fail "exec git-upload-pack: $!"; +daemonservice();