Tue Aug 9 18:14:22 2022 UTC ()
lintpkgsrc: fix conversion of glob pattern to regular expression

It is used for evaluating expression modifiers of the form
':S,from,to,'.

Bump version.


(rillig)
diff -r1.46 -r1.47 pkgsrc/pkgtools/lintpkgsrc/Makefile
diff -r1.56 -r1.57 pkgsrc/pkgtools/lintpkgsrc/files/lintpkgsrc.pl
diff -r1.4 -r1.5 pkgsrc/pkgtools/lintpkgsrc/files/t/glob.t

cvs diff -r1.46 -r1.47 pkgsrc/pkgtools/lintpkgsrc/Makefile (expand / switch to unified diff)

--- pkgsrc/pkgtools/lintpkgsrc/Makefile 2022/08/04 21:55:57 1.46
+++ pkgsrc/pkgtools/lintpkgsrc/Makefile 2022/08/09 18:14:22 1.47
@@ -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
3PKGNAME= lintpkgsrc-4.99 3PKGNAME= lintpkgsrc-2022.08.09
4CATEGORIES= pkgtools 4CATEGORIES= pkgtools
5 5
6MAINTAINER= pkgsrc-users@NetBSD.org 6MAINTAINER= pkgsrc-users@NetBSD.org
7HOMEPAGE= https://www.NetBSD.org/docs/pkgsrc/ 7HOMEPAGE= https://www.NetBSD.org/docs/pkgsrc/
8COMMENT= Sanity checks on the complete pkgsrc tree 8COMMENT= Sanity checks on the complete pkgsrc tree
9 9
10DEPENDS+= digest>=20010101:../../pkgtools/digest 10DEPENDS+= digest>=20010101:../../pkgtools/digest
11TEST_DEPENDS+= p5-File-Slurp>=0:../../devel/p5-File-Slurp 11TEST_DEPENDS+= p5-File-Slurp>=0:../../devel/p5-File-Slurp
12TEST_DEPENDS+= p5-IO-Null>=0:../../devel/p5-IO-Null 12TEST_DEPENDS+= p5-IO-Null>=0:../../devel/p5-IO-Null
13CONFLICTS+= pkglint<4.82 
14 13
15USE_TOOLS+= perl:run 14USE_TOOLS+= perl:run
16 15
17WRKSRC= ${WRKDIR} 16WRKSRC= ${WRKDIR}
18USE_LANGUAGES= # none 17USE_LANGUAGES= # none
19AUTO_MKDIRS= yes 18AUTO_MKDIRS= yes
20 19
21SUBST_CLASSES+= lp 20SUBST_CLASSES+= lp
22SUBST_STAGE.lp= post-configure 21SUBST_STAGE.lp= post-configure
23SUBST_FILES.lp+= lintpkgsrc.0 lintpkgsrc.1 lintpkgsrc.pl 22SUBST_FILES.lp+= lintpkgsrc.0 lintpkgsrc.1 lintpkgsrc.pl
24SUBST_SED.lp+= -e 's;@PKGSRCDIR@;${BATCH:D/usr/pkgsrc:U${PKGSRCDIR}};g' 23SUBST_SED.lp+= -e 's;@PKGSRCDIR@;${BATCH:D/usr/pkgsrc:U${PKGSRCDIR}};g'
25SUBST_VARS.lp+= MAKE 24SUBST_VARS.lp+= MAKE
26SUBST_VARS.lp+= PERL5 25SUBST_VARS.lp+= PERL5

cvs diff -r1.56 -r1.57 pkgsrc/pkgtools/lintpkgsrc/files/lintpkgsrc.pl (expand / switch to unified diff)

--- pkgsrc/pkgtools/lintpkgsrc/files/lintpkgsrc.pl 2022/08/04 21:55:58 1.56
+++ pkgsrc/pkgtools/lintpkgsrc/files/lintpkgsrc.pl 2022/08/09 18:14:22 1.57
@@ -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
16use locale; 16use 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.
877sub glob2regex($) { 880sub 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;

cvs diff -r1.4 -r1.5 pkgsrc/pkgtools/lintpkgsrc/files/t/glob.t (expand / switch to unified diff)

--- pkgsrc/pkgtools/lintpkgsrc/files/t/glob.t 2022/08/09 17:53:47 1.4
+++ pkgsrc/pkgtools/lintpkgsrc/files/t/glob.t 2022/08/09 18:14:22 1.5
@@ -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
3use strict; 3use strict;
4use warnings; 4use warnings;
5use Test; 5use Test;
6 6
7BEGIN { plan tests => 12, onfail => sub { die } } 7BEGIN { plan tests => 12, onfail => sub { die } }
8 8
9require('../lintpkgsrc.pl'); 9require('../lintpkgsrc.pl');
10 10
11sub test_glob2regex() { 11sub 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
62test_glob2regex(); 56test_glob2regex();