+ }
+ close $fh or die "close($f): $!";
+ my %map = (head => 'HEAD', description => undef);
+ while (my ($key, $fn) = each %map) {
+ my $val = $ent->{$key} // next;
+ $fn //= $key;
+ $fn = "$edst/$fn";
+ open $fh, '>', $fn or die "open($fn): $!";
+ print $fh $val, "\n" or die "print($fn): $!";
+ close $fh or die "close($fn): $!";
+ }
+}
+
+sub reap_clone { # async, called via SIGCHLD
+ my ($self, $cmd) = @_;
+ my $cerr = $?;
+ $? = 0; # don't let it influence normal exit
+ if ($cerr) {
+ kill('TERM', keys %$LIVE);
+ $self->{lei}->child_error($cerr, "@$cmd failed");
+ }
+}
+
+sub v1_done { # called via OnDestroy
+ my ($self) = @_;
+ return if $self->{dry_run} || !$LIVE;
+ _write_inbox_config($self);
+ my $dst = $self->{cur_dst} // $self->{dst};
+ if (defined(my $o = $self->{-ent} ? $self->{-ent}->{owner} : undef)) {
+ run_die([qw(git config -f), "$dst/config", 'gitweb.owner', $o]);
+ }
+ my $o = "$dst/objects";
+ if (open(my $fh, '<', "$o/info/alternates")) {
+ chomp(my @l = <$fh>);
+ for (@l) { $_ = File::Spec->abs2rel($_, $o)."\n" }
+ my $f = File::Temp->new(TEMPLATE => '.XXXX', DIR => "$o/info");
+ print $f @l;
+ $f->flush or die "flush($f): $!";
+ rename($f->filename, "$o/info/alternates") or
+ die "rename($f, $o/info/alternates): $!";
+ $f->unlink_on_destroy(0);
+ }
+ write_makefile($dst, 1);
+ index_cloned_inbox($self, 1);
+}
+
+sub v2_done { # called via OnDestroy
+ my ($self) = @_;
+ return if $self->{dry_run} || !$LIVE;
+ my $dst = $self->{cur_dst} // $self->{dst};
+ require PublicInbox::Lock;
+ my $lk = bless { lock_path => "$dst/inbox.lock" }, 'PublicInbox::Lock';
+ my $lck = $lk->lock_for_scope($$);
+ _write_inbox_config($self);
+ require PublicInbox::MultiGit;
+ my $mg = PublicInbox::MultiGit->new($dst, 'all.git', 'git');
+ $mg->fill_alternates;
+ for my $i ($mg->git_epochs) { $mg->epoch_cfg_set($i) }
+ my $entries = delete($self->{-ent}) // [];
+ while (@$entries) {
+ my ($edst, $ent) = splice(@$entries);
+ if (defined(my $o = $ent->{owner})) {
+ run_die [qw(git config -f), "$edst/config",
+ 'gitweb.owner', $o];
+ }
+ my $d = $ent->{description} // next;
+ my $fn = "$edst/description";
+ open my $fh, '>', $fn or die "open($fn): $!";
+ print $fh $d, "\n" or die "print($fn): $!";
+ close $fh or die "close($fn): $!";
+ }
+ for my $edst (@{delete($self->{-read_only}) // []}) {
+ my @st = stat($edst) or die "stat($edst): $!";
+ chmod($st[2] & 0555, $edst) or die "chmod(a-w, $edst): $!";
+ }
+ write_makefile($dst, 2);
+ undef $lck; # unlock
+ index_cloned_inbox($self, 2);
+}
+
+sub reap_live {
+ my $pid = waitpid(-1, 0) // die "waitpid(-1): $!";
+ if (my $x = delete $LIVE->{$pid}) {
+ my $cb = shift @$x;
+ $cb->(@$x);
+ } else {
+ warn "reaped unknown PID=$pid ($?)\n";
+ }