lintpkgsrc: fix conversion of glob pattern to regular expression It is used for evaluating expression modifiers of the form ':S,from,to,'. Bump version.diff -r1.46 -r1.47 pkgsrc/pkgtools/lintpkgsrc/Makefile
(rillig)
@@ -1,26 +1,25 @@ | @@ -1,26 +1,25 @@ | |||
1 | # $NetBSD: Makefile,v 1.46 2022/08/04 21:55:57 rillig Exp $ | 1 | # $NetBSD: Makefile,v 1.47 2022/08/09 18:14:22 rillig Exp $ | |
2 | 2 | |||
3 | PKGNAME= lintpkgsrc-4.99 | 3 | PKGNAME= lintpkgsrc-2022.08.09 | |
4 | CATEGORIES= pkgtools | 4 | CATEGORIES= pkgtools | |
5 | 5 | |||
6 | MAINTAINER= pkgsrc-users@NetBSD.org | 6 | MAINTAINER= pkgsrc-users@NetBSD.org | |
7 | HOMEPAGE= https://www.NetBSD.org/docs/pkgsrc/ | 7 | HOMEPAGE= https://www.NetBSD.org/docs/pkgsrc/ | |
8 | COMMENT= Sanity checks on the complete pkgsrc tree | 8 | COMMENT= Sanity checks on the complete pkgsrc tree | |
9 | 9 | |||
10 | DEPENDS+= digest>=20010101:../../pkgtools/digest | 10 | DEPENDS+= digest>=20010101:../../pkgtools/digest | |
11 | TEST_DEPENDS+= p5-File-Slurp>=0:../../devel/p5-File-Slurp | 11 | TEST_DEPENDS+= p5-File-Slurp>=0:../../devel/p5-File-Slurp | |
12 | TEST_DEPENDS+= p5-IO-Null>=0:../../devel/p5-IO-Null | 12 | TEST_DEPENDS+= p5-IO-Null>=0:../../devel/p5-IO-Null | |
13 | CONFLICTS+= pkglint<4.82 | |||
14 | 13 | |||
15 | USE_TOOLS+= perl:run | 14 | USE_TOOLS+= perl:run | |
16 | 15 | |||
17 | WRKSRC= ${WRKDIR} | 16 | WRKSRC= ${WRKDIR} | |
18 | USE_LANGUAGES= # none | 17 | USE_LANGUAGES= # none | |
19 | AUTO_MKDIRS= yes | 18 | AUTO_MKDIRS= yes | |
20 | 19 | |||
21 | SUBST_CLASSES+= lp | 20 | SUBST_CLASSES+= lp | |
22 | SUBST_STAGE.lp= post-configure | 21 | SUBST_STAGE.lp= post-configure | |
23 | SUBST_FILES.lp+= lintpkgsrc.0 lintpkgsrc.1 lintpkgsrc.pl | 22 | SUBST_FILES.lp+= lintpkgsrc.0 lintpkgsrc.1 lintpkgsrc.pl | |
24 | SUBST_SED.lp+= -e 's;@PKGSRCDIR@;${BATCH:D/usr/pkgsrc:U${PKGSRCDIR}};g' | 23 | SUBST_SED.lp+= -e 's;@PKGSRCDIR@;${BATCH:D/usr/pkgsrc:U${PKGSRCDIR}};g' | |
25 | SUBST_VARS.lp+= MAKE | 24 | SUBST_VARS.lp+= MAKE | |
26 | SUBST_VARS.lp+= PERL5 | 25 | SUBST_VARS.lp+= PERL5 |
@@ -1,16 +1,16 @@ | @@ -1,16 +1,16 @@ | |||
1 | #!@PERL5@ | 1 | #!@PERL5@ | |
2 | 2 | |||
3 | # $NetBSD: lintpkgsrc.pl,v 1.56 2022/08/04 21:55:58 rillig Exp $ | 3 | # $NetBSD: lintpkgsrc.pl,v 1.57 2022/08/09 18:14:22 rillig Exp $ | |
4 | 4 | |||
5 | # Written by David Brownlee <abs@netbsd.org>. | 5 | # Written by David Brownlee <abs@netbsd.org>. | |
6 | # | 6 | # | |
7 | # Caveats: | 7 | # Caveats: | |
8 | # The 'Makefile parsing' algorithm used to obtain package versions and | 8 | # The 'Makefile parsing' algorithm used to obtain package versions and | |
9 | # DEPENDS information is geared towards speed rather than perfection, | 9 | # DEPENDS information is geared towards speed rather than perfection, | |
10 | # though it has gotten somewhat better over time, it only parses the | 10 | # though it has gotten somewhat better over time, it only parses the | |
11 | # simpler Makefile conditionals. | 11 | # simpler Makefile conditionals. | |
12 | # | 12 | # | |
13 | # TODO: Handle fun DEPENDS like avifile-devel with | 13 | # TODO: Handle fun DEPENDS like avifile-devel with | |
14 | # {qt2-designer>=2.2.4,qt2-designer-kde>=2.3.1nb1} | 14 | # {qt2-designer>=2.2.4,qt2-designer-kde>=2.3.1nb1} | |
15 | 15 | |||
16 | use locale; | 16 | use locale; | |
@@ -864,40 +864,43 @@ sub list_pkgsrc_pkgdirs($$) { | @@ -864,40 +864,43 @@ sub list_pkgsrc_pkgdirs($$) { | |||
864 | if (!opendir(CAT, "$pkgsrcdir/$cat")) { | 864 | if (!opendir(CAT, "$pkgsrcdir/$cat")) { | |
865 | die("Unable to opendir($pkgsrcdir/$cat): $!"); | 865 | die("Unable to opendir($pkgsrcdir/$cat): $!"); | |
866 | } | 866 | } | |
867 | @pkgdirs = | 867 | @pkgdirs = | |
868 | sort grep($_ ne 'Makefile' | 868 | sort grep($_ ne 'Makefile' | |
869 | && $_ ne 'pkg' | 869 | && $_ ne 'pkg' | |
870 | && $_ ne 'CVS' | 870 | && $_ ne 'CVS' | |
871 | && substr($_, 0, 1) ne '.', | 871 | && substr($_, 0, 1) ne '.', | |
872 | readdir(CAT)); | 872 | readdir(CAT)); | |
873 | closedir(CAT); | 873 | closedir(CAT); | |
874 | @pkgdirs; | 874 | @pkgdirs; | |
875 | } | 875 | } | |
876 | 876 | |||
877 | # Convert the glob pattern to a regular expression. | |||
878 | # Return '' if the regular expression equals the glob expression. | |||
879 | # Return undef on error. | |||
877 | sub glob2regex($) { | 880 | sub glob2regex($) { | |
878 | my ($glob) = @_; | 881 | my ($glob) = @_; | |
879 | my (@chars, $in_alt); | 882 | my (@chars, $in_alt); | |
880 | my ($regex); | 883 | my ($regex); | |
881 | 884 | |||
882 | @chars = split(//, $glob); | 885 | @chars = split(//, $glob); | |
883 | while (defined($_ = shift @chars)) { | 886 | while (defined($_ = shift @chars)) { | |
884 | if ($_ eq '*') { | 887 | if ($_ eq '*') { | |
885 | $regex .= '.*'; | 888 | $regex .= '.*'; | |
886 | } elsif ($_ eq '?') { | 889 | } elsif ($_ eq '?') { | |
887 | $regex .= '.'; | 890 | $regex .= '.'; | |
888 | } elsif ($_ eq '+') { | 891 | } elsif ($_ eq '+') { | |
889 | $regex .= '.'; | 892 | $regex .= '\\+'; | |
890 | } elsif ($_ eq '\\+') { | 893 | } elsif ($_ eq '\\') { | |
891 | $regex .= $_ . shift @chars; | 894 | $regex .= $_ . shift @chars; | |
892 | } elsif ($_ eq '.' || $_ eq '|') { | 895 | } elsif ($_ eq '.' || $_ eq '|') { | |
893 | $regex .= quotemeta; | 896 | $regex .= quotemeta; | |
894 | } elsif ($_ eq '{') { | 897 | } elsif ($_ eq '{') { | |
895 | $regex .= '('; | 898 | $regex .= '('; | |
896 | ++$in_alt; | 899 | ++$in_alt; | |
897 | } elsif ($_ eq '}') { | 900 | } elsif ($_ eq '}') { | |
898 | if (!$in_alt) { | 901 | if (!$in_alt) { | |
899 | # Error | 902 | # Error | |
900 | return undef; | 903 | return undef; | |
901 | } | 904 | } | |
902 | $regex .= ')'; | 905 | $regex .= ')'; | |
903 | --$in_alt; | 906 | --$in_alt; |
@@ -1,62 +1,56 @@ | @@ -1,62 +1,56 @@ | |||
1 | # $NetBSD: glob.t,v 1.4 2022/08/09 17:53:47 rillig Exp $ | 1 | # $NetBSD: glob.t,v 1.5 2022/08/09 18:14:22 rillig Exp $ | |
2 | 2 | |||
3 | use strict; | 3 | use strict; | |
4 | use warnings; | 4 | use warnings; | |
5 | use Test; | 5 | use Test; | |
6 | 6 | |||
7 | BEGIN { plan tests => 12, onfail => sub { die } } | 7 | BEGIN { plan tests => 12, onfail => sub { die } } | |
8 | 8 | |||
9 | require('../lintpkgsrc.pl'); | 9 | require('../lintpkgsrc.pl'); | |
10 | 10 | |||
11 | sub test_glob2regex() { | 11 | sub test_glob2regex() { | |
12 | 12 | |||
13 | ok(glob2regex('*'), '^.*$'); | 13 | ok(glob2regex('*'), '^.*$'); | |
14 | 14 | |||
15 | ok(glob2regex('?'), '^.$'); | 15 | ok(glob2regex('?'), '^.$'); | |
16 | 16 | |||
17 | # The '' means that the regular expression equals the glob. | |||
18 | ok(glob2regex('[a-z]'), ''); | 17 | ok(glob2regex('[a-z]'), ''); | |
19 | 18 | |||
20 | # The '' means that the regular expression equals the glob. | |||
21 | ok(glob2regex('[a-z0-9]'), ''); | 19 | ok(glob2regex('[a-z0-9]'), ''); | |
22 | 20 | |||
23 | # The '' means that the regular expression equals the glob. | |||
24 | ok(glob2regex('[a-z0-9_]'), ''); | 21 | ok(glob2regex('[a-z0-9_]'), ''); | |
25 | 22 | |||
26 | # Outside of braces, the ',' is a regular character. | 23 | # Outside of braces, the ',' is a regular character. | |
27 | # The '' means that the regular expression equals the glob. | |||
28 | ok(glob2regex('a,b'), ''); | 24 | ok(glob2regex('a,b'), ''); | |
29 | 25 | |||
30 | # FIXME: Inside brackets, the '*' is a literal '*'. | 26 | # FIXME: Inside brackets, the '*' is a literal '*'. | |
31 | ok(glob2regex('[*]'), '^[.*]$'); | 27 | ok(glob2regex('[*]'), '^[.*]$'); | |
32 | 28 | |||
33 | # FIXME: After a backslash, the '*' must be preserved. | 29 | ok(glob2regex('\*'), ''); | |
34 | ok(glob2regex('\*'), '^\.*$'); | |||
35 | 30 | |||
36 | ok(glob2regex('*.[ch]'), '^.*\.[ch]$'); | 31 | ok(glob2regex('*.[ch]'), '^.*\.[ch]$'); | |
37 | 32 | |||
38 | ok(glob2regex('{one,two}'), '^(one|two)$'); | 33 | ok(glob2regex('{one,two}'), '^(one|two)$'); | |
39 | 34 | |||
40 | ok(glob2regex('{{thi,fou}r,fif}teen'), '^((thi|fou)r|fif)teen$'); | 35 | ok(glob2regex('{{thi,fou}r,fif}teen'), '^((thi|fou)r|fif)teen$'); | |
41 | 36 | |||
42 | # There is an unbalanced '}' at the very end. | 37 | # There is an unbalanced '}' at the very end. | |
43 | ok(glob2regex('{{thi,fou}r,fif}teen}'), undef); | 38 | ok(glob2regex('{{thi,fou}r,fif}teen}'), undef); | |
44 | 39 | |||
45 | # XXX: Why is '+' turned into '.'? | 40 | ok(glob2regex('a+b|c'), '^a\+b\|c$'); | |
46 | ok(glob2regex('a+b|c'), '^a.b\|c$'); | |||
47 | 41 | |||
48 | # XXX: Typo in the code, the case '\\+' is unreachable. | |||
49 | # Escaping the backslash works nevertheless. | |||
50 | ok(glob2regex('a\[b*'), '^a\[b.*$'); | 42 | ok(glob2regex('a\[b*'), '^a\[b.*$'); | |
51 | 43 | |||
52 | ok(glob2regex('a\+b'), '^a\.b$'); | 44 | ok(glob2regex('a\+b'), ''); | |
53 | 45 | |||
54 | # FIXME: Must be '^a\?b$' instead. | 46 | ok(glob2regex('a\?b'), ''); | |
55 | ok(glob2regex('a\?b'), '^a\.b$'); | |||
56 | 47 | |||
57 | # XXX: Depending on the exact implementation, the '\n' may be | 48 | # XXX: Depending on the exact implementation, the '\n' may be | |
58 | # interpreted as a newline, a literal 'n' or a literal '\' 'n'. | 49 | # interpreted as a newline, a literal 'n' or a literal '\' 'n'. | |
59 | ok(glob2regex('a\n*'), '^a\n.*$'); | 50 | ok(glob2regex('a\n*'), '^a\n.*$'); | |
51 | ||||
52 | # https://gnats.netbsd.org/12996 | |||
53 | ok(glob2regex('libsigc++'), '^libsigc\+\+$'); | |||
60 | } | 54 | } | |
61 | 55 | |||
62 | test_glob2regex(); | 56 | test_glob2regex(); |