Thu Mar 2 08:58:29 2023 UTC ()
pkgtools/pkglint: Update to 22.4.1

Changes since 22.4.0:

Allow pkglint to be run outside the pkgsrc top directory, in order to
allow individual makefiles to be formatted and checked as well. The many
pkgsrc-specific checks don't apply in this case. This mode is
experimental, there are still crashes to be expected.

Fix a crash for syntactically invalid conditions in '.if'.

Fix parsing of dependency lines that contain an escaped '#', which is
used for switching to another shell using a '.SHELL: ...' line.


(rillig)
diff -r1.739 -r1.740 pkgsrc/pkgtools/pkglint/Makefile
diff -r1.81 -r1.82 pkgsrc/pkgtools/pkglint/files/check_test.go
diff -r1.32 -r1.33 pkgsrc/pkgtools/pkglint/files/files.go
diff -r1.16 -r1.17 pkgsrc/pkgtools/pkglint/files/mkassignchecker.go
diff -r1.15 -r1.16 pkgsrc/pkgtools/pkglint/files/mkcondchecker.go
diff -r1.14 -r1.15 pkgsrc/pkgtools/pkglint/files/mkcondchecker_test.go
diff -r1.14 -r1.15 pkgsrc/pkgtools/pkglint/files/mklineparser.go
diff -r1.14 -r1.15 pkgsrc/pkgtools/pkglint/files/mkvarusechecker.go
diff -r1.86 -r1.87 pkgsrc/pkgtools/pkglint/files/mkline.go
diff -r1.85 -r1.86 pkgsrc/pkgtools/pkglint/files/mkline_test.go
diff -r1.71 -r1.72 pkgsrc/pkgtools/pkglint/files/mklinechecker.go
diff -r1.76 -r1.77 pkgsrc/pkgtools/pkglint/files/mklines.go
diff -r1.43 -r1.44 pkgsrc/pkgtools/pkglint/files/mkparser_test.go
diff -r1.93 -r1.94 pkgsrc/pkgtools/pkglint/files/package_test.go
diff -r1.47 -r1.48 pkgsrc/pkgtools/pkglint/files/patches.go
diff -r1.87 -r1.88 pkgsrc/pkgtools/pkglint/files/pkglint.go
diff -r1.73 -r1.74 pkgsrc/pkgtools/pkglint/files/pkglint_test.go
diff -r1.69 -r1.70 pkgsrc/pkgtools/pkglint/files/pkgsrc.go
diff -r1.10 -r1.11 pkgsrc/pkgtools/pkglint/files/var.go
diff -r1.29 -r1.30 pkgsrc/pkgtools/pkglint/files/vardefs_test.go

