From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 8C9F91F9FE; Wed, 21 Jul 2021 14:05:50 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Cc: Konstantin Ryabitsev Subject: [PATCH 2/2] init: allow arbitrary key-values via -c KEY=VALUE Date: Wed, 21 Jul 2021 14:05:50 +0000 Message-Id: <20210721140550.9901-2-e@80x24.org> In-Reply-To: <20210720211840.jl542wuyjh4ajowg@nitro.local> References: <20210720211840.jl542wuyjh4ajowg@nitro.local> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: This won't blindly append identical key=values, but allows specifying multiple, different key=value pairs as long as the values are different. --- Documentation/public-inbox-init.pod | 7 ++++++ script/public-inbox-init | 36 ++++++++++++++++++++++++++++- t/init.t | 34 +++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/Documentation/public-inbox-init.pod b/Documentation/public-inbox-init.pod index 62624f14..85c6c9e8 100644 --- a/Documentation/public-inbox-init.pod +++ b/Documentation/public-inbox-init.pod @@ -60,6 +60,13 @@ Available in public-inbox 1.6.0+. Default: none. +=item -c KEY=VALUE + +Allow setting arbitrary configs as C. +This is idempotent for the same C, but allows setting +multiple values for keys such as C and +C. + =item --skip-artnum This option allows archivists to publish incomplete archives diff --git a/script/public-inbox-init b/script/public-inbox-init index 335eb476..e22a0564 100755 --- a/script/public-inbox-init +++ b/script/public-inbox-init @@ -22,6 +22,7 @@ options: -V2 use scalable public-inbox-v2-format(5) -L LEVEL index level `basic', `medium', or `full' (default: full) --ng NEWSGROUP set NNTP newsgroup name + -c KEY=VALUE set additional config option(s) --skip-artnum=NUM NNTP article numbers to skip --skip-epoch=NUM epochs to skip (-V2 only) -j JOBS number of indexing jobs (-V2 only), (default: 4) @@ -35,6 +36,7 @@ PublicInbox::Admin::require_or_die('-base'); my ($version, $indexlevel, $skip_epoch, $skip_artnum, $jobs, $show_help); my $skip_docdata; my $ng = ''; +my @c_extra; my %opts = ( 'V|version=i' => \$version, 'L|index-level|indexlevel=s' => \$indexlevel, @@ -44,6 +46,7 @@ my %opts = ( 'ng|newsgroup=s' => \$ng, 'skip-docdata' => \$skip_docdata, 'help|h' => \$show_help, + 'c=s@' => \@c_extra, ); my $usage_cb = sub { print STDERR $help; @@ -51,13 +54,38 @@ my $usage_cb = sub { }; GetOptions(%opts) or $usage_cb->(); if ($show_help) { print $help; exit 0 }; -PublicInbox::Admin::indexlevel_ok_or_die($indexlevel) if defined $indexlevel; my $name = shift @ARGV or $usage_cb->(); my $inboxdir = shift @ARGV or $usage_cb->(); my $http_url = shift @ARGV or $usage_cb->(); my (@address) = @ARGV; @address or $usage_cb->(); +@c_extra = map { + my ($k, $v) = split(/=/, $_, 2); + defined($v) or die "Usage: -c KEY=VALUE\n"; + $k =~ /\A[a-z]+\z/i or die "$k contains invalid characters\n"; + $k = lc($k); + if ($k eq 'newsgroup') { + die "newsgroup already set ($ng)\n" if $ng ne ''; + $ng = $v; + (); + } elsif ($k eq 'address') { + push @address, $v; # for conflict checking + (); + } elsif ($k =~ /\A(?:inboxdir|mainrepo)\z/) { + die "$k not allowed via -c $_\n" + } elsif ($k eq 'indexlevel') { + defined($indexlevel) and + die "indexlevel already set ($indexlevel)\n"; + $indexlevel = $v; + (); + } else { + $_ + } +} @c_extra; + +PublicInbox::Admin::indexlevel_ok_or_die($indexlevel) if defined $indexlevel; + $ng =~ m![^A-Za-z0-9/_\.\-\~\@\+\=:]! and die "--newsgroup `$ng' is not valid\n"; ($ng =~ m!\A\.! || $ng =~ m!\.\z!) and @@ -201,6 +229,12 @@ if (defined($indexlevel)) { } run_die([@x, "$pfx.newsgroup", $ng]) if $ng ne ''; +for my $kv (@c_extra) { + my ($k, $v) = split(/=/, $kv, 2); + # --fixed-value for idempotent invocations + run_die([@x, qw(--replace-all --fixed-value), "$pfx.$k", $v, $v]); +} + # needed for git prior to v2.1.0 if (defined $perm) { chmod($perm & 07777, $pi_config_tmp) or diff --git a/t/init.t b/t/init.t index d46bef23..7382e05b 100644 --- a/t/init.t +++ b/t/init.t @@ -48,6 +48,40 @@ sub quiet_fail { is($? >> 8, 255, 'got expected exit code on lock failure'); ok(unlink("$cfgfile.lock"), '-init did not unlink lock on failure'); + + my @init_args = ('i', "$tmpdir/i", + qw(http://example.com/i i@example.com)); + $cmd = [ qw(-init -c .bogus=val), @init_args ]; + quiet_fail($cmd, 'invalid -c KEY=VALUE fails'); + $cmd = [ qw(-init -c .bogus=val), @init_args ]; + quiet_fail($cmd, '-c KEY-only fails'); + $cmd = [ qw(-init -c address=clist@example.com), @init_args ]; + quiet_fail($cmd, '-c address=CONFLICTING-VALUE fails'); + + $cmd = [ qw(-init -c no=problem -c no=problemo), @init_args ]; + ok(run_script($cmd), '-c KEY=VALUE runs'); + my $env = { GIT_CONFIG => "$ENV{PI_DIR}/config" }; + chomp(my @v = xqx([qw(git config --get-all publicinbox.i.no)], $env)); + is_deeply(\@v, [ qw(problem problemo) ]) or xbail(\@v); + + ok(run_script($cmd), '-c KEY=VALUE runs idempotently'); + chomp(my @v2 = xqx([qw(git config --get-all publicinbox.i.no)], $env)); + is_deeply(\@v, \@v2, 'nothing repeated') or xbail(\@v2); + + ok(run_script([@$cmd, '-c', 'no=more']), '-c KEY=VALUE addendum'); + chomp(@v = xqx([qw(git config --get-all publicinbox.i.no)], $env)); + is_deeply(\@v, [ qw(problem problemo more) ]) or xbail(\@v); + + + ok(run_script([@$cmd, '-c', 'no=problem']), '-c KEY=VALUE repeated'); + chomp(@v = xqx([qw(git config --get-all publicinbox.i.no)], $env)); + is_deeply(\@v, [ qw(problem problemo more) ]) or xbail(\@v); + + ok(run_script([@$cmd, '-c', 'address=j@example.com']), + '-c KEY=VALUE address'); + chomp(@v = xqx([qw(git config --get-all publicinbox.i.address)], $env)); + is_deeply(\@v, [ qw(i@example.com j@example.com) ], + 'extra address added via -c KEY=VALUE'); } { my $env = { PI_DIR => "$tmpdir/.public-inbox/" };