user/dev discussion of public-inbox itself
 help / color / mirror / code / Atom feed
* [PATCH] clone: support --post-update-hook= from grokmirror
@ 2022-12-28  2:56 Eric Wong
  0 siblings, 0 replies; only message in thread
From: Eric Wong @ 2022-12-28  2:56 UTC (permalink / raw)
  To: meta

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;

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2022-12-28  2:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-28  2:56 [PATCH] clone: support --post-update-hook= from grokmirror Eric Wong

Code repositories for project(s) associated with this public inbox

	https://80x24.org/public-inbox.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).