]> git.ipfire.org Git - thirdparty/public-inbox.git/commitdiff
treewide: move glob2re to PublicInbox::Config
authorEric Wong <e@80x24.org>
Fri, 17 Mar 2023 20:31:36 +0000 (20:31 +0000)
committerEric Wong <e@80x24.org>
Sat, 18 Mar 2023 04:17:44 +0000 (04:17 +0000)
It seems suitable for the config class since globs are a
config/option thing.

lib/PublicInbox/Config.pm
lib/PublicInbox/LeiExternal.pm
lib/PublicInbox/LeiLsExternal.pm
lib/PublicInbox/LeiLsMailSync.pm
lib/PublicInbox/LeiMirror.pm
t/config.t
t/lei_external.t

index cdf06d850e764c7e46f312043414b0fda12df904..34abcea3a140abe1d879393f5502f0b2baf8bf14 100644 (file)
@@ -10,6 +10,8 @@
 package PublicInbox::Config;
 use strict;
 use v5.10.1;
+use parent qw(Exporter);
+our @EXPORT_OK = qw(glob2re);
 use PublicInbox::Inbox;
 use PublicInbox::Spawn qw(popen_rd);
 our $LD_PRELOAD = $ENV{LD_PRELOAD}; # only valid at startup
@@ -577,4 +579,36 @@ sub squote_maybe ($) {
        $val;
 }
 
+my %re_map = ( '*' => '[^/]*?', '?' => '[^/]',
+               '[' => '[', ']' => ']', ',' => ',' );
+
+sub glob2re ($) {
+       my ($re) = @_;
+       my $p = '';
+       my $in_bracket = 0;
+       my $qm = 0;
+       my $schema_host_port = '';
+
+       # don't glob URL-looking things that look like IPv6
+       if ($re =~ s!\A([a-z0-9\+]+://\[[a-f0-9\:]+\](?::[0-9]+)?/)!!i) {
+               $schema_host_port = quotemeta $1; # "http://[::1]:1234"
+       }
+       my $changes = ($re =~ s!(.)!
+               $re_map{$p eq '\\' ? '' : do {
+                       if ($1 eq '[') { ++$in_bracket }
+                       elsif ($1 eq ']') { --$in_bracket }
+                       elsif ($1 eq ',') { ++$qm } # no change
+                       $p = $1;
+               }} // do {
+                       $p = $1;
+                       ($p eq '-' && $in_bracket) ? $p : (++$qm, "\Q$p")
+               }!sge);
+       # bashism (also supported by curl): {a,b,c} => (a|b|c)
+       $changes += ($re =~ s/([^\\]*)\\\{([^,]*,[^\\]*)\\\}/
+                       (my $in_braces = $2) =~ tr!,!|!;
+                       $1."($in_braces)";
+                       /sge);
+       ($changes - $qm) ? $schema_host_port.$re : undef;
+}
+
 1;
index a6562e7f08f6d36a9b27f8c412cafbef5696aae2..3e2a22887810a753586f333325a05a194260ee4d 100644 (file)
@@ -5,7 +5,7 @@
 package PublicInbox::LeiExternal;
 use strict;
 use v5.10.1;
-use PublicInbox::Config;
+use PublicInbox::Config qw(glob2re);
 
 sub externals_each {
        my ($self, $cb, @arg) = @_;
@@ -44,40 +44,6 @@ sub ext_canonicalize {
        }
 }
 
-# TODO: we will probably extract glob2re into a separate module for
-# PublicInbox::Filter::Base and maybe other places
-my %re_map = ( '*' => '[^/]*?', '?' => '[^/]',
-               '[' => '[', ']' => ']', ',' => ',' );
-
-sub glob2re {
-       my $re = $_[-1]; # $_[0] may be $lei
-       my $p = '';
-       my $in_bracket = 0;
-       my $qm = 0;
-       my $schema_host_port = '';
-
-       # don't glob URL-looking things that look like IPv6
-       if ($re =~ s!\A([a-z0-9\+]+://\[[a-f0-9\:]+\](?::[0-9]+)?/)!!i) {
-               $schema_host_port = quotemeta $1; # "http://[::1]:1234"
-       }
-       my $changes = ($re =~ s!(.)!
-               $re_map{$p eq '\\' ? '' : do {
-                       if ($1 eq '[') { ++$in_bracket }
-                       elsif ($1 eq ']') { --$in_bracket }
-                       elsif ($1 eq ',') { ++$qm } # no change
-                       $p = $1;
-               }} // do {
-                       $p = $1;
-                       ($p eq '-' && $in_bracket) ? $p : (++$qm, "\Q$p")
-               }!sge);
-       # bashism (also supported by curl): {a,b,c} => (a|b|c)
-       $changes += ($re =~ s/([^\\]*)\\\{([^,]*,[^\\]*)\\\}/
-                       (my $in_braces = $2) =~ tr!,!|!;
-                       $1."($in_braces)";
-                       /sge);
-       ($changes - $qm) ? $schema_host_port.$re : undef;
-}
-
 # get canonicalized externals list matching $loc
 # $is_exclude denotes it's for --exclude
 # otherwise it's for --only/--include is assumed
