X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FConfig.pm;h=2b99346a81d0ef021a20f7708b6a1d0a05ef41c1;hb=b41c19abcf0b0ac8a5f55678bfb0058ad50b3179;hp=6e85750a7832fc927631847199fd5d447d76574a;hpb=63636d78c9c1aba31c4141460b0012ffee96ff53;p=public-inbox.git
diff --git a/lib/PublicInbox/Config.pm b/lib/PublicInbox/Config.pm
index 6e85750a..2b99346a 100644
--- a/lib/PublicInbox/Config.pm
+++ b/lib/PublicInbox/Config.pm
@@ -1,4 +1,4 @@
-# Copyright (C) 2014-2018 all contributors
+# Copyright (C) 2014-2019 all contributors
# License: AGPL-3.0+
#
# Used throughout the project for reading configuration
@@ -20,11 +20,17 @@ sub _array ($) { ref($_[0]) eq 'ARRAY' ? $_[0] : [ $_[0] ] }
sub new {
my ($class, $file) = @_;
$file = default_file() unless defined($file);
- $file = ref $file ? $file : git_config_dump($file);
- my $self = bless $file, $class;
-
+ my $self;
+ if (ref($file) eq 'SCALAR') { # used by some tests
+ open my $fh, '<', $file or die; # PerlIO::scalar
+ $self = config_fh_parse($fh, "\n", '=');
+ } else {
+ $self = git_config_dump($file);
+ }
+ bless $self, $class;
# caches
$self->{-by_addr} ||= {};
+ $self->{-by_list_id} ||= {};
$self->{-by_name} ||= {};
$self->{-by_newsgroup} ||= {};
$self->{-no_obfuscate} ||= {};
@@ -57,31 +63,24 @@ sub new {
$self;
}
+sub _fill_all ($) { each_inbox($_[0], sub {}) }
+
+sub _lookup_fill ($$$) {
+ my ($self, $cache, $key) = @_;
+ $self->{$cache}->{$key} // do {
+ _fill_all($self);
+ $self->{$cache}->{$key};
+ }
+}
+
sub lookup {
my ($self, $recipient) = @_;
- my $addr = lc($recipient);
- my $ibx = $self->{-by_addr}->{$addr};
- return $ibx if $ibx;
-
- my $pfx;
-
- foreach my $k (keys %$self) {
- $k =~ m!\A(publicinbox\.[^/]+)\.address\z! or next;
- my $v = $self->{$k};
- if (ref($v) eq "ARRAY") {
- foreach my $alias (@$v) {
- (lc($alias) eq $addr) or next;
- $pfx = $1;
- last;
- }
- } else {
- (lc($v) eq $addr) or next;
- $pfx = $1;
- last;
- }
- }
- defined $pfx or return;
- _fill($self, $pfx);
+ _lookup_fill($self, '-by_addr', lc($recipient));
+}
+
+sub lookup_list_id {
+ my ($self, $list_id) = @_;
+ _lookup_fill($self, '-by_list_id', lc($list_id));
}
sub lookup_name ($$) {
@@ -91,41 +90,18 @@ sub lookup_name ($$) {
sub each_inbox {
my ($self, $cb) = @_;
- if (my $section_order = $self->{-section_order}) {
- foreach my $section (@$section_order) {
- next if $section !~ m!\Apublicinbox\.([^/]+)\z!;
- $self->{"publicinbox.$1.mainrepo"} or next;
- my $ibx = lookup_name($self, $1) or next;
- $cb->($ibx);
- }
- } else {
- my %seen;
- foreach my $k (keys %$self) {
- $k =~ m!\Apublicinbox\.([^/]+)\.mainrepo\z! or next;
- next if $seen{$1};
- $seen{$1} = 1;
- my $ibx = lookup_name($self, $1) or next;
- $cb->($ibx);
- }
+ # may auto-vivify if config file is non-existent:
+ foreach my $section (@{$self->{-section_order}}) {
+ next if $section !~ m!\Apublicinbox\.([^/]+)\z!;
+ $self->{"publicinbox.$1.mainrepo"} or next;
+ my $ibx = lookup_name($self, $1) or next;
+ $cb->($ibx);
}
}
sub lookup_newsgroup {
my ($self, $ng) = @_;
- $ng = lc($ng);
- my $ibx = $self->{-by_newsgroup}->{$ng};
- return $ibx if $ibx;
-
- foreach my $k (keys %$self) {
- $k =~ m!\A(publicinbox\.[^/]+)\.newsgroup\z! or next;
- my $v = $self->{$k};
- my $pfx = $1;
- if ($v eq $ng) {
- $ibx = _fill($self, $pfx);
- return $ibx;
- }
- }
- undef;
+ _lookup_fill($self, '-by_newsgroup', lc($ng));
}
sub limiter {
@@ -147,19 +123,14 @@ sub default_file {
config_dir() . '/config';
}
-sub git_config_dump {
- my ($file) = @_;
- my (%section_seen, @section_order);
- return {} unless -e $file;
- my @cmd = (qw/git config/, "--file=$file", '-l');
- my $cmd = join(' ', @cmd);
- my $fh = popen_rd(\@cmd) or die "popen_rd failed for $file: $!\n";
+sub config_fh_parse ($$$) {
+ my ($fh, $rs, $fs) = @_;
my %rv;
- local $/ = "\n";
+ my (%section_seen, @section_order);
+ local $/ = $rs;
while (defined(my $line = <$fh>)) {
chomp $line;
- my ($k, $v) = split(/=/, $line, 2);
-
+ my ($k, $v) = split($fs, $line, 2);
my ($section) = ($k =~ /\A(\S+)\.[^\.]+\z/);
unless (defined $section_seen{$section}) {
$section_seen{$section} = 1;
@@ -177,12 +148,22 @@ sub git_config_dump {
$rv{$k} = $v;
}
}
- close $fh or die "failed to close ($cmd) pipe: $?";
$rv{-section_order} = \@section_order;
\%rv;
}
+sub git_config_dump {
+ my ($file) = @_;
+ return {} unless -e $file;
+ my @cmd = (qw/git config -z -l/, "--file=$file");
+ my $cmd = join(' ', @cmd);
+ my $fh = popen_rd(\@cmd) or die "popen_rd failed for $file: $!\n";
+ my $rv = config_fh_parse($fh, "\0", "\n");
+ close $fh or die "failed to close ($cmd) pipe: $?";
+ $rv;
+}
+
sub valid_inbox_name ($) {
my ($name) = @_;
@@ -366,6 +347,17 @@ sub _fill_code_repo {
$git;
}
+sub _git_config_bool ($) {
+ my ($val) = @_;
+ if ($val =~ /\A(?:false|no|off|[\-\+]?(?:0x)?0+)\z/i) {
+ 0;
+ } elsif ($val =~ /\A(?:true|yes|on|[\-\+]?(?:0x)?[0-9]+)\z/i) {
+ 1;
+ } else {
+ undef;
+ }
+}
+
sub _fill {
my ($self, $pfx) = @_;
my $ibx = {};
@@ -379,17 +371,15 @@ sub _fill {
foreach my $k (qw(obfuscate)) {
my $v = $self->{"$pfx.$k"};
defined $v or next;
- if ($v =~ /\A(?:false|no|off|0)\z/) {
- $ibx->{$k} = 0;
- } elsif ($v =~ /\A(?:true|yes|on|1)\z/) {
- $ibx->{$k} = 1;
+ if (defined(my $bval = _git_config_bool($v))) {
+ $ibx->{$k} = $bval;
} else {
warn "Ignoring $pfx.$k=$v in config, not boolean\n";
}
}
# TODO: more arrays, we should support multi-value for
# more things to encourage decentralization
- foreach my $k (qw(address altid nntpmirror coderepo hide)) {
+ foreach my $k (qw(address altid nntpmirror coderepo hide listid)) {
if (defined(my $v = $self->{"$pfx.$k"})) {
$ibx->{$k} = _array($v);
}
@@ -412,6 +402,11 @@ sub _fill {
$self->{-by_addr}->{$lc_addr} = $ibx;
$self->{-no_obfuscate}->{$lc_addr} = 1;
}
+ if (my $listids = $ibx->{listid}) {
+ foreach my $list_id (@$listids) {
+ $self->{-by_list_id}->{$list_id} = $ibx;
+ }
+ }
if (my $ng = $ibx->{newsgroup}) {
$self->{-by_newsgroup}->{$ng} = $ibx;
}
@@ -419,7 +414,7 @@ sub _fill {
if ($ibx->{obfuscate}) {
$ibx->{-no_obfuscate} = $self->{-no_obfuscate};
$ibx->{-no_obfuscate_re} = $self->{-no_obfuscate_re};
- each_inbox($self, sub {}); # noop to populate -no_obfuscate
+ _fill_all($self); # noop to populate -no_obfuscate
}
if (my $ibx_code_repos = $ibx->{coderepo}) {