about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@yhbt.net>2020-06-27 10:03:41 +0000
committerEric Wong <e@yhbt.net>2020-06-28 22:27:18 +0000
commit67592c40510dae8604580cf4b2a0a0f665b84501 (patch)
tree426f2abd4af167df7b7f3e49d5ea95e7dfe8b773
parentbbf4159b7694241d2139be641ced4c485303714a (diff)
downloadpublic-inbox-67592c40510dae8604580cf4b2a0a0f665b84501.tar.gz
config: support ->urlmatch method for -watch
Since we have IMAP client support in -watch; make sure per-URL
settings are familiar to git users by taking advantage of git's
URL matching abilities.

This requires git 1.8.5+, which most users ought to have
(though base CentOS 7 is on 1.8.3).
-rw-r--r--lib/PublicInbox/Config.pm21
-rw-r--r--lib/PublicInbox/TestCommon.pm11
-rw-r--r--lib/PublicInbox/WatchMaildir.pm17
-rw-r--r--t/config.t18
-rw-r--r--t/imapd.t2
5 files changed, 55 insertions, 14 deletions
diff --git a/lib/PublicInbox/Config.pm b/lib/PublicInbox/Config.pm
index 19535beb..c0e2cc57 100644
--- a/lib/PublicInbox/Config.pm
+++ b/lib/PublicInbox/Config.pm
@@ -9,7 +9,7 @@
 
 package PublicInbox::Config;
 use strict;
-use warnings;
+use v5.10.1;
 use PublicInbox::Inbox;
 use PublicInbox::Spawn qw(popen_rd);
 
@@ -462,4 +462,23 @@ sub _fill {
         $ibx
 }
 
+sub urlmatch {
+        my ($self, $key, $url) = @_;
+        state $urlmatch_broken; # requires git 1.8.5
+        return if $urlmatch_broken;
+        my $file = default_file();
+        my $cmd = [qw/git config -z --includes --get-urlmatch/,
+                "--file=$file", $key, $url ];
+        my $fh = popen_rd($cmd);
+        local $/ = "\0";
+        my $val = <$fh>;
+        if (close($fh)) {
+                chomp($val);
+                $val;
+        } else {
+                $urlmatch_broken = 1 if (($? >> 8) != 1);
+                undef;
+        }
+}
+
 1;
diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm
index 14ebba10..7b4da8b5 100644
--- a/lib/PublicInbox/TestCommon.pm
+++ b/lib/PublicInbox/TestCommon.pm
@@ -55,15 +55,16 @@ sub tcp_connect {
 
 sub require_git ($;$) {
         my ($req, $maybe) = @_;
-        my ($req_maj, $req_min) = split(/\./, $req);
-        my ($cur_maj, $cur_min) = (`git --version` =~ /version (\d+)\.(\d+)/);
+        my ($req_maj, $req_min, $req_sub) = split(/\./, $req);
+        my ($cur_maj, $cur_min, $cur_sub) = (xqx([qw(git --version)])
+                        =~ /version (\d+)\.(\d+)(?:\.(\d+))?/);
 
-        my $req_int = ($req_maj << 24) | ($req_min << 16);
-        my $cur_int = ($cur_maj << 24) | ($cur_min << 16);
+        my $req_int = ($req_maj << 24) | ($req_min << 16) | ($req_sub // 0);
+        my $cur_int = ($cur_maj << 24) | ($cur_min << 16) | ($cur_sub // 0);
         if ($cur_int < $req_int) {
                 return 0 if $maybe;
                 Test::More::plan(skip_all =>
-                                "git $req+ required, have $cur_maj.$cur_min");
+                        "git $req+ required, have $cur_maj.$cur_min.$cur_sub");
         }
         1;
 }
diff --git a/lib/PublicInbox/WatchMaildir.pm b/lib/PublicInbox/WatchMaildir.pm
index ac980d9b..494fe7a8 100644
--- a/lib/PublicInbox/WatchMaildir.pm
+++ b/lib/PublicInbox/WatchMaildir.pm
@@ -235,9 +235,11 @@ sub imap_section ($) {
         $uri->scheme . '://' . $uri->authority;
 }
 
-sub cfg_intvl ($$) {
-        my ($cfg, $key) = @_;
-        defined(my $v = $cfg->{lc($key)}) or return;
+sub cfg_intvl ($$$$$) {
+        my ($cfg, $cfg_section, $cfg_key, $imap_section, $url) = @_;
+        my $key = "$cfg_section.$imap_section.$cfg_key";
+        my $v = $cfg->{lc($key)} //
+                $cfg->urlmatch("$cfg_section.$cfg_key", $url) // return;
         $v =~ /\A[0-9]+(?:\.[0-9]+)?\z/s and return $v + 0;
         if (ref($v) eq 'ARRAY') {
                 $v = join(', ', @$v);
@@ -257,7 +259,8 @@ sub imap_common_init ($) {
                 my $sec = imap_section($uri);
                 for my $k (qw(Starttls Debug Compress)) {
                         my $key = lc("imap.$sec.$k");
-                        defined(my $orig = $cfg->{$key}) or next;
+                        my $orig = $cfg->{$key} //
+                                $cfg->urlmatch("imap.$k", $url) // next;
                         my $v = PublicInbox::Config::_git_config_bool($orig);
                         if (defined($v)) {
                                 $mic_args->{$sec}->{$k} = $v;
@@ -265,11 +268,11 @@ sub imap_common_init ($) {
                                 warn "W: $key=$orig is not boolean\n";
                         }
                 }
-                my $to = cfg_intvl($cfg, "imap.$sec.Timeout");
+                my $to = cfg_intvl($cfg, 'imap', 'Timeout', $sec, $url);
                 $mic_args->{$sec}->{Timeout} = $to if $to;
-                $to = cfg_intvl($cfg, "imap.$sec.PollInterval");
+                $to = cfg_intvl($cfg, 'imap', 'PollInterval', $sec, $url);
                 $self->{imap_opt}->{$sec}->{poll_intvl} = $to if $to;
-                $to = cfg_intvl($cfg, "imap.$sec.IdleInterval");
+                $to = cfg_intvl($cfg, 'imap', 'IdleInterval', $sec, $url);
                 $self->{imap_opt}->{$sec}->{idle_intvl} = $to if $to;
         }
         $mic_args;
diff --git a/t/config.t b/t/config.t
index 3f41c004..ad543ad3 100644
--- a/t/config.t
+++ b/t/config.t
@@ -225,4 +225,22 @@ EOF
                 'bogus is undef');
 }
 
+SKIP: {
+        require_git('1.8.5', 2) or
+                skip 'git 1.8.5+ required for --url-match', 2;
+        my $f = "$tmpdir/urlmatch";
+        open my $fh, '>', $f or BAIL_OUT $!;
+        print $fh <<EOF or BAIL_OUT $!;
+[imap "imap://*.example.com"]
+        pollInterval = 9
+EOF
+        close $fh or BAIL_OUT;
+        local $ENV{PI_CONFIG} = $f;
+        my $cfg = PublicInbox::Config->new;
+        my $url = 'imap://mail.example.com/INBOX';
+        is($cfg->urlmatch('imap.pollInterval', $url), 9, 'urlmatch hit');
+        is($cfg->urlmatch('imap.idleInterval', $url), undef, 'urlmatch miss');
+};
+
+
 done_testing();
diff --git a/t/imapd.t b/t/imapd.t
index ee3a3b26..5626d247 100644
--- a/t/imapd.t
+++ b/t/imapd.t
@@ -486,7 +486,7 @@ ok($mic->logout, 'logged out');
 
         # try again with polling
         xsys(qw(git config), "--file=$home/.public-inbox/config",
-                "imap.imap://$ihost:$iport.PollInterval", 0.11) == 0
+                'imap.PollInterval', 0.11) == 0
                 or BAIL_OUT "git config $?";
         $w->kill('HUP');
         diag 'waiting for -watch reload + initial fetch';