From 48b21cb662c1e17b7219612bff6ea14b98c85221 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 14 May 2016 06:10:36 +0000 Subject: [PATCH] declare Inbox object for reusability From the beginning, we've avoided objects here in favor of faster startup time; but it may not be worth it since a persistent httpd/nntpd is faster and -mda isn't hit as often. --- lib/PublicInbox/Config.pm | 51 +++++++++++++++++++------- lib/PublicInbox/Inbox.pm | 76 +++++++++++++++++++++++++++++++++++++++ lib/PublicInbox/WWW.pm | 42 ++++++++-------------- script/public-inbox-init | 4 +-- script/public-inbox-mda | 4 +-- t/config.t | 6 ++-- 6 files changed, 136 insertions(+), 47 deletions(-) create mode 100644 lib/PublicInbox/Inbox.pm diff --git a/lib/PublicInbox/Config.pm b/lib/PublicInbox/Config.pm index 331d25c5..3f3707ec 100644 --- a/lib/PublicInbox/Config.pm +++ b/lib/PublicInbox/Config.pm @@ -7,6 +7,7 @@ use strict; use warnings; use base qw/Exporter/; our @EXPORT_OK = qw/try_cat/; +require PublicInbox::Inbox; use File::Path::Expand qw/expand_filename/; # returns key-value pairs of config directives in a hash @@ -14,12 +15,18 @@ use File::Path::Expand qw/expand_filename/; sub new { my ($class, $file) = @_; $file = default_file() unless defined($file); - bless git_config_dump($file), $class; + my $self = bless git_config_dump($file), $class; + $self->{-by_addr} = {}; + $self->{-by_name} = {}; + $self; } sub lookup { my ($self, $recipient) = @_; my $addr = lc($recipient); + my $inbox = $self->{-by_addr}->{$addr}; + return $inbox if $inbox; + my $pfx; foreach my $k (keys %$self) { @@ -37,20 +44,15 @@ sub lookup { last; } } - defined $pfx or return; + _fill($self, $pfx); +} - my %rv; - foreach my $k (qw(mainrepo address filter)) { - my $v = $self->{"$pfx.$k"}; - $rv{$k} = $v if defined $v; - } - my $inbox = $pfx; - $inbox =~ s/\Apublicinbox\.//; - $rv{inbox} = $inbox; - my $v = $rv{address}; - $rv{-primary_address} = ref($v) eq 'ARRAY' ? $v->[0] : $v; - \%rv; +sub lookup_name { + my ($self, $name) = @_; + my $rv = $self->{-by_name}->{$name}; + return $rv if $rv; + $self->{-by_name}->{$name} = _fill($self, "publicinbox.$name"); } sub get { @@ -105,4 +107,27 @@ sub try_cat { $rv; } +sub _fill { + my ($self, $pfx) = @_; + my $rv = {}; + + foreach my $k (qw(mainrepo address filter url)) { + my $v = $self->{"$pfx.$k"}; + $rv->{$k} = $v if defined $v; + } + my $inbox = $pfx; + $inbox =~ s/\Apublicinbox\.//; + $rv->{name} = $inbox; + my $v = $rv->{address} ||= 'public-inbox@example.com'; + $rv->{-primary_address} = ref($v) eq 'ARRAY' ? $v->[0] : $v; + $rv = PublicInbox::Inbox->new($rv); + if (ref($v) eq 'ARRAY') { + $self->{-by_addr}->{lc($_)} = $rv foreach @$v; + } else { + $self->{-by_addr}->{lc($v)} = $rv; + } + $rv; +} + + 1; diff --git a/lib/PublicInbox/Inbox.pm b/lib/PublicInbox/Inbox.pm new file mode 100644 index 00000000..5d9fdb36 --- /dev/null +++ b/lib/PublicInbox/Inbox.pm @@ -0,0 +1,76 @@ +# Copyright (C) 2016 all contributors +# License: AGPL-3.0+ +# +# Represents a public-inbox (which may have multiple mailing addresses) +package PublicInbox::Inbox; +use strict; +use warnings; +use Scalar::Util qw(weaken); +use PublicInbox::Git; + +sub new { + my ($class, $opts) = @_; + bless $opts, $class; +} + +sub weaken_all { + my ($self) = @_; + weaken($self->{$_}) foreach qw(git mm search); +} + +sub git { + my ($self) = @_; + $self->{git} ||= eval { PublicInbox::Git->new($self->{mainrepo}) }; +} + +sub mm { + my ($self) = @_; + $self->{mm} ||= eval { PublicInbox::Msgmap->new($self->{mainrepo}) }; +} + +sub search { + my ($self) = @_; + $self->{search} ||= eval { PublicInbox::Search->new($self->{mainrepo}) }; +} + +sub try_cat { + my ($path) = @_; + my $rv = ''; + if (open(my $fh, '<', $path)) { + local $/; + $rv = <$fh>; + } + $rv; +} + +sub description { + my ($self) = @_; + my $desc = $self->{description}; + return $desc if defined $desc; + $desc = try_cat("$self->{mainrepo}/description"); + chomp $desc; + $desc =~ s/\s+/ /smg; + $desc = '($GIT_DIR/description missing)' if $desc eq ''; + $self->{description} = $desc; +} + +sub cloneurl { + my ($self) = @_; + my $url = $self->{cloneurl}; + return $url if $url; + $url = try_cat("$self->{mainrepo}/cloneurl"); + my @url = split(/\s+/s, $url); + chomp @url; + $self->{cloneurl} = \@url; +} + +sub footer_html { + my ($self) = @_; + my $footer = $self->{footer}; + return $footer if defined $footer; + $footer = try_cat("$self->{mainrepo}/public-inbox/footer.html"); + chomp $footer; + $self->{footer} = $footer; +} + +1; diff --git a/lib/PublicInbox/WWW.pm b/lib/PublicInbox/WWW.pm index 51dc3daa..94ab032f 100644 --- a/lib/PublicInbox/WWW.pm +++ b/lib/PublicInbox/WWW.pm @@ -125,10 +125,11 @@ sub r { [ $_[0], ['Content-Type' => 'text/plain'], [ join(' ', @_, "\n") ] ] } # returns undef if valid, array ref response if invalid sub invalid_inbox { my ($self, $ctx, $inbox, $mid) = @_; - my $git_dir = $ctx->{pi_config}->get($inbox, "mainrepo"); - if (defined $git_dir) { - $ctx->{git_dir} = $git_dir; - $ctx->{git} = PublicInbox::Git->new($git_dir); + my $obj = $ctx->{pi_config}->lookup_name($inbox); + if (defined $obj) { + $ctx->{git_dir} = $obj->{mainrepo}; + $ctx->{git} = $obj->git; + $ctx->{-inbox} = $obj; $ctx->{inbox} = $inbox; return; } @@ -243,27 +244,18 @@ sub ctx_get { sub footer { my ($ctx) = @_; return '' unless $ctx; - my $git_dir = ctx_get($ctx, 'git_dir'); - - # favor user-supplied footer - my $footer = try_cat("$git_dir/public-inbox/footer.html"); - if (defined $footer) { - chomp $footer; - $ctx->{footer} = $footer; - return $footer; - } + my $obj = $ctx->{-inbox} or return ''; + my $footer = $obj->footer_html; + return $ctx->{footer} = $footer if $footer; # auto-generate a footer - my $inbox = ctx_get($ctx, 'inbox'); - my $desc = try_cat("$git_dir/description"); - $desc = '$GIT_DIR/description missing' unless defined $desc; - chomp $desc; + chomp(my $desc = $obj->description); - my $urls = try_cat("$git_dir/cloneurl"); - my @urls = split(/\r?\n/, $urls || ''); + my $urls; + my @urls = @{$obj->cloneurl}; my %seen = map { $_ => 1 } @urls; my $cgi = $ctx->{cgi}; - my $http = $cgi->base->as_string . $inbox; + my $http = $cgi->base->as_string . $obj->{name}; $seen{$http} or unshift @urls, $http; my $ssoma_url = PublicInbox::Hval::prurl($cgi->{env}, SSOMA_URL); if (scalar(@urls) == 1) { @@ -275,13 +267,7 @@ sub footer { join("\n", map { "\tgit clone --mirror $_" } @urls); } - my $addr = $ctx->{pi_config}->get($inbox, 'address'); - if (ref($addr) eq 'ARRAY') { - $addr = $addr->[0]; # first address is primary - } - - $addr = "$addr"; - + my $addr = $obj->{-primary_address}; $ctx->{footer} = join("\n", '- ' . $desc, "A {srch} = PublicInbox::Search->new($ctx->{git_dir}); + $ctx->{srch} = $ctx->{-inbox}->search; }; } diff --git a/script/public-inbox-init b/script/public-inbox-init index ca0f9ddf..54d6ce4c 100755 --- a/script/public-inbox-init +++ b/script/public-inbox-init @@ -43,10 +43,10 @@ if (-e $pi_config) { foreach my $addr (@address) { my $found = $cfg->lookup($addr); if ($found) { - if ($found->{inbox} ne $name) { + if ($found->{name} ne $name) { print STDERR "`$addr' already defined for ", - "`$found->{inbox}',\n", + "`$found->{name}',\n", "does not match intend `$name'\n"; $conflict = 1; } else { diff --git a/script/public-inbox-mda b/script/public-inbox-mda index 8e224a50..b606c59a 100755 --- a/script/public-inbox-mda +++ b/script/public-inbox-mda @@ -49,7 +49,7 @@ if (PublicInbox::MDA->precheck($filter, $dst->{address}) && } elsif ($fcfg eq 'scrub') { $filter_arg = undef; # the default for legacy versions } else { - warn "publicinbox.$dst->{inbox}.filter=$fcfg invalid\n"; + warn "publicinbox.$dst->{name}.filter=$fcfg invalid\n"; warn "must be either 'scrub' or 'reject' (the default)\n"; } @@ -65,7 +65,7 @@ if (PublicInbox::MDA->precheck($filter, $dst->{address}) && }; my $git = PublicInbox::Git->new($main_repo); my $im = PublicInbox::Import->new($git, - $dst->{inbox}, $recipient); + $dst->{name}, $recipient); if (defined $im->add($msg)) { $im->done; $filter->ignore; # exits diff --git a/t/config.t b/t/config.t index 7a63aa76..76f6065d 100644 --- a/t/config.t +++ b/t/config.t @@ -28,8 +28,9 @@ my $tmpdir = tempdir('pi-config-XXXXXX', TMPDIR => 1, CLEANUP => 1); is_deeply($cfg->lookup('meta@public-inbox.org'), { 'mainrepo' => '/home/pi/meta-main.git', 'address' => 'meta@public-inbox.org', + 'url' => 'http://example.com/meta', -primary_address => 'meta@public-inbox.org', - 'inbox' => 'meta', + 'name' => 'meta', }, "lookup matches expected output"); is($cfg->lookup('blah@example.com'), undef, @@ -42,7 +43,8 @@ my $tmpdir = tempdir('pi-config-XXXXXX', TMPDIR => 1, CLEANUP => 1); 'test@public-inbox.org'], -primary_address => 'try@public-inbox.org', 'mainrepo' => '/home/pi/test-main.git', - 'inbox' => 'test', + 'name' => 'test', + 'url' => 'http://example.com/test', }, "lookup matches expected output for test"); } -- 2.44.0