]> Sergey Matveev's repositories - public-inbox.git/commitdiff
clone: support --post-update-hook= from grokmirror
authorEric Wong <e@80x24.org>
Wed, 28 Dec 2022 02:56:56 +0000 (02:56 +0000)
committerEric Wong <e@80x24.org>
Fri, 30 Dec 2022 09:46:50 +0000 (09:46 +0000)
This should be compatible with both grokmirror 1 and 2 behavior
and serialized on a per-repo basis.

MANIFEST
lib/PublicInbox/LeiMirror.pm
script/public-inbox-clone
t/clone-coderepo-puh1.sh [new file with mode: 0755]
t/clone-coderepo-puh2.sh [new file with mode: 0755]
t/clone-coderepo.t

index 2966a12147d0b8b584b181ea528f7b3b83cb63ec..37357663662bd203b09a64365e138ce0ae698bf2 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -396,6 +396,8 @@ t/altid.t
 t/altid_v2.t
 t/cgi.t
 t/check-www-inbox.perl
+t/clone-coderepo-puh1.sh
+t/clone-coderepo-puh2.sh
 t/clone-coderepo.psgi
 t/clone-coderepo.t
 t/cmd_ipc.t
index 9843d1a67e3ab964d8e08a78d583a5ec4afcf527..5952ed52ec7300ab60ef5455eee56ed90ac843f7 100644 (file)
@@ -682,6 +682,22 @@ sub atomic_write ($$$) {
        ft_rename($ft, "$dn/$bn", 0666);
 }
 
+sub run_next_puh {
+       my ($self) = @_;
+       my $puh = shift @{$self->{-puh_todo}} // return;
+       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;
+       run_next_puh($self);
+}
+
 # modifies the to-be-written manifest entry, and sets values from it, too
 sub update_ent {
        my ($self) = @_;
@@ -773,6 +789,7 @@ 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);
@@ -1165,6 +1182,13 @@ 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};
+       if (defined(my $puh = $lei->{opt}->{'post-update-hook'})) {
+               require Text::ParseWords;
+               for (@$puh) {
+                       my $pfx = [ Text::ParseWords::shellwords($_) ];
+                       push @{$self->{-puh}}, $pfx;
+               }
+       }
        eval {
                my $ic = $lei->{opt}->{'inbox-config'} //= 'always';
                $ic =~ /\A(?:v1|v2|always|never)\z/s or die <<"";
index 677c56c89c619e577ac447e4f2e4d04cd119899c..6ed7ab6b9f25fc48cd9b0062a7a88b26c8af7f1d 100755 (executable)
@@ -27,7 +27,7 @@ EOF
 # support both :/
 GetOptions($opt, qw(help|h quiet|q verbose|v+ C=s@ c=s@ include|I=s@ exclude=s@
        inbox-config=s inbox-version=i objstore=s manifest=s
-       project-list|projectslist=s
+       project-list|projectslist=s post-update-hook=s@
        prune|p keep-going|k
        dry-run|n jobs|j=i no-torsocks torsocks=s epoch=s)) or die $help;
 if ($opt->{help}) { print $help; exit };
diff --git a/t/clone-coderepo-puh1.sh b/t/clone-coderepo-puh1.sh
new file mode 100755 (executable)
index 0000000..37a52bd
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+# sample --post-update-hook for t/clone-coderepo.t test
+case $CLONE_CODEREPO_TEST_OUT in
+'') ;;
+*) echo "uno $@" >> "$CLONE_CODEREPO_TEST_OUT" ;;
+esac
diff --git a/t/clone-coderepo-puh2.sh b/t/clone-coderepo-puh2.sh
new file mode 100755 (executable)
index 0000000..1170a08
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+# sample --post-update-hook for t/clone-coderepo.t test
+case $CLONE_CODEREPO_TEST_OUT in
+'') ;;
+*) echo "dos $@" >> "$CLONE_CODEREPO_TEST_OUT" ;;
+esac
index eb8f8b377bcfc91c46a07a518ee89bf1a1f409f7..947212073c8b2270158ff65366575cb6d9c9a618 100644 (file)
@@ -5,6 +5,7 @@ use v5.12;
 use PublicInbox::TestCommon;
 use PublicInbox::Import;
 use File::Temp;
+use File::Path qw(remove_tree);
 use Digest::SHA qw(sha1_hex);
 require_mods(qw(json Plack::Builder HTTP::Date HTTP::Status));
 require_git '1.8.5';
@@ -126,5 +127,26 @@ is(PublicInbox::Git::try_cat($dst_pl), "a.git\nb.git\n",
        like($err, qr/no longer exist.*\bgone\.git\b/s, 'gone.git noted');
 }
 
+{
+       my $x = [qw(-clone --inbox-config=never --manifest= --project-list=
+               --objstore= -p), $url, "$tmpdir/dst",
+               '--post-update-hook=./t/clone-coderepo-puh1.sh',
+               '--post-update-hook=./t/clone-coderepo-puh2.sh' ];
+       my $log = "$tmpdir/puh.log";
+       my $env = { CLONE_CODEREPO_TEST_OUT => $log };
+       ok(run_script($x, $env), 'no-op clone w/ post-update-hook');
+       ok(!-e $log, 'hooks not run on no-op');
+       remove_tree("$tmpdir/dst");
+       ok(run_script($x, $env), 'fresh clone w/ post-update-hook');
+       ok(-e $log, 'hooks run on fresh clone');
+       open my $lh, '<', $log or xbail "open $log: $!";
+       chomp(my @l = readline($lh));
+       is(scalar(@l), 4, '4 lines written by hooks');
+       for my $r (qw(a b)) {
+               is_xdeeply(['uno', 'dos'],
+                       [ (map { s/ .+//; $_ } grep(m!/$r\.git\z!, @l)) ],
+                       "$r.git hooks ran in order") or diag explain(\@l);
+       }
+}
 
 done_testing;