]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/LeiMirror.pm
ipc+lei: switch to awaitpid
[public-inbox.git] / lib / PublicInbox / LeiMirror.pm
index 5952ed52ec7300ab60ef5455eee56ed90ac843f7..abf663159855e3818f1e484d6d7ffe7060680102 100644 (file)
@@ -24,15 +24,15 @@ use POSIX qw(strftime);
 our $LIVE; # pid => callback
 our $FGRP_TODO; # objstore -> [ fgrp mirror objects ]
 our $TODO; # reference => [ non-fgrp mirror objects ]
+our @PUH; # post-update hooks
 
 sub keep_going ($) {
        $LIVE && (!$_[0]->{lei}->{child_error} ||
                $_[0]->{lei}->{opt}->{'keep-going'});
 }
 
-sub _wq_done_wait { # dwaitpid callback (via wq_eof)
-       my ($arg, $pid) = @_;
-       my ($mrr, $lei) = @$arg;
+sub _wq_done_wait { # awaitpid cb (via wq_eof / IPC->awaitpid_init)
+       my ($pid, $mrr, $lei) = @_;
        if ($?) {
                $lei->child_error($?);
        } elsif (!$lei->{child_error}) {
@@ -235,7 +235,7 @@ sub index_cloned_inbox {
                        my ($k) = ($sw =~ /\A([\w-]+)/);
                        $opt->{$k} = $lei->{opt}->{$k};
                }
-               # force synchronous dwaitpid for v2:
+               # force synchronous awaitpid for v2:
                local $PublicInbox::DS::in_loop = 0;
                my $cfg = PublicInbox::Config->new(undef, $lei->{2});
                my $env = PublicInbox::Admin::index_prepare($opt, $cfg);
@@ -299,7 +299,7 @@ sub fgrp_update {
        my $cmd = [ 'git', "--git-dir=$fgrp->{cur_dst}",
                qw(update-ref --stdin -z) ];
        my $lei = $fgrp->{lei};
-       my $pack = PublicInbox::OnDestroy->new($$, \&pack_dst, $fgrp);
+       my $pack = PublicInbox::OnDestroy->new($$, \&satellite_done, $fgrp);
        start_cmd($fgrp, $cmd, { 0 => $r, 2 => $lei->{2} }, $pack);
        close $r or die "close(r): $!";
        return if $fgrp->{dry_run};
@@ -319,9 +319,10 @@ sub fgrp_update {
        close($w) or warn "E: close(update-ref --stdin): $! (need git 1.8.5+)\n";
 }
 
-sub pack_dst { # packs lightweight satellite repos
+sub satellite_done {
        my ($fgrp) = @_;
        pack_refs($fgrp, $fgrp->{cur_dst});
+       run_puh($fgrp);
 }
 
 sub pack_refs {
@@ -493,7 +494,6 @@ sub cmp_fp_do {
        $self->{-show_ref} = $opt->{1};
        do_reap($self);
        $self->{lei}->qerr("# @$cmd");
-       return if $self->{dry_run};
        $LIVE->{spawn($cmd, undef, $opt)} = [ \&fp_done, $self, $cmd,
                                                $cb, @arg ];
 }
@@ -514,7 +514,9 @@ sub resume_fetch {
        my $cmd = [ @{$self->{-torsocks}}, @git,
                        fetch_args($self->{lei}, $opt), $rn ];
        push @$cmd, '-P' if $self->{lei}->{prune}; # --prune-tags implied
-       start_cmd($self, $cmd, $opt, $fini);
+       my $run_puh = PublicInbox::OnDestroy->new($$, \&run_puh, $self, $fini);
+       ++$self->{chg}->{nr_chg};
+       start_cmd($self, $cmd, $opt, $run_puh);
 }
 
 sub fgrp_enqueue {
@@ -531,6 +533,7 @@ sub fgrp_enqueue {
                $fgrp->{dry_run} ? $fgrp->{lei}->qerr("# @cmd @kv") :
                                run_die([@cmd, @kv], undef, $opt);
        }
+       ++$fgrp->{chg}->{nr_chg};
        push @{$FGRP_TODO->{$fgrp->{-osdir}}}, $fgrp;
 }
 
@@ -563,7 +566,9 @@ sub clone_v1 {
                                                "$self->{dst}$ref";
                        }
                }
-               start_cmd($self, $cmd, $opt, $fini);
+               ++$self->{chg}->{nr_chg};
+               start_cmd($self, $cmd, $opt, PublicInbox::OnDestroy->new($$,
+                                               \&run_puh, $self, $fini));
        }
        if (!$self->{-is_epoch} && $lei->{opt}->{'inbox-config'} =~
                                /\A(?:always|v1)\z/s) {
@@ -684,17 +689,17 @@ sub atomic_write ($$$) {
 
 sub run_next_puh {
        my ($self) = @_;
-       my $puh = shift @{$self->{-puh_todo}} // return;
+       my $puh = shift @{$self->{-puh_todo}} // return delete($self->{-fini});
        my $fini = PublicInbox::OnDestroy->new($$, \&run_next_puh, $self);
        my $cmd = [ @$puh, ($self->{cur_dst} // $self->{dst}) ];
        my $opt = +{ map { $_ => $self->{lei}->{$_} } (0..2) };
        start_cmd($self, $cmd, undef, $opt, $fini);
 }
 
-sub run_post_update_hooks {
-       my ($self) = @_;
-       my $puh = $self->{-puh} // return;
-       @{$self->{-puh_todo}} = @$puh;
+sub run_puh {
+       my ($self, $fini) = @_;
+       $self->{-fini} = $fini;
+       @{$self->{-puh_todo}} = @PUH;
        run_next_puh($self);
 }
 
@@ -747,6 +752,7 @@ sub update_ent {
                                }
                        }
                        symlink($tgt, $ln) or die "symlink($tgt, $ln): $!";
+                       ++$self->{chg}->{nr_chg};
                }
        }
        if (defined(my $t = $self->{-ent}->{modified})) {
@@ -789,7 +795,6 @@ sub v1_done { # called via OnDestroy
        }
        eval { set_description($self) };
        warn $@ if $@;
-       run_post_update_hooks($self);
        return if ($self->{-is_epoch} ||
                $self->{lei}->{opt}->{'inbox-config'} ne 'always');
        write_makefile($dst, 1);
@@ -1049,7 +1054,9 @@ EOM
        warn "\t", $_, "\n" for @local;
 
        my (undef, $dn, $bn) = File::Spec->splitpath($f);
-       atomic_write($dn, $bn, join("\n", @list, ''));
+       $self->{chg}->{nr_chg} += scalar(@remote) + scalar(@local);
+       my $new = join("\n", @list, '');
+       atomic_write($dn, $bn, $new) if $new ne $old;
 }
 
 # FIXME: this gets confused by single inbox instance w/ global manifest.js.gz
@@ -1080,7 +1087,10 @@ sub try_manifest {
        }
 
        # bail out if curl -z/--timecond hit 304 Not Modified, $ft will be empty
-       return $lei->qerr("# $manifest unchanged") if -f $manifest && !-s $ft;
+       if (-f $manifest && !-s $ft) {
+               $lei->child_error(127 << 8) if $lei->{opt}->{'exit-code'};
+               return $lei->qerr("# $manifest unchanged");
+       }
 
        my $m = eval { decode_manifest($ft, $ft, $uri) };
        if ($@) {
@@ -1168,6 +1178,8 @@ W: The following exist and have not been converted to symlinks
 EOM
        dump_project_list($self, $m);
        ft_rename($ft, $manifest, 0666);
+       !$self->{chg}->{nr_chg} && $lei->{opt}->{'exit-code'} and
+               $lei->child_error(127 << 8);
 }
 
 sub start_clone_url {
@@ -1182,12 +1194,10 @@ sub do_mirror { # via wq_io_do or public-inbox-clone
        $self->{dry_run} = 1 if $lei->{opt}->{'dry-run'};
        umask($lei->{client_umask}) if defined $lei->{client_umask};
        $self->{-initial_clone} = 1 if !-d $self->{dst};
+       local @PUH;
        if (defined(my $puh = $lei->{opt}->{'post-update-hook'})) {
                require Text::ParseWords;
-               for (@$puh) {
-                       my $pfx = [ Text::ParseWords::shellwords($_) ];
-                       push @{$self->{-puh}}, $pfx;
-               }
+               @PUH = map { [ Text::ParseWords::shellwords($_) ] } @$puh;
        }
        eval {
                my $ic = $lei->{opt}->{'inbox-config'} //= 'always';