From 48b21cb662c1e17b7219612bff6ea14b98c85221 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 14 May 2016 06:10:36 +0000 Subject: 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 +++++++++----------------- 3 files changed, 128 insertions(+), 41 deletions(-) create mode 100644 lib/PublicInbox/Inbox.pm (limited to 'lib/PublicInbox') 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; }; } -- cgit v1.2.3-24-ge0c7