From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.2 required=3.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id A128F1F698 for ; Wed, 28 Dec 2022 02:56:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=80x24.org; s=selector1; t=1672196215; bh=0Plp4QZ9oqWeQ5eBtDAn6ajhUg+r7jWqRJO4csEw3mI=; h=From:To:Subject:Date:From; b=MByi3h0IubDyu9yaTRBQxY2KyzPkqVXoBiIZWBCih1eFl35tW20c8UdSM6cyGoA0K PMtYEdnRMlNdwte5ff98pCOIWtn/z7SbaAvNujatjAi7MF0LOTgduul4AO9iNCH5Sr q8vvwn9O4soPFd3kfBSqGQv01r5JKm0t6balZtZA= From: Eric Wong To: meta@public-inbox.org Subject: [PATCH] clone: support --post-update-hook= from grokmirror Date: Wed, 28 Dec 2022 02:56:56 +0000 Message-Id: <20221228025656.2086503-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: This should be compatible with both grokmirror 1 and 2 behavior and serialized on a per-repo basis. --- MANIFEST | 2 ++ lib/PublicInbox/LeiMirror.pm | 24 ++++++++++++++++++++++++ script/public-inbox-clone | 2 +- t/clone-coderepo-puh1.sh | 6 ++++++ t/clone-coderepo-puh2.sh | 6 ++++++ t/clone-coderepo.t | 22 ++++++++++++++++++++++ 6 files changed, 61 insertions(+), 1 deletion(-) create mode 100755 t/clone-coderepo-puh1.sh create mode 100755 t/clone-coderepo-puh2.sh diff --git a/MANIFEST b/MANIFEST index 2966a121..37357663 100644 --- 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 diff --git a/lib/PublicInbox/LeiMirror.pm b/lib/PublicInbox/LeiMirror.pm index 9843d1a6..5952ed52 100644 --- a/lib/PublicInbox/LeiMirror.pm +++ b/lib/PublicInbox/LeiMirror.pm @@ -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 <<""; diff --git a/script/public-inbox-clone b/script/public-inbox-clone index 677c56c8..6ed7ab6b 100755 --- a/script/public-inbox-clone +++ b/script/public-inbox-clone @@ -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 index 00000000..37a52bd4 --- /dev/null +++ b/t/clone-coderepo-puh1.sh @@ -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 index 00000000..1170a08a --- /dev/null +++ b/t/clone-coderepo-puh2.sh @@ -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 diff --git a/t/clone-coderepo.t b/t/clone-coderepo.t index eb8f8b37..94721207 100644 --- a/t/clone-coderepo.t +++ b/t/clone-coderepo.t @@ -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;