cvs diff -r1.739 -r1.740 pkgsrc/pkgtools/pkglint/Makefile (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/Makefile 2023/02/16 15:02:04 1.739
+++ pkgsrc/pkgtools/pkglint/Makefile 2023/03/02 08:58:28 1.740
@@ -1,17 +1,16 @@ @@ -1,17 +1,16 @@
1# $NetBSD: Makefile,v 1.739 2023/02/16 15:02:04 bsiegert Exp $ 1# $NetBSD: Makefile,v 1.740 2023/03/02 08:58:28 rillig Exp $
2 2
3PKGNAME= pkglint-22.4.0 3PKGNAME= pkglint-22.4.1
4PKGREVISION= 1 
5CATEGORIES= pkgtools 4CATEGORIES= pkgtools
6 5
7MAINTAINER= rillig@NetBSD.org 6MAINTAINER= rillig@NetBSD.org
8HOMEPAGE= https://github.com/rillig/pkglint 7HOMEPAGE= https://github.com/rillig/pkglint
9COMMENT= Verifier for NetBSD packages 8COMMENT= Verifier for NetBSD packages
10LICENSE= 2-clause-bsd 9LICENSE= 2-clause-bsd
11CONFLICTS+= pkglint4-[0-9]* 10CONFLICTS+= pkglint4-[0-9]*
12 11
13USE_TOOLS+= pax 12USE_TOOLS+= pax
14CHECK_RELRO_SKIP+= bin/pkglint 13CHECK_RELRO_SKIP+= bin/pkglint
15 14
16 15
17SUBST_CLASSES+= pkglint 16SUBST_CLASSES+= pkglint

cvs diff -r1.81 -r1.82 pkgsrc/pkgtools/pkglint/files/Attic/check_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/check_test.go 2023/01/29 13:36:31 1.81
+++ pkgsrc/pkgtools/pkglint/files/Attic/check_test.go 2023/03/02 08:58:29 1.82
@@ -147,30 +147,33 @@ func Test__qa(t *testing.T) { @@ -147,30 +147,33 @@ func Test__qa(t *testing.T) {
147 // They are tested indirectly by the tests of their corresponding checks. 147 // They are tested indirectly by the tests of their corresponding checks.
148 ck.Configure("*", "*", "warn[A-Z]*", -intqa.EMissingTest) 148 ck.Configure("*", "*", "warn[A-Z]*", -intqa.EMissingTest)
149 149
150 // Generated code doesn't need a unit test. 150 // Generated code doesn't need a unit test.
151 // If any, every grammar production in the corresponding yacc file 151 // If any, every grammar production in the corresponding yacc file
152 // should have a unit test. 152 // should have a unit test.
153 ck.Configure("*yacc.go", "*", "*", intqa.ENone) 153 ck.Configure("*yacc.go", "*", "*", intqa.ENone)
154 154
155 // Type definitions don't need a unit test. 155 // Type definitions don't need a unit test.
156 // Only functions and methods do. 156 // Only functions and methods do.
157 ck.Configure("*", "*", "", -intqa.EMissingTest) 157 ck.Configure("*", "*", "", -intqa.EMissingTest)
158 158
159 // The Suite type is used for testing all parts of pkglint. 159 // The Suite type is used for testing all parts of pkglint.
160 // Therefore its test methods may be everywhere. 160 // Therefore, its test methods may be everywhere.
161 ck.Configure("*.go", "Suite", "*", -intqa.EMethodsSameFile) 161 ck.Configure("*.go", "Suite", "*", -intqa.EMethodsSameFile)
162 ck.Configure("*.go", "Tester", "*", -intqa.EMethodsSameFile) 162 ck.Configure("*.go", "Tester", "*", -intqa.EMethodsSameFile)
163 163
 164 // When running gobco, it inserts the function 'GobcoCover'.
 165 ck.Configure("*", "", "GobcoCover", -intqa.EMissingTest)
 166
164 ck.Check() 167 ck.Check()
165} 168}
166 169
167var _ = check.Suite(new(Suite)) 170var _ = check.Suite(new(Suite))
168 171
169func Test(t *testing.T) { check.TestingT(t) } 172func Test(t *testing.T) { check.TestingT(t) }
170 173
171// Tester provides utility methods for testing pkglint. 174// Tester provides utility methods for testing pkglint.
172// It is separated from the Suite since the latter contains 175// It is separated from the Suite since the latter contains
173// all the test methods, which makes it difficult to find 176// all the test methods, which makes it difficult to find
174// a method by auto-completion. 177// a method by auto-completion.
175type Tester struct { 178type Tester struct {
176 c *check.C // Only usable during the test method itself 179 c *check.C // Only usable during the test method itself
@@ -218,27 +221,27 @@ func (t *Tester) SetUpCommandLine(args . @@ -218,27 +221,27 @@ func (t *Tester) SetUpCommandLine(args .
218 G.Logger.verbose = true 221 G.Logger.verbose = true
219 222
220 t.seenSetUpCommandLine = true 223 t.seenSetUpCommandLine = true
221} 224}
222 225
223// SetUpVartypes registers a few hundred variables like MASTER_SITES, 226// SetUpVartypes registers a few hundred variables like MASTER_SITES,
224// WRKSRC, SUBST_SED.*, so that their data types are known to pkglint. 227// WRKSRC, SUBST_SED.*, so that their data types are known to pkglint.
225// 228//
226// Without calling this, there will be many warnings about undefined 229// Without calling this, there will be many warnings about undefined
227// or unused variables, or unknown shell commands. 230// or unused variables, or unknown shell commands.
228// 231//
229// See SetUpTool for registering tools like echo, awk, perl. 232// See SetUpTool for registering tools like echo, awk, perl.
230func (t *Tester) SetUpVartypes() { 233func (t *Tester) SetUpVartypes() {
231 G.Pkgsrc.vartypes.Init(&G.Pkgsrc) 234 G.Pkgsrc.vartypes.Init(G.Pkgsrc)
232} 235}
233 236
234func (t *Tester) SetUpMasterSite(varname string, urls ...string) { 237func (t *Tester) SetUpMasterSite(varname string, urls ...string) {
235 if !G.Pkgsrc.vartypes.IsDefinedExact(varname) { 238 if !G.Pkgsrc.vartypes.IsDefinedExact(varname) {
236 t.SetUpVarType(varname, BtFetchURL, 239 t.SetUpVarType(varname, BtFetchURL,
237 List|SystemProvided, 240 List|SystemProvided,
238 "buildlink3.mk: none", 241 "buildlink3.mk: none",
239 "*: use") 242 "*: use")
240 } 243 }
241 244
242 for _, url := range urls { 245 for _, url := range urls {
243 G.Pkgsrc.registerMasterSite(varname, url) 246 G.Pkgsrc.registerMasterSite(varname, url)
244 } 247 }
@@ -1088,32 +1091,34 @@ func (t *Tester) NewLinesAt(filename Cur @@ -1088,32 +1091,34 @@ func (t *Tester) NewLinesAt(filename Cur
1088// not exist." because an intermediate directory in the path does not exist. 1091// not exist." because an intermediate directory in the path does not exist.
1089// 1092//
1090// If the filename is irrelevant for the particular test, just use filename.mk. 1093// If the filename is irrelevant for the particular test, just use filename.mk.
1091func (t *Tester) NewMkLines(filename CurrPath, lines ...string) *MkLines { 1094func (t *Tester) NewMkLines(filename CurrPath, lines ...string) *MkLines {
1092 return t.NewMkLinesPkg(filename, nil, lines...) 1095 return t.NewMkLinesPkg(filename, nil, lines...)
1093} 1096}
1094 1097
1095func (t *Tester) NewMkLinesPkg(filename CurrPath, pkg *Package, lines ...string) *MkLines { 1098func (t *Tester) NewMkLinesPkg(filename CurrPath, pkg *Package, lines ...string) *MkLines {
1096 basename := filename.Base() 1099 basename := filename.Base()
1097 assertf( 1100 assertf(
1098 basename.HasSuffixText(".mk") || basename == "Makefile" || basename.HasPrefixText("Makefile."), 1101 basename.HasSuffixText(".mk") || basename == "Makefile" || basename.HasPrefixText("Makefile."),
1099 "filename %q must be realistic, otherwise the variable permissions are wrong", filename) 1102 "filename %q must be realistic, otherwise the variable permissions are wrong", filename)
1100 1103
1101 var rawText strings.Builder 1104 var sb strings.Builder
1102 for _, line := range lines { 1105 for _, line := range lines {
1103 rawText.WriteString(line) 1106 sb.WriteString(line)
1104 rawText.WriteString("\n") 1107 sb.WriteString("\n")
1105 } 1108 }
1106 return NewMkLines(convertToLogicalLines(filename, rawText.String(), true), pkg, nil) 1109 rawText := sb.String()
 1110 logicalLines := convertToLogicalLines(filename, rawText, true)
 1111 return NewMkLines(logicalLines, pkg, nil)
1107} 1112}
1108 1113
1109// Returns and consumes the output from both stdout and stderr. 1114// Returns and consumes the output from both stdout and stderr.
1110// In the output, the temporary directory is replaced with a tilde (~). 1115// In the output, the temporary directory is replaced with a tilde (~).
1111func (t *Tester) Output() string { 1116func (t *Tester) Output() string {
1112 stdout := t.stdout.String() 1117 stdout := t.stdout.String()
1113 stderr := t.stderr.String() 1118 stderr := t.stderr.String()
1114 1119
1115 t.stdout.Reset() 1120 t.stdout.Reset()
1116 t.stderr.Reset() 1121 t.stderr.Reset()
1117 if G.isUsable() { 1122 if G.isUsable() {
1118 G.Logger.logged = Once{} 1123 G.Logger.logged = Once{}
1119 if G.Logger.out != nil { // Necessary because Main resets the G variable. 1124 if G.Logger.out != nil { // Necessary because Main resets the G variable.

cvs diff -r1.32 -r1.33 pkgsrc/pkgtools/pkglint/files/Attic/files.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/files.go 2020/02/15 13:48:40 1.32
+++ pkgsrc/pkgtools/pkglint/files/Attic/files.go 2023/03/02 08:58:29 1.33
@@ -49,26 +49,29 @@ func Load(filename CurrPath, options Loa @@ -49,26 +49,29 @@ func Load(filename CurrPath, options Loa
49 } 49 }
50 50
51 if G.Profiling { 51 if G.Profiling {
52 G.loaded.Add(filename.Clean().String(), 1) 52 G.loaded.Add(filename.Clean().String(), 1)
53 } 53 }
54 54
55 result := convertToLogicalLines(filename, rawText, options&Makefile != 0) 55 result := convertToLogicalLines(filename, rawText, options&Makefile != 0)
56 if filename.HasSuffixText(".mk") { 56 if filename.HasSuffixText(".mk") {
57 G.fileCache.Put(filename, options, result) 57 G.fileCache.Put(filename, options, result)
58 } 58 }
59 return result 59 return result
60} 60}
61 61
 62// convertToLogicalLines splits the raw text into lines.
 63// If joinBackslashes is true, lines that end with an odd number of backslashes
 64// are joined with the following line.
62func convertToLogicalLines(filename CurrPath, rawText string, joinBackslashLines bool) *Lines { 65func convertToLogicalLines(filename CurrPath, rawText string, joinBackslashLines bool) *Lines {
63 var rawLines []*RawLine 66 var rawLines []*RawLine
64 for _, rawLine := range strings.SplitAfter(rawText, "\n") { 67 for _, rawLine := range strings.SplitAfter(rawText, "\n") {
65 if rawLine != "" { 68 if rawLine != "" {
66 rawLines = append(rawLines, &RawLine{rawLine}) 69 rawLines = append(rawLines, &RawLine{rawLine})
67 } 70 }
68 } 71 }
69 72
70 var loglines []*Line 73 var loglines []*Line
71 if joinBackslashLines { 74 if joinBackslashLines {
72 for lineno := 0; lineno < len(rawLines); { 75 for lineno := 0; lineno < len(rawLines); {
73 line, nextLineno := nextLogicalLine(filename, rawLines, lineno) 76 line, nextLineno := nextLogicalLine(filename, rawLines, lineno)
74 loglines = append(loglines, line) 77 loglines = append(loglines, line)

cvs diff -r1.16 -r1.17 pkgsrc/pkgtools/pkglint/files/Attic/mkassignchecker.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mkassignchecker.go 2022/08/19 17:35:43 1.16
+++ pkgsrc/pkgtools/pkglint/files/Attic/mkassignchecker.go 2023/03/02 08:58:29 1.17
@@ -19,36 +19,40 @@ func NewMkAssignChecker(mkLine *MkLine,  @@ -19,36 +19,40 @@ func NewMkAssignChecker(mkLine *MkLine,
19func (ck *MkAssignChecker) check() { 19func (ck *MkAssignChecker) check() {
20 ck.checkLeft() 20 ck.checkLeft()
21 ck.checkOp() 21 ck.checkOp()
22 ck.checkRight() 22 ck.checkRight()
23} 23}
24 24
25// checkLeft checks everything to the left of the assignment operator. 25// checkLeft checks everything to the left of the assignment operator.
26func (ck *MkAssignChecker) checkLeft() { 26func (ck *MkAssignChecker) checkLeft() {
27 varname := ck.MkLine.Varname() 27 varname := ck.MkLine.Varname()
28 if !ck.mayBeDefined(varname) { 28 if !ck.mayBeDefined(varname) {
29 ck.MkLine.Warnf("Variable names starting with an underscore (%s) are reserved for internal pkgsrc use.", varname) 29 ck.MkLine.Warnf("Variable names starting with an underscore (%s) are reserved for internal pkgsrc use.", varname)
30 } 30 }
31 31
 32 if G.Pkgsrc == nil {
 33 goto checkVarUse
 34 }
32 ck.checkLeftNotUsed() 35 ck.checkLeftNotUsed()
33 ck.checkLeftOpsys() 36 ck.checkLeftOpsys()
34 ck.checkLeftDeprecated() 37 ck.checkLeftDeprecated()
35 ck.checkLeftBsdPrefs() 38 ck.checkLeftBsdPrefs()
36 if !ck.checkLeftUserSettable() { 39 if !ck.checkLeftUserSettable() {
37 ck.checkLeftPermissions() 40 ck.checkLeftPermissions()
38 ck.checkLeftAbiDepends() 41 ck.checkLeftAbiDepends()
39 } 42 }
40 ck.checkLeftRationale() 43 ck.checkLeftRationale()
41 44
 45checkVarUse:
42 NewMkLineChecker(ck.MkLines, ck.MkLine).checkTextVarUse( 46 NewMkLineChecker(ck.MkLines, ck.MkLine).checkTextVarUse(
43 varname, 47 varname,
44 NewVartype(BtVariableName, NoVartypeOptions, NewACLEntry("*", aclpAll)), 48 NewVartype(BtVariableName, NoVartypeOptions, NewACLEntry("*", aclpAll)),
45 VucLoadTime) 49 VucLoadTime)
46} 50}
47 51
48// checkLeftNotUsed checks whether the left-hand side of a variable 52// checkLeftNotUsed checks whether the left-hand side of a variable
49// assignment is not used. If it is unused and also doesn't have a predefined 53// assignment is not used. If it is unused and also doesn't have a predefined
50// data type, it may be a spelling mistake. 54// data type, it may be a spelling mistake.
51func (ck *MkAssignChecker) checkLeftNotUsed() { 55func (ck *MkAssignChecker) checkLeftNotUsed() {
52 varname := ck.MkLine.Varname() 56 varname := ck.MkLine.Varname()
53 varcanon := varnameCanon(varname) 57 varcanon := varnameCanon(varname)
54 58
@@ -689,27 +693,27 @@ func (ck *MkAssignChecker) checkVaruseSh @@ -689,27 +693,27 @@ func (ck *MkAssignChecker) checkVaruseSh
689 vuc := VarUseContext{vartype, time, atom.Quoting.ToVarUseContext(), wordPart} 693 vuc := VarUseContext{vartype, time, atom.Quoting.ToVarUseContext(), wordPart}
690 NewMkVarUseChecker(varuse, ck.MkLines, mkline).Check(&vuc) 694 NewMkVarUseChecker(varuse, ck.MkLines, mkline).Check(&vuc)
691 } 695 }
692 } 696 }
693} 697}
694 698
695func (ck *MkAssignChecker) mayBeDefined(varname string) bool { 699func (ck *MkAssignChecker) mayBeDefined(varname string) bool {
696 if !hasPrefix(varname, "_") { 700 if !hasPrefix(varname, "_") {
697 return true 701 return true
698 } 702 }
699 if G.Infrastructure { 703 if G.Infrastructure {
700 return true 704 return true
701 } 705 }
702 if G.Pkgsrc.vartypes.Canon(varname) != nil { 706 if G.Pkgsrc == nil || G.Pkgsrc.vartypes.Canon(varname) != nil {
703 return true 707 return true
704 } 708 }
705 709
706 // Defining the group 'cmake' allows the variable names '_CMAKE_*', 710 // Defining the group 'cmake' allows the variable names '_CMAKE_*',
707 // it's kind of a namespace declaration. 711 // it's kind of a namespace declaration.
708 vargroups := ck.MkLines.allVars.FirstDefinition("_VARGROUPS") 712 vargroups := ck.MkLines.allVars.FirstDefinition("_VARGROUPS")
709 if vargroups != nil { 713 if vargroups != nil {
710 prefix := "_" + strings.ToUpper(vargroups.Value()) + "_" 714 prefix := "_" + strings.ToUpper(vargroups.Value()) + "_"
711 if hasPrefix(varname, prefix) { 715 if hasPrefix(varname, prefix) {
712 return true 716 return true
713 } 717 }
714 } 718 }
715 719

cvs diff -r1.15 -r1.16 pkgsrc/pkgtools/pkglint/files/Attic/mkcondchecker.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mkcondchecker.go 2022/11/28 23:33:28 1.15
+++ pkgsrc/pkgtools/pkglint/files/Attic/mkcondchecker.go 2023/03/02 08:58:29 1.16
@@ -15,27 +15,27 @@ type MkCondChecker struct { @@ -15,27 +15,27 @@ type MkCondChecker struct {
15 15
16func NewMkCondChecker(mkLine *MkLine, mkLines *MkLines) *MkCondChecker { 16func NewMkCondChecker(mkLine *MkLine, mkLines *MkLines) *MkCondChecker {
17 return &MkCondChecker{MkLine: mkLine, MkLines: mkLines} 17 return &MkCondChecker{MkLine: mkLine, MkLines: mkLines}
18} 18}
19 19
20func (ck *MkCondChecker) Check() { 20func (ck *MkCondChecker) Check() {
21 mkline := ck.MkLine 21 mkline := ck.MkLine
22 if trace.Tracing { 22 if trace.Tracing {
23 defer trace.Call1(mkline.Args())() 23 defer trace.Call1(mkline.Args())()
24 } 24 }
25 25
26 p := NewMkParser(nil, mkline.Args()) // No emitWarnings here, see the code below. 26 p := NewMkParser(nil, mkline.Args()) // No emitWarnings here, see the code below.
27 cond := p.MkCond() 27 cond := p.MkCond()
28 if !p.EOF() { 28 if !p.EOF() || cond == nil {
29 mkline.Warnf("Invalid condition, unrecognized part: %q.", p.Rest()) 29 mkline.Warnf("Invalid condition, unrecognized part: %q.", p.Rest())
30 return 30 return
31 } 31 }
32 32
33 checkVarUse := func(varuse *MkVarUse) { 33 checkVarUse := func(varuse *MkVarUse) {
34 var vartype *Vartype // TODO: Insert a better type guess here. 34 var vartype *Vartype // TODO: Insert a better type guess here.
35 // See Test_MkVarUseChecker_checkAssignable__shell_command_in_exists. 35 // See Test_MkVarUseChecker_checkAssignable__shell_command_in_exists.
36 vuc := VarUseContext{vartype, VucLoadTime, VucQuotPlain, false} 36 vuc := VarUseContext{vartype, VucLoadTime, VucQuotPlain, false}
37 NewMkVarUseChecker(varuse, ck.MkLines, mkline).Check(&vuc) 37 NewMkVarUseChecker(varuse, ck.MkLines, mkline).Check(&vuc)
38 } 38 }
39 39
40 // Skip subconditions that have already been handled as part of the !(...). 40 // Skip subconditions that have already been handled as part of the !(...).
41 done := make(map[interface{}]bool) 41 done := make(map[interface{}]bool)
@@ -155,27 +155,27 @@ func (ck *MkCondChecker) checkEmptyType( @@ -155,27 +155,27 @@ func (ck *MkCondChecker) checkEmptyType(
155// that may be used without surrounding quotes in a comparison such as 155// that may be used without surrounding quotes in a comparison such as
156// ${PKGPATH} == category/package. 156// ${PKGPATH} == category/package.
157// TODO: Check whether the ',' really needs to be here. 157// TODO: Check whether the ',' really needs to be here.
158var mkCondStringLiteralUnquoted = textproc.NewByteSet("-+,./0-9@A-Z_a-z") 158var mkCondStringLiteralUnquoted = textproc.NewByteSet("-+,./0-9@A-Z_a-z")
159 159
160// mkCondModifierPatternLiteral contains a safe subset of the characters 160// mkCondModifierPatternLiteral contains a safe subset of the characters
161// that are interpreted literally in the :M and :N modifiers. 161// that are interpreted literally in the :M and :N modifiers.
162// TODO: Check whether the ',' really needs to be here. 162// TODO: Check whether the ',' really needs to be here.
163var mkCondModifierPatternLiteral = textproc.NewByteSet("-+,./0-9<=>@A-Z_a-z") 163var mkCondModifierPatternLiteral = textproc.NewByteSet("-+,./0-9<=>@A-Z_a-z")
164 164
165func (ck *MkCondChecker) checkCompare(left *MkCondTerm, op string, right *MkCondTerm) { 165func (ck *MkCondChecker) checkCompare(left *MkCondTerm, op string, right *MkCondTerm) {
166 switch { 166 switch {
167 case right.Num != "": 167 case right.Num != "":
168 ck.checkCompareVarNum(left, op, right.Num) 168 ck.checkCompareWithNum(left, op, right.Num)
169 case left.Var != nil && right.Var == nil: 169 case left.Var != nil && right.Var == nil:
170 ck.checkCompareVarStr(left.Var, op, right.Str) 170 ck.checkCompareVarStr(left.Var, op, right.Str)
171 } 171 }
172} 172}
173 173
174func (ck *MkCondChecker) checkCompareVarStr(varuse *MkVarUse, op string, str string) { 174func (ck *MkCondChecker) checkCompareVarStr(varuse *MkVarUse, op string, str string) {
175 varname := varuse.varname 175 varname := varuse.varname
176 varmods := varuse.modifiers 176 varmods := varuse.modifiers
177 switch len(varmods) { 177 switch len(varmods) {
178 case 0: 178 case 0:
179 mkLineChecker := NewMkLineChecker(ck.MkLines, ck.MkLine) 179 mkLineChecker := NewMkLineChecker(ck.MkLines, ck.MkLine)
180 mkLineChecker.checkVartype(varname, opUseCompare, str, "") 180 mkLineChecker.checkVartype(varname, opUseCompare, str, "")
181 181
@@ -199,54 +199,54 @@ func (ck *MkCondChecker) checkCompareVar @@ -199,54 +199,54 @@ func (ck *MkCondChecker) checkCompareVar
199 // This case covers ${VAR:Mfilter:O:u} or similar uses in conditions. 199 // This case covers ${VAR:Mfilter:O:u} or similar uses in conditions.
200 // To check these properly, pkglint first needs to know the most common 200 // To check these properly, pkglint first needs to know the most common
201 // modifiers and how they interact. 201 // modifiers and how they interact.
202 // As of March 2019, the modifiers are not modeled. 202 // As of March 2019, the modifiers are not modeled.
203 // The following tracing statement makes it easy to discover these cases, 203 // The following tracing statement makes it easy to discover these cases,
204 // in order to decide whether checking them is worthwhile. 204 // in order to decide whether checking them is worthwhile.
205 if trace.Tracing { 205 if trace.Tracing {
206 trace.Stepf("checkCompareVarStr ${%s%s} %s %s", 206 trace.Stepf("checkCompareVarStr ${%s%s} %s %s",
207 varuse.varname, varuse.Mod(), op, str) 207 varuse.varname, varuse.Mod(), op, str)
208 } 208 }
209 } 209 }
210} 210}
211 211
212func (ck *MkCondChecker) checkCompareVarNum(left *MkCondTerm, op string, num string) { 212func (ck *MkCondChecker) checkCompareWithNum(left *MkCondTerm, op string, num string) {
213 ck.checkCompareVarNumVersion(op, num) 213 ck.checkCompareWithNumVersion(op, num)
214 ck.checkCompareVarNumPython(left, op, num) 214 ck.checkCompareWithNumPython(left, op, num)
215} 215}
216 216
217func (ck *MkCondChecker) checkCompareVarNumVersion(op string, num string) { 217func (ck *MkCondChecker) checkCompareWithNumVersion(op string, num string) {
218 if !contains(num, ".") { 218 if !contains(num, ".") {
219 return 219 return
220 } 220 }
221 221
222 mkline := ck.MkLine 222 mkline := ck.MkLine
223 mkline.Warnf("Numeric comparison %s %s.", op, num) 223 mkline.Warnf("Numeric comparison %s %s.", op, num)
224 mkline.Explain( 224 mkline.Explain(
225 "The numeric comparison of bmake is not suitable for version numbers", 225 "The numeric comparison of bmake is not suitable for version numbers",
226 "since 5.1 == 5.10 == 5.1000000.", 226 "since 5.1 == 5.10 == 5.1000000.",
227 "", 227 "",
228 "To fix this, either enclose the number in double quotes,", 228 "To fix this, either enclose the number in double quotes,",
229 "or use pattern matching:", 229 "or use pattern matching:",
230 "", 230 "",
231 "\t${OS_VERSION} == \"6.5\"", 231 "\t${OS_VERSION} == \"6.5\"",
232 "\t${OS_VERSION:M1.[1-9]} || ${OS_VERSION:M1.[1-9].*}", 232 "\t${OS_VERSION:M1.[1-9]} || ${OS_VERSION:M1.[1-9].*}",
233 "", 233 "",
234 "The second example needs to be split into two parts", 234 "The second example needs to be split into two parts",
235 "since with a single comparison of the form ${OS_VERSION:M1.[1-9]*},", 235 "since with a single comparison of the form ${OS_VERSION:M1.[1-9]*},",
236 "the version number 1.11 would also match, which is not intended.") 236 "the version number 1.11 would also match, which is not intended.")
237} 237}
238 238
239func (ck *MkCondChecker) checkCompareVarNumPython(left *MkCondTerm, op string, num string) { 239func (ck *MkCondChecker) checkCompareWithNumPython(left *MkCondTerm, op string, num string) {
240 if left.Var != nil && left.Var.varname == "_PYTHON_VERSION" && 240 if left.Var != nil && left.Var.varname == "_PYTHON_VERSION" &&
241 op != "==" && op != "!=" && 241 op != "==" && op != "!=" &&
242 matches(num, `^\d+$`) { 242 matches(num, `^\d+$`) {
243 243
244 ck.MkLine.Errorf("The Python version must not be compared numerically.") 244 ck.MkLine.Errorf("The Python version must not be compared numerically.")
245 ck.MkLine.Explain( 245 ck.MkLine.Explain(
246 "The variable _PYTHON_VERSION must not be compared", 246 "The variable _PYTHON_VERSION must not be compared",
247 "against an integer number, as these comparisons are", 247 "against an integer number, as these comparisons are",
248 "not meaningful.", 248 "not meaningful.",
249 "For example, 27 < 39 < 40 < 41 < 310, which means that", 249 "For example, 27 < 39 < 40 < 41 < 310, which means that",
250 "Python 3.10 would be considered newer than a", 250 "Python 3.10 would be considered newer than a",
251 "possible future Python 4.0.", 251 "possible future Python 4.0.",
252 "", 252 "",
@@ -279,37 +279,41 @@ func (ck *MkCondChecker) checkCompareVar @@ -279,37 +279,41 @@ func (ck *MkCondChecker) checkCompareVar
279func (ck *MkCondChecker) checkNotCompare(not *MkCond) { 279func (ck *MkCondChecker) checkNotCompare(not *MkCond) {
280 if not.Compare == nil { 280 if not.Compare == nil {
281 return 281 return
282 } 282 }
283 283
284 ck.MkLine.Warnf("The ! should use parentheses or be merged into the comparison operator.") 284 ck.MkLine.Warnf("The ! should use parentheses or be merged into the comparison operator.")
285} 285}
286 286
287func (ck *MkCondChecker) checkContradictions() { 287func (ck *MkCondChecker) checkContradictions() {
288 mkline := ck.MkLine 288 mkline := ck.MkLine
289 289
290 byVarname := make(map[string][]VarFact) 290 byVarname := make(map[string][]VarFact)
291 levels := ck.MkLines.indentation.levels 291 levels := ck.MkLines.indentation.levels
 292 if len(levels) == 0 {
 293 goto skip // For .elif outside .if
 294 }
292 for _, level := range levels[:len(levels)-1] { 295 for _, level := range levels[:len(levels)-1] {
293 if !level.mkline.NeedsCond() { 296 if !level.mkline.NeedsCond() {
294 continue 297 continue
295 } 298 }
296 prevFacts := ck.collectFacts(level.mkline) 299 prevFacts := ck.collectFacts(level.mkline)
297 for _, prevFact := range prevFacts { 300 for _, prevFact := range prevFacts {
298 varname := prevFact.Varname 301 varname := prevFact.Varname
299 byVarname[varname] = append(byVarname[varname], prevFact) 302 byVarname[varname] = append(byVarname[varname], prevFact)
300 } 303 }
301 } 304 }
302 305
 306skip:
303 facts := ck.collectFacts(mkline) 307 facts := ck.collectFacts(mkline)
304 for _, curr := range facts { 308 for _, curr := range facts {
305 varname := curr.Varname 309 varname := curr.Varname
306 for _, prev := range byVarname[varname] { 310 for _, prev := range byVarname[varname] {
307 both := makepat.Intersect(prev.Matches, curr.Matches) 311 both := makepat.Intersect(prev.Matches, curr.Matches)
308 if !both.CanMatch() { 312 if !both.CanMatch() {
309 if prev.MkLine != mkline { 313 if prev.MkLine != mkline {
310 mkline.Errorf("The patterns %q from %s and %q cannot match at the same time.", 314 mkline.Errorf("The patterns %q from %s and %q cannot match at the same time.",
311 prev.Text, mkline.RelMkLine(prev.MkLine), curr.Text) 315 prev.Text, mkline.RelMkLine(prev.MkLine), curr.Text)
312 } else { 316 } else {
313 mkline.Errorf("The patterns %q and %q cannot match at the same time.", 317 mkline.Errorf("The patterns %q and %q cannot match at the same time.",
314 prev.Text, curr.Text) 318 prev.Text, curr.Text)
315 } 319 }

cvs diff -r1.14 -r1.15 pkgsrc/pkgtools/pkglint/files/Attic/mkcondchecker_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mkcondchecker_test.go 2022/11/28 23:33:28 1.14
+++ pkgsrc/pkgtools/pkglint/files/Attic/mkcondchecker_test.go 2023/03/02 08:58:29 1.15
@@ -119,26 +119,33 @@ func (s *Suite) Test_MkCondChecker_Check @@ -119,26 +119,33 @@ func (s *Suite) Test_MkCondChecker_Check
119 119
120 test(".if ${VAR} == 3", 120 test(".if ${VAR} == 3",
121 "WARN: filename.mk:4: VAR is used but not defined.") 121 "WARN: filename.mk:4: VAR is used but not defined.")
122 122
123 test(".if \"value\" == ${VAR}", 123 test(".if \"value\" == ${VAR}",
124 "WARN: filename.mk:4: VAR is used but not defined.") 124 "WARN: filename.mk:4: VAR is used but not defined.")
125 125
126 test(".if ${MASTER_SITES:Mftp://*} == \"ftp://netbsd.org/\"", 126 test(".if ${MASTER_SITES:Mftp://*} == \"ftp://netbsd.org/\"",
127 // XXX: duplicate diagnostic, see MkParser.MkCond. 127 // XXX: duplicate diagnostic, see MkParser.MkCond.
128 "WARN: filename.mk:4: Invalid variable modifier \"//*\" for \"MASTER_SITES\".", 128 "WARN: filename.mk:4: Invalid variable modifier \"//*\" for \"MASTER_SITES\".",
129 "WARN: filename.mk:4: Invalid variable modifier \"//*\" for \"MASTER_SITES\".", 129 "WARN: filename.mk:4: Invalid variable modifier \"//*\" for \"MASTER_SITES\".",
130 "WARN: filename.mk:4: \"ftp\" is not a valid URL.", 130 "WARN: filename.mk:4: \"ftp\" is not a valid URL.",
131 "WARN: filename.mk:4: MASTER_SITES should not be used at load time in any file.") 131 "WARN: filename.mk:4: MASTER_SITES should not be used at load time in any file.")
 132
 133 test(".if !",
 134 "WARN: filename.mk:4: Invalid condition, unrecognized part: \"\".")
 135
 136 // TODO: There should be another error for the '.elif' outside '.if'.
 137 test(".elif 0",
 138 "ERROR: filename.mk:5: Unmatched .endif.")
132} 139}
133 140
134func (s *Suite) Test_MkCondChecker_Check__tracing(c *check.C) { 141func (s *Suite) Test_MkCondChecker_Check__tracing(c *check.C) {
135 t := s.Init(c) 142 t := s.Init(c)
136 143
137 t.EnableTracingToLog() 144 t.EnableTracingToLog()
138 mklines := t.NewMkLines("filename.mk", 145 mklines := t.NewMkLines("filename.mk",
139 MkCvsID, 146 MkCvsID,
140 ".if ${VAR:Mpattern1:Mpattern2} == comparison", 147 ".if ${VAR:Mpattern1:Mpattern2} == comparison",
141 ".endif") 148 ".endif")
142 149
143 mklines.Check() 150 mklines.Check()
144 151
@@ -589,89 +596,88 @@ func (s *Suite) Test_MkCondChecker_check @@ -589,89 +596,88 @@ func (s *Suite) Test_MkCondChecker_check
589 t.SetUpVartypes() 596 t.SetUpVartypes()
590 mklines := t.NewMkLines("filename.mk", 597 mklines := t.NewMkLines("filename.mk",
591 ".if ${DISTFILES:Mpattern:O:u} == NetBSD") 598 ".if ${DISTFILES:Mpattern:O:u} == NetBSD")
592 t.DisableTracing() 599 t.DisableTracing()
593 600
594 ck := NewMkCondChecker(mklines.mklines[0], mklines) 601 ck := NewMkCondChecker(mklines.mklines[0], mklines)
595 varUse := b.VarUse("DISTFILES", "Mpattern", "O", "u") 602 varUse := b.VarUse("DISTFILES", "Mpattern", "O", "u")
596 // TODO: mklines.ForEach 603 // TODO: mklines.ForEach
597 ck.checkCompareVarStr(varUse, "==", "distfile-1.0.tar.gz") 604 ck.checkCompareVarStr(varUse, "==", "distfile-1.0.tar.gz")
598 605
599 t.CheckOutputEmpty() 606 t.CheckOutputEmpty()
600} 607}
601 608
602func (s *Suite) Test_MkCondChecker_checkCompareVarNum(c *check.C) { 609func (s *Suite) Test_MkCondChecker_checkCompareWithNum(c *check.C) {
603 t := s.Init(c) 610 t := s.Init(c)
604 611
605 mklines := t.NewMkLines("filename.mk", 612 mklines := t.NewMkLines("filename.mk",
606 MkCvsID, 613 MkCvsID,
607 "", 614 "",
608 "OS_VERSION=\t6.0", 615 "OS_VERSION=\t6.0",
609 ".if ${OS_VERSION} > 6.5 || ${_PYTHON_VERSION} < 38", 616 ".if ${OS_VERSION} > 6.5 || ${_PYTHON_VERSION} < 38",
610 ".endif") 617 ".endif")
611 618
612 mklines.Check() 619 mklines.Check()
613 620
614 t.CheckOutputLines( 621 t.CheckOutputLines(
615 "WARN: filename.mk:4: Numeric comparison > 6.5.", 622 "WARN: filename.mk:4: Numeric comparison > 6.5.",
616 "ERROR: filename.mk:4: The Python version must not be compared numerically.", 623 "ERROR: filename.mk:4: The Python version must not be compared numerically.",
617 "WARN: filename.mk:4: _PYTHON_VERSION is used but not defined.") 624 "WARN: filename.mk:4: _PYTHON_VERSION is used but not defined.")
618} 625}
619 626
620func (s *Suite) Test_MkCondChecker_checkCompareVarNumVersion(c *check.C) { 627func (s *Suite) Test_MkCondChecker_checkCompareWithNumVersion(c *check.C) {
621 t := s.Init(c) 628 t := s.Init(c)
622 629
623 mklines := t.NewMkLines("filename.mk", 630 mklines := t.NewMkLines("filename.mk",
624 MkCvsID, 631 MkCvsID,
625 "", 632 "",
626 "OS_VERSION=\t9.0", 633 "OS_VERSION=\t9.0",
627 "", 634 "",
628 ".if ${OS_VERSION} > 6.5", 635 ".if ${OS_VERSION} > 6.5",
629 ".endif", 636 ".endif",
630 "", 637 "",
631 ".if ${OS_VERSION} == 6.5", 638 ".if ${OS_VERSION} == 6.5",
632 ".endif") 639 ".endif")
633 640
634 mklines.Check() 641 mklines.Check()
635 642
636 t.CheckOutputLines( 643 t.CheckOutputLines(
637 "WARN: filename.mk:5: Numeric comparison > 6.5.", 644 "WARN: filename.mk:5: Numeric comparison > 6.5.",
638 "WARN: filename.mk:8: Numeric comparison == 6.5.") 645 "WARN: filename.mk:8: Numeric comparison == 6.5.")
639} 646}
640 647
641func (s *Suite) Test_MkCondChecker_checkCompareVarNumPython(c *check.C) { 648func (s *Suite) Test_MkCondChecker_checkCompareWithNumPython(c *check.C) {
642 t := s.Init(c) 649 t := s.Init(c)
643 650
644 mklines := t.NewMkLines("filename.mk", 651 mklines := t.NewMkLines("filename.mk",
645 MkCvsID, 652 MkCvsID,
646 "", 653 "",
647 "_PYTHON_VERSION=\tnone", 654 "_PYTHON_VERSION=\tnone",
648 "", 655 "",
649 ".if ${_PYTHON_VERSION} < 38", 656 ".if ${_PYTHON_VERSION} < 38",
650 ".endif", 657 ".elif ${_PYTHON_VERSION} < 310",
651 "", 658 ".elif \"\" < 310",
652 ".if ${_PYTHON_VERSION} < 310", 
653 ".endif") 659 ".endif")
654 660
655 mklines.Check() 661 mklines.Check()
656 662
657 t.CheckOutputLines( 663 t.CheckOutputLines(
658 "WARN: filename.mk:3: "+ 664 "WARN: filename.mk:3: "+
659 "Variable names starting with an underscore "+ 665 "Variable names starting with an underscore "+
660 "(_PYTHON_VERSION) are reserved "+ 666 "(_PYTHON_VERSION) are reserved "+
661 "for internal pkgsrc use.", 667 "for internal pkgsrc use.",
662 "ERROR: filename.mk:5: "+ 668 "ERROR: filename.mk:5: "+
663 "The Python version must not be compared numerically.", 669 "The Python version must not be compared numerically.",
664 "ERROR: filename.mk:8: "+ 670 "ERROR: filename.mk:6: "+
665 "The Python version must not be compared numerically.") 671 "The Python version must not be compared numerically.")
666} 672}
667 673
668func (s *Suite) Test_MkCondChecker_checkCompareVarStrCompiler(c *check.C) { 674func (s *Suite) Test_MkCondChecker_checkCompareVarStrCompiler(c *check.C) {
669 t := s.Init(c) 675 t := s.Init(c)
670 676
671 t.SetUpPkgsrc() 677 t.SetUpPkgsrc()
672 t.Chdir("category/package") 678 t.Chdir("category/package")
673 t.FinishSetUp() 679 t.FinishSetUp()
674 680
675 doTest := func(cond string) { 681 doTest := func(cond string) {
676 mklines := t.SetUpFileMkLines("filename.mk", 682 mklines := t.SetUpFileMkLines("filename.mk",
677 MkCvsID, 683 MkCvsID,

cvs diff -r1.14 -r1.15 pkgsrc/pkgtools/pkglint/files/Attic/mklineparser.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mklineparser.go 2020/06/06 20:42:56 1.14
+++ pkgsrc/pkgtools/pkglint/files/Attic/mklineparser.go 2023/03/02 08:58:29 1.15
@@ -250,27 +250,27 @@ func (p MkLineParser) parseInclude(line  @@ -250,27 +250,27 @@ func (p MkLineParser) parseInclude(line
250 250
251func (p MkLineParser) parseSysinclude(line *Line, splitResult mkLineSplitResult) *MkLine { 251func (p MkLineParser) parseSysinclude(line *Line, splitResult mkLineSplitResult) *MkLine {
252 m, indent, directive, includedFile := match3(splitResult.main, `^\.([\t ]*)(s?include)[\t ]+<([^>]+)>$`) 252 m, indent, directive, includedFile := match3(splitResult.main, `^\.([\t ]*)(s?include)[\t ]+<([^>]+)>$`)
253 if !m { 253 if !m {
254 return nil 254 return nil
255 } 255 }
256 256
257 return &MkLine{line, splitResult, &mkLineInclude{directive == "include", true, indent, NewRelPathString(includedFile), nil}} 257 return &MkLine{line, splitResult, &mkLineInclude{directive == "include", true, indent, NewRelPathString(includedFile), nil}}
258} 258}
259 259
260func (p MkLineParser) parseDependency(line *Line, splitResult mkLineSplitResult) *MkLine { 260func (p MkLineParser) parseDependency(line *Line, splitResult mkLineSplitResult) *MkLine {
261 // XXX: Replace this regular expression with proper parsing. 261 // XXX: Replace this regular expression with proper parsing.
262 // There might be a ${VAR:M*.c} in these variables, which the below regular expression cannot handle. 262 // There might be a ${VAR:M*.c} in these variables, which the below regular expression cannot handle.
263 m, targets, whitespace, sources := match3(line.Text, `^([^\t :]+(?:[\t ]*[^\t :]+)*)([\t ]*):[\t ]*([^#]*?)(?:[\t ]*#.*)?$`) 263 m, targets, whitespace, sources := match3(splitResult.main, `^([^\t :]+(?:[\t ]*[^\t :]+)*)([\t ]*):[\t ]*(.*)$`)
264 if !m { 264 if !m {
265 return nil 265 return nil
266 } 266 }
267 267
268 if whitespace != "" { 268 if whitespace != "" {
269 line.Notef("Space before colon in dependency line.") 269 line.Notef("Space before colon in dependency line.")
270 } 270 }
271 return &MkLine{line, splitResult, mkLineDependency{targets, sources}} 271 return &MkLine{line, splitResult, mkLineDependency{targets, sources}}
272} 272}
273 273
274func (p MkLineParser) parseMergeConflict(line *Line, splitResult mkLineSplitResult) *MkLine { 274func (p MkLineParser) parseMergeConflict(line *Line, splitResult mkLineSplitResult) *MkLine {
275 if !matches(line.Text, `^(<<<<<<<|=======|>>>>>>>)`) { 275 if !matches(line.Text, `^(<<<<<<<|=======|>>>>>>>)`) {
276 return nil 276 return nil

cvs diff -r1.14 -r1.15 pkgsrc/pkgtools/pkglint/files/Attic/mkvarusechecker.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mkvarusechecker.go 2021/06/06 07:41:34 1.14
+++ pkgsrc/pkgtools/pkglint/files/Attic/mkvarusechecker.go 2023/03/02 08:58:29 1.15
@@ -23,31 +23,35 @@ func NewMkVarUseChecker(use *MkVarUse, m @@ -23,31 +23,35 @@ func NewMkVarUseChecker(use *MkVarUse, m
23func (ck *MkVarUseChecker) Check(vuc *VarUseContext) { 23func (ck *MkVarUseChecker) Check(vuc *VarUseContext) {
24 if ck.use.IsExpression() { 24 if ck.use.IsExpression() {
25 return 25 return
26 } 26 }
27 27
28 ck.checkUndefined() 28 ck.checkUndefined()
29 ck.checkPermissions(vuc) 29 ck.checkPermissions(vuc)
30 30
31 ck.checkVarname(vuc.time) 31 ck.checkVarname(vuc.time)
32 ck.checkModifiers() 32 ck.checkModifiers()
33 ck.checkAssignable(vuc) 33 ck.checkAssignable(vuc)
34 ck.checkQuoting(vuc) 34 ck.checkQuoting(vuc)
35 35
 36 if G.Pkgsrc == nil {
 37 goto checkVarUse
 38 }
36 ck.checkToolsPlatform() 39 ck.checkToolsPlatform()
37 ck.checkBuildDefs() 40 ck.checkBuildDefs()
38 ck.checkDeprecated() 41 ck.checkDeprecated()
39 ck.checkPkgBuildOptions() 42 ck.checkPkgBuildOptions()
40 43
 44checkVarUse:
41 NewMkLineChecker(ck.MkLines, ck.MkLine). 45 NewMkLineChecker(ck.MkLines, ck.MkLine).
42 checkTextVarUse(ck.use.varname, ck.vartype, vuc.time) 46 checkTextVarUse(ck.use.varname, ck.vartype, vuc.time)
43} 47}
44 48
45func (ck *MkVarUseChecker) checkUndefined() { 49func (ck *MkVarUseChecker) checkUndefined() {
46 varuse := ck.use 50 varuse := ck.use
47 vartype := ck.vartype 51 vartype := ck.vartype
48 varname := varuse.varname 52 varname := varuse.varname
49 53
50 switch { 54 switch {
51 case !G.WarnExtra, 55 case !G.WarnExtra,
52 // Well-known variables are probably defined by the infrastructure. 56 // Well-known variables are probably defined by the infrastructure.
53 vartype != nil && !vartype.IsGuessed(), 57 vartype != nil && !vartype.IsGuessed(),

cvs diff -r1.86 -r1.87 pkgsrc/pkgtools/pkglint/files/Attic/mkline.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mkline.go 2023/01/29 13:36:31 1.86
+++ pkgsrc/pkgtools/pkglint/files/Attic/mkline.go 2023/03/02 08:58:29 1.87
@@ -1295,26 +1295,29 @@ func (ind *Indentation) TrackAfter(mklin @@ -1295,26 +1295,29 @@ func (ind *Indentation) TrackAfter(mklin
1295 ind.Pop() 1295 ind.Pop()
1296 } 1296 }
1297 } 1297 }
1298 1298
1299 switch directive { 1299 switch directive {
1300 case "if", "elif": 1300 case "if", "elif":
1301 cond := mkline.Cond() 1301 cond := mkline.Cond()
1302 if cond == nil { 1302 if cond == nil {
1303 break 1303 break
1304 } 1304 }
1305 1305
1306 ind.RememberUsedVariables(cond) 1306 ind.RememberUsedVariables(cond)
1307 1307
 1308 if G.Pkgsrc == nil {
 1309 break
 1310 }
1308 cond.Walk(&MkCondCallback{ 1311 cond.Walk(&MkCondCallback{
1309 Call: func(name string, arg string) { 1312 Call: func(name string, arg string) {
1310 if name == "exists" && !NewPath(arg).IsAbs() { 1313 if name == "exists" && !NewPath(arg).IsAbs() {
1311 rel := G.Pkgsrc.Rel(mkline.File(NewRelPathString(arg))) 1314 rel := G.Pkgsrc.Rel(mkline.File(NewRelPathString(arg)))
1312 ind.AddCheckedFile(rel) 1315 ind.AddCheckedFile(rel)
1313 } 1316 }
1314 }}) 1317 }})
1315 } 1318 }
1316} 1319}
1317 1320
1318func (ind *Indentation) CheckFinish(filename CurrPath) { 1321func (ind *Indentation) CheckFinish(filename CurrPath) {
1319 if ind.IsEmpty() { 1322 if ind.IsEmpty() {
1320 return 1323 return

cvs diff -r1.85 -r1.86 pkgsrc/pkgtools/pkglint/files/Attic/mkline_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mkline_test.go 2023/01/29 13:36:31 1.85
+++ pkgsrc/pkgtools/pkglint/files/Attic/mkline_test.go 2023/03/02 08:58:29 1.86
@@ -323,26 +323,40 @@ func (s *Suite) Test_MkLine_ValueFields_ @@ -323,26 +323,40 @@ func (s *Suite) Test_MkLine_ValueFields_
323 t.CheckEquals(rest, "") 323 t.CheckEquals(rest, "")
324 324
325 words = mkline.ValueFields(url) 325 words = mkline.ValueFields(url)
326 326
327 t.CheckDeepEquals(words, []string{url}) 327 t.CheckDeepEquals(words, []string{url})
328 328
329 words = mkline.ValueFields("a b \"c c c\" d;;d;; \"e\"''`` 'rest") 329 words = mkline.ValueFields("a b \"c c c\" d;;d;; \"e\"''`` 'rest")
330 330
331 t.CheckDeepEquals(words, []string{"a", "b", "\"c c c\"", "d;;d;;", "\"e\"''``"}) 331 t.CheckDeepEquals(words, []string{"a", "b", "\"c c c\"", "d;;d;;", "\"e\"''``"})
332 // The rest "'rest" is silently discarded. 332 // The rest "'rest" is silently discarded.
333 // Most probably, the shell will complain about it when it is executed. 333 // Most probably, the shell will complain about it when it is executed.
334} 334}
335 335
 336func (s *Suite) Test_MkLine_ValueFields__escaped_number_sign(c *check.C) {
 337 t := s.Init(c)
 338 mklines := t.NewMkLines("filename.mk",
 339 ".SHELL: \\",
 340 "\tname=sh \\",
 341 "\tpath=${.SHELL} \\",
 342 "\tquiet=\"\\# .echoOff\"")
 343 mkline := mklines.mklines[0]
 344
 345 words := mkline.ValueFields(mkline.Sources())
 346
 347 t.CheckDeepEquals(words, []string{"name=sh", "path=${.SHELL}", "quiet=\"# .echoOff\""})
 348}
 349
336func (s *Suite) Test_MkLine_ValueTokens(c *check.C) { 350func (s *Suite) Test_MkLine_ValueTokens(c *check.C) {
337 t := s.Init(c) 351 t := s.Init(c)
338 b := NewMkTokenBuilder() 352 b := NewMkTokenBuilder()
339 text := b.TextToken 353 text := b.TextToken
340 varUseText := b.VaruseTextToken 354 varUseText := b.VaruseTextToken
341 tokens := b.Tokens 355 tokens := b.Tokens
342 356
343 test := func(value string, expected []*MkToken, diagnostics ...string) { 357 test := func(value string, expected []*MkToken, diagnostics ...string) {
344 mkline := t.NewMkLine("Makefile", 1, "PATH=\t"+value) 358 mkline := t.NewMkLine("Makefile", 1, "PATH=\t"+value)
345 actualTokens, _ := mkline.ValueTokens() 359 actualTokens, _ := mkline.ValueTokens()
346 t.CheckDeepEquals(actualTokens, expected) 360 t.CheckDeepEquals(actualTokens, expected)
347 t.CheckOutput(diagnostics) 361 t.CheckOutput(diagnostics)
348 } 362 }
@@ -629,27 +643,27 @@ func (s *Suite) Test_MkLine_VariableNeed @@ -629,27 +643,27 @@ func (s *Suite) Test_MkLine_VariableNeed
629 "MASTER_SITES=\t${HOMEPAGE}") 643 "MASTER_SITES=\t${HOMEPAGE}")
630 mkline := mklines.mklines[1] 644 mkline := mklines.mklines[1]
631 645
632 vuc := VarUseContext{G.Pkgsrc.vartypes.Canon("MASTER_SITES"), VucRunTime, VucQuotPlain, false} 646 vuc := VarUseContext{G.Pkgsrc.vartypes.Canon("MASTER_SITES"), VucRunTime, VucQuotPlain, false}
633 nq := mkline.VariableNeedsQuoting(nil, NewMkVarUse("HOMEPAGE"), G.Pkgsrc.vartypes.Canon("HOMEPAGE"), &vuc) 647 nq := mkline.VariableNeedsQuoting(nil, NewMkVarUse("HOMEPAGE"), G.Pkgsrc.vartypes.Canon("HOMEPAGE"), &vuc)
634 648
635 t.CheckEquals(nq, no) 649 t.CheckEquals(nq, no)
636 650
637 NewMkAssignChecker(mkline, mklines).check() 651 NewMkAssignChecker(mkline, mklines).check()
638 652
639 t.CheckOutputEmpty() // Up to version 5.3.6, pkglint warned about a missing :Q here, which was wrong. 653 t.CheckOutputEmpty() // Up to version 5.3.6, pkglint warned about a missing :Q here, which was wrong.
640} 654}
641 655
642func (s *Suite) Test_MkLine_VariableNeedsQuoting__append_list_to_list(c *check.C) { 656func (s *Suite) Test_MkLine_VariableNeedsQuoting__assign_list_to_list(c *check.C) {
643 t := s.Init(c) 657 t := s.Init(c)
644 658
645 t.SetUpVartypes() 659 t.SetUpVartypes()
646 t.SetUpMasterSite("MASTER_SITE_SOURCEFORGE", "http://downloads.sourceforge.net/sourceforge/") 660 t.SetUpMasterSite("MASTER_SITE_SOURCEFORGE", "http://downloads.sourceforge.net/sourceforge/")
647 mklines := t.NewMkLines("Makefile", 661 mklines := t.NewMkLines("Makefile",
648 MkCvsID, 662 MkCvsID,
649 "MASTER_SITES=\t${MASTER_SITE_SOURCEFORGE:=squirrel-sql/}") 663 "MASTER_SITES=\t${MASTER_SITE_SOURCEFORGE:=squirrel-sql/}")
650 664
651 NewMkAssignChecker(mklines.mklines[1], mklines).check() 665 NewMkAssignChecker(mklines.mklines[1], mklines).check()
652 666
653 // Assigning lists to lists is ok. 667 // Assigning lists to lists is ok.
654 t.CheckOutputEmpty() 668 t.CheckOutputEmpty()
655} 669}

cvs diff -r1.71 -r1.72 pkgsrc/pkgtools/pkglint/files/Attic/mklinechecker.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mklinechecker.go 2023/01/29 13:36:31 1.71
+++ pkgsrc/pkgtools/pkglint/files/Attic/mklinechecker.go 2023/03/02 08:58:29 1.72
@@ -237,26 +237,29 @@ func (ck MkLineChecker) checkInclude() { @@ -237,26 +237,29 @@ func (ck MkLineChecker) checkInclude() {
237 defer trace.Call0()() 237 defer trace.Call0()()
238 } 238 }
239 239
240 mkline := ck.MkLine 240 mkline := ck.MkLine
241 if mkline.Indent() != "" { 241 if mkline.Indent() != "" {
242 ck.checkDirectiveIndentation(ck.MkLines.indentation.Depth("include")) 242 ck.checkDirectiveIndentation(ck.MkLines.indentation.Depth("include"))
243 } 243 }
244 244
245 includedFile := mkline.IncludedFile() 245 includedFile := mkline.IncludedFile()
246 mustExist := mkline.MustExist() 246 mustExist := mkline.MustExist()
247 if trace.Tracing { 247 if trace.Tracing {
248 trace.Stepf("includingFile=%s includedFile=%s", mkline.Filename(), includedFile) 248 trace.Stepf("includingFile=%s includedFile=%s", mkline.Filename(), includedFile)
249 } 249 }
 250 if G.Pkgsrc == nil {
 251 return
 252 }
250 ck.CheckRelativePath(NewPackagePath(includedFile), includedFile, mustExist) 253 ck.CheckRelativePath(NewPackagePath(includedFile), includedFile, mustExist)
251 254
252 switch { 255 switch {
253 case includedFile.HasBase("Makefile"): 256 case includedFile.HasBase("Makefile"):
254 mkline.Errorf("Other Makefiles must not be included directly.") 257 mkline.Errorf("Other Makefiles must not be included directly.")
255 mkline.Explain( 258 mkline.Explain(
256 "To include portions of another Makefile, extract the common parts", 259 "To include portions of another Makefile, extract the common parts",
257 "and put them into a Makefile.common or a Makefile fragment called", 260 "and put them into a Makefile.common or a Makefile fragment called",
258 "module.mk or similar.", 261 "module.mk or similar.",
259 "After that, both this one and the other package should include the newly created file.") 262 "After that, both this one and the other package should include the newly created file.")
260 263
261 case mkline.Basename != "Makefile" && includedFile.HasBase("bsd.pkg.mk"): 264 case mkline.Basename != "Makefile" && includedFile.HasBase("bsd.pkg.mk"):
262 mkline.Errorf("The file bsd.pkg.mk must only be included by package Makefiles, not by other Makefile fragments.") 265 mkline.Errorf("The file bsd.pkg.mk must only be included by package Makefiles, not by other Makefile fragments.")

cvs diff -r1.76 -r1.77 pkgsrc/pkgtools/pkglint/files/Attic/mklines.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mklines.go 2022/10/02 15:11:19 1.76
+++ pkgsrc/pkgtools/pkglint/files/Attic/mklines.go 2023/03/02 08:58:29 1.77
@@ -52,27 +52,29 @@ type mklinesCheckAll struct { @@ -52,27 +52,29 @@ type mklinesCheckAll struct {
52 forVars map[string]bool 52 forVars map[string]bool
53 53
54 // Custom action that is run after checking each line 54 // Custom action that is run after checking each line
55 postLine func(mkline *MkLine) 55 postLine func(mkline *MkLine)
56} 56}
57 57
58func NewMkLines(lines *Lines, pkg *Package, extraScope *Scope) *MkLines { 58func NewMkLines(lines *Lines, pkg *Package, extraScope *Scope) *MkLines {
59 mklines := make([]*MkLine, lines.Len()) 59 mklines := make([]*MkLine, lines.Len())
60 for i, line := range lines.Lines { 60 for i, line := range lines.Lines {
61 mklines[i] = NewMkLineParser().Parse(line) 61 mklines[i] = NewMkLineParser().Parse(line)
62 } 62 }
63 63
64 tools := NewTools() 64 tools := NewTools()
65 tools.Fallback(G.Pkgsrc.Tools) 65 if G.Pkgsrc != nil {
 66 tools.Fallback(G.Pkgsrc.Tools)
 67 }
66 68
67 return &MkLines{ 69 return &MkLines{
68 mklines, 70 mklines,
69 lines, 71 lines,
70 pkg, 72 pkg,
71 extraScope, 73 extraScope,
72 NewScope(), 74 NewScope(),
73 make(map[string]bool), 75 make(map[string]bool),
74 make(map[string]*MkLine), 76 make(map[string]*MkLine),
75 make(map[string]*MkLine), 77 make(map[string]*MkLine),
76 false, 78 false,
77 tools, 79 tools,
78 nil, 80 nil,

cvs diff -r1.43 -r1.44 pkgsrc/pkgtools/pkglint/files/Attic/mkparser_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mkparser_test.go 2022/07/09 06:40:55 1.43
+++ pkgsrc/pkgtools/pkglint/files/Attic/mkparser_test.go 2023/03/02 08:58:29 1.44
@@ -292,26 +292,31 @@ func (s *Suite) Test_MkParser_MkCond(c * @@ -292,26 +292,31 @@ func (s *Suite) Test_MkParser_MkCond(c *
292 292
293 // Function calls need round parentheses instead of curly braces. 293 // Function calls need round parentheses instead of curly braces.
294 // As of July 2019, bmake silently accepts this wrong expression 294 // As of July 2019, bmake silently accepts this wrong expression
295 // and interprets it as !defined(empty{USE_CROSS_COMPILE:M[yY][eE][sS]}), 295 // and interprets it as !defined(empty{USE_CROSS_COMPILE:M[yY][eE][sS]}),
296 // which is always true, except if a variable of this strange name 296 // which is always true, except if a variable of this strange name
297 // were actually defined. 297 // were actually defined.
298 testRest("!empty{USE_CROSS_COMPILE:M[yY][eE][sS]}", 298 testRest("!empty{USE_CROSS_COMPILE:M[yY][eE][sS]}",
299 nil, 299 nil,
300 "empty{USE_CROSS_COMPILE:M[yY][eE][sS]}") 300 "empty{USE_CROSS_COMPILE:M[yY][eE][sS]}")
301 301
302 testRest("unknown(arg)", 302 testRest("unknown(arg)",
303 nil, 303 nil,
304 "unknown(arg)") 304 "unknown(arg)")
 305
 306 // The '!' is consumed by the parser.
 307 testRest("!",
 308 nil,
 309 "")
305} 310}
306 311
307func (s *Suite) Test_MkParser_mkCondCompare(c *check.C) { 312func (s *Suite) Test_MkParser_mkCondCompare(c *check.C) {
308 t := s.Init(c) 313 t := s.Init(c)
309 b := NewMkTokenBuilder() 314 b := NewMkTokenBuilder()
310 315
311 mkline := t.NewMkLine("Makefile", 123, ".if ${PKGPATH} == category/pack.age-3+") 316 mkline := t.NewMkLine("Makefile", 123, ".if ${PKGPATH} == category/pack.age-3+")
312 p := NewMkParser(mkline.Line, mkline.Args()) 317 p := NewMkParser(mkline.Line, mkline.Args())
313 cond := p.MkCond() 318 cond := p.MkCond()
314 319
315 t.CheckEquals(p.Rest(), "") 320 t.CheckEquals(p.Rest(), "")
316 t.CheckDeepEquals( 321 t.CheckDeepEquals(
317 cond, 322 cond,

cvs diff -r1.93 -r1.94 pkgsrc/pkgtools/pkglint/files/Attic/package_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/package_test.go 2023/01/29 13:36:31 1.93
+++ pkgsrc/pkgtools/pkglint/files/Attic/package_test.go 2023/03/02 08:58:29 1.94
@@ -3143,27 +3143,27 @@ func (s *Suite) Test_Package_pkgnameFrom @@ -3143,27 +3143,27 @@ func (s *Suite) Test_Package_pkgnameFrom
3143 "WARN: ~/category/package/Makefile:4: "+ 3143 "WARN: ~/category/package/Makefile:4: "+
3144 "Missing closing \"}\" for \"DISTNAME\".") 3144 "Missing closing \"}\" for \"DISTNAME\".")
3145 3145
3146 // Parse error with an unparseable rest. 3146 // Parse error with an unparseable rest.
3147 test("$", "package-1.0", "", 3147 test("$", "package-1.0", "",
3148 nil...) 3148 nil...)
3149} 3149}
3150 3150
3151func (s *Suite) Test_Package_checkPossibleDowngrade(c *check.C) { 3151func (s *Suite) Test_Package_checkPossibleDowngrade(c *check.C) {
3152 t := s.Init(c) 3152 t := s.Init(c)
3153 3153
3154 t.CreateFileLines("doc/CHANGES-2018", 3154 t.CreateFileLines("doc/CHANGES-2018",
3155 "\tUpdated category/pkgbase to 1.8 [committer 2018-01-05]") 3155 "\tUpdated category/pkgbase to 1.8 [committer 2018-01-05]")
3156 G.Pkgsrc.changes.load(&G.Pkgsrc) 3156 G.Pkgsrc.changes.load(G.Pkgsrc)
3157 3157
3158 t.Chdir("category/pkgbase") 3158 t.Chdir("category/pkgbase")
3159 pkg := NewPackage(".") 3159 pkg := NewPackage(".")
3160 pkg.EffectivePkgname = "package-1.0nb15" 3160 pkg.EffectivePkgname = "package-1.0nb15"
3161 pkg.EffectivePkgnameLine = t.NewMkLine("Makefile", 5, "PKGNAME=dummy") 3161 pkg.EffectivePkgnameLine = t.NewMkLine("Makefile", 5, "PKGNAME=dummy")
3162 3162
3163 pkg.checkPossibleDowngrade() 3163 pkg.checkPossibleDowngrade()
3164 3164
3165 t.CheckOutputLines( 3165 t.CheckOutputLines(
3166 "WARN: Makefile:5: The package is being downgraded from 1.8 (see ../../doc/CHANGES-2018:1) to 1.0nb15.") 3166 "WARN: Makefile:5: The package is being downgraded from 1.8 (see ../../doc/CHANGES-2018:1) to 1.0nb15.")
3167 3167
3168 G.Pkgsrc.changes.LastChange["category/pkgbase"].target = "1.0nb22" 3168 G.Pkgsrc.changes.LastChange["category/pkgbase"].target = "1.0nb22"
3169 3169

cvs diff -r1.47 -r1.48 pkgsrc/pkgtools/pkglint/files/Attic/patches.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/patches.go 2022/07/06 06:14:24 1.47
+++ pkgsrc/pkgtools/pkglint/files/Attic/patches.go 2023/03/02 08:58:29 1.48
@@ -173,28 +173,29 @@ func (ck *PatchChecker) checkUnifiedDiff @@ -173,28 +173,29 @@ func (ck *PatchChecker) checkUnifiedDiff
173 173
174 default: 174 default:
175 line.Errorf("Invalid line in unified patch hunk: %s", text) 175 line.Errorf("Invalid line in unified patch hunk: %s", text)
176 return 176 return
177 } 177 }
178 } 178 }
179 179
180 // When these two counts are equal, they may refer to context 180 // When these two counts are equal, they may refer to context
181 // lines that consist only of whitespace and have therefore 181 // lines that consist only of whitespace and have therefore
182 // been lost during transmission. There is no way to detect 182 // been lost during transmission. There is no way to detect
183 // this by looking only at the patch file. 183 // this by looking only at the patch file.
184 if linesToAdd != linesToDel { 184 if linesToAdd != linesToDel {
185 line := ck.llex.PreviousLine() 185 line := ck.llex.PreviousLine()
186 line.Warnf("Premature end of patch hunk (expected %d lines to be deleted and %d lines to be added).", 186 line.Warnf("Premature end of patch hunk (expected %d %s to be deleted and %d %s to be added).",
187 linesToDel, linesToAdd) 187 linesToDel, condStr(linesToDel != 1, "lines", "line"),
 188 linesToAdd, condStr(linesToAdd != 1, "lines", "line"))
188 } 189 }
189 } 190 }
190 191
191 if !hasHunks { 192 if !hasHunks {
192 ck.llex.CurrentLine().Errorf("No patch hunks for %q.", patchedFile.String()) 193 ck.llex.CurrentLine().Errorf("No patch hunks for %q.", patchedFile.String())
193 } 194 }
194 195
195 if !ck.llex.EOF() { 196 if !ck.llex.EOF() {
196 line := ck.llex.CurrentLine() 197 line := ck.llex.CurrentLine()
197 if !ck.isEmptyLine(line.Text) && !matches(line.Text, rePatchUniFileDel) { 198 if !ck.isEmptyLine(line.Text) && !matches(line.Text, rePatchUniFileDel) {
198 line.Warnf("Empty line or end of file expected.") 199 line.Warnf("Empty line or end of file expected.")
199 line.Explain( 200 line.Explain(
200 "This line is not part of the patch anymore, although it may look so.", 201 "This line is not part of the patch anymore, although it may look so.",

cvs diff -r1.87 -r1.88 pkgsrc/pkgtools/pkglint/files/Attic/pkglint.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/pkglint.go 2023/01/29 13:36:31 1.87
+++ pkgsrc/pkgtools/pkglint/files/Attic/pkglint.go 2023/03/02 08:58:29 1.88
@@ -22,27 +22,27 @@ const confVersion = "@VERSION@" @@ -22,27 +22,27 @@ const confVersion = "@VERSION@"
22type Pkglint struct { 22type Pkglint struct {
23 CheckGlobal bool 23 CheckGlobal bool
24 24
25 WarnExtra, 25 WarnExtra,
26 WarnPerm, 26 WarnPerm,
27 WarnQuoting bool 27 WarnQuoting bool
28 28
29 Profiling, 29 Profiling,
30 DumpMakefile, 30 DumpMakefile,
31 Import, 31 Import,
32 Network, 32 Network,
33 Recursive bool 33 Recursive bool
34 34
35 Pkgsrc Pkgsrc // Global data, mostly extracted from mk/*. 35 Pkgsrc *Pkgsrc // Global data, mostly extracted from mk/*.
36 36
37 Todo CurrPathQueue // The files or directories that still need to be checked. 37 Todo CurrPathQueue // The files or directories that still need to be checked.
38 38
39 Wip bool // Is the currently checked file or package from pkgsrc-wip? 39 Wip bool // Is the currently checked file or package from pkgsrc-wip?
40 Infrastructure bool // Is the currently checked file from the pkgsrc infrastructure? 40 Infrastructure bool // Is the currently checked file from the pkgsrc infrastructure?
41 Testing bool // Is pkglint in self-testing mode (only during development)? 41 Testing bool // Is pkglint in self-testing mode (only during development)?
42 Experimental bool // For experimental features, only enabled individually in tests 42 Experimental bool // For experimental features, only enabled individually in tests
43 Username string // For checking against OWNER and MAINTAINER 43 Username string // For checking against OWNER and MAINTAINER
44 44
45 cvsEntriesDir CurrPath // Cached to avoid I/O 45 cvsEntriesDir CurrPath // Cached to avoid I/O
46 cvsEntries map[RelPath]CvsEntry 46 cvsEntries map[RelPath]CvsEntry
47 47
48 Logger Logger 48 Logger Logger
@@ -180,43 +180,47 @@ func (p *Pkglint) setUpProfiling() func( @@ -180,43 +180,47 @@ func (p *Pkglint) setUpProfiling() func(
180 p.loaded.PrintStats(p.Logger.out.out, "loaded", 10) 180 p.loaded.PrintStats(p.Logger.out.out, "loaded", 10)
181 p.Logger.out.WriteLine(sprintf("fileCache: %d hits, %d misses", p.fileCache.hits, p.fileCache.misses)) 181 p.Logger.out.WriteLine(sprintf("fileCache: %d hits, %d misses", p.fileCache.hits, p.fileCache.misses))
182 }) 182 })
183 183
184 return func() { 184 return func() {
185 for i := range cleanups { 185 for i := range cleanups {
186 cleanups[len(cleanups)-1-i]() 186 cleanups[len(cleanups)-1-i]()
187 } 187 }
188 } 188 }
189} 189}
190 190
191func (p *Pkglint) prepareMainLoop() { 191func (p *Pkglint) prepareMainLoop() {
192 firstDir := p.Todo.Front() 192 firstDir := p.Todo.Front()
193 if firstDir.IsFile() { 193 isFile := firstDir.IsFile()
 194 if isFile {
194 firstDir = firstDir.Dir() 195 firstDir = firstDir.Dir()
195 } 196 }
196 197
197 relTopdir := p.findPkgsrcTopdir(firstDir) 198 relTopdir := p.findPkgsrcTopdir(firstDir)
198 if relTopdir.IsEmpty() { 199 if relTopdir.IsEmpty() {
199 // If the first argument to pkglint is not inside a pkgsrc tree, 200 // If the first argument to pkglint is not inside a pkgsrc tree,
200 // pkglint doesn't know where to load the infrastructure files from, 201 // pkglint doesn't know where to load the infrastructure files from.
201 // Since virtually every single check needs these files, 202 if isFile {
202 // the only sensible thing to do is to quit immediately. 203 // Allow this mode nevertheless, for checking the basic syntax
203 G.Logger.TechFatalf(firstDir, "Must be inside a pkgsrc tree.") 204 // and for formatting individual makefiles outside pkgsrc.
 205 } else {
 206 G.Logger.TechFatalf(firstDir, "Must be inside a pkgsrc tree.")
 207 }
 208 } else {
 209 p.Pkgsrc = NewPkgsrc(firstDir.JoinNoClean(relTopdir))
 210 p.Wip = p.Pkgsrc.IsWip(firstDir) // See Pkglint.checkMode.
 211 p.Pkgsrc.LoadInfrastructure()
204 } 212 }
205 213
206 p.Pkgsrc = NewPkgsrc(firstDir.JoinNoClean(relTopdir)) 
207 p.Wip = p.Pkgsrc.IsWip(firstDir) // See Pkglint.checkMode. 
208 p.Pkgsrc.LoadInfrastructure() 
209 
210 currentUser, err := user.Current() 214 currentUser, err := user.Current()
211 assertNil(err, "user.Current") 215 assertNil(err, "user.Current")
212 // On Windows, this is `Computername\Username`. 216 // On Windows, this is `Computername\Username`.
213 p.Username = replaceAll(currentUser.Username, `^.*\\`, "") 217 p.Username = replaceAll(currentUser.Username, `^.*\\`, "")
214} 218}
215 219
216func (p *Pkglint) ParseCommandLine(args []string) int { 220func (p *Pkglint) ParseCommandLine(args []string) int {
217 lopts := &p.Logger.Opts 221 lopts := &p.Logger.Opts
218 opts := getopt.NewOptions() 222 opts := getopt.NewOptions()
219 223
220 var showHelp bool 224 var showHelp bool
221 var showVersion bool 225 var showVersion bool
222 226
@@ -298,26 +302,31 @@ func (p *Pkglint) checkMode(dirent CurrP @@ -298,26 +302,31 @@ func (p *Pkglint) checkMode(dirent CurrP
298 // TODO: merge duplicate code in Package.checkDirent 302 // TODO: merge duplicate code in Package.checkDirent
299 isDir := mode.IsDir() 303 isDir := mode.IsDir()
300 isReg := mode.IsRegular() 304 isReg := mode.IsRegular()
301 if !isDir && !isReg { 305 if !isDir && !isReg {
302 NewLineWhole(dirent).Errorf("No such file or directory.") 306 NewLineWhole(dirent).Errorf("No such file or directory.")
303 return 307 return
304 } 308 }
305 309
306 dir := dirent 310 dir := dirent
307 if !isDir { 311 if !isDir {
308 dir = dirent.Dir() 312 dir = dirent.Dir()
309 } 313 }
310 314
 315 if isReg && p.Pkgsrc == nil {
 316 CheckFileMk(dirent, nil)
 317 return
 318 }
 319
311 pkgsrcRel := p.Pkgsrc.Rel(dirent) 320 pkgsrcRel := p.Pkgsrc.Rel(dirent)
312 321
313 p.Wip = pkgsrcRel.HasPrefixPath("wip") 322 p.Wip = pkgsrcRel.HasPrefixPath("wip")
314 p.Infrastructure = pkgsrcRel.HasPrefixPath("mk") || 323 p.Infrastructure = pkgsrcRel.HasPrefixPath("mk") ||
315 pkgsrcRel.HasPrefixPath("wip/mk") 324 pkgsrcRel.HasPrefixPath("wip/mk")
316 pkgsrcdir := p.findPkgsrcTopdir(dir) 325 pkgsrcdir := p.findPkgsrcTopdir(dir)
317 if pkgsrcdir.IsEmpty() { 326 if pkgsrcdir.IsEmpty() {
318 G.Logger.TechErrorf("", 327 G.Logger.TechErrorf("",
319 "Cannot determine the pkgsrc root directory for %q.", 328 "Cannot determine the pkgsrc root directory for %q.",
320 dirent) 329 dirent)
321 return 330 return
322 } 331 }
323 332

cvs diff -r1.73 -r1.74 pkgsrc/pkgtools/pkglint/files/Attic/pkglint_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/pkglint_test.go 2023/01/29 13:36:31 1.73
+++ pkgsrc/pkgtools/pkglint/files/Attic/pkglint_test.go 2023/03/02 08:58:29 1.74
@@ -234,27 +234,27 @@ func (s *Suite) Test_Pkglint_Main__compl @@ -234,27 +234,27 @@ func (s *Suite) Test_Pkglint_Main__compl
234 t.Main("-Wall", "-Call", "sysutils/checkperms") 234 t.Main("-Wall", "-Call", "sysutils/checkperms")
235 235
236 t.CheckOutputLines( 236 t.CheckOutputLines(
237 "NOTE: ~/sysutils/checkperms/Makefile:3: "+ 237 "NOTE: ~/sysutils/checkperms/Makefile:3: "+
238 "Package version \"1.11\" is greater than the latest \"1.10\" "+ 238 "Package version \"1.11\" is greater than the latest \"1.10\" "+
239 "from ../../doc/CHANGES-2018:5.", 239 "from ../../doc/CHANGES-2018:5.",
240 "WARN: ~/sysutils/checkperms/Makefile:3: "+ 240 "WARN: ~/sysutils/checkperms/Makefile:3: "+
241 "This package should be updated to 1.13 (supports more file formats; see ../../doc/TODO:5).", 241 "This package should be updated to 1.13 (supports more file formats; see ../../doc/TODO:5).",
242 "ERROR: ~/sysutils/checkperms/Makefile:4: Invalid category \"tools\".", 242 "ERROR: ~/sysutils/checkperms/Makefile:4: Invalid category \"tools\".",
243 "ERROR: ~/sysutils/checkperms/TODO: Packages in main pkgsrc must not have a TODO file.", 243 "ERROR: ~/sysutils/checkperms/TODO: Packages in main pkgsrc must not have a TODO file.",
244 "ERROR: ~/sysutils/checkperms/distinfo:6: SHA1 hash of patches/patch-checkperms.c differs "+ 244 "ERROR: ~/sysutils/checkperms/distinfo:6: SHA1 hash of patches/patch-checkperms.c differs "+
245 "(distinfo has asdfasdf, patch file has bcfb79696cb6bf4d2222a6d78a530e11bf1c0cea).", 245 "(distinfo has asdfasdf, patch file has bcfb79696cb6bf4d2222a6d78a530e11bf1c0cea).",
246 "WARN: ~/sysutils/checkperms/patches/patch-checkperms.c:12: Premature end of patch hunk "+ 246 "WARN: ~/sysutils/checkperms/patches/patch-checkperms.c:12: Premature end of patch hunk "+
247 "(expected 1 lines to be deleted and 0 lines to be added).", 247 "(expected 1 line to be deleted and 0 lines to be added).",
248 "3 errors, 2 warnings and 1 note found.", 248 "3 errors, 2 warnings and 1 note found.",
249 t.Shquote("(Run \"pkglint -e -Wall -Call %s\" to show explanations.)", "sysutils/checkperms"), 249 t.Shquote("(Run \"pkglint -e -Wall -Call %s\" to show explanations.)", "sysutils/checkperms"),
250 t.Shquote("(Run \"pkglint -fs -Wall -Call %s\" to show what can be fixed automatically.)", "sysutils/checkperms"), 250 t.Shquote("(Run \"pkglint -fs -Wall -Call %s\" to show what can be fixed automatically.)", "sysutils/checkperms"),
251 t.Shquote("(Run \"pkglint -F -Wall -Call %s\" to automatically fix some issues.)", "sysutils/checkperms")) 251 t.Shquote("(Run \"pkglint -F -Wall -Call %s\" to automatically fix some issues.)", "sysutils/checkperms"))
252} 252}
253 253
254func (s *Suite) Test_Pkglint_Main__autofix_exitcode(c *check.C) { 254func (s *Suite) Test_Pkglint_Main__autofix_exitcode(c *check.C) {
255 t := s.Init(c) 255 t := s.Init(c)
256 256
257 t.SetUpPkgsrc() 257 t.SetUpPkgsrc()
258 t.CreateFileLines("filename.mk", 258 t.CreateFileLines("filename.mk",
259 "") 259 "")
260 260

cvs diff -r1.69 -r1.70 pkgsrc/pkgtools/pkglint/files/Attic/pkgsrc.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/pkgsrc.go 2023/01/29 13:36:31 1.69
+++ pkgsrc/pkgtools/pkglint/files/Attic/pkgsrc.go 2023/03/02 08:58:29 1.70
@@ -37,28 +37,28 @@ type Pkgsrc struct { @@ -37,28 +37,28 @@ type Pkgsrc struct {
37 listVersions map[string][]string // See Pkgsrc.ListVersions 37 listVersions map[string][]string // See Pkgsrc.ListVersions
38 38
39 // Variables that may be overridden by the pkgsrc user. 39 // Variables that may be overridden by the pkgsrc user.
40 // They are typically defined in mk/defaults/mk.conf. 40 // They are typically defined in mk/defaults/mk.conf.
41 // 41 //
42 // Whenever a package uses such a variable, it must add the variable name 42 // Whenever a package uses such a variable, it must add the variable name
43 // to BUILD_DEFS. 43 // to BUILD_DEFS.
44 UserDefinedVars Scope 44 UserDefinedVars Scope
45 45
46 Deprecated map[string]string 46 Deprecated map[string]string
47 vartypes VarTypeRegistry 47 vartypes VarTypeRegistry
48} 48}
49 49
50func NewPkgsrc(dir CurrPath) Pkgsrc { 50func NewPkgsrc(dir CurrPath) *Pkgsrc {
51 return Pkgsrc{ 51 return &Pkgsrc{
52 dir, 52 dir,
53 make(map[string]bool), 53 make(map[string]bool),
54 NewTools(), 54 NewTools(),
55 make(map[string]string), 55 make(map[string]string),
56 make(map[string]string), 56 make(map[string]string),
57 make(map[string]string), 57 make(map[string]string),
58 nil, 58 nil,
59 nil, 59 nil,
60 Changes{}, 60 Changes{},
61 make(map[string][]string), 61 make(map[string][]string),
62 NewScope(), 62 NewScope(),
63 make(map[string]string), 63 make(map[string]string),
64 NewVarTypeRegistry()} 64 NewVarTypeRegistry()}
@@ -726,26 +726,29 @@ func (src *Pkgsrc) ListVersions(category @@ -726,26 +726,29 @@ func (src *Pkgsrc) ListVersions(category
726 var repls = make([]string, len(names)) 726 var repls = make([]string, len(names))
727 for i, name := range names { 727 for i, name := range names {
728 repls[i] = replaceAll(name, re, repl) 728 repls[i] = replaceAll(name, re, repl)
729 } 729 }
730 730
731 src.listVersions[cacheKey] = repls 731 src.listVersions[cacheKey] = repls
732 return repls 732 return repls
733} 733}
734 734
735// VariableType returns the type of the variable 735// VariableType returns the type of the variable
736// (possibly guessed based on the variable name), 736// (possibly guessed based on the variable name),
737// or nil if the type cannot even be guessed. 737// or nil if the type cannot even be guessed.
738func (src *Pkgsrc) VariableType(mklines *MkLines, varname string) (vartype *Vartype) { 738func (src *Pkgsrc) VariableType(mklines *MkLines, varname string) (vartype *Vartype) {
 739 if src == nil {
 740 return nil
 741 }
739 if trace.Tracing { 742 if trace.Tracing {
740 defer trace.Call(varname, trace.Result(&vartype))() 743 defer trace.Call(varname, trace.Result(&vartype))()
741 } 744 }
742 745
743 // When scanning mk/** for otherwise unknown variables, their type 746 // When scanning mk/** for otherwise unknown variables, their type
744 // is set to BtUnknown. These variables must not override the guess 747 // is set to BtUnknown. These variables must not override the guess
745 // based on the variable name. 748 // based on the variable name.
746 vartype = src.vartypes.Canon(varname) 749 vartype = src.vartypes.Canon(varname)
747 if vartype != nil && vartype.basicType != BtUnknown { 750 if vartype != nil && vartype.basicType != BtUnknown {
748 return vartype 751 return vartype
749 } 752 }
750 753
751 if tool := G.ToolByVarname(mklines, varname); tool != nil { 754 if tool := G.ToolByVarname(mklines, varname); tool != nil {

cvs diff -r1.10 -r1.11 pkgsrc/pkgtools/pkglint/files/Attic/var.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/var.go 2023/01/29 13:36:31 1.10
+++ pkgsrc/pkgtools/pkglint/files/Attic/var.go 2023/03/02 08:58:29 1.11
@@ -177,27 +177,27 @@ func (v *Var) Write(mkline *MkLine, cond @@ -177,27 +177,27 @@ func (v *Var) Write(mkline *MkLine, cond
177 v.writeLocations = append(v.writeLocations, mkline) 177 v.writeLocations = append(v.writeLocations, mkline)
178 178
179 if conditional { 179 if conditional {
180 v.conditional = true 180 v.conditional = true
181 } 181 }
182 v.conditionalVars.AddAll(conditionVarnames) 182 v.conditionalVars.AddAll(conditionVarnames)
183 183
184 mkline.ForEachUsed(func(varUse *MkVarUse, time VucTime) { 184 mkline.ForEachUsed(func(varUse *MkVarUse, time VucTime) {
185 v.refs.Add(varUse.varname) 185 v.refs.Add(varUse.varname)
186 }) 186 })
187 v.refs.AddAll(conditionVarnames) 187 v.refs.AddAll(conditionVarnames)
188 188
189 v.update(mkline, &v.valueInfra) 189 v.update(mkline, &v.valueInfra)
190 if !G.Pkgsrc.IsInfra(mkline.Line.Filename()) { 190 if G.Pkgsrc != nil && !G.Pkgsrc.IsInfra(mkline.Line.Filename()) {
191 v.update(mkline, &v.value) 191 v.update(mkline, &v.value)
192 } 192 }
193 193
194 v.updateConstantValue(mkline) 194 v.updateConstantValue(mkline)
195} 195}
196 196
197func (v *Var) update(mkline *MkLine, update *string) { 197func (v *Var) update(mkline *MkLine, update *string) {
198 firstWrite := len(v.writeLocations) == 1 198 firstWrite := len(v.writeLocations) == 1
199 if v.IsConditional() && !firstWrite { 199 if v.IsConditional() && !firstWrite {
200 return 200 return
201 } 201 }
202 202
203 value := mkline.Value() 203 value := mkline.Value()

cvs diff -r1.29 -r1.30 pkgsrc/pkgtools/pkglint/files/Attic/vardefs_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/vardefs_test.go 2020/06/07 15:49:23 1.29
+++ pkgsrc/pkgtools/pkglint/files/Attic/vardefs_test.go 2023/03/02 08:58:29 1.30
@@ -31,27 +31,27 @@ func (s *Suite) Test_VarTypeRegistry_com @@ -31,27 +31,27 @@ func (s *Suite) Test_VarTypeRegistry_com
31 ".if ${USE_LANGUAGES:Mexpr-lang} || !empty(USE_LANGUAGES:Mempty-lang)", 31 ".if ${USE_LANGUAGES:Mexpr-lang} || !empty(USE_LANGUAGES:Mempty-lang)",
32 ".endif", 32 ".endif",
33 "", 33 "",
34 // Just for code coverage 34 // Just for code coverage
35 ".if ${OTHER} || ${USE_LANGUAGES} \\", 35 ".if ${OTHER} || ${USE_LANGUAGES} \\",
36 " || ${USE_LANGUAGES:O} || ${USE_LANGUAGES:Mc++-*}", 36 " || ${USE_LANGUAGES:O} || ${USE_LANGUAGES:Mc++-*}",
37 ".endif", 37 ".endif",
38 "", 38 "",
39 // Just for code coverage 39 // Just for code coverage
40 ".if", // missing condition 40 ".if", // missing condition
41 ".endif") 41 ".endif")
42 reg := NewVarTypeRegistry() 42 reg := NewVarTypeRegistry()
43 43
44 compilerLanguages := reg.compilerLanguages(&G.Pkgsrc) 44 compilerLanguages := reg.compilerLanguages(G.Pkgsrc)
45 45
46 enumValues := compilerLanguages.AllowedEnums() 46 enumValues := compilerLanguages.AllowedEnums()
47 t.CheckEquals(enumValues, "empty-lang expr-lang gnu++14") 47 t.CheckEquals(enumValues, "empty-lang expr-lang gnu++14")
48} 48}
49 49
50func (s *Suite) Test_VarTypeRegistry_enumFrom(c *check.C) { 50func (s *Suite) Test_VarTypeRegistry_enumFrom(c *check.C) {
51 t := s.Init(c) 51 t := s.Init(c)
52 52
53 t.CreateFileLines("editors/emacs/modules.mk", 53 t.CreateFileLines("editors/emacs/modules.mk",
54 MkCvsID, 54 MkCvsID,
55 "", 55 "",
56 "_EMACS_VERSIONS_ALL= emacs31", 56 "_EMACS_VERSIONS_ALL= emacs31",
57 "_EMACS_VERSIONS_ALL+= emacs29") 57 "_EMACS_VERSIONS_ALL+= emacs29")
@@ -91,29 +91,29 @@ func (s *Suite) Test_VarTypeRegistry_enu @@ -91,29 +91,29 @@ func (s *Suite) Test_VarTypeRegistry_enu
91 "gnu++03 gnu++0x gnu++11 gnu++14 (list, package-settable)") 91 "gnu++03 gnu++0x gnu++11 gnu++14 (list, package-settable)")
92 test("PKGSRC_COMPILER", "enum: ccache distcc f2c g95 gcc ido mipspro-ucode sunpro (list, user-settable)") 92 test("PKGSRC_COMPILER", "enum: ccache distcc f2c g95 gcc ido mipspro-ucode sunpro (list, user-settable)")
93} 93}
94 94
95func (s *Suite) Test_VarTypeRegistry_enumFrom__no_tracing(c *check.C) { 95func (s *Suite) Test_VarTypeRegistry_enumFrom__no_tracing(c *check.C) {
96 t := s.Init(c) 96 t := s.Init(c)
97 97
98 t.CreateFileLines("mk/existing.mk", 98 t.CreateFileLines("mk/existing.mk",
99 MkCvsID, 99 MkCvsID,
100 "VAR=\tfirst second") 100 "VAR=\tfirst second")
101 reg := NewVarTypeRegistry() 101 reg := NewVarTypeRegistry()
102 t.DisableTracing() 102 t.DisableTracing()
103 103
104 existingType := reg.enumFrom(&G.Pkgsrc, "mk/existing.mk", "defval", "VAR") 104 existingType := reg.enumFrom(G.Pkgsrc, "mk/existing.mk", "defval", "VAR")
105 noAssignmentsType := reg.enumFrom(&G.Pkgsrc, "mk/existing.mk", "defval", "OTHER_VAR") 105 noAssignmentsType := reg.enumFrom(G.Pkgsrc, "mk/existing.mk", "defval", "OTHER_VAR")
106 nonexistentType := reg.enumFrom(&G.Pkgsrc, "mk/nonexistent.mk", "defval", "VAR") 106 nonexistentType := reg.enumFrom(G.Pkgsrc, "mk/nonexistent.mk", "defval", "VAR")
107 107
108 t.CheckEquals(existingType.AllowedEnums(), "first second") 108 t.CheckEquals(existingType.AllowedEnums(), "first second")
109 t.CheckEquals(noAssignmentsType.AllowedEnums(), "defval") 109 t.CheckEquals(noAssignmentsType.AllowedEnums(), "defval")
110 t.CheckEquals(nonexistentType.AllowedEnums(), "defval") 110 t.CheckEquals(nonexistentType.AllowedEnums(), "defval")
111} 111}
112 112
113func (s *Suite) Test_VarTypeRegistry_enumFrom__no_testing(c *check.C) { 113func (s *Suite) Test_VarTypeRegistry_enumFrom__no_testing(c *check.C) {
114 t := s.Init(c) 114 t := s.Init(c)
115 115
116 G.Testing = false 116 G.Testing = false
117 117
118 t.ExpectFatal( 118 t.ExpectFatal(
119 t.SetUpVartypes, 119 t.SetUpVartypes,
@@ -152,27 +152,27 @@ func (s *Suite) Test_VarTypeRegistry_enu @@ -152,27 +152,27 @@ func (s *Suite) Test_VarTypeRegistry_enu
152 } 152 }
153 153
154 test("PYPKGPREFIX", "enum: py28 py33 (system-provided)") 154 test("PYPKGPREFIX", "enum: py28 py33 (system-provided)")
155} 155}
156 156
157func (s *Suite) Test_VarTypeRegistry_enumFromDirs__no_testing(c *check.C) { 157func (s *Suite) Test_VarTypeRegistry_enumFromDirs__no_testing(c *check.C) {
158 t := s.Init(c) 158 t := s.Init(c)
159 159
160 G.Testing = false 160 G.Testing = false
161 161
162 t.ExpectFatal( 162 t.ExpectFatal(
163 func() { 163 func() {
164 G.Pkgsrc.vartypes.enumFromDirs( 164 G.Pkgsrc.vartypes.enumFromDirs(
165 &G.Pkgsrc, "category", `^pack.*`, "$0", "default") 165 G.Pkgsrc, "category", `^pack.*`, "$0", "default")
166 }, 166 },
167 "FATAL: ~/category: Must contain at least 1 "+ 167 "FATAL: ~/category: Must contain at least 1 "+
168 "subdirectory matching \"^pack.*\".") 168 "subdirectory matching \"^pack.*\".")
169} 169}
170 170
171func (s *Suite) Test_VarTypeRegistry_enumFromFiles(c *check.C) { 171func (s *Suite) Test_VarTypeRegistry_enumFromFiles(c *check.C) {
172 t := s.Init(c) 172 t := s.Init(c)
173 173
174 t.CreateFileLines("mk/platform/NetBSD.mk") 174 t.CreateFileLines("mk/platform/NetBSD.mk")
175 t.CreateFileLines("mk/platform/README") 175 t.CreateFileLines("mk/platform/README")
176 t.CreateFileLines("mk/platform/SunOS.mk") 176 t.CreateFileLines("mk/platform/SunOS.mk")
177 t.CreateFileLines("mk/platform/SunOS.mk~") 177 t.CreateFileLines("mk/platform/SunOS.mk~")
178 178
@@ -183,50 +183,50 @@ func (s *Suite) Test_VarTypeRegistry_enu @@ -183,50 +183,50 @@ func (s *Suite) Test_VarTypeRegistry_enu
183 t.CheckEquals(vartype, values) 183 t.CheckEquals(vartype, values)
184 } 184 }
185 185
186 test("OPSYS", "enum: NetBSD SunOS (system-provided)") 186 test("OPSYS", "enum: NetBSD SunOS (system-provided)")
187} 187}
188 188
189func (s *Suite) Test_VarTypeRegistry_enumFromFiles__no_testing(c *check.C) { 189func (s *Suite) Test_VarTypeRegistry_enumFromFiles__no_testing(c *check.C) {
190 t := s.Init(c) 190 t := s.Init(c)
191 191
192 G.Testing = false 192 G.Testing = false
193 193
194 t.ExpectFatal( 194 t.ExpectFatal(
195 func() { 195 func() {
196 G.Pkgsrc.vartypes.enumFromFiles(&G.Pkgsrc, 196 G.Pkgsrc.vartypes.enumFromFiles(G.Pkgsrc,
197 "mk/platform", `^(\w+)\.mk$`, "$1", "default") 197 "mk/platform", `^(\w+)\.mk$`, "$1", "default")
198 }, 198 },
199 "FATAL: ~/mk/platform: Must contain at least 1 "+ 199 "FATAL: ~/mk/platform: Must contain at least 1 "+
200 "file matching \"^(\\\\w+)\\\\.mk$\".") 200 "file matching \"^(\\\\w+)\\\\.mk$\".")
201} 201}
202 202
203func (s *Suite) Test_VarTypeRegistry_options__assertion(c *check.C) { 203func (s *Suite) Test_VarTypeRegistry_options__assertion(c *check.C) {
204 t := s.Init(c) 204 t := s.Init(c)
205 205
206 reg := NewVarTypeRegistry() 206 reg := NewVarTypeRegistry()
207 207
208 t.ExpectAssert(func() { 208 t.ExpectAssert(func() {
209 reg.options( 209 reg.options(
210 SystemProvided, 210 SystemProvided,
211 []vartypeOptions{DefinedIfInScope, NonemptyIfDefined}) 211 []vartypeOptions{DefinedIfInScope, NonemptyIfDefined})
212 }) 212 })
213} 213}
214 214
215func (s *Suite) Test_VarTypeRegistry_Init(c *check.C) { 215func (s *Suite) Test_VarTypeRegistry_Init(c *check.C) {
216 t := s.Init(c) 216 t := s.Init(c)
217 217
218 src := NewPkgsrc(t.File(".")) 218 src := NewPkgsrc(t.File("."))
219 src.vartypes.Init(&src) 219 src.vartypes.Init(src)
220 220
221 t.CheckEquals(src.vartypes.Canon("BSD_MAKE_ENV").basicType.name, "ShellWord") 221 t.CheckEquals(src.vartypes.Canon("BSD_MAKE_ENV").basicType.name, "ShellWord")
222 t.CheckEquals(src.vartypes.Canon("USE_BUILTIN.*").basicType.name, "YesNoIndirectly") 222 t.CheckEquals(src.vartypes.Canon("USE_BUILTIN.*").basicType.name, "YesNoIndirectly")
223} 223}
224 224
225func (s *Suite) Test_VarTypeRegistry_Init__LP64PLATFORMS(c *check.C) { 225func (s *Suite) Test_VarTypeRegistry_Init__LP64PLATFORMS(c *check.C) {
226 t := s.Init(c) 226 t := s.Init(c)
227 227
228 pkg := t.SetUpPackage("category/package", 228 pkg := t.SetUpPackage("category/package",
229 "BROKEN_ON_PLATFORM=\t${LP64PLATFORMS}") 229 "BROKEN_ON_PLATFORM=\t${LP64PLATFORMS}")
230 t.FinishSetUp() 230 t.FinishSetUp()
231 231
232 G.Check(pkg) 232 G.Check(pkg)