From: Eric Wong Date: Sat, 15 Feb 2025 11:10:09 +0000 (+0000) Subject: cfgwrite: new module to batch commit writes X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d59cb4199f421b2df764e198ddfde26f5a314d11;p=thirdparty%2Fpublic-inbox.git cfgwrite: new module to batch commit writes Hoisting git config writing code into a separate module will make it easier to use libgit2 to avoid process spawning overhead in a future change. --- diff --git a/MANIFEST b/MANIFEST index 2ca7755ce..f0b42826a 100644 --- a/MANIFEST +++ b/MANIFEST @@ -164,6 +164,7 @@ lib/PublicInbox/AdminEdit.pm lib/PublicInbox/AltId.pm lib/PublicInbox/Aspawn.pm lib/PublicInbox/AutoReap.pm +lib/PublicInbox/CfgWr.pm lib/PublicInbox/Cgit.pm lib/PublicInbox/CidxComm.pm lib/PublicInbox/CidxLogP.pm diff --git a/lib/PublicInbox/CfgWr.pm b/lib/PublicInbox/CfgWr.pm new file mode 100644 index 000000000..2b3fd5078 --- /dev/null +++ b/lib/PublicInbox/CfgWr.pm @@ -0,0 +1,54 @@ +# Copyright (C) all contributors +# License: AGPL-3.0+ + +# config writer, may use libgit2 in the future +package PublicInbox::CfgWr; +use v5.12; +use PublicInbox::Git qw(git_exe); +use PublicInbox::Spawn qw(run_die run_wait); + +sub new { + my ($cls, $f) = @_; + bless { -f => $f }, $cls; +} + +sub set { + my ($self, $k, $v) = @_; + push @{$self->{todo}}, [ $k, $v ]; + $self; +} + +sub add { + my ($self, $k, $v) = @_; + push @{$self->{todo}}, [ '--add', $k, $v ]; + $self; +} + +sub replace_all { + my ($self, $k, $v, $re) = @_; + push @{$self->{todo}}, [ '--replace-all', $k, $v, $re ]; + $self; +} + +sub unset_all { + my ($self, $k) = @_; + push @{$self->{todo}}, [ '--unset-all', $k ]; + $self; +} + +sub commit { + my ($self, $opt) = @_; + my @x = (git_exe, 'config', '-f', $self->{-f}); + for my $c (@{delete $self->{todo} // []}) { + unshift @$c, @x; + if ($c->[scalar(@x)] eq '--unset-all') { + run_wait $c, undef, $opt; + # ignore ret=5 if no matches (see git-config(1)) + die "E: @$c \$?=$?" if ($? && ($? >> 8) != 5); + } else { + run_die $c, undef, $opt; + } + } +} + +1; diff --git a/lib/PublicInbox/LeiMirror.pm b/lib/PublicInbox/LeiMirror.pm index 0f14cebae..51d0d9ac4 100644 --- a/lib/PublicInbox/LeiMirror.pm +++ b/lib/PublicInbox/LeiMirror.pm @@ -19,6 +19,7 @@ use PublicInbox::Config qw(glob2re); use PublicInbox::Inbox; use PublicInbox::LeiCurl; use PublicInbox::OnDestroy; +use PublicInbox::CfgWr; use PublicInbox::SHA qw(sha256_hex sha_all); use POSIX qw(strftime); use PublicInbox::Admin qw(fmt_localtime); @@ -415,16 +416,13 @@ sub fgrp_fetch_all { my ($old, $new) = @$fgrp_old_new; @$old = sort { $b->{-sort} <=> $a->{-sort} } @$old; # $new is ordered by {references} - my $cmd = [ git_exe, "--git-dir=$osdir", qw(config -f), $f ]; + my $cfgwr = PublicInbox::CfgWr->new($f); # clobber settings from previous run atomically for ("remotes.$grp", 'fetch.hideRefs') { - my $c = [ @$cmd, '--unset-all', $_ ]; - $self->{lei}->qerr("# @$c"); - next if $self->{dry_run}; - run_wait($c, undef, $opt); - die "E: @$c \$?=$?" if ($? && ($? >> 8) != 5); + $cfgwr->unset_all($_) if !$self->{dry_run}; } + $cfgwr->commit($opt); # permanent configs: my $cfg = PublicInbox::Config->git_config_dump($f); @@ -436,12 +434,10 @@ sub fgrp_fetch_all { my ($k, $v) = split(/=/, $_, 2); $k = "remote.$rn.$k"; next if ($cfg->{$k} // '') eq $v; - my $c = [@$cmd, $k, $v]; - $fgrp->{lei}->qerr("# @$c"); - next if $fgrp->{dry_run}; - run_die($c, undef, $opt); + $cfgwr->set($k, $v) if !$fgrp->{dry_run}; } } + $cfgwr->commit($opt); if (!$self->{dry_run}) { # update the config atomically via O_APPEND while @@ -460,7 +456,7 @@ sub fgrp_fetch_all { write_file '>>', $f, @buf; unlink("$f.lock"); } - $cmd = [ @git, "--git-dir=$osdir", @fetch, $grp ]; + my $cmd = [ @git, "--git-dir=$osdir", @fetch, $grp ]; push @$old, @$new; my $end = on_destroy \&fgrpv_done, $old; start_cmd($self, $cmd, $opt, $end); @@ -809,9 +805,8 @@ sub update_ent { $cur = $self->{-local_manifest}->{$key}->{owner} // "\0"; return if $cur eq $new; utf8::encode($new); # to octets - my $cmd = [ git_exe, qw(config -f), "$dst/config", - 'gitweb.owner', $new ]; - start_cmd($self, $cmd, { 2 => $self->{lei}->{2} }); + PublicInbox::CfgWr->new( + "$dst/config")->set('gitweb.owner', $new)->commit; } sub v1_done { # called via OnDestroy diff --git a/lib/PublicInbox/LeiSavedSearch.pm b/lib/PublicInbox/LeiSavedSearch.pm index 612d1f439..574cf9aa8 100644 --- a/lib/PublicInbox/LeiSavedSearch.pm +++ b/lib/PublicInbox/LeiSavedSearch.pm @@ -10,6 +10,7 @@ use PublicInbox::Git qw(git_exe); use PublicInbox::OverIdx; use PublicInbox::LeiSearch; use PublicInbox::Config; +use PublicInbox::CfgWr; use PublicInbox::Spawn qw(run_die); use PublicInbox::ContentHash qw(git_sha); use PublicInbox::MID qw(mids_for_index); @@ -179,9 +180,9 @@ EOM sub description { $_[0]->{qstr} } # for WWW sub cfg_set { # called by LeiXSearch - my ($self, @args) = @_; + my ($self, $k, $v) = @_; my $lk = $self->lock_for_scope; # git-config doesn't wait - run_die([git_exe, qw(config -f), $self->{'-f'}, @args]); + PublicInbox::CfgWr->new($self->{-f})->set($k, $v)->commit; } # drop-in for LeiDedupe API diff --git a/lib/PublicInbox/MultiGit.pm b/lib/PublicInbox/MultiGit.pm index 9be3a876e..c99a11cbe 100644 --- a/lib/PublicInbox/MultiGit.pm +++ b/lib/PublicInbox/MultiGit.pm @@ -7,6 +7,7 @@ use strict; use v5.10.1; use PublicInbox::Spawn qw(run_die run_qx); use PublicInbox::Import; +use PublicInbox::CfgWr; use PublicInbox::Git qw(git_exe); use File::Temp 0.19; use List::Util qw(max); @@ -116,7 +117,7 @@ sub epoch_cfg_set { chomp(my $x = run_qx(\@cmd)); return if $x eq $v; } - run_die [@cmd, $v]; + PublicInbox::CfgWr->new($f)->set('include.path', $v)->commit; } sub add_epoch { diff --git a/script/public-inbox-init b/script/public-inbox-init index b9e234e30..b959fd917 100755 --- a/script/public-inbox-init +++ b/script/public-inbox-init @@ -163,7 +163,8 @@ my $pi_config_tmp = $fh->filename; close($fh); my $pfx = "publicinbox.$name"; -my @x = (qw/git config/, "--file=$pi_config_tmp"); +require PublicInbox::CfgWr; +my $cfgwr = PublicInbox::CfgWr->new($pi_config_tmp); $inboxdir = PublicInbox::Config::rel2abs_collapsed($inboxdir); die "`\\n' not allowed in `$inboxdir'\n" if index($inboxdir, "\n") >= 0; @@ -225,15 +226,15 @@ require PublicInbox::Spawn; PublicInbox::Spawn->import(qw(run_die)); for my $addr (grep { !$seen{lc $_} } @address) { - run_die([@x, "--add", "$pfx.address", $addr]); + $cfgwr->add("$pfx.address", $addr); } -run_die([@x, "$pfx.url", $http_url]) if +$cfgwr->set("$pfx.url", $http_url) if (!$old_ibx || !grep(/\Q$http_url\E/, @{$old_ibx->{url} // []})); -run_die([@x, "$pfx.inboxdir", $inboxdir]) if +$cfgwr->set("$pfx.inboxdir", $inboxdir) if (!$old_ibx || ($old_ibx->{inboxdir} ne $inboxdir)); -run_die([@x, "$pfx.indexlevel", $indexlevel]) if defined($indexlevel) && +$cfgwr->set("$pfx.indexlevel", $indexlevel) if defined($indexlevel) && (!$old_ibx || (($old_ibx->{indexlevel} // '') ne $indexlevel)); -run_die([@x, "$pfx.newsgroup", $ng]) if $ng ne '' && +$cfgwr->set("$pfx.newsgroup", $ng) if $ng ne '' && (!$old_ibx || (($old_ibx->{newsgroup} // '') ne $ng)); for my $kv (@c_extra) { @@ -242,8 +243,9 @@ for my $kv (@c_extra) { # but that's too new to depend on in 2021. Perl quotemeta # seems compatible enough for POSIX ERE which git uses my $re = '^'.quotemeta($v).'$'; - run_die([@x, qw(--replace-all), "$pfx.$k", $v, $re]); + $cfgwr->replace_all("$pfx.$k", $v, $re); } +$cfgwr->commit; # needed for git prior to v2.1.0 chmod($perm & 07777, $pi_config_tmp);