index e624cbd48af16296a6f0f056224720149f8944cb..2cdd0c4d74190d2cfcedb856283210ce8fbf097d 100644 (file)
@@ -5,6 +5,7 @@
 package PublicInbox::LeiLsExternal;
 use strict;
 use v5.10.1;
+use PublicInbox::Config qw(glob2re);
 
 # TODO: does this need JSON output?
 sub lei_ls_external {
@@ -12,7 +13,7 @@ sub lei_ls_external {
        my $do_glob = !$lei->{opt}->{globoff}; # glob by default
        my ($OFS, $ORS) = $lei->{opt}->{z} ? ("\0", "\0\0") : (" ", "\n");
        $filter //= '*';
-       my $re = $do_glob ? $lei->glob2re($filter) : undef;
+       my $re = $do_glob ? glob2re($filter) : undef;
        $re .= '/?\\z' if defined $re;
        $re //= index($filter, '/') < 0 ?
                        qr!/\Q$filter\E/?\z! : # exact basename match
index 8da0c284799a81418aff2d1ef0fd58513728bffb..1400d48854746345de61782cf597e64212d1e88b 100644 (file)
@@ -6,12 +6,13 @@ package PublicInbox::LeiLsMailSync;
 use strict;
 use v5.10.1;
 use PublicInbox::LeiMailSync;
+use PublicInbox::Config qw(glob2re);
 
 sub lei_ls_mail_sync {
        my ($lei, $filter) = @_;
        my $lms = $lei->lms or return;
        my $opt = $lei->{opt};
-       my $re = $opt->{globoff} ? undef : $lei->glob2re($filter // '*');
+       my $re = $opt->{globoff} ? undef : glob2re($filter // '*');
        $re .= '/?\\z' if defined $re;
        $re //= index($filter, '/') < 0 ?
                        qr!/\Q$filter\E/?\z! : # exact basename match
index 18932cf4ca5d2564d1d640dddc183846a473ac0b..c8d28ebaf8d17172f073a1404a7f9a83b08c9514 100644 (file)
@@ -14,7 +14,7 @@ use File::Spec ();
 use Fcntl qw(SEEK_SET O_CREAT O_EXCL O_WRONLY);
 use Carp qw(croak);
 use URI;
-use PublicInbox::Config;
+use PublicInbox::Config qw(glob2re);
 use PublicInbox::Inbox;
 use PublicInbox::Git;
 use PublicInbox::LeiCurl;
@@ -983,7 +983,7 @@ sub multi_inbox ($$$) {
        my @orig = defined($incl // $excl) ? (keys %$v2, @v1) : ();
        if (defined $incl) {
                my $re = '(?:'.join('\\z|', map {
-                               $self->{lei}->glob2re($_) // qr/\A\Q$_\E/
+                               glob2re($_) // qr/\A\Q$_\E/
                        } @$incl).'\\z)';
                my @gone = delete @$v2{grep(!/$re/, keys %$v2)};
                delete @$m{map { @$_ } @gone} and $self->{chg}->{manifest} = 1;
@@ -992,7 +992,7 @@ sub multi_inbox ($$$) {
        }
        if (defined $excl) {
                my $re = '(?:'.join('\\z|', map {
-                               $self->{lei}->glob2re($_) // qr/\A\Q$_\E/
+                               glob2re($_) // qr/\A\Q$_\E/
                        } @$excl).'\\z)';
                my @gone = delete @$v2{grep(/$re/, keys %$v2)};
                delete @$m{map { @$_ } @gone} and $self->{chg}->{manifest} = 1;
index ba83e63f669eae842f1d146e1a66d4b8f001bff5..d67931da170c788057f4f0089ff50e4ec94897fd 100644 (file)
@@ -1,7 +1,6 @@
 # Copyright (C) all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
-use strict;
-use v5.10.1;
+use v5.12;
 use PublicInbox::TestCommon;
 use PublicInbox::Import;
 use_ok 'PublicInbox';
@@ -260,5 +259,20 @@ EOF
        is($cfg->urlmatch('imap.idleInterval', $url), undef, 'urlmatch miss');
 };
 
+my $glob2re = PublicInbox::Config->can('glob2re');
+is($glob2re->('http://[::1]:1234/foo/'), undef, 'IPv6 URL not globbed');
+is($glob2re->('foo'), undef, 'plain string unchanged');
+is_deeply($glob2re->('[f-o]'), '[f-o]' , 'range accepted');
+is_deeply($glob2re->('*'), '[^/]*?' , 'wildcard accepted');
+is_deeply($glob2re->('{a,b,c}'), '(a|b|c)' , 'braces');
+is_deeply($glob2re->('{,b,c}'), '(|b|c)' , 'brace with empty @ start');
+is_deeply($glob2re->('{a,b,}'), '(a|b|)' , 'brace with empty @ end');
+is_deeply($glob2re->('{a}'), undef, 'ungrouped brace');
+is_deeply($glob2re->('{a'), undef, 'open left brace');
+is_deeply($glob2re->('a}'), undef, 'open right brace');
+is_deeply($glob2re->('*.[ch]'), '[^/]*?\\.[ch]', 'suffix glob');
+is_deeply($glob2re->('{[a-z],9,}'), '([a-z]|9|)' , 'brace with range');
+is_deeply($glob2re->('\\{a,b\\}'), undef, 'escaped brace');
+is_deeply($glob2re->('\\\\{a,b}'), '\\\\\\\\(a|b)', 'fake escape brace');
 
 done_testing();
index 51d0af5c6333e52d436ed6722791e5bfab229857..573cbc601726626dd86dab458de8067729d39d9f 100644 (file)
@@ -1,8 +1,8 @@
 #!perl -w
-# Copyright (C) 2020-2021 all contributors <meta@public-inbox.org>
+# Copyright (C) all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 # internal unit test, see t/lei-externals.t for functional tests
-use strict; use v5.10.1; use Test::More;
+use v5.12; use Test::More;
 my $cls = 'PublicInbox::LeiExternal';
 require_ok $cls;
 my $canon = $cls->can('ext_canonicalize');
@@ -16,20 +16,4 @@ is($canon->('/this/path/is/nonexistent/'), '/this/path/is/nonexistent',
 is($canon->('/this//path/'), '/this/path', 'extra slashes gone');
 is($canon->('/ALL/CAPS'), '/ALL/CAPS', 'caps preserved');
 
-my $glob2re = $cls->can('glob2re');
-is($glob2re->('http://[::1]:1234/foo/'), undef, 'IPv6 URL not globbed');
-is($glob2re->('foo'), undef, 'plain string unchanged');
-is_deeply($glob2re->('[f-o]'), '[f-o]' , 'range accepted');
-is_deeply($glob2re->('*'), '[^/]*?' , 'wildcard accepted');
-is_deeply($glob2re->('{a,b,c}'), '(a|b|c)' , 'braces');
-is_deeply($glob2re->('{,b,c}'), '(|b|c)' , 'brace with empty @ start');
-is_deeply($glob2re->('{a,b,}'), '(a|b|)' , 'brace with empty @ end');
-is_deeply($glob2re->('{a}'), undef, 'ungrouped brace');
-is_deeply($glob2re->('{a'), undef, 'open left brace');
-is_deeply($glob2re->('a}'), undef, 'open right brace');
-is_deeply($glob2re->('*.[ch]'), '[^/]*?\\.[ch]', 'suffix glob');
-is_deeply($glob2re->('{[a-z],9,}'), '([a-z]|9|)' , 'brace with range');
-is_deeply($glob2re->('\\{a,b\\}'), undef, 'escaped brace');
-is_deeply($glob2re->('\\\\{a,b}'), '\\\\\\\\(a|b)', 'fake escape brace');
-
 done_testing;