pkgsrc-Changes archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
CVS commit: pkgsrc/pkgtools/pkglint
Module Name: pkgsrc
Committed By: rillig
Date: Tue Oct 1 21:38:00 UTC 2019
Modified Files:
pkgsrc/pkgtools/pkglint: Makefile
pkgsrc/pkgtools/pkglint/files: alternatives.go category.go
check_test.go distinfo.go distinfo_test.go licenses_test.go
logging.go logging_test.go mkline.go mkline_test.go
mklinechecker.go mklinechecker_test.go mklines_test.go mkparser.go
mkparser_test.go mktokenslexer.go mktokenslexer_test.go
mktypes_test.go package.go package_test.go pkglint.go
pkglint_test.go pkgsrc.go pkgsrc_test.go shell.go shell_test.go
substcontext.go tools_test.go toplevel.go toplevel_test.go util.go
util_test.go vardefs.go vargroups.go vargroups_test.go vartype.go
vartypecheck.go vartypecheck_test.go
pkgsrc/pkgtools/pkglint/files/textproc: lexer.go lexer_test.go
Log Message:
pkgtools/pkglint: update to 19.3.0
Changes since 5.7.24:
* There is no need to ask the dummy MAINTAINER from url2pkg whether
committing changes is ok.
* When autofixing a condition like !empty(PKGPATH:Mliteral), don't
generate unnecessary parentheses around ${PKGPATH} == literal.
* In a _VARGROUPS section, the public variables should be listed
before the private variables, to put important things first.
* When pkglint suggests to be run again with the -e, -fs or -F options,
repeat the whole command line, to allow for copy-and-paste.
* The checks for PKGPATH are fixed and enhanced. It is not a relative
path like in ../../category/package, but relative to the pkgsrc root.
* Unintended file globbing in sed commands such as s,.*,any, gets a
warning.
* MASTER_SITES should normally end with a slash, in rare cases an
equals sign or a colon are correct, too.
* Detect redundant directories in INSTALLATION_DIRS.
To generate a diff of this commit:
cvs rdiff -u -r1.598 -r1.599 pkgsrc/pkgtools/pkglint/Makefile
cvs rdiff -u -r1.13 -r1.14 pkgsrc/pkgtools/pkglint/files/alternatives.go \
pkgsrc/pkgtools/pkglint/files/mktypes_test.go
cvs rdiff -u -r1.21 -r1.22 pkgsrc/pkgtools/pkglint/files/category.go
cvs rdiff -u -r1.48 -r1.49 pkgsrc/pkgtools/pkglint/files/check_test.go \
pkgsrc/pkgtools/pkglint/files/mklines_test.go
cvs rdiff -u -r1.35 -r1.36 pkgsrc/pkgtools/pkglint/files/distinfo.go \
pkgsrc/pkgtools/pkglint/files/pkgsrc.go
cvs rdiff -u -r1.32 -r1.33 pkgsrc/pkgtools/pkglint/files/distinfo_test.go \
pkgsrc/pkgtools/pkglint/files/mkparser_test.go
cvs rdiff -u -r1.23 -r1.24 pkgsrc/pkgtools/pkglint/files/licenses_test.go
cvs rdiff -u -r1.27 -r1.28 pkgsrc/pkgtools/pkglint/files/logging.go \
pkgsrc/pkgtools/pkglint/files/substcontext.go
cvs rdiff -u -r1.20 -r1.21 pkgsrc/pkgtools/pkglint/files/logging_test.go \
pkgsrc/pkgtools/pkglint/files/toplevel.go
cvs rdiff -u -r1.58 -r1.59 pkgsrc/pkgtools/pkglint/files/mkline.go
cvs rdiff -u -r1.67 -r1.68 pkgsrc/pkgtools/pkglint/files/mkline_test.go
cvs rdiff -u -r1.46 -r1.47 pkgsrc/pkgtools/pkglint/files/mklinechecker.go
cvs rdiff -u -r1.42 -r1.43 \
pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go
cvs rdiff -u -r1.33 -r1.34 pkgsrc/pkgtools/pkglint/files/mkparser.go \
pkgsrc/pkgtools/pkglint/files/util_test.go
cvs rdiff -u -r1.1 -r1.2 pkgsrc/pkgtools/pkglint/files/mktokenslexer.go
cvs rdiff -u -r1.3 -r1.4 pkgsrc/pkgtools/pkglint/files/mktokenslexer_test.go
cvs rdiff -u -r1.62 -r1.63 pkgsrc/pkgtools/pkglint/files/package.go \
pkgsrc/pkgtools/pkglint/files/vartypecheck.go
cvs rdiff -u -r1.53 -r1.54 pkgsrc/pkgtools/pkglint/files/package_test.go
cvs rdiff -u -r1.60 -r1.61 pkgsrc/pkgtools/pkglint/files/pkglint.go
cvs rdiff -u -r1.47 -r1.48 pkgsrc/pkgtools/pkglint/files/pkglint_test.go
cvs rdiff -u -r1.29 -r1.30 pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go
cvs rdiff -u -r1.45 -r1.46 pkgsrc/pkgtools/pkglint/files/shell.go
cvs rdiff -u -r1.52 -r1.53 pkgsrc/pkgtools/pkglint/files/shell_test.go \
pkgsrc/pkgtools/pkglint/files/util.go
cvs rdiff -u -r1.19 -r1.20 pkgsrc/pkgtools/pkglint/files/tools_test.go \
pkgsrc/pkgtools/pkglint/files/toplevel_test.go
cvs rdiff -u -r1.72 -r1.73 pkgsrc/pkgtools/pkglint/files/vardefs.go
cvs rdiff -u -r1.2 -r1.3 pkgsrc/pkgtools/pkglint/files/vargroups.go \
pkgsrc/pkgtools/pkglint/files/vargroups_test.go
cvs rdiff -u -r1.36 -r1.37 pkgsrc/pkgtools/pkglint/files/vartype.go
cvs rdiff -u -r1.54 -r1.55 pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go
cvs rdiff -u -r1.5 -r1.6 pkgsrc/pkgtools/pkglint/files/textproc/lexer.go \
pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: pkgsrc/pkgtools/pkglint/Makefile
diff -u pkgsrc/pkgtools/pkglint/Makefile:1.598 pkgsrc/pkgtools/pkglint/Makefile:1.599
--- pkgsrc/pkgtools/pkglint/Makefile:1.598 Thu Sep 26 20:10:51 2019
+++ pkgsrc/pkgtools/pkglint/Makefile Tue Oct 1 21:37:59 2019
@@ -1,7 +1,6 @@
-# $NetBSD: Makefile,v 1.598 2019/09/26 20:10:51 bsiegert Exp $
+# $NetBSD: Makefile,v 1.599 2019/10/01 21:37:59 rillig Exp $
-PKGNAME= pkglint-5.7.24
-PKGREVISION= 1
+PKGNAME= pkglint-19.3.0
CATEGORIES= pkgtools
DISTNAME= tools
MASTER_SITES= ${MASTER_SITE_GITHUB:=golang/}
Index: pkgsrc/pkgtools/pkglint/files/alternatives.go
diff -u pkgsrc/pkgtools/pkglint/files/alternatives.go:1.13 pkgsrc/pkgtools/pkglint/files/alternatives.go:1.14
--- pkgsrc/pkgtools/pkglint/files/alternatives.go:1.13 Sun Jul 14 21:25:47 2019
+++ pkgsrc/pkgtools/pkglint/files/alternatives.go Tue Oct 1 21:37:59 2019
@@ -49,7 +49,7 @@ func CheckFileAlternatives(filename stri
if !m {
line.Errorf("Invalid line %q.", line.Text)
line.Explain(
- sprintf("Run %q for more information.", makeHelp("alternatives")))
+ sprintf("Run %q for more information.", bmakeHelp("alternatives")))
continue
}
Index: pkgsrc/pkgtools/pkglint/files/mktypes_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mktypes_test.go:1.13 pkgsrc/pkgtools/pkglint/files/mktypes_test.go:1.14
--- pkgsrc/pkgtools/pkglint/files/mktypes_test.go:1.13 Sun Jul 14 21:25:47 2019
+++ pkgsrc/pkgtools/pkglint/files/mktypes_test.go Tue Oct 1 21:37:59 2019
@@ -99,7 +99,7 @@ func (s *Suite) Test_MkVarUseModifier_Ma
t.CheckEquals(ok, true)
t.CheckEquals(regex, false)
- t.CheckEquals(from, "\\/")
+ t.CheckEquals(from, "/")
t.CheckEquals(to, "\\:")
t.CheckEquals(options, "")
}
Index: pkgsrc/pkgtools/pkglint/files/category.go
diff -u pkgsrc/pkgtools/pkglint/files/category.go:1.21 pkgsrc/pkgtools/pkglint/files/category.go:1.22
--- pkgsrc/pkgtools/pkglint/files/category.go:1.21 Sun Jul 14 21:25:47 2019
+++ pkgsrc/pkgtools/pkglint/files/category.go Tue Oct 1 21:37:59 2019
@@ -158,7 +158,7 @@ func CheckdirCategory(dir string) {
var recurseInto []string
for _, msub := range mSubdirs {
if !msub.line.IsCommentedVarassign() {
- recurseInto = append(recurseInto, dir+"/"+msub.name)
+ recurseInto = append(recurseInto, joinPath(dir, msub.name))
}
}
G.Todo = append(recurseInto, G.Todo...)
Index: pkgsrc/pkgtools/pkglint/files/check_test.go
diff -u pkgsrc/pkgtools/pkglint/files/check_test.go:1.48 pkgsrc/pkgtools/pkglint/files/check_test.go:1.49
--- pkgsrc/pkgtools/pkglint/files/check_test.go:1.48 Sun Aug 25 21:44:37 2019
+++ pkgsrc/pkgtools/pkglint/files/check_test.go Tue Oct 1 21:37:59 2019
@@ -125,6 +125,7 @@ func Test(t *testing.T) { check.TestingT
type Tester struct {
c *check.C // Only usable during the test method itself
testName string
+ argv []string // from the last invocation of Tester.SetUpCommandLine
stdout bytes.Buffer
stderr bytes.Buffer
@@ -149,7 +150,9 @@ func (t *Tester) SetUpCommandLine(args .
prevTracing := trace.Tracing
defer func() { trace.Tracing = prevTracing }()
- exitcode := G.ParseCommandLine(append([]string{"pkglint"}, args...))
+ argv := append([]string{"pkglint"}, args...)
+ t.argv = argv
+ exitcode := G.ParseCommandLine(argv)
if exitcode != -1 && exitcode != 0 {
t.CheckOutputEmpty()
t.c.Fatalf("Cannot parse command line: %#v", args)
@@ -516,7 +519,7 @@ func (t *Tester) File(relativeFileName s
if t.relCwd != "" {
return path.Clean(relativeFileName)
}
- return path.Clean(t.tmpdir + "/" + relativeFileName)
+ return path.Clean(joinPath(t.tmpdir, relativeFileName))
}
// Copy copies a file inside the temporary directory.
@@ -1155,3 +1158,12 @@ func (t *Tester) CheckFileLinesDetab(rel
// development.
func (t *Tester) Use(functions ...interface{}) {
}
+
+func (t *Tester) Shquote(format string, rels ...string) string {
+ var subs []interface{}
+ for _, rel := range rels {
+ quoted := shquote(path.Join(t.tmpdir, rel))
+ subs = append(subs, strings.Replace(quoted, t.tmpdir, "~", -1))
+ }
+ return sprintf(format, subs...)
+}
Index: pkgsrc/pkgtools/pkglint/files/mklines_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.48 pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.49
--- pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.48 Tue Jul 30 18:16:13 2019
+++ pkgsrc/pkgtools/pkglint/files/mklines_test.go Tue Oct 1 21:37:59 2019
@@ -716,6 +716,7 @@ func (s *Suite) Test_MkLines_Check__inde
mklines.Check()
t.CheckOutputLines(
+ "ERROR: ~/module.mk:3: There is no package in \"category/package\".",
"NOTE: ~/module.mk:5: This directive should be indented by 2 spaces.",
"NOTE: ~/module.mk:7: This directive should be indented by 2 spaces.")
}
Index: pkgsrc/pkgtools/pkglint/files/distinfo.go
diff -u pkgsrc/pkgtools/pkglint/files/distinfo.go:1.35 pkgsrc/pkgtools/pkglint/files/distinfo.go:1.36
--- pkgsrc/pkgtools/pkglint/files/distinfo.go:1.35 Sun Jun 30 20:56:19 2019
+++ pkgsrc/pkgtools/pkglint/files/distinfo.go Tue Oct 1 21:37:59 2019
@@ -67,7 +67,7 @@ func (ck *distinfoLinesChecker) parse()
return no
case ck.pkg == nil:
return unknown
- case fileExists(ck.pkg.File(ck.patchdir + "/" + prevFilename)):
+ case fileExists(ck.pkg.File(joinPath(ck.patchdir, prevFilename))):
return yes
default:
return no
@@ -195,7 +195,7 @@ func (ck *distinfoLinesChecker) checkAlg
distdir := G.Pkgsrc.File("distfiles")
- distfile := cleanpath(distdir + "/" + info.filename())
+ distfile := cleanpath(joinPath(distdir, info.filename()))
if !fileExists(distfile) {
// It's a rare situation that the explanation is generated
@@ -315,7 +315,7 @@ func (ck *distinfoLinesChecker) checkUnr
if file.Mode().IsRegular() && ck.infos[patchName].isPatch != yes && hasPrefix(patchName, "patch-") {
line := NewLineWhole(ck.lines.Filename)
line.Errorf("Patch %q is not recorded. Run %q.",
- line.PathToFile(ck.pkg.File(ck.patchdir+"/"+patchName)),
+ line.PathToFile(ck.pkg.File(joinPath(ck.patchdir, patchName))),
bmake("makepatchsum"))
}
}
@@ -371,7 +371,7 @@ func (ck *distinfoLinesChecker) checkUnc
hash := info.hash
line := info.line
- patchFileName := ck.patchdir + "/" + patchName
+ patchFileName := joinPath(ck.patchdir, patchName)
resolvedPatchFileName := ck.pkg.File(patchFileName)
if ck.distinfoIsCommitted && !isCommitted(resolvedPatchFileName) {
line.Warnf("%s is registered in distinfo but not added to CVS.", line.PathToFile(resolvedPatchFileName))
Index: pkgsrc/pkgtools/pkglint/files/pkgsrc.go
diff -u pkgsrc/pkgtools/pkglint/files/pkgsrc.go:1.35 pkgsrc/pkgtools/pkglint/files/pkgsrc.go:1.36
--- pkgsrc/pkgtools/pkglint/files/pkgsrc.go:1.35 Sun Sep 8 22:47:47 2019
+++ pkgsrc/pkgtools/pkglint/files/pkgsrc.go Tue Oct 1 21:37:59 2019
@@ -264,7 +264,7 @@ func (src *Pkgsrc) checkToplevelUnusedLi
for _, licenseFile := range src.ReadDir("licenses") {
licenseName := licenseFile.Name()
if !G.InterPackage.LicenseUsed(licenseName) {
- licensePath := licensesDir + "/" + licenseName
+ licensePath := joinPath(licensesDir, licenseName)
NewLineWhole(licensePath).Warnf("This license seems to be unused.")
}
}
@@ -597,7 +597,7 @@ func (src *Pkgsrc) loadDocChanges() {
src.LastChange = make(map[string]*Change)
for _, filename := range filenames {
- changes := src.loadDocChangesFromFile(docDir + "/" + filename)
+ changes := src.loadDocChangesFromFile(joinPath(docDir, filename))
for _, change := range changes {
src.LastChange[change.Pkgpath] = change
if change.Action == Renamed || change.Action == Moved {
@@ -841,7 +841,7 @@ func (src *Pkgsrc) ReadDir(dirName strin
var relevantFiles []os.FileInfo
for _, dirent := range files {
name := dirent.Name()
- if !dirent.IsDir() || !isIgnoredFilename(name) && !isEmptyDir(dir+"/"+name) {
+ if !dirent.IsDir() || !isIgnoredFilename(name) && !isEmptyDir(joinPath(dir, name)) {
relevantFiles = append(relevantFiles, dirent)
}
}
@@ -855,7 +855,7 @@ func (src *Pkgsrc) ReadDir(dirName strin
// NewPkgsrc("/usr/pkgsrc").File("distfiles") => "/usr/pkgsrc/distfiles"
func (src *Pkgsrc) File(relativeName string) string {
// TODO: Package.File resolves variables, Pkgsrc.File doesn't. They should behave the same.
- return cleanpath(src.topdir + "/" + relativeName)
+ return cleanpath(joinPath(src.topdir, relativeName))
}
// ToRel returns the path of `filename`, relative to the pkgsrc top directory.
@@ -988,12 +988,12 @@ func (src *Pkgsrc) guessVariableType(var
varbase := varnameBase(varname)
switch {
case hasSuffix(varbase, "DIRS"):
- return listType(BtPathmask, aclpAllRuntime)
+ return listType(BtPathPattern, aclpAllRuntime)
case hasSuffix(varbase, "DIR") && !hasSuffix(varbase, "DESTDIR"), hasSuffix(varname, "_HOME"):
// TODO: hasSuffix(varbase, "BASE")
return plainType(BtPathname, aclpAllRuntime)
case hasSuffix(varbase, "FILES"):
- return listType(BtPathmask, aclpAllRuntime)
+ return listType(BtPathPattern, aclpAllRuntime)
case hasSuffix(varbase, "FILE"):
return plainType(BtPathname, aclpAllRuntime)
case hasSuffix(varbase, "PATH"):
@@ -1020,7 +1020,7 @@ func (src *Pkgsrc) guessVariableType(var
// TODO: Add BtGuard for inclusion guards, since these variables may only be checked using defined().
return plainType(BtUnknown, aclpAll)
case hasSuffix(varbase, "_SKIP"):
- return listType(BtPathmask, aclpAllRuntime)
+ return listType(BtPathPattern, aclpAllRuntime)
}
// Variables whose name doesn't match the above patterns may be
Index: pkgsrc/pkgtools/pkglint/files/distinfo_test.go
diff -u pkgsrc/pkgtools/pkglint/files/distinfo_test.go:1.32 pkgsrc/pkgtools/pkglint/files/distinfo_test.go:1.33
--- pkgsrc/pkgtools/pkglint/files/distinfo_test.go:1.32 Sun Jul 14 21:25:47 2019
+++ pkgsrc/pkgtools/pkglint/files/distinfo_test.go Tue Oct 1 21:37:59 2019
@@ -177,7 +177,7 @@ func (s *Suite) Test_distinfoLinesChecke
"",
".include \"../mk/misc/category.mk\"")
- t.Main("-r", "-Wall", "-Call", t.File("."))
+ t.Main("-r", "-Wall", "-Call", ".")
t.CheckOutputLines(
"ERROR: ~/category/package1/distinfo:3: "+
@@ -201,7 +201,7 @@ func (s *Suite) Test_distinfoLinesChecke
"WARN: ~/licenses/gnu-gpl-v2: This license seems to be unused.",
"8 errors and 1 warning found.",
- "(Run \"pkglint -e\" to show explanations.)")
+ t.Shquote("(Run \"pkglint -e -r -Wall -Call %s\" to show explanations.)", "."))
// Ensure that hex.DecodeString does not waste memory here.
t.CheckEquals(len(G.InterPackage.hashes["SHA512:distfile-1.0.tar.gz"].hash), 8)
Index: pkgsrc/pkgtools/pkglint/files/mkparser_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mkparser_test.go:1.32 pkgsrc/pkgtools/pkglint/files/mkparser_test.go:1.33
--- pkgsrc/pkgtools/pkglint/files/mkparser_test.go:1.32 Sun Sep 8 22:47:47 2019
+++ pkgsrc/pkgtools/pkglint/files/mkparser_test.go Tue Oct 1 21:37:59 2019
@@ -378,6 +378,24 @@ func (s *Suite) Test_MkParser_VarUse(c *
varuseText("${${", "${"),
"WARN: Test_MkParser_VarUse.mk:1: Missing closing \"}\" for \"\".",
"WARN: Test_MkParser_VarUse.mk:1: Missing closing \"}\" for \"${\".")
+
+ test("${arbitrary :Mpattern:---:Q}",
+ varuseText("${arbitrary :Mpattern:---:Q}", "arbitrary ", "Mpattern", "Q"),
+ // TODO: Swap the order of these message
+ "WARN: Test_MkParser_VarUse.mk:1: Invalid variable modifier \"---\" for \"arbitrary \".",
+ "WARN: Test_MkParser_VarUse.mk:1: Invalid part \" \" after variable name \"arbitrary\".")
+
+ // Variable names containing spaces do not occur in pkgsrc.
+ // Technically they are possible:
+ //
+ // VARNAME= name with spaces
+ // ${VARNAME}= value
+ //
+ // all:
+ // @echo ${name with spaces:Q}''
+ test("${arbitrary text}",
+ varuse("arbitrary text"),
+ "WARN: Test_MkParser_VarUse.mk:1: Invalid part \" text\" after variable name \"arbitrary\".")
}
func (s *Suite) Test_MkParser_varUseModifier__invalid_ts_modifier_with_warning(c *check.C) {
Index: pkgsrc/pkgtools/pkglint/files/licenses_test.go
diff -u pkgsrc/pkgtools/pkglint/files/licenses_test.go:1.23 pkgsrc/pkgtools/pkglint/files/licenses_test.go:1.24
--- pkgsrc/pkgtools/pkglint/files/licenses_test.go:1.23 Sat Apr 20 17:43:24 2019
+++ pkgsrc/pkgtools/pkglint/files/licenses_test.go Tue Oct 1 21:37:59 2019
@@ -9,39 +9,38 @@ func (s *Suite) Test_LicenseChecker_Chec
t.CreateFileLines("licenses/gnu-gpl-v2",
"The licenses for most software are designed to take away ...")
- mkline := t.NewMkLine("Makefile", 7, "LICENSE=dummy")
- licenseChecker := LicenseChecker{nil, mkline}
- licenseChecker.Check("gpl-v2", opAssign)
+ test := func(licenseValue string, diagnostics ...string) {
+ mklines := t.NewMkLines("Makefile",
+ "LICENSE=\t"+licenseValue)
- t.CheckOutputLines(
- "WARN: Makefile:7: License file ~/licenses/gpl-v2 does not exist.")
-
- licenseChecker.Check("no-profit shareware", opAssign)
+ mklines.ForEach(func(mkline *MkLine) {
+ (&LicenseChecker{mklines, mkline}).Check(mkline.Value(), opAssign)
+ })
- t.CheckOutputLines(
- "ERROR: Makefile:7: Parse error for license condition \"no-profit shareware\".")
+ t.CheckOutput(diagnostics)
+ }
- licenseChecker.Check("no-profit AND shareware", opAssign)
+ test("gpl-v2",
+ "WARN: Makefile:1: License file ~/licenses/gpl-v2 does not exist.")
- t.CheckOutputLines(
- "WARN: Makefile:7: License file ~/licenses/no-profit does not exist.",
- "ERROR: Makefile:7: License \"no-profit\" must not be used.",
- "WARN: Makefile:7: License file ~/licenses/shareware does not exist.",
- "ERROR: Makefile:7: License \"shareware\" must not be used.")
+ test("no-profit shareware",
+ "ERROR: Makefile:1: Parse error for license condition \"no-profit shareware\".")
- licenseChecker.Check("gnu-gpl-v2", opAssign)
+ test("no-profit AND shareware",
+ "WARN: Makefile:1: License file ~/licenses/no-profit does not exist.",
+ "ERROR: Makefile:1: License \"no-profit\" must not be used.",
+ "WARN: Makefile:1: License file ~/licenses/shareware does not exist.",
+ "ERROR: Makefile:1: License \"shareware\" must not be used.")
- t.CheckOutputEmpty()
-
- licenseChecker.Check("gnu-gpl-v2 AND gnu-gpl-v2 OR gnu-gpl-v2", opAssign)
-
- t.CheckOutputLines(
- "ERROR: Makefile:7: AND and OR operators in license conditions can only be combined using parentheses.")
+ test("gnu-gpl-v2",
+ nil...)
- licenseChecker.Check("(gnu-gpl-v2 OR gnu-gpl-v2) AND gnu-gpl-v2", opAssign)
+ test("gnu-gpl-v2 AND gnu-gpl-v2 OR gnu-gpl-v2",
+ "ERROR: Makefile:1: AND and OR operators in license conditions can only be combined using parentheses.")
- t.CheckOutputEmpty()
+ test("(gnu-gpl-v2 OR gnu-gpl-v2) AND gnu-gpl-v2",
+ nil...)
}
func (s *Suite) Test_LicenseChecker_checkName__LICENSE_FILE(c *check.C) {
Index: pkgsrc/pkgtools/pkglint/files/logging.go
diff -u pkgsrc/pkgtools/pkglint/files/logging.go:1.27 pkgsrc/pkgtools/pkglint/files/logging.go:1.28
--- pkgsrc/pkgtools/pkglint/files/logging.go:1.27 Thu Sep 12 21:15:48 2019
+++ pkgsrc/pkgtools/pkglint/files/logging.go Tue Oct 1 21:37:59 2019
@@ -6,6 +6,7 @@ import (
"netbsd.org/pkglint/histogram"
"netbsd.org/pkglint/textproc"
"path"
+ "strings"
)
type Logger struct {
@@ -118,7 +119,7 @@ func (l *Logger) Explain(explanation ...
l.out.WriteLine("")
}
-func (l *Logger) ShowSummary() {
+func (l *Logger) ShowSummary(args []string) {
if l.Opts.Quiet || l.Opts.Autofix {
return
}
@@ -147,14 +148,22 @@ func (l *Logger) ShowSummary() {
l.out.WriteLine("Looks fine.")
}
+ commandLine := func(arg string) string {
+ argv := append([]string{args[0], arg}, args[1:]...)
+ for i := range argv {
+ argv[i] = shquote(argv[i])
+ }
+ return strings.Join(argv, " ")
+ }
+
if l.explanationsAvailable && !l.Opts.Explain {
- l.out.WriteLine("(Run \"pkglint -e\" to show explanations.)")
+ l.out.WriteLine(sprintf("(Run \"%s\" to show explanations.)", commandLine("-e")))
}
if l.autofixAvailable {
if !l.Opts.ShowAutofix {
- l.out.WriteLine("(Run \"pkglint -fs\" to show what can be fixed automatically.)")
+ l.out.WriteLine(sprintf("(Run \"%s\" to show what can be fixed automatically.)", commandLine("-fs")))
}
- l.out.WriteLine("(Run \"pkglint -F\" to automatically fix some issues.)")
+ l.out.WriteLine(sprintf("(Run \"%s\" to automatically fix some issues.)", commandLine("-F")))
}
}
Index: pkgsrc/pkgtools/pkglint/files/substcontext.go
diff -u pkgsrc/pkgtools/pkglint/files/substcontext.go:1.27 pkgsrc/pkgtools/pkglint/files/substcontext.go:1.28
--- pkgsrc/pkgtools/pkglint/files/substcontext.go:1.27 Sun Jul 14 21:25:47 2019
+++ pkgsrc/pkgtools/pkglint/files/substcontext.go Tue Oct 1 21:37:59 2019
@@ -251,7 +251,7 @@ func (ctx *SubstContext) suggestSubstVar
tokens, _ := splitIntoShellTokens(mkline.Line, mkline.Value())
for _, token := range tokens {
- varname := ctx.extractVarname(mkline.UnquoteShell(token))
+ varname := ctx.extractVarname(mkline.UnquoteShell(token, false))
if varname == "" {
continue
}
Index: pkgsrc/pkgtools/pkglint/files/logging_test.go
diff -u pkgsrc/pkgtools/pkglint/files/logging_test.go:1.20 pkgsrc/pkgtools/pkglint/files/logging_test.go:1.21
--- pkgsrc/pkgtools/pkglint/files/logging_test.go:1.20 Thu Sep 12 21:15:48 2019
+++ pkgsrc/pkgtools/pkglint/files/logging_test.go Tue Oct 1 21:37:59 2019
@@ -591,7 +591,7 @@ func (s *Suite) Test_Logger_ShowSummary_
// Neither the warning nor the corresponding explanation are logged.
line.Warnf("Filtered warning.")
line.Explain("Explanation for the above warning.")
- G.Logger.ShowSummary()
+ G.Logger.ShowSummary(t.argv)
// Since the above warning is filtered out by the --only option,
// adding --explain to the options would not show any explanation.
@@ -603,13 +603,13 @@ func (s *Suite) Test_Logger_ShowSummary_
line.Warnf("This warning is interesting.")
line.Explain("This explanation is available.")
- G.Logger.ShowSummary()
+ G.Logger.ShowSummary(t.argv)
t.CheckEquals(G.Logger.explanationsAvailable, true)
t.CheckOutputLines(
"WARN: Makefile:27: This warning is interesting.",
"1 warning found.",
- "(Run \"pkglint -e\" to show explanations.)")
+ "(Run \"pkglint -e --only interesting\" to show explanations.)")
}
func (s *Suite) Test_Logger_ShowSummary__looks_fine(c *check.C) {
@@ -617,7 +617,7 @@ func (s *Suite) Test_Logger_ShowSummary_
logger := Logger{out: NewSeparatorWriter(&t.stdout)}
- logger.ShowSummary()
+ logger.ShowSummary([]string{"pkglint"})
t.CheckOutputLines(
"Looks fine.")
@@ -630,7 +630,7 @@ func (s *Suite) Test_Logger_ShowSummary_
logger.Logf(Error, "", "", ".", ".")
logger.Logf(Warn, "", "", ".", ".")
- logger.ShowSummary()
+ logger.ShowSummary([]string{"pkglint"})
t.CheckOutputLines(
"ERROR: .",
@@ -648,7 +648,7 @@ func (s *Suite) Test_Logger_ShowSummary_
logger.Logf(Warn, "", "", "4.", "4.")
logger.Logf(Warn, "", "", "5.", "5.")
- logger.ShowSummary()
+ logger.ShowSummary([]string{"pkglint"})
t.CheckOutputLines(
"ERROR: 1.",
@@ -665,7 +665,7 @@ func (s *Suite) Test_Logger_ShowSummary_
logger := Logger{out: NewSeparatorWriter(&t.stdout)}
logger.Opts.Quiet = true
- logger.ShowSummary()
+ logger.ShowSummary([]string{"pkglint"})
t.CheckOutputEmpty()
}
@@ -678,7 +678,7 @@ func (s *Suite) Test_Logger_ShowSummary_
logger.Logf(Error, "", "", ".", ".")
logger.Logf(Warn, "", "", ".", ".")
- logger.ShowSummary()
+ logger.ShowSummary([]string{"pkglint"})
t.CheckOutputLines(
"ERROR: .",
@@ -693,7 +693,7 @@ func (s *Suite) Test_Logger_ShowSummary_
logger.Explain(
"Explanation.")
- logger.ShowSummary()
+ logger.ShowSummary([]string{"pkglint"})
t.CheckOutputLines(
"ERROR: .",
@@ -712,7 +712,7 @@ func (s *Suite) Test_Logger_ShowSummary_
// Since the --explain option is already given, it need not be advertised.
logger.Opts.Explain = true
- logger.ShowSummary()
+ logger.ShowSummary([]string{"pkglint"})
t.CheckOutputLines(
"ERROR: .",
@@ -725,7 +725,7 @@ func (s *Suite) Test_Logger_ShowSummary_
logger := Logger{out: NewSeparatorWriter(&t.stdout)}
logger.autofixAvailable = true // See SaveAutofixChanges
- logger.ShowSummary()
+ logger.ShowSummary([]string{"pkglint"})
t.CheckOutputLines(
"Looks fine.",
@@ -740,7 +740,7 @@ func (s *Suite) Test_Logger_ShowSummary_
logger.autofixAvailable = true // See SaveAutofixChanges
logger.Opts.ShowAutofix = true
- logger.ShowSummary()
+ logger.ShowSummary([]string{"pkglint"})
// Since the --show-autofix option is already given, it need not be advertised.
// But the --autofix option is not given, therefore mention it.
@@ -756,7 +756,7 @@ func (s *Suite) Test_Logger_ShowSummary_
logger.autofixAvailable = true // See SaveAutofixChanges
logger.Opts.Autofix = true
- logger.ShowSummary()
+ logger.ShowSummary([]string{"pkglint"})
// Since the --autofix option is already given, it need not be advertised.
// Mentioning the --show-autofix option would be pointless here since the
@@ -766,6 +766,20 @@ func (s *Suite) Test_Logger_ShowSummary_
t.CheckOutputEmpty()
}
+func (s *Suite) Test_Logger_ShowSummary__quoting(c *check.C) {
+ t := s.Init(c)
+
+ logger := Logger{out: NewSeparatorWriter(&t.stdout)}
+ logger.errors = 1
+ logger.explanationsAvailable = true
+
+ logger.ShowSummary([]string{"pkglint", "--only", "string with 'quotes'"})
+
+ t.CheckOutputLines(
+ "1 error found.",
+ "(Run \"pkglint -e --only 'string with '\\''quotes'\\'''\" to show explanations.)")
+}
+
// In rare cases, the explanations for the same warning may differ
// when they appear in different contexts. In such a case, if the
// warning is suppressed, the explanation must not appear on its own.
@@ -931,7 +945,7 @@ func (s *Suite) Test_Logger_Diag__source
t.SetUpPackage("category/package2",
"PATCHDIR=\t../../category/dependency/patches")
- t.Main("--source", "-Wall", t.File("category/package1"), t.File("category/package2"))
+ t.Main("--source", "-Wall", "category/package1", "category/package2")
t.CheckOutputLines(
"ERROR: ~/category/package1/distinfo: "+
@@ -947,7 +961,8 @@ func (s *Suite) Test_Logger_Diag__source
"Run \""+confMake+" makepatchsum\".",
"",
"3 errors found.",
- "(Run \"pkglint -e\" to show explanations.)")
+ t.Shquote("(Run \"pkglint -e --source -Wall %s %s\" to show explanations.)",
+ "category/package1", "category/package2"))
}
func (s *Suite) Test_Logger_shallBeLogged(c *check.C) {
Index: pkgsrc/pkgtools/pkglint/files/toplevel.go
diff -u pkgsrc/pkgtools/pkglint/files/toplevel.go:1.20 pkgsrc/pkgtools/pkglint/files/toplevel.go:1.21
--- pkgsrc/pkgtools/pkglint/files/toplevel.go:1.20 Sun Jul 14 21:25:47 2019
+++ pkgsrc/pkgtools/pkglint/files/toplevel.go Tue Oct 1 21:37:59 2019
@@ -45,7 +45,7 @@ func (ctx *Toplevel) checkSubdir(mkline
}
}
- if containsVarRef(subdir) || !fileExists(ctx.dir+"/"+subdir+"/Makefile") {
+ if containsVarRef(subdir) || !fileExists(joinPath(ctx.dir, subdir, "Makefile")) {
return
}
@@ -63,6 +63,6 @@ func (ctx *Toplevel) checkSubdir(mkline
ctx.previousSubdir = subdir
if !mkline.IsCommentedVarassign() {
- ctx.subdirs = append(ctx.subdirs, ctx.dir+"/"+subdir)
+ ctx.subdirs = append(ctx.subdirs, joinPath(ctx.dir, subdir))
}
}
Index: pkgsrc/pkgtools/pkglint/files/mkline.go
diff -u pkgsrc/pkgtools/pkglint/files/mkline.go:1.58 pkgsrc/pkgtools/pkglint/files/mkline.go:1.59
--- pkgsrc/pkgtools/pkglint/files/mkline.go:1.58 Thu Sep 12 21:15:48 2019
+++ pkgsrc/pkgtools/pkglint/files/mkline.go Tue Oct 1 21:37:59 2019
@@ -549,40 +549,81 @@ var notSpace = textproc.Space.Inverse()
//
// Compare devel/bmake/files/str.c, function brk_string.
//
-// TODO: Compare with brk_string from devel/bmake, especially for backticks.
+// See UnquoteShell.
func (mkline *MkLine) ValueFields(value string) []string {
- if trace.Tracing {
- defer trace.Call(mkline, value)()
- }
+ var fields []string
+ var field strings.Builder
- p := NewShTokenizer(mkline.Line, value, false)
- atoms := p.ShAtoms()
+ lexer := NewMkTokensLexer(mkline.Tokenize(value, false))
+ lexer.SkipHspace()
- if len(atoms) > 0 && atoms[0].Type == shtSpace {
- atoms = atoms[1:]
+ emit := func() {
+ if field.Len() > 0 {
+ fields = append(fields, field.String())
+ field.Reset()
+ }
}
- var word strings.Builder
- var words []string
- for _, atom := range atoms {
- if atom.Type == shtSpace && atom.Quoting == shqPlain {
- words = append(words, word.String())
- word.Reset()
+ plain := func() {
+ varUse := lexer.NextVarUse()
+ if varUse != nil {
+ field.WriteString(varUse.Text)
} else {
- word.WriteString(atom.MkText)
+ field.WriteByte(lexer.NextByte())
}
}
- if word.Len() > 0 && atoms[len(atoms)-1].Quoting == shqPlain {
- words = append(words, word.String())
- word.Reset()
- }
- // TODO: Handle parse errors
- word.WriteString(p.parser.Rest())
- rest := word.String()
- _ = rest
+ for !lexer.EOF() {
+ switch {
+ case lexer.SkipByte('\''):
+ // Note: bmake's brk_string treats single quotes and double
+ // quotes in the same way regarding backslash escape sequences.
+ // It seems this is a mistake, and until this is confirmed to
+ // not be a bug, pkglint parses single quotes like in the shell.
+ field.WriteByte('\'')
+ for {
+ if lexer.EOF() {
+ return fields // without the incomplete last field
+ } else if lexer.SkipByte('\'') {
+ field.WriteByte('\'')
+ break
+ } else {
+ plain()
+ }
+ }
+
+ case lexer.SkipByte('"'):
+ field.WriteByte('"')
+ for {
+ if lexer.EOF() {
+ return fields // without the incomplete last field
+ } else if lexer.SkipByte('"') {
+ field.WriteByte('"')
+ break
+ } else if lexer.SkipByte('\\') {
+ field.WriteByte('\\')
+ plain()
+ } else {
+ plain()
+ }
+ }
+
+ case lexer.SkipByte(' '), lexer.SkipByte('\t'), lexer.SkipByte('\n'):
+ emit()
+
+ case lexer.SkipByte('\\'):
+ field.WriteByte('\\')
+ if !lexer.EOF() {
+ plain()
+ }
+
+ default:
+ plain()
+ }
+ }
+ emit()
- return words
+ return fields
}
func (mkline *MkLine) ValueTokens() ([]*MkToken, string) {
@@ -1093,47 +1134,75 @@ func (mkline *MkLine) ForEachUsed(action
}
}
-func (*MkLine) UnquoteShell(str string) string {
+// UnquoteShell removes one level of double and single quotes,
+// like in the shell.
+//
+// See ValueFields.
+func (mkline *MkLine) UnquoteShell(str string, warn bool) string {
var sb strings.Builder
- n := len(str)
+ lexer := NewMkTokensLexer(mkline.Tokenize(str, false))
+
+ plain := func() {
+ varUse := lexer.NextVarUse()
+ if varUse != nil {
+ sb.WriteString(varUse.Text)
+ } else {
+ sb.WriteByte(lexer.NextByte())
+ }
+ }
outer:
- for i := 0; i < n; i++ {
- switch str[i] {
- case '"':
- for i++; i < n; i++ {
- switch str[i] {
- case '"':
+ for !lexer.EOF() {
+ switch {
+ case lexer.SkipByte('"'):
+ for !lexer.EOF() {
+ if lexer.SkipByte('"') {
continue outer
- case '\\':
- i++
- if i < n {
- sb.WriteByte(str[i])
+ } else if lexer.SkipByte('\\') {
+ if !lexer.EOF() {
+ plain()
}
- default:
- sb.WriteByte(str[i])
+ } else {
+ plain()
}
}
- case '\'':
- for i++; i < n && str[i] != '\''; i++ {
- sb.WriteByte(str[i])
+ case lexer.SkipByte('\''):
+ for !lexer.EOF() && !lexer.SkipByte('\'') {
+ plain()
}
- case '\\':
- i++
- if i < n {
- sb.WriteByte(str[i])
+ case lexer.SkipByte('\\'):
+ if !lexer.EOF() {
+ plain()
}
default:
- sb.WriteByte(str[i])
+ if warn {
+ mkline.checkFileGlobbing(lexer.PeekByte(), str)
+ }
+ plain()
}
}
return sb.String()
}
+func (mkline *MkLine) checkFileGlobbing(ch int, str string) {
+ if !(ch == '*' || ch == '?' || ch == '[') {
+ return
+ }
+
+ if !mkline.once.FirstTimeSlice("unintended file globbing", string(ch)) {
+ return
+ }
+
+ mkline.Warnf("The %q in the word %q may lead to unintended file globbing.",
+ string(ch), str)
+ mkline.Explain(
+ "To fix this, enclose the word in \"double\" or 'single' quotes.")
+}
+
type MkOperator uint8
const (
Index: pkgsrc/pkgtools/pkglint/files/mkline_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mkline_test.go:1.67 pkgsrc/pkgtools/pkglint/files/mkline_test.go:1.68
--- pkgsrc/pkgtools/pkglint/files/mkline_test.go:1.67 Thu Sep 12 21:15:48 2019
+++ pkgsrc/pkgtools/pkglint/files/mkline_test.go Tue Oct 1 21:37:59 2019
@@ -1048,6 +1048,31 @@ func (s *Suite) Test_MkLine_VariableNeed
t.CheckOutputEmpty()
}
+func (s *Suite) Test_MkLine_VariableNeedsQuoting__only_D_modifier(c *check.C) {
+ t := s.Init(c)
+
+ t.SetUpVartypes()
+
+ mklines := t.SetUpFileMkLines("Makefile",
+ MkCvsID,
+ "",
+ "SUBST_CLASSES+=\t\turl2pkg",
+ "SUBST_STAGE.url2pkg=\tpost-configure",
+ "SUBST_FILES.url2pkg=\t*.in",
+ "SUBST_SED.url2pkg=\t-e 's,@PKGSRCDIR@,${BATCH:D${PKGSRCDIR}},'")
+
+ mklines.Check()
+
+ // Since the value of the BATCH variable does not appear in the output,
+ // there should be no warning saying that "BATCH should be quoted".
+ // If any, the variable PKGSRCDIR should be quoted, but that is a safe
+ // variable since it is a pkgsrc-specific directory and it appears as
+ // part of a word, therefore it cannot result in an empty string.
+ // FIXME: Don't warn in this situation.
+ t.CheckOutputLines(
+ "WARN: ~/Makefile:6: The variable BATCH should be quoted as part of a shell word.")
+}
+
// As of October 2018, these examples from real pkgsrc end up in the
// final "unknown" case.
func (s *Suite) Test_MkLine_VariableNeedsQuoting__uncovered_cases(c *check.C) {
@@ -1338,6 +1363,56 @@ func (s *Suite) Test_MkLine_ValueFields(
"${VAR2}two",
"words;;;",
"'word three'")
+
+ test("\"double quotes\" group words",
+ "\"double quotes\"",
+ "group",
+ "words")
+
+ test("\"unfinished",
+ nil...) // the rest is silently discarded
+
+ test("'single quotes' group words",
+ "'single quotes'",
+ "group",
+ "words")
+
+ test("'unfinished",
+ nil...) // the rest is silently discarded
+
+ // This is how it works in bmake.
+ test("'\\' ' end",
+ "'\\'") // the "' end" is silently discarded
+
+ // This is how it works in pkglint.
+ test("'\\' end",
+ "'\\'",
+ "end")
+
+ test("`backticks do not group words`",
+ "`backticks",
+ "do",
+ "not",
+ "group",
+ "words`")
+
+ test("plain${VAR}plain",
+ "plain${VAR}plain")
+
+ test("\"${DOUBLE}\" \"\\${DOUBLE}\"",
+ "\"${DOUBLE}\"",
+ "\"\\${DOUBLE}\"")
+
+ test("'${SINGLE}' '\\${SINGLE}'",
+ "'${SINGLE}'",
+ "'\\${SINGLE}'")
+
+ test("\"\"''\"\"",
+ "\"\"''\"\"")
+
+ test("$@ $<",
+ "$@",
+ "$<")
}
// Before 2018-11-26, this test panicked.
@@ -2024,9 +2099,11 @@ func (s *Suite) Test_MkLine_ForEachUsed(
func (s *Suite) Test_MkLine_UnquoteShell(c *check.C) {
t := s.Init(c)
- test := func(input, output string) {
- unquoted := (*MkLine).UnquoteShell(nil, input)
+ test := func(input, output string, diagnostics ...string) {
+ mkline := t.NewMkLine("filename.mk", 1, "")
+ unquoted := mkline.UnquoteShell(input, true)
t.CheckEquals(unquoted, output)
+ t.CheckOutput(diagnostics)
}
test("", "")
@@ -2046,8 +2123,28 @@ func (s *Suite) Test_MkLine_UnquoteShell
test("\\", "")
test("\"\\", "")
test("'", "")
- test("\"$(\"", "$(")
+
+ test("\"$(\"", "$(\"",
+ "WARN: filename.mk:1: Missing closing \")\" for \"\\\"\".",
+ "WARN: filename.mk:1: Invalid part \"\\\"\" after variable name \"\".")
+
test("`", "`")
+
+ // Quotes inside a varuse are not unquoted.
+ test("${VAR}", "${VAR}")
+ test("${VAR:S,',',g}", "${VAR:S,',',g}")
+
+ test("\"*?[\"", "*?[")
+ test("'*?['", "*?[")
+
+ test("*?[", "*?[",
+ "WARN: filename.mk:1: The \"*\" in the word \"*?[\" may lead to unintended file globbing.",
+ "WARN: filename.mk:1: The \"?\" in the word \"*?[\" may lead to unintended file globbing.",
+ "WARN: filename.mk:1: The \"[\" in the word \"*?[\" may lead to unintended file globbing.")
+
+ test("'single'*\"double\"", "single*double",
+ "WARN: filename.mk:1: The \"*\" in the word \"'single'*\\\"double\\\"\" "+
+ "may lead to unintended file globbing.")
}
func (s *Suite) Test_MkLineParser_unescapeComment(c *check.C) {
Index: pkgsrc/pkgtools/pkglint/files/mklinechecker.go
diff -u pkgsrc/pkgtools/pkglint/files/mklinechecker.go:1.46 pkgsrc/pkgtools/pkglint/files/mklinechecker.go:1.47
--- pkgsrc/pkgtools/pkglint/files/mklinechecker.go:1.46 Thu Sep 12 21:15:48 2019
+++ pkgsrc/pkgtools/pkglint/files/mklinechecker.go Tue Oct 1 21:37:59 2019
@@ -1285,6 +1285,29 @@ func (ck MkLineChecker) checkVarassignMi
mkline.Notef("Consider setting NOT_FOR_PLATFORM instead of " +
"PKG_SKIP_REASON depending on ${OPSYS}.")
}
+
+ ck.checkVarassignMiscRedundantInstallationDirs()
+}
+
+func (ck MkLineChecker) checkVarassignMiscRedundantInstallationDirs() {
+ mkline := ck.MkLine
+ varname := mkline.Varname()
+
+ switch {
+ case G.Pkg == nil,
+ varname != "INSTALLATION_DIRS",
+ !matches(G.Pkg.vars.LastValue("AUTO_MKDIRS"), `^[Yy][Ee][Ss]$`):
+ return
+ }
+
+ for _, dir := range mkline.ValueFields(mkline.Value()) {
+ if G.Pkg.Plist.Dirs[dir] != nil {
+ mkline.Notef("The directory %q is redundant in %s.", dir, varname)
+ mkline.Explain(
+ "This package defines AUTO_MKDIR, and the directory is contained in the PLIST.",
+ "Therefore it will be created anyways.")
+ }
+ }
}
func (ck MkLineChecker) checkVarassignLeftBsdPrefs() {
@@ -1587,14 +1610,6 @@ func (ck MkLineChecker) simplifyConditio
quote := condStr(matches(pattern, `[^\-/0-9@A-Za-z]`), "\"", "")
to := "${" + varname + "} " + op + " " + quote + pattern + quote
-
- // TODO: Check in more cases whether the parentheses are really necessary.
- // In a !!${VAR} expression, parentheses are necessary.
- needParen := !toplevel
- if needParen {
- to = "(" + to + ")"
- }
-
return from, to
}
@@ -1618,6 +1633,8 @@ func (ck MkLineChecker) simplifyConditio
continue
}
+ // FIXME: This transformation is only valid if the variable is guaranteed to
+ // be defined. If that's not the case, the :U modifier must be added.
fix := ck.MkLine.Autofix()
fix.Notef("%s should be compared using %s instead of matching against %q.",
varname, condStr(positive == notEmpty, "==", "!="), ":"+modifier.Text)
@@ -1735,7 +1752,7 @@ func (ck MkLineChecker) CheckRelativePat
return
}
- abs := path.Dir(mkline.Filename) + "/" + resolvedPath
+ abs := joinPath(path.Dir(mkline.Filename), resolvedPath)
if _, err := os.Stat(abs); err != nil {
if mustExist && !ck.MkLines.indentation.HasExists(resolvedPath) {
mkline.Errorf("Relative path %q does not exist.", resolvedPath)
Index: pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go:1.42 pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go:1.43
--- pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go:1.42 Thu Sep 12 21:15:48 2019
+++ pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go Tue Oct 1 21:37:59 2019
@@ -1323,9 +1323,9 @@ func (s *Suite) Test_MkLineChecker_check
func (s *Suite) Test_MkLineChecker_checkVarusePermissions__load_time_in_condition(c *check.C) {
t := s.Init(c)
- G.Pkgsrc.vartypes.DefineParse("LOAD_TIME", BtPathmask, List,
+ G.Pkgsrc.vartypes.DefineParse("LOAD_TIME", BtPathPattern, List,
"special:filename.mk: use-loadtime")
- G.Pkgsrc.vartypes.DefineParse("RUN_TIME", BtPathmask, List,
+ G.Pkgsrc.vartypes.DefineParse("RUN_TIME", BtPathPattern, List,
"special:filename.mk: use")
mklines := t.NewMkLines("filename.mk",
@@ -1342,9 +1342,9 @@ func (s *Suite) Test_MkLineChecker_check
func (s *Suite) Test_MkLineChecker_checkVarusePermissions__load_time_in_for_loop(c *check.C) {
t := s.Init(c)
- G.Pkgsrc.vartypes.DefineParse("LOAD_TIME", BtPathmask, List,
+ G.Pkgsrc.vartypes.DefineParse("LOAD_TIME", BtPathPattern, List,
"special:filename.mk: use-loadtime")
- G.Pkgsrc.vartypes.DefineParse("RUN_TIME", BtPathmask, List,
+ G.Pkgsrc.vartypes.DefineParse("RUN_TIME", BtPathPattern, List,
"special:filename.mk: use")
mklines := t.NewMkLines("filename.mk",
@@ -1491,7 +1491,7 @@ func (s *Suite) Test_MkLineChecker_check
func (s *Suite) Test_MkLineChecker_checkVarusePermissions__usable_only_at_loadtime_in_other_file(c *check.C) {
t := s.Init(c)
- G.Pkgsrc.vartypes.DefineParse("VAR", BtFileName, NoVartypeOptions,
+ G.Pkgsrc.vartypes.DefineParse("VAR", BtFilename, NoVartypeOptions,
"*: set, use-loadtime")
mklines := t.NewMkLines("Makefile",
MkCvsID,
@@ -1754,6 +1754,9 @@ func (s *Suite) Test_MkLineChecker_Check
test("../../other/does-not-exist",
"ERROR: ~/category/package/Makefile:1: Relative path \"../../other/does-not-exist/Makefile\" does not exist.")
+
+ test("${OTHER_PACKAGE}",
+ nil...)
}
// PR pkg/46570, item 2
@@ -1782,24 +1785,24 @@ func (s *Suite) Test_MkLineChecker_Check
t.SetUpVartypes()
mklines := t.NewMkLines("x11/xkeyboard-config/Makefile",
- "FILES_SUBST+=XKBCOMP_SYMLINK=${${XKBBASE}/xkbcomp:L:Q}",
- "FILES_SUBST+=XKBCOMP_SYMLINK=${${XKBBASE}/xkbcomp:Q}")
+ MkCvsID,
+ "FILES_SUBST+=\tXKBCOMP_SYMLINK=${${XKBBASE}/xkbcomp:L:Q}",
+ "FILES_SUBST+=\tXKBCOMP_SYMLINK=${${XKBBASE}/xkbcomp:Q}")
- MkLineChecker{mklines, mklines.mklines[0]}.Check()
- MkLineChecker{mklines, mklines.mklines[1]}.Check()
+ mklines.Check()
- // In line 1, don't warn that ${XKBBASE}/xkbcomp is used but not defined.
+ // In line 2, don't warn that ${XKBBASE}/xkbcomp is used but not defined.
// This is because the :L modifier interprets everything before as an expression
// instead of a variable name.
//
- // In line 2 the :L modifier is missing, therefore ${XKBBASE}/xkbcomp is the
+ // In line 3 the :L modifier is missing, therefore ${XKBBASE}/xkbcomp is the
// name of another variable, and that variable is not known. Only XKBBASE is known.
//
- // In line 2, warn about the invalid "/" as part of the variable name.
+ // In line 3, warn about the invalid "/" as part of the variable name.
t.CheckOutputLines(
- "WARN: x11/xkeyboard-config/Makefile:2: "+
+ "WARN: x11/xkeyboard-config/Makefile:3: "+
"Invalid part \"/xkbcomp\" after variable name \"${XKBBASE}\".",
- "WARN: x11/xkeyboard-config/Makefile:2: XKBBASE is used but not defined.")
+ "WARN: x11/xkeyboard-config/Makefile:3: XKBBASE is used but not defined.")
}
func (s *Suite) Test_MkLineChecker_checkDirectiveCond__comparison_with_shell_command(c *check.C) {
@@ -1860,10 +1863,18 @@ func (s *Suite) Test_MkLineChecker_check
ck := MkLineChecker{mklines, mklines.mklines[1]}
t.SetUpCommandLine("-Wall")
- ck.checkDirectiveCond()
+ mklines.ForEach(func(mkline *MkLine) {
+ if mkline == mklines.mklines[1] {
+ ck.checkDirectiveCond()
+ }
+ })
t.SetUpCommandLine("-Wall", "--autofix")
- ck.checkDirectiveCond()
+ mklines.ForEach(func(mkline *MkLine) {
+ if mkline == mklines.mklines[1] {
+ ck.checkDirectiveCond()
+ }
+ })
mklines.SaveAutofixChanges()
afterMklines := t.LoadMkInclude("module.mk")
@@ -1944,18 +1955,18 @@ func (s *Suite) Test_MkLineChecker_check
// test for emptiness, therefore the diagnostics should suggest
// the != operator instead of ==.
"NOTE: module.mk:2: PKGPATH should be compared using == instead of matching against \":Mpattern\".",
- "AUTOFIX: module.mk:2: Replacing \"!empty(PKGPATH:Mpattern)\" with \"(${PKGPATH} == pattern)\".",
+ "AUTOFIX: module.mk:2: Replacing \"!empty(PKGPATH:Mpattern)\" with \"${PKGPATH} == pattern\".",
- // TODO: This condition could be simplified even more.
+ // TODO: The ! and == could be combined into a !=.
// Luckily the !! pattern doesn't occur in practice.
- ".if !(${PKGPATH} == pattern)")
+ ".if !${PKGPATH} == pattern")
test(".if empty(PKGPATH:Mpattern) || 0",
"NOTE: module.mk:2: PKGPATH should be compared using != instead of matching against \":Mpattern\".",
- "AUTOFIX: module.mk:2: Replacing \"empty(PKGPATH:Mpattern)\" with \"(${PKGPATH} != pattern)\".",
+ "AUTOFIX: module.mk:2: Replacing \"empty(PKGPATH:Mpattern)\" with \"${PKGPATH} != pattern\".",
- ".if (${PKGPATH} != pattern) || 0")
+ ".if ${PKGPATH} != pattern || 0")
// No note in this case since there is no implicit !empty around the varUse.
test(".if ${PKGPATH:Mpattern} != ${OTHER}",
@@ -1984,9 +1995,9 @@ func (s *Suite) Test_MkLineChecker_check
".if !!${PKGPATH:Mpattern}",
"NOTE: module.mk:2: PKGPATH should be compared using != instead of matching against \":Mpattern\".",
- "AUTOFIX: module.mk:2: Replacing \"!${PKGPATH:Mpattern}\" with \"(${PKGPATH} != pattern)\".",
+ "AUTOFIX: module.mk:2: Replacing \"!${PKGPATH:Mpattern}\" with \"${PKGPATH} != pattern\".",
- ".if !(${PKGPATH} != pattern)")
+ ".if !${PKGPATH} != pattern")
// This pattern with spaces doesn't make sense at all in the :M
// modifier since it can never match.
@@ -1995,7 +2006,8 @@ func (s *Suite) Test_MkLineChecker_check
test(
".if ${PKGPATH:Mpattern with spaces}",
- "WARN: module.mk:2: The pathname pattern \"pattern with spaces\" contains the invalid characters \" \".",
+ "WARN: module.mk:2: The pathname pattern \"pattern with spaces\" "+
+ "contains the invalid characters \" \".",
".if ${PKGPATH:Mpattern with spaces}")
// TODO: ".if ${PKGPATH} == \"pattern with spaces\"")
@@ -2003,7 +2015,8 @@ func (s *Suite) Test_MkLineChecker_check
test(
".if ${PKGPATH:M'pattern with spaces'}",
- "WARN: module.mk:2: The pathname pattern \"'pattern with spaces'\" contains the invalid characters \"' '\".",
+ "WARN: module.mk:2: The pathname pattern \"'pattern with spaces'\" "+
+ "contains the invalid characters \"' '\".",
".if ${PKGPATH:M'pattern with spaces'}")
// TODO: ".if ${PKGPATH} == 'pattern with spaces'")
@@ -2011,7 +2024,8 @@ func (s *Suite) Test_MkLineChecker_check
test(
".if ${PKGPATH:M&&}",
- "WARN: module.mk:2: The pathname pattern \"&&\" contains the invalid characters \"&&\".",
+ "WARN: module.mk:2: The pathname pattern \"&&\" "+
+ "contains the invalid characters \"&&\".",
".if ${PKGPATH:M&&}")
// TODO: ".if ${PKGPATH} == '&&'")
@@ -2051,11 +2065,10 @@ func (s *Suite) Test_MkLineChecker_check
"NOTE: module.mk:2: PKGPATH should be compared using == instead of matching against \":Mpath1\".",
"NOTE: module.mk:2: PKGPATH should be compared using == instead of matching against \":Mpath2\".",
- "AUTOFIX: module.mk:2: Replacing \"${PKGPATH:Mpath1}\" with \"(${PKGPATH} == path1)\".",
- "AUTOFIX: module.mk:2: Replacing \"${PKGPATH:Mpath2}\" with \"(${PKGPATH} == path2)\".",
+ "AUTOFIX: module.mk:2: Replacing \"${PKGPATH:Mpath1}\" with \"${PKGPATH} == path1\".",
+ "AUTOFIX: module.mk:2: Replacing \"${PKGPATH:Mpath2}\" with \"${PKGPATH} == path2\".",
- // TODO: remove the redundant parentheses
- ".if (${PKGPATH} == path1) || (${PKGPATH} == path2)")
+ ".if ${PKGPATH} == path1 || ${PKGPATH} == path2")
test(
".if (((((${PKGPATH:Mpath})))))",
@@ -2064,6 +2077,15 @@ func (s *Suite) Test_MkLineChecker_check
"AUTOFIX: module.mk:2: Replacing \"${PKGPATH:Mpath}\" with \"${PKGPATH} == path\".",
".if (((((${PKGPATH} == path)))))")
+
+ // Note: this combination doesn't make sense since the patterns "one" and "two" don't overlap.
+ test(
+ ".if ${PKGPATH:Mone:Mtwo}",
+
+ "NOTE: module.mk:2: PKGPATH should be compared using == instead of matching against \":Mone\".",
+ "NOTE: module.mk:2: PKGPATH should be compared using == instead of matching against \":Mtwo\".",
+
+ ".if ${PKGPATH:Mone:Mtwo}")
}
func (s *Suite) Test_MkLineChecker_checkDirectiveCond__comparing_PKGSRC_COMPILER_with_eqeq(c *check.C) {
@@ -2109,12 +2131,14 @@ func (s *Suite) Test_MkLineChecker_check
words := mkline.Fields()
- t.CheckDeepEquals(words, []string{"`pkg-config pidgin --cflags`"})
+ // bmake handles backticks in the same way, treating them as ordinary characters
+ t.CheckDeepEquals(words, []string{"`pkg-config", "pidgin", "--cflags`"})
ck := MkLineChecker{mklines, mklines.mklines[1]}
ck.checkVartype("CFLAGS", opAssignAppend, "`pkg-config pidgin --cflags`", "")
// No warning about "`pkg-config" being an unknown CFlag.
+ // As of September 2019, there is no such check anymore in pkglint.
t.CheckOutputEmpty()
}
Index: pkgsrc/pkgtools/pkglint/files/mkparser.go
diff -u pkgsrc/pkgtools/pkglint/files/mkparser.go:1.33 pkgsrc/pkgtools/pkglint/files/mkparser.go:1.34
--- pkgsrc/pkgtools/pkglint/files/mkparser.go:1.33 Sun Sep 8 22:47:47 2019
+++ pkgsrc/pkgtools/pkglint/files/mkparser.go Tue Oct 1 21:37:59 2019
@@ -289,7 +289,7 @@ func (p *MkParser) varUseModifier(varnam
}
modifier := lexer.Since(mark)
- // ${SOURCES:%.c=%.o} or ${:!uname -a:[2]}
+ // ${SOURCES:%.c=%.o} or ${:!uname -a!:[2]}
if contains(modifier, "=") || (hasPrefix(modifier, "!") && hasSuffix(modifier, "!")) {
return modifier
}
@@ -330,6 +330,10 @@ func (p *MkParser) varUseModifierSubst(c
lexer.Skip(1)
separator := byte(sep)
+ unescape := func(s string) string {
+ return strings.Replace(s, "\\"+string(separator), string(separator), -1)
+ }
+
isOther := func(b byte) bool {
return b != separator && b != '$' && b != '\\'
}
@@ -360,7 +364,7 @@ func (p *MkParser) varUseModifierSubst(c
lexer.SkipByte('^')
skipOther()
lexer.SkipByte('$')
- from = lexer.Since(fromStart)
+ from = unescape(lexer.Since(fromStart))
if !lexer.SkipByte(separator) {
return
@@ -368,7 +372,7 @@ func (p *MkParser) varUseModifierSubst(c
toStart := lexer.Mark()
skipOther()
- to = lexer.Since(toStart)
+ to = unescape(lexer.Since(toStart))
if !lexer.SkipByte(separator) {
return
Index: pkgsrc/pkgtools/pkglint/files/util_test.go
diff -u pkgsrc/pkgtools/pkglint/files/util_test.go:1.33 pkgsrc/pkgtools/pkglint/files/util_test.go:1.34
--- pkgsrc/pkgtools/pkglint/files/util_test.go:1.33 Sun Sep 8 22:47:47 2019
+++ pkgsrc/pkgtools/pkglint/files/util_test.go Tue Oct 1 21:37:59 2019
@@ -936,10 +936,10 @@ func (s *Suite) Test_FileCache_Evict__so
t.Check(cache.Get("filename6.mk", 0), check.NotNil)
}
-func (s *Suite) Test_makeHelp(c *check.C) {
+func (s *Suite) Test_bmakeHelp(c *check.C) {
t := s.Init(c)
- t.CheckEquals(makeHelp("subst"), confMake+" help topic=subst")
+ t.CheckEquals(bmakeHelp("subst"), confMake+" help topic=subst")
}
func (s *Suite) Test_hasAlnumPrefix(c *check.C) {
@@ -1169,3 +1169,16 @@ func (s *Suite) Test_StringInterner(c *c
t.CheckEquals(si.Intern("Hello, world"), "Hello, world")
t.CheckEquals(si.Intern("Hello, world"[0:5]), "Hello")
}
+
+func (s *Suite) Test_shquote(c *check.C) {
+ t := s.Init(c)
+
+ test := func(in, out string) {
+ t.CheckEquals(shquote(in), out)
+ }
+
+ test("", "''")
+ test("'", "''\\'''")
+ test("simple", "simple")
+ test("~", "'~'")
+}
Index: pkgsrc/pkgtools/pkglint/files/mktokenslexer.go
diff -u pkgsrc/pkgtools/pkglint/files/mktokenslexer.go:1.1 pkgsrc/pkgtools/pkglint/files/mktokenslexer.go:1.2
--- pkgsrc/pkgtools/pkglint/files/mktokenslexer.go:1.1 Sun Mar 10 19:01:50 2019
+++ pkgsrc/pkgtools/pkglint/files/mktokenslexer.go Tue Oct 1 21:37:59 2019
@@ -48,12 +48,12 @@ func (m *MkTokensLexer) Rest() string {
// NextVarUse returns the next varuse token, unless there is some plain text
// before it. In that case or at EOF, it returns nil.
-func (m *MkTokensLexer) NextVarUse() *MkVarUse {
+func (m *MkTokensLexer) NextVarUse() *MkToken {
if m.Lexer.EOF() && len(m.tokens) > 0 && m.tokens[0].Varuse != nil {
token := m.tokens[0]
m.tokens = m.tokens[1:]
m.next()
- return token.Varuse
+ return token
}
return nil
}
Index: pkgsrc/pkgtools/pkglint/files/mktokenslexer_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mktokenslexer_test.go:1.3 pkgsrc/pkgtools/pkglint/files/mktokenslexer_test.go:1.4
--- pkgsrc/pkgtools/pkglint/files/mktokenslexer_test.go:1.3 Sun Jul 14 21:25:47 2019
+++ pkgsrc/pkgtools/pkglint/files/mktokenslexer_test.go Tue Oct 1 21:37:59 2019
@@ -37,49 +37,53 @@ func (s *Suite) Test_MkTokensLexer__sing
func (s *Suite) Test_MkTokensLexer__single_varuse_token(c *check.C) {
t := s.Init(c)
- lexer := NewMkTokensLexer([]*MkToken{{"${VAR:Mpattern}", NewMkVarUse("VAR", "Mpattern")}})
+ tokens := []*MkToken{{"${VAR:Mpattern}", NewMkVarUse("VAR", "Mpattern")}}
+ lexer := NewMkTokensLexer(tokens)
t.CheckEquals(lexer.EOF(), false)
t.CheckEquals(lexer.PeekByte(), -1)
- t.CheckDeepEquals(lexer.NextVarUse(), NewMkVarUse("VAR", "Mpattern"))
+ t.CheckDeepEquals(lexer.NextVarUse(), tokens[0])
}
func (s *Suite) Test_MkTokensLexer__plain_then_varuse(c *check.C) {
t := s.Init(c)
- lexer := NewMkTokensLexer([]*MkToken{
+ tokens := []*MkToken{
{"plain text", nil},
- {"${VAR:Mpattern}", NewMkVarUse("VAR", "Mpattern")}})
+ {"${VAR:Mpattern}", NewMkVarUse("VAR", "Mpattern")}}
+ lexer := NewMkTokensLexer(tokens)
t.CheckEquals(lexer.NextBytesSet(textproc.Digit.Inverse()), "plain text")
- t.CheckDeepEquals(lexer.NextVarUse(), NewMkVarUse("VAR", "Mpattern"))
+ t.CheckDeepEquals(lexer.NextVarUse(), tokens[1])
t.CheckEquals(lexer.EOF(), true)
}
func (s *Suite) Test_MkTokensLexer__varuse_varuse_varuse(c *check.C) {
t := s.Init(c)
- lexer := NewMkTokensLexer([]*MkToken{
+ tokens := []*MkToken{
{"${dirs:O:u}", NewMkVarUse("dirs", "O", "u")},
{"${VAR:Mpattern}", NewMkVarUse("VAR", "Mpattern")},
- {"${.TARGET}", NewMkVarUse(".TARGET")}})
+ {"${.TARGET}", NewMkVarUse(".TARGET")}}
+ lexer := NewMkTokensLexer(tokens)
- t.CheckDeepEquals(lexer.NextVarUse(), NewMkVarUse("dirs", "O", "u"))
- t.CheckDeepEquals(lexer.NextVarUse(), NewMkVarUse("VAR", "Mpattern"))
- t.CheckDeepEquals(lexer.NextVarUse(), NewMkVarUse(".TARGET"))
+ t.CheckDeepEquals(lexer.NextVarUse(), tokens[0])
+ t.CheckDeepEquals(lexer.NextVarUse(), tokens[1])
+ t.CheckDeepEquals(lexer.NextVarUse(), tokens[2])
t.Check(lexer.NextVarUse(), check.IsNil)
}
func (s *Suite) Test_MkTokensLexer__mark_reset_since_in_initial_state(c *check.C) {
t := s.Init(c)
- lexer := NewMkTokensLexer([]*MkToken{
+ tokens := []*MkToken{
{"${dirs:O:u}", NewMkVarUse("dirs", "O", "u")},
{"${VAR:Mpattern}", NewMkVarUse("VAR", "Mpattern")},
- {"${.TARGET}", NewMkVarUse(".TARGET")}})
+ {"${.TARGET}", NewMkVarUse(".TARGET")}}
+ lexer := NewMkTokensLexer(tokens)
start := lexer.Mark()
- t.CheckDeepEquals(lexer.NextVarUse(), NewMkVarUse("dirs", "O", "u"))
+ t.CheckDeepEquals(lexer.NextVarUse(), tokens[0])
middle := lexer.Mark()
t.CheckEquals(lexer.Rest(), "${VAR:Mpattern}${.TARGET}")
lexer.Reset(start)
@@ -127,12 +131,13 @@ func (s *Suite) Test_MkTokensLexer__mark
func (s *Suite) Test_MkTokensLexer__mark_reset_since_after_varuse(c *check.C) {
t := s.Init(c)
- lexer := NewMkTokensLexer([]*MkToken{
+ tokens := []*MkToken{
{"${VAR:Mpattern}", NewMkVarUse("VAR", "Mpattern")},
- {"rest", nil}})
+ {"rest", nil}}
+ lexer := NewMkTokensLexer(tokens)
start := lexer.Mark()
- t.CheckDeepEquals(lexer.NextVarUse(), NewMkVarUse("VAR", "Mpattern"))
+ t.CheckEquals(lexer.NextVarUse(), tokens[0])
end := lexer.Mark()
t.CheckEquals(lexer.Rest(), "rest")
lexer.Reset(start)
@@ -166,17 +171,18 @@ func (s *Suite) Test_MkTokensLexer__mult
func (s *Suite) Test_MkTokensLexer__multiple_marks_in_varuse(c *check.C) {
t := s.Init(c)
- lexer := NewMkTokensLexer([]*MkToken{
+ tokens := []*MkToken{
{"${VAR1}", NewMkVarUse("VAR1")},
{"${VAR2}", NewMkVarUse("VAR2")},
- {"${VAR3}", NewMkVarUse("VAR3")}})
+ {"${VAR3}", NewMkVarUse("VAR3")}}
+ lexer := NewMkTokensLexer(tokens)
start := lexer.Mark()
- t.CheckDeepEquals(lexer.NextVarUse(), NewMkVarUse("VAR1"))
+ t.CheckDeepEquals(lexer.NextVarUse(), tokens[0])
middle := lexer.Mark()
- t.CheckDeepEquals(lexer.NextVarUse(), NewMkVarUse("VAR2"))
+ t.CheckDeepEquals(lexer.NextVarUse(), tokens[1])
further := lexer.Mark()
- t.CheckDeepEquals(lexer.NextVarUse(), NewMkVarUse("VAR3"))
+ t.CheckDeepEquals(lexer.NextVarUse(), tokens[2])
end := lexer.Mark()
t.CheckEquals(lexer.Rest(), "")
lexer.Reset(middle)
@@ -232,15 +238,16 @@ func (s *Suite) Test_MkTokensLexer__cons
func (s *Suite) Test_MkTokensLexer__peek_after_varuse(c *check.C) {
t := s.Init(c)
- lexer := NewMkTokensLexer([]*MkToken{
+ tokens := []*MkToken{
{"${VAR}", NewMkVarUse("VAR")},
{"${VAR}", NewMkVarUse("VAR")},
- {"text", nil}})
+ {"text", nil}}
+ lexer := NewMkTokensLexer(tokens)
- t.CheckDeepEquals(lexer.NextVarUse(), NewMkVarUse("VAR"))
+ t.CheckDeepEquals(lexer.NextVarUse(), tokens[0])
t.CheckEquals(lexer.PeekByte(), -1)
- t.CheckDeepEquals(lexer.NextVarUse(), NewMkVarUse("VAR"))
+ t.CheckDeepEquals(lexer.NextVarUse(), tokens[1])
t.CheckEquals(lexer.PeekByte(), int('t'))
}
Index: pkgsrc/pkgtools/pkglint/files/package.go
diff -u pkgsrc/pkgtools/pkglint/files/package.go:1.62 pkgsrc/pkgtools/pkglint/files/package.go:1.63
--- pkgsrc/pkgtools/pkglint/files/package.go:1.62 Sun Sep 8 22:47:47 2019
+++ pkgsrc/pkgtools/pkglint/files/package.go Tue Oct 1 21:37:59 2019
@@ -101,7 +101,7 @@ func NewPackage(dir string) *Package {
// as resolved from the package's directory.
// Variables that are known in the package are resolved, e.g. ${PKGDIR}.
func (pkg *Package) File(relativeFileName string) string {
- return cleanpath(resolveVariableRefs(nil, pkg.dir+"/"+relativeFileName))
+ return cleanpath(resolveVariableRefs(nil /* XXX: or maybe some mklines? */, joinPath(pkg.dir, relativeFileName)))
}
// Rel returns the path by which the given filename (as seen from the
@@ -497,7 +497,7 @@ func (pkg *Package) loadIncluded(mkline
dirname, _ := path.Split(includingFile)
dirname = cleanpath(dirname)
- fullIncluded := dirname + "/" + includedFile
+ fullIncluded := joinPath(dirname, includedFile)
relIncludedFile := relpath(pkg.dir, fullIncluded)
if !pkg.diveInto(includingFile, includedFile) {
@@ -535,7 +535,7 @@ func (pkg *Package) loadIncluded(mkline
dirname = pkgBasedir
- fullIncludedFallback := dirname + "/" + includedFile
+ fullIncludedFallback := joinPath(dirname, includedFile)
includedMklines = LoadMk(fullIncludedFallback, 0)
if includedMklines == nil {
return nil, false
@@ -598,7 +598,7 @@ func (pkg *Package) resolveIncludedFile(
// TODO: resolveVariableRefs uses G.Pkg implicitly. It should be made explicit.
// TODO: Try to combine resolveVariableRefs and ResolveVarsInRelativePath.
- includedFile := resolveVariableRefs(nil, mkline.ResolveVarsInRelativePath(mkline.IncludedFile()))
+ includedFile := resolveVariableRefs(nil /* XXX: or maybe some mklines? */, mkline.ResolveVarsInRelativePath(mkline.IncludedFile()))
if containsVarRef(includedFile) {
if trace.Tracing && !contains(includingFilename, "/mk/") {
trace.Stepf("%s:%s: Skipping unresolvable include file %q.",
@@ -1195,7 +1195,7 @@ func (pkg *Package) checkFileMakefileExt
"are extension.mk, module.mk, version.mk.",
"",
"These topic files should be documented properly so that their",
- sprintf("content can be queried using %q.", makeHelp("help")))
+ sprintf("content can be queried using %q.", bmakeHelp("help")))
}
// checkOwnerMaintainer checks files that are about to be committed.
@@ -1211,7 +1211,7 @@ func (pkg *Package) checkOwnerMaintainer
owner := pkg.vars.LastValue("OWNER")
maintainer := pkg.vars.LastValue("MAINTAINER")
- if maintainer == "pkgsrc-users%NetBSD.org@localhost" {
+ if maintainer == "pkgsrc-users%NetBSD.org@localhost" || maintainer == "INSERT_YOUR_MAIL_ADDRESS_HERE" {
maintainer = ""
}
if owner == "" && maintainer == "" {
@@ -1260,7 +1260,7 @@ func (pkg *Package) checkFreeze(filename
line.Notef("Pkgsrc is frozen since %s.", freezeStart)
line.Explain(
"During a pkgsrc freeze, changes to pkgsrc should only be made very carefully.",
- "See https://www.netbsd.org/developers/pkgsrc/ for the exact rules.")
+ "See https://www.NetBSD.org/developers/pkgsrc/ for the exact rules.")
}
func (pkg *Package) checkIncludeConditionally(mkline *MkLine, indentation *Indentation) {
Index: pkgsrc/pkgtools/pkglint/files/vartypecheck.go
diff -u pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.62 pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.63
--- pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.62 Wed Aug 21 16:45:17 2019
+++ pkgsrc/pkgtools/pkglint/files/vartypecheck.go Tue Oct 1 21:37:59 2019
@@ -2,6 +2,7 @@ package pkglint
import (
"netbsd.org/pkglint/regex"
+ "netbsd.org/pkglint/textproc"
"path"
"sort"
"strings"
@@ -159,9 +160,69 @@ func (cv *VartypeCheck) AwkCommand() {
}
}
+// BasicRegularExpression checks for a basic regular expression, as
+// defined by POSIX.
+//
+// When they are used in a list variable (as for CHECK_FILES_SKIP), they
+// cannot include spaces. Instead, a dot or [[:space:]] must be used.
+// The regular expressions do not need any quotation for the shell; all
+// quoting issues are handled by the pkgsrc infrastructure.
+//
+// The opposite situation is when the regular expression is part of a sed
+// command. In such a case the shell quoting is undone before checking the
+// regular expression, and this is where spaces and tabs can appear.
+//
+// TODO: Add check for EREs as well.
+//
+// See https://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_03.
+// See https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03.
func (cv *VartypeCheck) BasicRegularExpression() {
- if trace.Tracing {
- trace.Step1("Unchecked basic regular expression: %q", cv.Value)
+
+ // same order as in the OpenGroup spec
+ allowedAfterBackslash := textproc.NewByteSet(")({}1-9.[\\*^$")
+
+ lexer := textproc.NewLexer(cv.ValueNoVar)
+
+ parseCharacterClass := func() {
+ for !lexer.EOF() {
+ if lexer.SkipByte('\\') {
+ if !lexer.EOF() {
+ lexer.Skip(1)
+ }
+ } else if lexer.SkipByte(']') {
+ return
+ } else {
+ lexer.Skip(1)
+ }
+ }
+ }
+
+ parseBackslash := func() {
+ if lexer.EOF() {
+ return
+ }
+
+ if !lexer.TestByteSet(allowedAfterBackslash) {
+ cv.Warnf("In a basic regular expression, a backslash followed by %q is undefined.", lexer.Rest()[:1])
+ cv.Explain(
+ "Only the characters . [ \\ * ^ $ may be escaped using a backslash.",
+ "Except when the escaped character appears in a character class like [\\.a-z].",
+ "",
+ "To fix this, remove the backslash before the character.")
+ }
+ lexer.Skip(1)
+ }
+
+ for !lexer.EOF() {
+ switch {
+ case lexer.SkipByte('['):
+ parseCharacterClass()
+
+ case lexer.SkipByte('\\'):
+ parseBackslash()
+
+ case lexer.Skip(1):
+ }
}
}
@@ -492,26 +553,28 @@ func (cv *VartypeCheck) Enum(allowedValu
}
func (cv *VartypeCheck) FetchURL() {
+ fetchURL := cv.Value
+ url := strings.TrimPrefix(fetchURL, "-")
+ hyphen := condStr(len(fetchURL) > len(url), "-", "")
+ hyphenSubst := condStr(hyphen != "", ":S,^,-,", "")
- // TODO: Handle leading "-".
-
- cv.URL()
+ cv.WithValue(url).URL()
for siteURL, siteName := range G.Pkgsrc.MasterSiteURLToVar {
- if hasPrefix(cv.Value, siteURL) {
- subdir := cv.Value[len(siteURL):]
- if hasPrefix(cv.Value, "https://github.com/") {
+ if hasPrefix(url, siteURL) {
+ subdir := url[len(siteURL):]
+ if hasPrefix(url, "https://github.com/") {
subdir = strings.SplitAfter(subdir, "/")[0]
- cv.Warnf("Please use ${%s:=%s} instead of %q and run %q for further instructions.",
- siteName, subdir, cv.Value[:len(siteURL)+len(subdir)], makeHelp("github"))
+ cv.Warnf("Please use ${%s%s:=%s} instead of %q and run %q for further instructions.",
+ siteName, hyphenSubst, subdir, hyphen+url[:len(siteURL)+len(subdir)], bmakeHelp("github"))
} else {
- cv.Warnf("Please use ${%s:=%s} instead of %q.", siteName, subdir, cv.Value)
+ cv.Warnf("Please use ${%s%s:=%s} instead of %q.", siteName, hyphenSubst, subdir, hyphen+url)
}
return
}
}
- tokens := cv.MkLine.Tokenize(cv.Value, false)
+ tokens := cv.MkLine.Tokenize(url, false)
for _, token := range tokens {
varUse := token.Varuse
if varUse == nil {
@@ -538,6 +601,26 @@ func (cv *VartypeCheck) FetchURL() {
cv.Errorf("The subdirectory in %s must end with a slash.", name)
}
}
+
+ switch {
+ case cv.Op == opUseMatch,
+ hasSuffix(fetchURL, "/"),
+ hasSuffix(fetchURL, "="),
+ hasSuffix(fetchURL, ":"),
+ hasPrefix(fetchURL, "-"),
+ len(tokens) == 0 || tokens[len(tokens)-1].Varuse != nil:
+ break
+
+ default:
+ cv.Warnf("The fetch URL %q should end with a slash.", fetchURL)
+ cv.Explain(
+ "The filename from DISTFILES is appended directly to this base URL.",
+ "Therefore it should typically end with a slash, or sometimes with",
+ "an equals sign or a colon.",
+ "",
+ "To specify a full URL directly, prefix it with a hyphen, such as in",
+ "-https://example.org/distfile-1.0.tar.gz.")
+ }
}
// Filename checks that filenames use only limited special characters.
@@ -563,7 +646,7 @@ func (cv *VartypeCheck) Filename() {
invalid)
}
-func (cv *VartypeCheck) FileMask() {
+func (cv *VartypeCheck) FilePattern() {
// TODO: Decide whether to call this a "mask" or a "pattern", and use only that word everywhere.
@@ -857,10 +940,10 @@ func (cv *VartypeCheck) Pathlist() {
}
}
-// PathMask is a shell pattern for pathnames, possibly including slashes.
+// PathPattern is a shell pattern for pathnames, possibly including slashes.
//
-// See FileMask.
-func (cv *VartypeCheck) PathMask() {
+// See FilePattern.
+func (cv *VartypeCheck) PathPattern() {
invalid := replaceAll(cv.ValueNoVar, `[%*+,\-./0-9?@A-Z\[\]_a-z~]`, "")
if invalid == "" {
return
@@ -945,15 +1028,36 @@ func (cv *VartypeCheck) PkgOptionsVar()
}
}
-// PkgPath checks a directory name relative to the top-level pkgsrc directory.
+// Pkgpath checks a directory name relative to the top-level pkgsrc directory.
//
// Despite its name, it is more similar to RelativePkgDir than to RelativePkgPath.
-func (cv *VartypeCheck) PkgPath() {
- pkgsrcdir := cv.MkLine.PathToFile(G.Pkgsrc.File("."))
- MkLineChecker{cv.MkLines, cv.MkLine}.CheckRelativePkgdir(pkgsrcdir + "/" + cv.Value)
+func (cv *VartypeCheck) Pkgpath() {
+ cv.Pathname()
+
+ pkgpath := cv.Value
+ if pkgpath != cv.ValueNoVar || cv.Op == opUseMatch {
+ return
+ }
+
+ if !G.Wip && hasPrefix(pkgpath, "wip/") {
+ cv.MkLine.Errorf("A main pkgsrc package must not depend on a pkgsrc-wip package.")
+ }
+
+ if !fileExists(G.Pkgsrc.File(joinPath(pkgpath, "Makefile"))) {
+ cv.MkLine.Errorf("There is no package in %q.",
+ relpath(path.Dir(cv.MkLine.Filename), G.Pkgsrc.File(pkgpath)))
+ return
+ }
+
+ if !matches(pkgpath, `^([^./][^/]*/[^./][^/]*)$`) {
+ cv.MkLine.Errorf("%q is not a valid path to a package.", pkgpath)
+ cv.MkLine.Explain(
+ "A path to a package has the form \"category/pkgbase\".",
+ "It is relative to the pkgsrc root.")
+ }
}
-func (cv *VartypeCheck) PkgRevision() {
+func (cv *VartypeCheck) Pkgrevision() {
if !matches(cv.Value, `^[1-9]\d*$`) {
cv.Warnf("%s must be a positive integer number.", cv.Varname)
}
@@ -1099,38 +1203,65 @@ func (cv *VartypeCheck) SedCommands() {
ntokens := len(tokens)
ncommands := 0
+ extended := false
+
+ checkSedCommand := func(quotedCommand string) {
+ // TODO: Remember the extended flag for the whole file, especially
+ // for SUBST_SED.* variables.
+ if !extended {
+ command := cv.MkLine.UnquoteShell(quotedCommand, true)
+ if !hasPrefix(command, "s") {
+ return
+ }
+
+ // The :C modifier is similar enough for parsing.
+ ok, _, from, _, _ := MkVarUseModifier{"C" + command[1:]}.MatchSubst()
+ if !ok {
+ return
+ }
+
+ cv.WithValue(from).BasicRegularExpression()
+ }
+ }
for i := 0; i < ntokens; i++ {
token := tokens[i]
switch {
case token == "-e":
- if i+1 < ntokens {
- // Check the real sed command here.
- i++
- ncommands++
- if ncommands > 1 {
- cv.Notef("Each sed command should appear in an assignment of its own.")
- cv.Explain(
- "For example, instead of",
- " SUBST_SED.foo+= -e s,command1,, -e s,command2,,",
- "use",
- " SUBST_SED.foo+= -e s,command1,,",
- " SUBST_SED.foo+= -e s,command2,,",
- "",
- "This way, short sed commands cannot be hidden at the end of a line.")
- }
- } else {
+ if i+1 >= ntokens {
cv.Errorf("The -e option to sed requires an argument.")
+ break
}
+
+ // Check the real sed command here.
+ i++
+ ncommands++
+ if ncommands > 1 {
+ cv.Notef("Each sed command should appear in an assignment of its own.")
+ cv.Explain(
+ "For example, instead of",
+ " SUBST_SED.foo+= -e s,command1,, -e s,command2,,",
+ "use",
+ " SUBST_SED.foo+= -e s,command1,,",
+ " SUBST_SED.foo+= -e s,command2,,",
+ "",
+ "This way, short sed commands cannot be hidden at the end of a line.")
+ }
+
+ checkSedCommand(tokens[i])
+
case token == "-E":
// Switch to extended regular expressions mode.
+ extended = true
case token == "-n":
// Don't print lines per default.
case matches(token, `^["']?(\d+|/.*/)?s`):
+ // TODO: "prefix with" instead of "use".
cv.Notef("Please always use \"-e\" in sed commands, even if there is only one substitution.")
+ checkSedCommand(token)
default:
cv.Warnf("Unknown sed command %q.", token)
Index: pkgsrc/pkgtools/pkglint/files/package_test.go
diff -u pkgsrc/pkgtools/pkglint/files/package_test.go:1.53 pkgsrc/pkgtools/pkglint/files/package_test.go:1.54
--- pkgsrc/pkgtools/pkglint/files/package_test.go:1.53 Sun Sep 8 22:47:47 2019
+++ pkgsrc/pkgtools/pkglint/files/package_test.go Tue Oct 1 21:37:59 2019
@@ -1551,7 +1551,7 @@ func (s *Suite) Test_Package_checkUpdate
"WARN: category/pkg2/Makefile:4: This package should be updated to 2.0 ([nice new features]).",
"NOTE: category/pkg3/Makefile:4: This package is newer than the update request to 3.0 ([security update]).",
"4 warnings and 2 notes found.",
- "(Run \"pkglint -e\" to show explanations.)")
+ "(Run \"pkglint -e -Wall,no-space category/pkg1 category/pkg2 category/pkg3\" to show explanations.)")
}
func (s *Suite) Test_NewPackage(c *check.C) {
@@ -2625,12 +2625,30 @@ func (s *Suite) Test_Package_checkOwnerM
G.Check(pkg)
+ // No warning for the patches directory, only for regular files.
t.CheckOutputLines(
"NOTE: ~/category/package/Makefile: " +
"Please only commit changes that " +
"maintainer%example.org@localhost would approve.")
}
+func (s *Suite) Test_Package_checkOwnerMaintainer__url2pkg(c *check.C) {
+ t := s.Init(c)
+
+ G.Username = "example-user"
+ pkg := t.SetUpPackage("category/package",
+ "MAINTAINER=\tINSERT_YOUR_MAIL_ADDRESS_HERE")
+ t.CreateFileLines("category/package/CVS/Entries",
+ "/Makefile//modified//")
+ t.FinishSetUp()
+
+ G.Check(pkg)
+
+ t.CheckOutputLines(
+ "WARN: ~/category/package/Makefile:8: " +
+ "\"INSERT_YOUR_MAIL_ADDRESS_HERE\" is not a valid mail address.")
+}
+
func (s *Suite) Test_Package_checkFreeze(c *check.C) {
t := s.Init(c)
@@ -2648,7 +2666,7 @@ func (s *Suite) Test_Package_checkFreeze
"NOTE: ~/category/package/Makefile: Pkgsrc is frozen since 2018-03-20.",
"",
"\tDuring a pkgsrc freeze, changes to pkgsrc should only be made very",
- "\tcarefully. See https://www.netbsd.org/developers/pkgsrc/ for the",
+ "\tcarefully. See https://www.NetBSD.org/developers/pkgsrc/ for the",
"\texact rules.",
"")
}
Index: pkgsrc/pkgtools/pkglint/files/pkglint.go
diff -u pkgsrc/pkgtools/pkglint/files/pkglint.go:1.60 pkgsrc/pkgtools/pkglint/files/pkglint.go:1.61
--- pkgsrc/pkgtools/pkglint/files/pkglint.go:1.60 Sun Sep 8 22:47:47 2019
+++ pkgsrc/pkgtools/pkglint/files/pkglint.go Tue Oct 1 21:37:59 2019
@@ -198,7 +198,7 @@ func (pkglint *Pkglint) Main(stdout io.W
pkglint.Pkgsrc.checkToplevelUnusedLicenses()
- pkglint.Logger.ShowSummary()
+ pkglint.Logger.ShowSummary(args)
if pkglint.Logger.errors != 0 {
return 1
}
@@ -272,7 +272,7 @@ func (pkglint *Pkglint) prepareMainLoop(
dummyLine.Fatalf("%q must be inside a pkgsrc tree.", firstDir)
}
- pkglint.Pkgsrc = NewPkgsrc(firstDir + "/" + relTopdir)
+ pkglint.Pkgsrc = NewPkgsrc(joinPath(firstDir, relTopdir))
pkglint.Wip = matches(pkglint.Pkgsrc.ToRel(firstDir), `^wip(/|$)`) // Same as in Pkglint.Check.
pkglint.Pkgsrc.LoadInfrastructure()
@@ -431,7 +431,7 @@ func (pkglint *Pkglint) checkdirPackage(
// Returns the pkgsrc top-level directory, relative to the given directory.
func findPkgsrcTopdir(dirname string) string {
for _, dir := range [...]string{".", "..", "../..", "../../.."} {
- if fileExists(dirname + "/" + dir + "/mk/bsd.pkg.mk") {
+ if fileExists(joinPath(dirname, dir, "mk/bsd.pkg.mk")) {
return dir
}
}
Index: pkgsrc/pkgtools/pkglint/files/pkglint_test.go
diff -u pkgsrc/pkgtools/pkglint/files/pkglint_test.go:1.47 pkgsrc/pkgtools/pkglint/files/pkglint_test.go:1.48
--- pkgsrc/pkgtools/pkglint/files/pkglint_test.go:1.47 Sun Sep 8 22:47:47 2019
+++ pkgsrc/pkgtools/pkglint/files/pkglint_test.go Tue Oct 1 21:37:59 2019
@@ -215,7 +215,7 @@ func (s *Suite) Test_Pkglint_Main__compl
"Size (checkperms-1.12.tar.gz) = 6621 bytes",
"SHA1 (patch-checkperms.c) = asdfasdf") // Invalid SHA-1 checksum
- t.Main("-Wall", "-Call", t.File("sysutils/checkperms"))
+ t.Main("-Wall", "-Call", "sysutils/checkperms")
t.CheckOutputLines(
"NOTE: ~/sysutils/checkperms/Makefile:3: "+
@@ -231,9 +231,9 @@ func (s *Suite) Test_Pkglint_Main__compl
"WARN: ~/sysutils/checkperms/patches/patch-checkperms.c:12: Premature end of patch hunk "+
"(expected 1 lines to be deleted and 0 lines to be added).",
"4 errors, 2 warnings and 1 note found.",
- "(Run \"pkglint -e\" to show explanations.)",
- "(Run \"pkglint -fs\" to show what can be fixed automatically.)",
- "(Run \"pkglint -F\" to automatically fix some issues.)")
+ t.Shquote("(Run \"pkglint -e -Wall -Call %s\" to show explanations.)", "sysutils/checkperms"),
+ t.Shquote("(Run \"pkglint -fs -Wall -Call %s\" to show what can be fixed automatically.)", "sysutils/checkperms"),
+ t.Shquote("(Run \"pkglint -F -Wall -Call %s\" to automatically fix some issues.)", "sysutils/checkperms"))
}
func (s *Suite) Test_Pkglint_Main__autofix_exitcode(c *check.C) {
@@ -611,7 +611,7 @@ func (s *Suite) Test_Pkglint_checkReg__a
t.CheckOutputLines(
"ERROR: ~/category/package/ALTERNATIVES:1: Alternative implementation \"bin/gnu-tar\" must be an absolute path.",
"1 error found.",
- "(Run \"pkglint -e\" to show explanations.)")
+ t.Shquote("(Run \"pkglint -e %s\" to show explanations.)", "category/package/ALTERNATIVES"))
}
// Just for branch coverage.
Index: pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go
diff -u pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go:1.29 pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go:1.30
--- pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go:1.29 Tue Jul 30 18:31:43 2019
+++ pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go Tue Oct 1 21:37:59 2019
@@ -464,7 +464,7 @@ func (s *Suite) Test_Pkgsrc_loadDocChang
t.CheckOutputLines(
"WARN: ~/category/package/Makefile:3: The package is being downgraded from 2.0 (see ../../doc/CHANGES-2018:9) to 1.0.",
"1 warning found.",
- "(Run \"pkglint -e\" to show explanations.)")
+ t.Shquote("(Run \"pkglint -e %s\" to show explanations.)", "category/package"))
// Only when the global checks are enabled, the errors from doc/CHANGES are shown.
t.Main("-Cglobal", "-Wall", ".")
@@ -475,7 +475,7 @@ func (s *Suite) Test_Pkgsrc_loadDocChang
"WARN: ~/doc/CHANGES-2018:8: Unknown doc/CHANGES line: \tInvalid pkgpath to 1.16 [rillig 2019-06-16]",
"WARN: ~/doc/CHANGES-2018:9: Year \"2019\" for category/package does not match the filename ~/doc/CHANGES-2018.",
"4 warnings found.",
- "(Run \"pkglint -e\" to show explanations.)")
+ t.Shquote("(Run \"pkglint -e -Cglobal -Wall %s\" to show explanations.)", "."))
}
func (s *Suite) Test_Pkgsrc_loadDocChangesFromFile__wrong_indentation(c *check.C) {
@@ -496,7 +496,7 @@ func (s *Suite) Test_Pkgsrc_loadDocChang
"WARN: ~/doc/CHANGES-2018:5: Package changes should be indented using a single tab, not \" \".",
"WARN: ~/doc/CHANGES-2018:6: Package changes should be indented using a single tab, not \" \\t\".",
"2 warnings found.",
- "(Run \"pkglint -e\" to show explanations.)")
+ t.Shquote("(Run \"pkglint -e -Cglobal -Wall %s\" to show explanations.)", "category/package"))
}
// Once or twice in a decade, changes to the pkgsrc infrastructure are also
@@ -967,12 +967,12 @@ func (s *Suite) Test_Pkgsrc_VariableType
t1 := G.Pkgsrc.VariableType(nil, "FONT_DIRS")
c.Assert(t1, check.NotNil)
- t.CheckEquals(t1.String(), "PathMask (list, guessed)")
+ t.CheckEquals(t1.String(), "PathPattern (list, guessed)")
t2 := G.Pkgsrc.VariableType(nil, "FONT_DIRS.ttf")
c.Assert(t2, check.NotNil)
- t.CheckEquals(t2.String(), "PathMask (list, guessed)")
+ t.CheckEquals(t2.String(), "PathPattern (list, guessed)")
}
// Guessing the variable type also works for variables that are
@@ -1019,7 +1019,7 @@ func (s *Suite) Test_Pkgsrc_VariableType
"WARN: ~/category/package/Makefile:21: PKGSRC_UNKNOWN_ENV is defined but not used.",
"WARN: ~/category/package/Makefile:21: ABCPATH is used but not defined.",
"2 warnings found.",
- "(Run \"pkglint -e\" to show explanations.)")
+ t.Shquote("(Run \"pkglint -e -Wall %s\" to show explanations.)", "category/package"))
}
func (s *Suite) Test_Pkgsrc_guessVariableType__SKIP(c *check.C) {
Index: pkgsrc/pkgtools/pkglint/files/shell.go
diff -u pkgsrc/pkgtools/pkglint/files/shell.go:1.45 pkgsrc/pkgtools/pkglint/files/shell.go:1.46
--- pkgsrc/pkgtools/pkglint/files/shell.go:1.45 Sun Sep 8 22:47:47 2019
+++ pkgsrc/pkgtools/pkglint/files/shell.go Tue Oct 1 21:37:59 2019
@@ -189,8 +189,8 @@ func (ck *ShellLineChecker) checkVaruseT
case (quoting == shqSquot || quoting == shqDquot) && matches(varname, `^(?:.*DIR|.*FILE|.*PATH|.*_VAR|PREFIX|.*BASE|PKGNAME)$`):
// This is ok as long as these variables don't have embedded [$\\"'`].
- case quoting == shqDquot && varuse.IsQ():
- ck.Warnf("The :Q modifier should not be used inside double quotes.")
+ case quoting != shqPlain && varuse.IsQ():
+ ck.Warnf("The :Q modifier should not be used inside quotes.")
ck.Explain(
"The :Q modifier is intended for embedding a string into a shell program.",
"It escapes all characters that have a special meaning in shell programs.",
@@ -312,7 +312,7 @@ func (ck *ShellLineChecker) CheckShellCo
"hidden behind the scenes.",
"",
// TODO: Provide a copy-and-paste example.
- sprintf("Run %q for more information.", makeHelp("subst")))
+ sprintf("Run %q for more information.", bmakeHelp("subst")))
if contains(shelltext, "#") {
line.Explain(
"When migrating to the SUBST framework, pay attention to \"#\" characters.",
@@ -375,7 +375,7 @@ func (ck *ShellLineChecker) CheckShellCo
}
walker.Callback.AndOr = func(andor *MkShAndOr) {
if G.Opts.WarnExtra && !*pSetE && walker.Current().Index != 0 {
- spc.checkSetE(walker.Parent(1).(*MkShList), walker.Current().Index, andor)
+ spc.checkSetE(walker.Parent(1).(*MkShList), walker.Current().Index)
}
}
walker.Callback.Pipeline = func(pipeline *MkShPipeline) {
@@ -976,7 +976,7 @@ func (spc *ShellProgramChecker) canFail(
return true
}
-func (spc *ShellProgramChecker) checkSetE(list *MkShList, index int, andor *MkShAndOr) {
+func (spc *ShellProgramChecker) checkSetE(list *MkShList, index int) {
if trace.Tracing {
defer trace.Call0()()
}
Index: pkgsrc/pkgtools/pkglint/files/shell_test.go
diff -u pkgsrc/pkgtools/pkglint/files/shell_test.go:1.52 pkgsrc/pkgtools/pkglint/files/shell_test.go:1.53
--- pkgsrc/pkgtools/pkglint/files/shell_test.go:1.52 Thu Sep 12 21:15:48 2019
+++ pkgsrc/pkgtools/pkglint/files/shell_test.go Tue Oct 1 21:37:59 2019
@@ -183,11 +183,18 @@ func (s *Suite) Test_ShellLineChecker_Ch
"NOTE: filename.mk:1: The :Q modifier isn't necessary for ${PKGNAME} here.")
test("echo \"${CFLAGS:Q}\"", // VucQuotDquot
- "WARN: filename.mk:1: The :Q modifier should not be used inside double quotes.",
+
+ // ShellLineChecker.checkVaruseToken
+ "WARN: filename.mk:1: The :Q modifier should not be used inside quotes.",
+
+ // ShellLineChecker.checkVaruseToken
+ // MkLineChecker.CheckVaruse
+ // MkLineChecker.checkVarUseQuoting
"WARN: filename.mk:1: Please use ${CFLAGS:M*:Q} instead of ${CFLAGS:Q} "+
"and make sure the variable appears outside of any quoting characters.")
test("echo '${COMMENT:Q}'", // VucQuotSquot
+ "WARN: filename.mk:1: The :Q modifier should not be used inside quotes.",
"WARN: filename.mk:1: Please move ${COMMENT:Q} outside of any quoting characters.")
test("echo target=$@ exitcode=$$? '$$' \"\\$$\"",
@@ -1463,6 +1470,33 @@ func (s *Suite) Test_SimpleCommandChecke
"NOTE: filename.mk:1: You can use \"INSTALLATION_DIRS+= share/other\" instead of \"${INSTALL_DATA_DIR}\".")
}
+func (s *Suite) Test_SimpleCommandChecker_checkAutoMkdirs__redundant(c *check.C) {
+ t := s.Init(c)
+
+ t.SetUpPackage("category/package",
+ "AUTO_MKDIRS=\tyes",
+ "INSTALLATION_DIRS+=\tshare/redundant",
+ "INSTALLATION_DIRS+=\tnot/redundant ${EGDIR}")
+ t.CreateFileLines("category/package/PLIST",
+ PlistCvsID,
+ "share/redundant/file",
+ "${EGDIR}/file")
+
+ t.Main("-Wall", "-q", "category/package")
+
+ t.CheckOutputLines(
+ "NOTE: ~/category/package/Makefile:21: The directory \"share/redundant\" "+
+ "is redundant in INSTALLATION_DIRS.",
+ // The below is not proven to be always correct. It assumes that a
+ // variable in the Makefile has the same value as the corresponding
+ // variable from PLIST_SUBST. Violating this assumption would be
+ // confusing to the pkgsrc developers, therefore it's a safe bet.
+ // A notable counterexample is PKGNAME in PLIST, which corresponds
+ // to PKGNAME_NOREV in the package Makefile.
+ "NOTE: ~/category/package/Makefile:22: The directory \"${EGDIR}\" "+
+ "is redundant in INSTALLATION_DIRS.")
+}
+
// The AUTO_MKDIRS code in mk/install/install.mk (install-dirs-from-PLIST)
// skips conditional directories, as well as directories with placeholders.
func (s *Suite) Test_SimpleCommandChecker_checkAutoMkdirs__conditional_PLIST(c *check.C) {
Index: pkgsrc/pkgtools/pkglint/files/util.go
diff -u pkgsrc/pkgtools/pkglint/files/util.go:1.52 pkgsrc/pkgtools/pkglint/files/util.go:1.53
--- pkgsrc/pkgtools/pkglint/files/util.go:1.52 Thu Sep 12 21:15:48 2019
+++ pkgsrc/pkgtools/pkglint/files/util.go Tue Oct 1 21:37:59 2019
@@ -238,7 +238,7 @@ func isEmptyDir(filename string) bool {
if isIgnoredFilename(name) {
continue
}
- if dirent.IsDir() && isEmptyDir(filename+"/"+name) {
+ if dirent.IsDir() && isEmptyDir(joinPath(filename, name)) {
continue
}
return false
@@ -255,7 +255,7 @@ func getSubdirs(filename string) []strin
var subdirs []string
for _, dirent := range dirents {
name := dirent.Name()
- if dirent.IsDir() && !isIgnoredFilename(name) && !isEmptyDir(filename+"/"+name) {
+ if dirent.IsDir() && !isIgnoredFilename(name) && !isEmptyDir(joinPath(filename, name)) {
subdirs = append(subdirs, name)
}
}
@@ -278,7 +278,7 @@ func dirglob(dirname string) []string {
var filenames []string
for _, info := range infos {
if !(isIgnoredFilename(info.Name())) {
- filenames = append(filenames, cleanpath(dirname+"/"+info.Name()))
+ filenames = append(filenames, cleanpath(joinPath(dirname, info.Name())))
}
}
return filenames
@@ -444,6 +444,13 @@ func mkopSubst(s string, left bool, from
})
}
+func joinPath(a, b string, others ...string) string {
+ if len(others) == 0 {
+ return a + "/" + b
+ }
+ return a + "/" + b + "/" + strings.Join(others, "/")
+}
+
// relpath returns the relative path from the directory "from"
// to the filesystem entry "to".
//
@@ -502,7 +509,7 @@ func relpath(from, to string) (result st
fromTop, err := filepath.Rel(absTopdir, absTo)
assertNil(err, "relpath from topdir %q to %q", absTopdir, absTo)
- result = cleanpath(filepath.ToSlash(toTop) + "/" + filepath.ToSlash(fromTop))
+ result = cleanpath(joinPath(filepath.ToSlash(toTop), filepath.ToSlash(fromTop)))
if trace.Tracing {
trace.Stepf("relpath from %q to %q = %q", cfrom, cto, result)
@@ -513,7 +520,7 @@ func relpath(from, to string) (result st
func abspath(filename string) string {
abs := filename
if !filepath.IsAbs(filename) {
- abs = G.cwd + "/" + abs
+ abs = joinPath(G.cwd, abs)
}
return path.Clean(abs)
}
@@ -1108,7 +1115,7 @@ func (c *FileCache) key(filename string)
return path.Clean(filename)
}
-func makeHelp(topic string) string { return bmake("help topic=" + topic) }
+func bmakeHelp(topic string) string { return bmake("help topic=" + topic) }
func bmake(target string) string { return sprintf("%s %s", confMake, target) }
@@ -1353,7 +1360,10 @@ func (s *StringSet) AddAll(elements []st
}
}
-func (s *StringSet) Contains(needle string) bool {
- _, found := s.seen[needle]
- return found
+// See mk/tools/shquote.sh.
+func shquote(s string) string {
+ if matches(s, `^[!%+,\-./0-9:=@A-Z_a-z]+$`) {
+ return s
+ }
+ return "'" + strings.Replace(s, "'", "'\\''", -1) + "'"
}
Index: pkgsrc/pkgtools/pkglint/files/tools_test.go
diff -u pkgsrc/pkgtools/pkglint/files/tools_test.go:1.19 pkgsrc/pkgtools/pkglint/files/tools_test.go:1.20
--- pkgsrc/pkgtools/pkglint/files/tools_test.go:1.19 Sun Jul 14 21:25:47 2019
+++ pkgsrc/pkgtools/pkglint/files/tools_test.go Tue Oct 1 21:37:59 2019
@@ -144,7 +144,7 @@ func (s *Suite) Test_Tools__USE_TOOLS_pr
"WARN: ~/module.mk:5: Unknown shell command \"${AWK}\".",
"WARN: ~/module.mk:5: AWK is used but not defined.",
"2 warnings found.",
- "(Run \"pkglint -e\" to show explanations.)")
+ t.Shquote("(Run \"pkglint -e -Wall %s\" to show explanations.)", "module.mk"))
}
// It may happen that a tool is first defined without knowing its
Index: pkgsrc/pkgtools/pkglint/files/toplevel_test.go
diff -u pkgsrc/pkgtools/pkglint/files/toplevel_test.go:1.19 pkgsrc/pkgtools/pkglint/files/toplevel_test.go:1.20
--- pkgsrc/pkgtools/pkglint/files/toplevel_test.go:1.19 Sun Jul 14 21:25:47 2019
+++ pkgsrc/pkgtools/pkglint/files/toplevel_test.go Tue Oct 1 21:37:59 2019
@@ -101,7 +101,7 @@ func (s *Suite) Test_CheckdirToplevel__r
t.CheckOutputLines(
"WARN: ~/category/package/Makefile:20: UNKNOWN is defined but not used.",
"1 warning found.",
- "(Run \"pkglint -e\" to show explanations.)")
+ t.Shquote("(Run \"pkglint -e -Wall -r %s\" to show explanations.)", "."))
}
func (s *Suite) Test_CheckdirToplevel__recursive_inter_package(c *check.C) {
@@ -130,7 +130,7 @@ func (s *Suite) Test_CheckdirToplevel__r
"WARN: ~/category/package/Makefile:20: UNKNOWN is defined but not used.",
"WARN: ~/licenses/gnu-gpl-v2: This license seems to be unused.",
"2 warnings found.",
- "(Run \"pkglint -e\" to show explanations.)")
+ t.Shquote("(Run \"pkglint -e -Wall -Call -r %s\" to show explanations.)", "."))
}
func (s *Suite) Test_CheckdirToplevel__indentation(c *check.C) {
@@ -150,7 +150,7 @@ func (s *Suite) Test_CheckdirToplevel__i
t.CheckOutputLines(
"NOTE: ~/Makefile:4: This variable value should be aligned to column 17.",
"Looks fine.",
- "(Run \"pkglint -e\" to show explanations.)",
- "(Run \"pkglint -fs\" to show what can be fixed automatically.)",
- "(Run \"pkglint -F\" to automatically fix some issues.)")
+ t.Shquote("(Run \"pkglint -e -Wall %s\" to show explanations.)", "."),
+ t.Shquote("(Run \"pkglint -fs -Wall %s\" to show what can be fixed automatically.)", "."),
+ t.Shquote("(Run \"pkglint -F -Wall %s\" to automatically fix some issues.)", "."))
}
Index: pkgsrc/pkgtools/pkglint/files/vardefs.go
diff -u pkgsrc/pkgtools/pkglint/files/vardefs.go:1.72 pkgsrc/pkgtools/pkglint/files/vardefs.go:1.73
--- pkgsrc/pkgtools/pkglint/files/vardefs.go:1.72 Thu Sep 12 21:15:48 2019
+++ pkgsrc/pkgtools/pkglint/files/vardefs.go Tue Oct 1 21:37:59 2019
@@ -510,7 +510,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.usr("MOTIFBASE", BtPathname)
reg.usr("PKGINFODIR", BtPathname)
- reg.usr("PKGMANDIR", BtPathname)
+ reg.usr("PKGMANDIR", BtPrefixPathname)
reg.usr("PKGGNUDIR", BtPathname)
reg.usr("BSDSRCDIR", BtPathname)
reg.usr("BSDXSRCDIR", BtPathname)
@@ -529,10 +529,10 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.usr("PATCH_FUZZ_FACTOR", enum("none -F0 -F1 -F2 -F3"))
reg.usrlist("ACCEPTABLE_LICENSES", BtIdentifier)
reg.usr("SPECIFIC_PKGS", BtYes)
- reg.usrlist("SITE_SPECIFIC_PKGS", BtPkgPath)
- reg.usrlist("HOST_SPECIFIC_PKGS", BtPkgPath)
- reg.usrlist("GROUP_SPECIFIC_PKGS", BtPkgPath)
- reg.usrlist("USER_SPECIFIC_PKGS", BtPkgPath)
+ reg.usrlist("SITE_SPECIFIC_PKGS", BtPkgpath)
+ reg.usrlist("HOST_SPECIFIC_PKGS", BtPkgpath)
+ reg.usrlist("GROUP_SPECIFIC_PKGS", BtPkgpath)
+ reg.usrlist("USER_SPECIFIC_PKGS", BtPkgpath)
reg.usr("FAILOVER_FETCH", BtYes)
reg.usrlist("MASTER_SORT", BtUnknown)
reg.usrlist("MASTER_SORT_REGEX", BtUnknown)
@@ -629,7 +629,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.usr("ICECAST_SOURCE_BUFFSIZE", BtInteger)
reg.usr("IMAP_UW_CCLIENT_MBOX_FMT",
enum("mbox mbx mh mmdf mtx mx news phile tenex unix"))
- reg.usr("IMAP_UW_MAILSPOOLHOME", BtFileName)
+ reg.usr("IMAP_UW_MAILSPOOLHOME", BtFilename)
reg.usr("IMDICTDIR", BtPathname)
reg.usr("INN_DATA_DIR", BtPathname)
reg.usr("INN_USER", BtUserGroupName)
@@ -711,7 +711,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.usr("PILRC_USE_GTK", BtYesNo)
reg.usr("PKG_JVM_DEFAULT", jvms)
reg.usr("POPTOP_USE_MPPE", BtYes)
- reg.usr("PROCMAIL_MAILSPOOLHOME", BtFileName)
+ reg.usr("PROCMAIL_MAILSPOOLHOME", BtFilename)
// Comma-separated list of string or integer literals.
reg.usr("PROCMAIL_TRUSTED_IDS", BtUnknown)
reg.usr("PVM_SSH", BtPathname)
@@ -740,7 +740,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.usr("RSSH_CVS_PATH", BtPathname)
reg.usr("RSSH_RDIST_PATH", BtPathname)
reg.usr("RSSH_RSYNC_PATH", BtPathname)
- reg.usrlist("SAWFISH_THEMES", BtFileName)
+ reg.usrlist("SAWFISH_THEMES", BtFilename)
reg.usr("SCREWS_GROUP", BtUserGroupName)
reg.usr("SCREWS_USER", BtUserGroupName)
reg.usr("SDIST_PAWD", enum("pawd pwd"))
@@ -783,13 +783,13 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.sys(".TARGET", BtPathname)
reg.sys("@", BtPathname)
reg.pkglistbl3("ALL_ENV", BtShellWord)
- reg.pkg("ALTERNATIVES_FILE", BtFileName)
+ reg.pkg("ALTERNATIVES_FILE", BtFilename)
reg.pkglist("ALTERNATIVES_SRC", BtPathname)
reg.pkg("APACHE_MODULE", BtYes)
reg.sys("AR", BtShellCommand)
reg.sys("AS", BtShellCommand)
reg.pkglist("AUTOCONF_REQD", BtVersion)
- reg.pkglist("AUTOMAKE_OVERRIDE", BtPathmask)
+ reg.pkglist("AUTOMAKE_OVERRIDE", BtPathPattern)
reg.pkglist("AUTOMAKE_REQD", BtVersion)
reg.pkg("AUTO_MKDIRS", BtYesNo)
reg.usr("BATCH", BtYes)
@@ -841,7 +841,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.acl("BUILDLINK_DIR", BtPathname,
PackageSettable,
"*: use")
- reg.bl3list("BUILDLINK_FILES.*", BtPathmask)
+ reg.bl3list("BUILDLINK_FILES.*", BtPathPattern)
reg.pkgbl3("BUILDLINK_FILES_CMD.*", BtShellCommand)
reg.acllist("BUILDLINK_INCDIRS.*", BtPathname,
PackageSettable,
@@ -917,7 +917,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
PackageSettable,
"builtin.mk: set, use, use-loadtime",
"Makefile, Makefile.*, *.mk: use, use-loadtime")
- reg.acl("BUILTIN_PKG.*", BtPkgName,
+ reg.acl("BUILTIN_PKG.*", BtPkgname,
PackageSettable,
"builtin.mk: set, use, use-loadtime")
reg.pkglistbl3("BUILTIN_FIND_FILES_VAR", BtVariableName)
@@ -953,27 +953,27 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.pkglist("CHECK_FILES_SKIP", BtBasicRegularExpression)
reg.pkg("CHECK_FILES_SUPPORTED", BtYesNo)
reg.usr("CHECK_HEADERS", BtYesNo)
- reg.pkglist("CHECK_HEADERS_SKIP", BtPathmask)
+ reg.pkglist("CHECK_HEADERS_SKIP", BtPathPattern)
reg.usr("CHECK_INTERPRETER", BtYesNo)
- reg.pkglist("CHECK_INTERPRETER_SKIP", BtPathmask)
+ reg.pkglist("CHECK_INTERPRETER_SKIP", BtPathPattern)
reg.usr("CHECK_PERMS", BtYesNo)
- reg.pkglist("CHECK_PERMS_SKIP", BtPathmask)
+ reg.pkglist("CHECK_PERMS_SKIP", BtPathPattern)
reg.usr("CHECK_PORTABILITY", BtYesNo)
- reg.pkglist("CHECK_PORTABILITY_SKIP", BtPathmask)
+ reg.pkglist("CHECK_PORTABILITY_SKIP", BtPathPattern)
reg.usr("CHECK_RELRO", BtYesNo)
- reg.pkglist("CHECK_RELRO_SKIP", BtPathmask)
+ reg.pkglist("CHECK_RELRO_SKIP", BtPathPattern)
reg.pkg("CHECK_RELRO_SUPPORTED", BtYesNo)
reg.pkg("CHECK_SHLIBS", BtYesNo)
- reg.pkglist("CHECK_SHLIBS_SKIP", BtPathmask)
+ reg.pkglist("CHECK_SHLIBS_SKIP", BtPathPattern)
reg.pkg("CHECK_SHLIBS_SUPPORTED", BtYesNo)
- reg.pkglist("CHECK_WRKREF_SKIP", BtPathmask)
+ reg.pkglist("CHECK_WRKREF_SKIP", BtPathPattern)
reg.pkg("CMAKE_ARG_PATH", BtPathname)
reg.pkglist("CMAKE_ARGS", BtShellWord)
reg.pkglist("CMAKE_ARGS.*", BtShellWord)
- reg.pkglist("CMAKE_DEPENDENCIES_REWRITE", BtPathmask) // Relative to WRKSRC
- reg.pkglist("CMAKE_MODULE_PATH_OVERRIDE", BtPathmask) // Relative to WRKSRC
+ reg.pkglist("CMAKE_DEPENDENCIES_REWRITE", BtPathPattern) // Relative to WRKSRC
+ reg.pkglist("CMAKE_MODULE_PATH_OVERRIDE", BtPathPattern) // Relative to WRKSRC
reg.pkg("CMAKE_PKGSRC_BUILD_FLAGS", BtYesNo)
- reg.pkglist("CMAKE_PREFIX_PATH", BtPathmask)
+ reg.pkglist("CMAKE_PREFIX_PATH", BtPathPattern)
reg.pkg("CMAKE_USE_GNU_INSTALL_DIRS", BtYesNo)
reg.pkg("CMAKE_INSTALL_PREFIX", BtPathname) // The default is ${PREFIX}.
reg.pkgappend("COMMENT", BtComment)
@@ -988,10 +988,10 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.pkg("CONFIGURE_HAS_LIBDIR", BtYesNo)
reg.pkg("CONFIGURE_HAS_MANDIR", BtYesNo)
reg.pkg("CONFIGURE_SCRIPT", BtPathname)
- reg.pkglist("CONFIG_GUESS_OVERRIDE", BtPathmask)
- reg.pkglist("CONFIG_STATUS_OVERRIDE", BtPathmask)
+ reg.pkglist("CONFIG_GUESS_OVERRIDE", BtPathPattern)
+ reg.pkglist("CONFIG_STATUS_OVERRIDE", BtPathPattern)
reg.pkg("CONFIG_SHELL", BtPathname)
- reg.pkglist("CONFIG_SUB_OVERRIDE", BtPathmask)
+ reg.pkglist("CONFIG_SUB_OVERRIDE", BtPathPattern)
reg.pkglist("CONFLICTS", BtDependency)
reg.pkgappend("CONF_FILES", BtConfFiles)
reg.pkg("CONF_FILES_MODE", enum("0644 0640 0600 0400"))
@@ -1016,15 +1016,15 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.pkg("DESTDIR_VARNAME", BtVariableName)
reg.sys("DEVOSSAUDIO", BtPathname)
reg.sys("DEVOSSSOUND", BtPathname)
- reg.pkglist("DISTFILES", BtFileName)
+ reg.pkglist("DISTFILES", BtFilename)
reg.pkg("DISTINFO_FILE", BtRelativePkgPath)
- reg.pkg("DISTNAME", BtFileName)
+ reg.pkg("DISTNAME", BtFilename)
reg.pkg("DIST_SUBDIR", BtPathname)
reg.pkglist("DJB_BUILD_ARGS", BtShellWord)
reg.pkglist("DJB_BUILD_TARGETS", BtIdentifier)
reg.pkgappend("DJB_CONFIG_CMDS", BtShellCommands)
reg.pkglist("DJB_CONFIG_DIRS", BtWrksrcSubdirectory)
- reg.pkg("DJB_CONFIG_HOME", BtFileName)
+ reg.pkg("DJB_CONFIG_HOME", BtFilename)
reg.pkg("DJB_CONFIG_PREFIX", BtPathname)
reg.pkglist("DJB_INSTALL_TARGETS", BtIdentifier)
reg.pkg("DJB_MAKE_TARGETS", BtYesNo)
@@ -1079,7 +1079,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.sys("EXTRACT_CMD", BtShellCommand)
reg.pkg("EXTRACT_DIR", BtPathname)
reg.pkg("EXTRACT_DIR.*", BtPathname)
- reg.pkglist("EXTRACT_ELEMENTS", BtPathmask)
+ reg.pkglist("EXTRACT_ELEMENTS", BtPathPattern)
reg.pkglist("EXTRACT_ENV", BtShellWord)
reg.pkglist("EXTRACT_ONLY", BtPathname)
reg.pkglist("EXTRACT_OPTS", BtShellWord)
@@ -1109,7 +1109,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.pkgappend("GENERATE_PLIST", BtShellCommands)
reg.pkg("GITHUB_PROJECT", BtIdentifier)
reg.pkg("GITHUB_TAG", BtIdentifier)
- reg.pkg("GITHUB_RELEASE", BtFileName)
+ reg.pkg("GITHUB_RELEASE", BtFilename)
reg.pkg("GITHUB_TYPE", enum("tag release"))
reg.pkgrat("GMAKE_REQD", BtVersion)
// Some packages need to set GNU_ARCH.i386 to either i486 or i586.
@@ -1175,9 +1175,9 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.sys("JAVA_BINPREFIX", BtPathname)
reg.pkg("JAVA_CLASSPATH", BtShellWord)
reg.pkg("JAVA_HOME", BtPathname)
- reg.pkg("JAVA_NAME", BtFileName)
+ reg.pkg("JAVA_NAME", BtFilename)
reg.pkglist("JAVA_UNLIMIT", enum("cmdsize datasize stacksize"))
- reg.pkglist("JAVA_WRAPPERS", BtFileName)
+ reg.pkglist("JAVA_WRAPPERS", BtFilename)
reg.pkg("JAVA_WRAPPER_BIN.*", BtPathname)
reg.sys("KRB5BASE", BtPathname)
reg.pkglist("KRB5_ACCEPTED", enum("heimdal mit-krb5"))
@@ -1194,7 +1194,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.pkglist("LIBS", BtLdFlag)
reg.pkglist("LIBS.*", BtLdFlag)
reg.sys("LIBTOOL", BtShellCommand)
- reg.pkglist("LIBTOOL_OVERRIDE", BtPathmask)
+ reg.pkglist("LIBTOOL_OVERRIDE", BtPathPattern)
reg.pkglistrat("LIBTOOL_REQD", BtVersion)
reg.pkgappend("LICENCE", BtLicense)
reg.pkgappend("LICENSE", BtLicense)
@@ -1205,7 +1205,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.sys("LOWER_OPSYS", BtIdentifier)
reg.sys("LOWER_VENDOR", BtIdentifier)
reg.syslist("LP64PLATFORMS", BtMachinePlatformPattern)
- reg.pkglist("LTCONFIG_OVERRIDE", BtPathmask)
+ reg.pkglist("LTCONFIG_OVERRIDE", BtPathPattern)
reg.sysload("MACHINE_ARCH", enumMachineArch)
reg.sysload("MACHINE_GNU_ARCH", enumMachineGnuArch)
reg.sysload("MACHINE_GNU_PLATFORM", BtMachineGnuPlatform)
@@ -1256,8 +1256,8 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.pkglistrat("NOT_FOR_BULK_PLATFORM", BtMachinePlatformPattern)
reg.pkglistrat("NOT_FOR_PLATFORM", BtMachinePlatformPattern)
reg.pkgrat("NOT_FOR_UNPRIVILEGED", BtYesNo)
- reg.pkglistrat("NOT_PAX_ASLR_SAFE", BtPathmask)
- reg.pkglistrat("NOT_PAX_MPROTECT_SAFE", BtPathmask)
+ reg.pkglistrat("NOT_PAX_ASLR_SAFE", BtPathPattern)
+ reg.pkglistrat("NOT_PAX_MPROTECT_SAFE", BtPathPattern)
reg.pkg("NO_BIN_ON_CDROM", BtRestricted)
reg.pkg("NO_BIN_ON_FTP", BtRestricted)
reg.pkgload("NO_BUILD", BtYes)
@@ -1282,12 +1282,12 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.pkg("OVERRIDE_DIRDEPTH*", BtInteger)
reg.pkg("OVERRIDE_GNU_CONFIG_SCRIPTS", BtYes)
reg.pkg("OWNER", BtMailAddress)
- reg.pkglist("OWN_DIRS", BtPathmask)
+ reg.pkglist("OWN_DIRS", BtPathPattern)
reg.pkglist("OWN_DIRS_PERMS", BtPerms)
reg.sys("PAMBASE", BtPathname)
reg.usr("PAM_DEFAULT", enum("linux-pam openpam solaris-pam"))
reg.pkgload("PATCHDIR", BtRelativePkgPath)
- reg.pkglist("PATCHFILES", BtFileName)
+ reg.pkglist("PATCHFILES", BtFilename)
reg.pkglist("PATCH_ARGS", BtShellWord)
reg.pkglist("PATCH_DIST_ARGS", BtShellWord)
reg.pkg("PATCH_DIST_CAT", BtShellCommand)
@@ -1339,19 +1339,19 @@ func (reg *VarTypeRegistry) Init(src *Pk
PackageSettable,
"builtin.mk: set, append",
"special:pkgconfig-builtin.mk: use-loadtime")
- reg.pkglist("PKGCONFIG_OVERRIDE", BtPathmask)
+ reg.pkglist("PKGCONFIG_OVERRIDE", BtPathPattern)
reg.pkg("PKGCONFIG_OVERRIDE_STAGE", BtStage)
reg.pkg("PKGDIR", BtRelativePkgDir)
reg.sys("PKGDIRMODE", BtFileMode)
reg.sys("PKGLOCALEDIR", BtPathname)
- reg.pkg("PKGNAME", BtPkgName)
- reg.sys("PKGNAME_NOREV", BtPkgName)
- reg.sysload("PKGPATH", BtPathname)
+ reg.pkg("PKGNAME", BtPkgname)
+ reg.sys("PKGNAME_NOREV", BtPkgname)
+ reg.sysload("PKGPATH", BtPkgpath)
reg.sys("PKGREPOSITORY", BtUnknown)
// This variable is special in that it really only makes sense to
// be set in a package Makefile.
- // See VartypeCheck.PkgRevision for details.
- reg.acl("PKGREVISION", BtPkgRevision,
+ // See VartypeCheck.Pkgrevision for details.
+ reg.acl("PKGREVISION", BtPkgrevision,
PackageSettable,
"Makefile: set")
reg.sys("PKGSRCDIR", BtPathname)
@@ -1364,7 +1364,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.syslist("PKGTOOLS_ENV", BtShellWord)
reg.sys("PKGVERSION", BtVersion)
reg.sys("PKGVERSION_NOREV", BtVersion) // Without the nb* part.
- reg.sys("PKGWILDCARD", BtFileMask)
+ reg.sys("PKGWILDCARD", BtFilePattern)
reg.sysload("PKG_ADMIN", BtShellCommand)
reg.sys("PKG_APACHE", enum("apache24"))
reg.pkglistrat("PKG_APACHE_ACCEPTED", enum("apache24"))
@@ -1456,8 +1456,8 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.acl("PREFIX", BtPathname,
UserSettable,
"*: use")
- // BtPathname instead of BtPkgPath since the original package doesn't exist anymore.
- // It would be more precise to check for a PkgPath that doesn't exist anymore.
+ // BtPathname instead of BtPkgpath since the original package doesn't exist anymore.
+ // It would be more precise to check for a Pkgpath that doesn't exist anymore.
reg.pkg("PREV_PKGPATH", BtPathname)
reg.acl("PRINT_PLIST_AWK", BtAwkCommand,
PackageSettable,
@@ -1483,7 +1483,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.usr("PYTHON_VERSION_REQD", BtVersion)
reg.pkglist("PYTHON_VERSIONED_DEPENDENCIES", BtPythonDependency)
reg.sys("RANLIB", BtShellCommand)
- reg.pkglist("RCD_SCRIPTS", BtFileName)
+ reg.pkglist("RCD_SCRIPTS", BtFilename)
// TODO: Is the definition in www/squid3/Makefile detected as being redundant?
// No, but it could if the RedundancyScope were able to resolve ${FILESDIR}
// to "files".
@@ -1499,17 +1499,17 @@ func (reg *VarTypeRegistry) Init(src *Pk
// is a plain string.
reg.pkg("REPLACE.*", BtUnknown)
- reg.pkglist("REPLACE_AWK", BtPathmask)
- reg.pkglist("REPLACE_BASH", BtPathmask)
- reg.pkglist("REPLACE_CSH", BtPathmask)
- reg.pkglist("REPLACE_FILES.*", BtPathmask)
+ reg.pkglist("REPLACE_AWK", BtPathPattern)
+ reg.pkglist("REPLACE_BASH", BtPathPattern)
+ reg.pkglist("REPLACE_CSH", BtPathPattern)
+ reg.pkglist("REPLACE_FILES.*", BtPathPattern)
reg.pkglist("REPLACE_INTERPRETER", BtIdentifier)
- reg.pkglist("REPLACE_KSH", BtPathmask)
- reg.pkglist("REPLACE_LOCALEDIR_PATTERNS", BtFileMask)
- reg.pkglist("REPLACE_LUA", BtPathmask)
- reg.pkglist("REPLACE_PERL", BtPathmask)
- reg.pkglist("REPLACE_PYTHON", BtPathmask)
- reg.pkglist("REPLACE_SH", BtPathmask)
+ reg.pkglist("REPLACE_KSH", BtPathPattern)
+ reg.pkglist("REPLACE_LOCALEDIR_PATTERNS", BtFilePattern)
+ reg.pkglist("REPLACE_LUA", BtPathPattern)
+ reg.pkglist("REPLACE_PERL", BtPathPattern)
+ reg.pkglist("REPLACE_PYTHON", BtPathPattern)
+ reg.pkglist("REPLACE_SH", BtPathPattern)
reg.pkglist("REQD_DIRS", BtPathname)
reg.pkglist("REQD_DIRS_PERMS", BtPerms)
reg.pkglist("REQD_FILES", BtPathname)
@@ -1518,7 +1518,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.pkg("RESTRICTED", BtMessage)
reg.usr("ROOT_USER", BtUserGroupName)
reg.usr("ROOT_GROUP", BtUserGroupName)
- reg.pkglist("RPMIGNOREPATH", BtPathmask)
+ reg.pkglist("RPMIGNOREPATH", BtPathPattern)
reg.acl("RUBY_BASE",
reg.enumFromDirs(src, "lang", `^ruby(\d+)$`, "ruby$1", "ruby22 ruby23 ruby24 ruby25"),
SystemProvided,
@@ -1543,16 +1543,16 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.sys("SHAREOWN", BtUserGroupName)
reg.sys("SHCOMMENT", BtShellCommand)
reg.sys("SHLIBTOOL", BtShellCommand)
- reg.pkglist("SHLIBTOOL_OVERRIDE", BtPathmask)
+ reg.pkglist("SHLIBTOOL_OVERRIDE", BtPathPattern)
reg.sysload("SHLIB_TYPE",
enum("COFF ECOFF ELF SOM XCOFF Mach-O PE PEwin a.out aixlib dylib none"))
reg.pkglist("SITES.*", BtFetchURL)
reg.usr("SMF_PREFIS", BtPathname)
reg.pkg("SMF_SRCDIR", BtPathname)
- reg.pkg("SMF_NAME", BtFileName)
+ reg.pkg("SMF_NAME", BtFilename)
reg.pkg("SMF_MANIFEST", BtPathname)
reg.pkglist("SMF_INSTANCES", BtIdentifier)
- reg.pkglist("SMF_METHODS", BtFileName)
+ reg.pkglist("SMF_METHODS", BtFilename)
reg.pkg("SMF_METHOD_SRC.*", BtPathname)
reg.pkg("SMF_METHOD_SHELL", BtShellCommand)
reg.pkglist("SPECIAL_PERMS", BtPerms)
@@ -1560,13 +1560,13 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.sys("STRIP", BtShellCommand) // see mk/tools/strip.mk
// Only valid in the top-level and the category Makefiles.
- reg.acllist("SUBDIR", BtFileName,
+ reg.acllist("SUBDIR", BtFilename,
PackageSettable,
"Makefile: append")
reg.pkglistbl3("SUBST_CLASSES", BtIdentifier)
reg.pkglistbl3("SUBST_CLASSES.*", BtIdentifier) // OPSYS-specific
- reg.pkglistbl3("SUBST_FILES.*", BtPathmask)
+ reg.pkglistbl3("SUBST_FILES.*", BtPathPattern)
reg.pkgbl3("SUBST_FILTER_CMD.*", BtShellCommand)
reg.pkgbl3("SUBST_MESSAGE.*", BtMessage)
reg.pkgappendbl3("SUBST_SED.*", BtSedCommands)
@@ -1580,7 +1580,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.pkglist("TEST_TARGET", BtIdentifier)
reg.pkglistrat("TEXINFO_REQD", BtVersion)
reg.pkglistbl3("TOOL_DEPENDS", BtDependencyWithPath)
- reg.syslist("TOOLS_ALIASES", BtFileName)
+ reg.syslist("TOOLS_ALIASES", BtFilename)
reg.syslist("TOOLS_BROKEN", BtTool)
reg.sys("TOOLS_CMD.*", BtPathname)
reg.pkglist("TOOLS_CREATE", BtTool)
@@ -1596,10 +1596,10 @@ func (reg *VarTypeRegistry) Init(src *Pk
enum("cputime datasize memorysize stacksize"))
reg.usr("UNPRIVILEGED_USER", BtUserGroupName)
reg.usr("UNPRIVILEGED_GROUP", BtUserGroupName)
- reg.pkglist("UNWRAP_FILES", BtPathmask)
+ reg.pkglist("UNWRAP_FILES", BtPathPattern)
reg.usrlist("UPDATE_TARGET", BtIdentifier)
reg.pkg("USERGROUP_PHASE", enum("configure build pre-install"))
- reg.usrlist("USER_ADDITIONAL_PKGS", BtPkgPath)
+ reg.usrlist("USER_ADDITIONAL_PKGS", BtPkgpath)
reg.pkg("USE_BSD_MAKEFILE", BtYes)
// USE_BUILTIN.* is usually set by the builtin.mk file, after checking
Index: pkgsrc/pkgtools/pkglint/files/vargroups.go
diff -u pkgsrc/pkgtools/pkglint/files/vargroups.go:1.2 pkgsrc/pkgtools/pkglint/files/vargroups.go:1.3
--- pkgsrc/pkgtools/pkglint/files/vargroups.go:1.2 Thu Sep 12 21:15:48 2019
+++ pkgsrc/pkgtools/pkglint/files/vargroups.go Tue Oct 1 21:37:59 2019
@@ -54,6 +54,11 @@ func (ck *VargroupsChecker) init() {
ck.ignVars = make(map[string]*MkLine)
ck.sortedVars = make(map[string]*MkLine)
ck.listedVars = make(map[string]*MkLine)
+ userPrivate := ""
+ pkgPrivate := ""
+ sysPrivate := ""
+ defPrivate := ""
+ usePrivate := ""
group := ""
@@ -65,7 +70,7 @@ func (ck *VargroupsChecker) init() {
}
}
- appendTo := func(vars map[string]*MkLine, mkline *MkLine, public bool) {
+ appendTo := func(vars map[string]*MkLine, mkline *MkLine, publicGroup bool, firstPrivate *string) {
checkGroupName(mkline)
for _, varname := range mkline.ValueFields(mkline.Value()) {
@@ -73,11 +78,22 @@ func (ck *VargroupsChecker) init() {
continue
}
- if public && hasPrefix(varname, "_") {
+ private := hasPrefix(varname, "_")
+ if publicGroup && private {
mkline.Warnf("%s should list only variables that start with a letter, not %q.",
mkline.Varname(), varname)
}
+ if firstPrivate != nil {
+ if *firstPrivate != "" && !private {
+ mkline.Warnf("The public variable %s should be listed before the private variable %s.",
+ varname, *firstPrivate)
+ }
+ if private && *firstPrivate == "" {
+ *firstPrivate = varname
+ }
+ }
+
if ck.registered[varname] != nil {
mkline.Warnf("Duplicate variable name %s, already appeared in %s.",
varname, mkline.RefTo(ck.registered[varname]))
@@ -105,17 +121,17 @@ func (ck *VargroupsChecker) init() {
case "_VARGROUPS":
group = mkline.Value()
case "_USER_VARS.*":
- appendTo(ck.userVars, mkline, true)
+ appendTo(ck.userVars, mkline, true, &userPrivate)
case "_PKG_VARS.*":
- appendTo(ck.pkgVars, mkline, true)
+ appendTo(ck.pkgVars, mkline, true, &pkgPrivate)
case "_SYS_VARS.*":
- appendTo(ck.sysVars, mkline, true)
+ appendTo(ck.sysVars, mkline, true, &sysPrivate)
case "_DEF_VARS.*":
- appendTo(ck.defVars, mkline, false)
+ appendTo(ck.defVars, mkline, false, &defPrivate)
case "_USE_VARS.*":
- appendTo(ck.useVars, mkline, false)
+ appendTo(ck.useVars, mkline, false, &usePrivate)
case "_IGN_VARS.*":
- appendTo(ck.ignVars, mkline, false)
+ appendTo(ck.ignVars, mkline, false, nil)
case "_SORTED_VARS.*":
appendToStyle(ck.sortedVars, mkline)
case "_LISTED_VARS.*":
Index: pkgsrc/pkgtools/pkglint/files/vargroups_test.go
diff -u pkgsrc/pkgtools/pkglint/files/vargroups_test.go:1.2 pkgsrc/pkgtools/pkglint/files/vargroups_test.go:1.3
--- pkgsrc/pkgtools/pkglint/files/vargroups_test.go:1.2 Thu Sep 12 21:15:48 2019
+++ pkgsrc/pkgtools/pkglint/files/vargroups_test.go Tue Oct 1 21:37:59 2019
@@ -202,7 +202,8 @@ func (s *Suite) Test_VargroupsChecker__u
"",
".if ${USER_VAR:U}",
".endif",
- "BUILD_DEFS+=\t${_USER_VARS.group}")
+ "BUILD_DEFS+=\t\t${_USER_VARS.group}",
+ "BUILD_DEFS_EFFECTS+=\t${_SYS_VARS.group}")
mklines.Check()
@@ -220,6 +221,8 @@ func (s *Suite) Test_VargroupsChecker__i
"",
"_VARGROUPS+=\t\tgroup",
"_IGN_VARS.group=\tPREFER_*",
+ "_IGN_VARS.group+=\t[",
+ "_UNDERSCORE=\t\t_", // This is not an isVargroups name.
"",
".if ${PREFER_PKGSRC:U} || ${WRKOBJDIR:U}",
".endif")
@@ -227,5 +230,38 @@ func (s *Suite) Test_VargroupsChecker__i
mklines.Check()
t.CheckOutputLines(
- "WARN: Makefile:6: Variable WRKOBJDIR is used but not mentioned in the _VARGROUPS section.")
+ "WARN: Makefile:5: \"[\" is not a valid variable name pattern.",
+ "WARN: Makefile:6: Variable names starting with an underscore (_UNDERSCORE) "+
+ "are reserved for internal pkgsrc use.",
+ "WARN: Makefile:6: _UNDERSCORE is defined but not used.",
+ "WARN: Makefile:6: Variable _UNDERSCORE is defined but not mentioned in the _VARGROUPS section.",
+ "WARN: Makefile:8: Variable WRKOBJDIR is used but not mentioned in the _VARGROUPS section.")
+}
+
+func (s *Suite) Test_VargroupsChecker__private_before_public(c *check.C) {
+ t := s.Init(c)
+
+ t.SetUpVartypes()
+
+ mklines := t.NewMkLines("Makefile",
+ MkCvsID,
+ "",
+ "_VARGROUPS+=\t\tgroup",
+ "_DEF_VARS.group=\t_PRIVATE1 _PRIVATE2 PUBLIC",
+ "_PRIVATE1=\t\tprivate",
+ "_PRIVATE2=\t\tprivate",
+ "PUBLIC=\t\t\tpublic")
+
+ mklines.Check()
+
+ t.CheckOutputLines(
+ "WARN: Makefile:4: The public variable PUBLIC should be listed "+
+ "before the private variable _PRIVATE1.",
+ "WARN: Makefile:5: Variable names starting with an underscore (_PRIVATE1) "+
+ "are reserved for internal pkgsrc use.",
+ "WARN: Makefile:5: _PRIVATE1 is defined but not used.",
+ "WARN: Makefile:6: Variable names starting with an underscore (_PRIVATE2) "+
+ "are reserved for internal pkgsrc use.",
+ "WARN: Makefile:6: _PRIVATE2 is defined but not used.",
+ "WARN: Makefile:7: PUBLIC is defined but not used.")
}
Index: pkgsrc/pkgtools/pkglint/files/vartype.go
diff -u pkgsrc/pkgtools/pkglint/files/vartype.go:1.36 pkgsrc/pkgtools/pkglint/files/vartype.go:1.37
--- pkgsrc/pkgtools/pkglint/files/vartype.go:1.36 Wed Aug 21 16:45:17 2019
+++ pkgsrc/pkgtools/pkglint/files/vartype.go Tue Oct 1 21:37:59 2019
@@ -250,7 +250,7 @@ func (bt *BasicType) NeedsQ() bool {
BtDistSuffix,
BtEmulPlatform,
BtFileMode,
- BtFileName,
+ BtFilename,
BtIdentifier,
BtInteger,
BtMachineGnuPlatform,
@@ -258,10 +258,10 @@ func (bt *BasicType) NeedsQ() bool {
BtOption,
BtPathname,
BtPerl5Packlist,
- BtPkgName,
+ BtPkgname,
BtPkgOptionsVar,
- BtPkgPath,
- BtPkgRevision,
+ BtPkgpath,
+ BtPkgrevision,
BtPrefixPathname,
BtPythonDependency,
BtRPkgName,
@@ -314,8 +314,8 @@ var (
BtDistSuffix = &BasicType{"DistSuffix", (*VartypeCheck).DistSuffix}
BtEmulPlatform = &BasicType{"EmulPlatform", (*VartypeCheck).EmulPlatform}
BtFetchURL = &BasicType{"FetchURL", (*VartypeCheck).FetchURL}
- BtFileName = &BasicType{"Filename", (*VartypeCheck).Filename}
- BtFileMask = &BasicType{"FileMask", (*VartypeCheck).FileMask}
+ BtFilename = &BasicType{"Filename", (*VartypeCheck).Filename}
+ BtFilePattern = &BasicType{"FilePattern", (*VartypeCheck).FilePattern}
BtFileMode = &BasicType{"FileMode", (*VartypeCheck).FileMode}
BtGccReqd = &BasicType{"GccReqd", (*VartypeCheck).GccReqd}
BtHomepage = &BasicType{"Homepage", (*VartypeCheck).Homepage}
@@ -330,14 +330,14 @@ var (
BtMessage = &BasicType{"Message", (*VartypeCheck).Message}
BtOption = &BasicType{"Option", (*VartypeCheck).Option}
BtPathlist = &BasicType{"Pathlist", (*VartypeCheck).Pathlist}
- BtPathmask = &BasicType{"PathMask", (*VartypeCheck).PathMask}
+ BtPathPattern = &BasicType{"PathPattern", (*VartypeCheck).PathPattern}
BtPathname = &BasicType{"Pathname", (*VartypeCheck).Pathname}
BtPerl5Packlist = &BasicType{"Perl5Packlist", (*VartypeCheck).Perl5Packlist}
BtPerms = &BasicType{"Perms", (*VartypeCheck).Perms}
- BtPkgName = &BasicType{"Pkgname", (*VartypeCheck).Pkgname}
- BtPkgPath = &BasicType{"PkgPath", (*VartypeCheck).PkgPath}
+ BtPkgname = &BasicType{"Pkgname", (*VartypeCheck).Pkgname}
+ BtPkgpath = &BasicType{"Pkgpath", (*VartypeCheck).Pkgpath}
BtPkgOptionsVar = &BasicType{"PkgOptionsVar", (*VartypeCheck).PkgOptionsVar}
- BtPkgRevision = &BasicType{"PkgRevision", (*VartypeCheck).PkgRevision}
+ BtPkgrevision = &BasicType{"Pkgrevision", (*VartypeCheck).Pkgrevision}
BtPrefixPathname = &BasicType{"PrefixPathname", (*VartypeCheck).PrefixPathname}
BtPythonDependency = &BasicType{"PythonDependency", (*VartypeCheck).PythonDependency}
BtRPkgName = &BasicType{"RPkgName", (*VartypeCheck).RPkgName}
Index: pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go
diff -u pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go:1.54 pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go:1.55
--- pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go:1.54 Wed Aug 21 16:45:17 2019
+++ pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go Tue Oct 1 21:37:59 2019
@@ -6,9 +6,9 @@ import (
func (s *Suite) Test_VartypeCheck_AwkCommand(c *check.C) {
t := s.Init(c)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).AwkCommand)
+ vt := NewVartypeCheckTester(t, BtAwkCommand)
- vt.Varname("PLIST_AWK")
+ vt.Varname("PRINT_PLIST_AWK")
vt.Op(opAssignAppend)
vt.Values(
"{print $0}",
@@ -30,25 +30,65 @@ func (s *Suite) Test_VartypeCheck_AwkCom
func (s *Suite) Test_VartypeCheck_BasicRegularExpression(c *check.C) {
t := s.Init(c)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).BasicRegularExpression)
+ vt := NewVartypeCheckTester(t, BtBasicRegularExpression)
- vt.Varname("REPLACE_FILES.pl")
+ vt.Varname("CHECK_FILES_SKIP")
vt.Values(
".*\\.pl$",
- ".*\\.pl$$")
- t.DisableTracing()
- vt.Values(
- ".*\\.pl$",
- ".*\\.pl$$")
+ ".*\\.pl$$",
+ "\u1E9E",
+ "\\(capture\\)\\1",
+ "\\+")
vt.Output(
"WARN: filename.mk:1: Internal pkglint error in MkLine.Tokenize at \"$\".",
- "WARN: filename.mk:3: Internal pkglint error in MkLine.Tokenize at \"$\".")
+ "WARN: filename.mk:5: In a basic regular expression, a backslash followed by \"+\" is undefined.")
+
+ // Check for special characters that appear outside of character classes.
+ vt.Values(
+ "\u0007",
+ " !\"\"\\#$$%&''()*+,-./09:;<=>?",
+ "@AZ[\\\\]^_``az{|}~",
+ "\t")
+
+ vt.OutputEmpty()
+
+ vt.Values(
+ "?",
+ "\\?",
+ "\\\\?",
+ "\\\\\\?")
+ vt.Output(
+ "WARN: filename.mk:22: In a basic regular expression, a backslash followed by \"?\" is undefined.",
+ "WARN: filename.mk:24: In a basic regular expression, a backslash followed by \"?\" is undefined.")
+
+ vt.Values(
+ "package-[0-9][0-9.]*",
+ "unclosed-[",
+ // TODO: Warn about the unclosed character class.
+ "backslash-[\\")
+
+ vt.OutputEmpty()
+
+ vt.Values(
+ // TODO: Warn about incomplete regular expression escape
+ "\\",
+ "\\\\")
+
+ vt.OutputEmpty()
+
+ vt.Values(
+ "${VAR}*",
+ "\\?${VAR}\\/")
+
+ vt.Output(
+ "WARN: filename.mk:52: In a basic regular expression, a backslash followed by \"?\" is undefined.",
+ "WARN: filename.mk:52: In a basic regular expression, a backslash followed by \"/\" is undefined.")
}
func (s *Suite) Test_VartypeCheck_BuildlinkDepmethod(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).BuildlinkDepmethod)
+ vt := NewVartypeCheckTester(s.Init(c), BtBuildlinkDepmethod)
vt.Varname("BUILDLINK_DEPMETHOD.libc")
vt.Op(opAssignDefault)
@@ -63,7 +103,7 @@ func (s *Suite) Test_VartypeCheck_Buildl
func (s *Suite) Test_VartypeCheck_Category(c *check.C) {
t := s.Init(c)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).Category)
+ vt := NewVartypeCheckTester(t, BtCategory)
t.CreateFileLines("filesyscategory/Makefile",
"# empty")
@@ -83,7 +123,7 @@ func (s *Suite) Test_VartypeCheck_Catego
}
func (s *Suite) Test_VartypeCheck_CFlag(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).CFlag)
+ vt := NewVartypeCheckTester(s.Init(c), BtCFlag)
vt.tester.SetUpTool("pkg-config", "", AtRunTime)
@@ -131,7 +171,7 @@ func (s *Suite) Test_VartypeCheck_CFlag(
func (s *Suite) Test_VartypeCheck_Comment(c *check.C) {
t := s.Init(c)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).Comment)
+ vt := NewVartypeCheckTester(t, BtComment)
G.Pkg = NewPackage(t.File("category/converter"))
G.Pkg.EffectivePkgbase = "converter"
@@ -169,7 +209,7 @@ func (s *Suite) Test_VartypeCheck_Commen
}
func (s *Suite) Test_VartypeCheck_ConfFiles(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).ConfFiles)
+ vt := NewVartypeCheckTester(s.Init(c), BtConfFiles)
vt.Varname("CONF_FILES")
vt.Op(opAssignAppend)
@@ -188,7 +228,7 @@ func (s *Suite) Test_VartypeCheck_ConfFi
// See Test_MkParser_Dependency.
func (s *Suite) Test_VartypeCheck_Dependency(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Dependency)
+ vt := NewVartypeCheckTester(s.Init(c), BtDependency)
vt.Varname("CONFLICTS")
vt.Op(opAssignAppend)
@@ -298,7 +338,7 @@ func (s *Suite) Test_VartypeCheck_Depend
func (s *Suite) Test_VartypeCheck_DependencyWithPath(c *check.C) {
t := s.Init(c)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).DependencyWithPath)
+ vt := NewVartypeCheckTester(t, BtDependencyWithPath)
t.CreateFileLines("category/package/Makefile")
t.CreateFileLines("databases/py-sqlite3/Makefile")
@@ -367,7 +407,7 @@ func (s *Suite) Test_VartypeCheck_Depend
}
func (s *Suite) Test_VartypeCheck_DistSuffix(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).DistSuffix)
+ vt := NewVartypeCheckTester(s.Init(c), BtDistSuffix)
vt.Varname("EXTRACT_SUFX")
vt.Values(
@@ -380,7 +420,7 @@ func (s *Suite) Test_VartypeCheck_DistSu
}
func (s *Suite) Test_VartypeCheck_EmulPlatform(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).EmulPlatform)
+ vt := NewVartypeCheckTester(s.Init(c), BtEmulPlatform)
vt.Varname("EMUL_PLATFORM")
vt.Values(
@@ -411,7 +451,9 @@ func (s *Suite) Test_VartypeCheck_EmulPl
}
func (s *Suite) Test_VartypeCheck_Enum(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), enum("jdk1 jdk2 jdk4").checker)
+ basicType := enum("jdk1 jdk2 jdk4")
+ G.Pkgsrc.vartypes.Define("JDK", basicType, UserSettable)
+ vt := NewVartypeCheckTester(s.Init(c), basicType)
vt.Varname("JDK")
vt.Op(opUseMatch)
@@ -471,7 +513,7 @@ func (s *Suite) Test_VartypeCheck_FetchU
"MASTER_SITE_OWN=\thttps://example.org/")
t.FinishSetUp()
- vt := NewVartypeCheckTester(t, (*VartypeCheck).FetchURL)
+ vt := NewVartypeCheckTester(t, BtFetchURL)
t.SetUpMasterSite("MASTER_SITE_GNU", "http://ftp.gnu.org/pub/gnu/")
t.SetUpMasterSite("MASTER_SITE_GITHUB", "https://github.com/")
@@ -501,7 +543,9 @@ func (s *Suite) Test_VartypeCheck_FetchU
vt.Values(
"https://example.org/download.cgi?filename=filename&sha1=12341234")
- vt.OutputEmpty()
+ vt.Output(
+ "WARN: filename.mk:11: The fetch URL \"https://example.org/download.cgi" +
+ "?filename=filename&sha1=12341234\" should end with a slash.")
vt.Values(
"http://example.org/distfiles/",
@@ -509,7 +553,12 @@ func (s *Suite) Test_VartypeCheck_FetchU
"http://example.org/download?filename=<distfile>;version=<version>")
vt.Output(
- "WARN: filename.mk:23: \"http://example.org/download?filename=<distfile>;version=<version>\" is not a valid URL.")
+ "WARN: filename.mk:22: The fetch URL \"http://example.org/download"+
+ "?filename=distfile;version=1.0\" should end with a slash.",
+ "WARN: filename.mk:23: \"http://example.org/download"+
+ "?filename=<distfile>;version=<version>\" is not a valid URL.",
+ "WARN: filename.mk:23: The fetch URL \"http://example.org/download"+
+ "?filename=<distfile>;version=<version>\" should end with a slash.")
vt.Values(
"${MASTER_SITE_GITHUB:S,^,-,:=project/archive/${DISTFILE}}")
@@ -523,6 +572,7 @@ func (s *Suite) Test_VartypeCheck_FetchU
// As of June 2019, the :S modifier is not analyzed since it is unusual.
vt.Values(
+ "${MASTER_SITE_GNU:S,$,subdir,}",
"${MASTER_SITE_GNU:S,$,subdir/,}")
vt.OutputEmpty()
@@ -532,12 +582,35 @@ func (s *Suite) Test_VartypeCheck_FetchU
"WARN: filename.mk:51: Please use ${MASTER_SITE_GITHUB:=transmission/} " +
"instead of \"https://github.com/transmission/\" " +
"and run \"" + confMake + " help topic=github\" for further instructions.")
+
+ vt.Values(
+ "-https://example.org/distfile.tar.gz",
+ "-http://ftp.gnu.org/pub/gnu/bash-5.0.tar.gz",
+ "-http://ftp.gnu.org/pub/gnu/bash/bash-5.0.tar.gz")
+
+ vt.Output(
+ "WARN: filename.mk:62: Please use ${MASTER_SITE_GNU:S,^,-,:=bash-5.0.tar.gz} "+
+ "instead of \"-http://ftp.gnu.org/pub/gnu/bash-5.0.tar.gz\".",
+ "WARN: filename.mk:63: Please use ${MASTER_SITE_GNU:S,^,-,:=bash/bash-5.0.tar.gz} "+
+ "instead of \"-http://ftp.gnu.org/pub/gnu/bash/bash-5.0.tar.gz\".")
+
+ vt.Values(
+ "https://example.org/pub",
+ "https://example.org/$@", // Doesn't make sense at all.
+ "https://example.org/?f=",
+ "https://example.org/download:",
+ "https://example.org/download?")
+
+ vt.Output(
+ "WARN: filename.mk:71: The fetch URL \"https://example.org/pub\" should end with a slash.",
+ "WARN: filename.mk:72: \"https://example.org/$@\" is not a valid URL.",
+ "WARN: filename.mk:75: The fetch URL \"https://example.org/download?\" should end with a slash.")
}
func (s *Suite) Test_VartypeCheck_FetchURL__without_package(c *check.C) {
t := s.Init(c)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).FetchURL)
+ vt := NewVartypeCheckTester(t, BtFetchURL)
vt.Varname("MASTER_SITES")
vt.Values(
@@ -549,9 +622,9 @@ func (s *Suite) Test_VartypeCheck_FetchU
}
func (s *Suite) Test_VartypeCheck_Filename(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Filename)
+ vt := NewVartypeCheckTester(s.Init(c), BtFilename)
- vt.Varname("FNAME")
+ vt.Varname("JAVA_NAME")
vt.Values(
"Filename with spaces.docx",
"OS/2-manual.txt")
@@ -571,41 +644,41 @@ func (s *Suite) Test_VartypeCheck_Filena
"contains the invalid characters \" \".")
}
-func (s *Suite) Test_VartypeCheck_FileMask(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).FileMask)
+func (s *Suite) Test_VartypeCheck_FilePattern(c *check.C) {
+ vt := NewVartypeCheckTester(s.Init(c), BtFilePattern)
- vt.Varname("FNAME")
+ vt.Varname("PKGWILDCARD")
vt.Values(
"filename.txt",
"*.txt",
"[12345].txt",
"[0-9].txt",
"???.txt",
- "FileMask with spaces.docx",
+ "FilePattern with spaces.docx",
"OS/2-manual.txt")
vt.Output(
- "WARN: filename.mk:6: The filename pattern \"FileMask with spaces.docx\" "+
+ "WARN: filename.mk:6: The filename pattern \"FilePattern with spaces.docx\" "+
"contains the invalid characters \" \".",
"WARN: filename.mk:7: The filename pattern \"OS/2-manual.txt\" "+
"contains the invalid character \"/\".")
vt.Op(opUseMatch)
vt.Values(
- "FileMask with spaces.docx")
+ "FilePattern with spaces.docx")
// There's no guarantee that a filename only contains [A-Za-z0-9.].
// Therefore it might be necessary to allow all characters here.
// TODO: Investigate whether this restriction is useful in practice.
vt.Output(
- "WARN: filename.mk:11: The filename pattern \"FileMask with spaces.docx\" " +
+ "WARN: filename.mk:11: The filename pattern \"FilePattern with spaces.docx\" " +
"contains the invalid characters \" \".")
}
func (s *Suite) Test_VartypeCheck_FileMode(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).FileMode)
+ vt := NewVartypeCheckTester(s.Init(c), BtFileMode)
- vt.Varname("HIGHSCORE_PERMS")
+ vt.Varname("GAMEMODE")
vt.Values(
"u+rwx",
"0600",
@@ -630,7 +703,7 @@ func (s *Suite) Test_VartypeCheck_FileMo
}
func (s *Suite) Test_VartypeCheck_GccReqd(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).GccReqd)
+ vt := NewVartypeCheckTester(s.Init(c), BtGccReqd)
vt.Varname("GCC_REQD")
vt.Op(opAssignAppend)
@@ -649,7 +722,7 @@ func (s *Suite) Test_VartypeCheck_GccReq
func (s *Suite) Test_VartypeCheck_Homepage(c *check.C) {
t := s.Init(c)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).Homepage)
+ vt := NewVartypeCheckTester(t, BtHomepage)
vt.Varname("HOMEPAGE")
vt.Values(
@@ -712,7 +785,7 @@ func (s *Suite) Test_VartypeCheck_Homepa
func (s *Suite) Test_VartypeCheck_Identifier(c *check.C) {
t := s.Init(c)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).Identifier)
+ vt := NewVartypeCheckTester(t, BtIdentifier)
vt.Varname("MYSQL_CHARSET")
vt.Values(
@@ -740,9 +813,9 @@ func (s *Suite) Test_VartypeCheck_Identi
func (s *Suite) Test_VartypeCheck_Integer(c *check.C) {
t := s.Init(c)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).Integer)
+ vt := NewVartypeCheckTester(t, BtInteger)
- vt.Varname("NUMBER")
+ vt.Varname("MAKE_JOBS")
vt.Values(
"${OTHER_VAR}",
"123",
@@ -755,7 +828,7 @@ func (s *Suite) Test_VartypeCheck_Intege
}
func (s *Suite) Test_VartypeCheck_LdFlag(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).LdFlag)
+ vt := NewVartypeCheckTester(s.Init(c), BtLdFlag)
vt.tester.SetUpTool("pkg-config", "", AtRunTime)
@@ -812,7 +885,7 @@ func (s *Suite) Test_VartypeCheck_Licens
// Also registers the PERL5_LICENSE variable in the package.
mklines.collectVariables()
- vt := NewVartypeCheckTester(t, (*VartypeCheck).License)
+ vt := NewVartypeCheckTester(t, BtLicense)
vt.Varname("LICENSE")
vt.Values(
@@ -837,7 +910,7 @@ func (s *Suite) Test_VartypeCheck_Licens
}
func (s *Suite) Test_VartypeCheck_MachineGnuPlatform(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).MachineGnuPlatform)
+ vt := NewVartypeCheckTester(s.Init(c), BtMachineGnuPlatform)
vt.Varname("MACHINE_GNU_PLATFORM")
vt.Op(opUseMatch)
@@ -865,7 +938,7 @@ func (s *Suite) Test_VartypeCheck_Machin
}
func (s *Suite) Test_VartypeCheck_MachinePlatformPattern(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).MachinePlatformPattern)
+ vt := NewVartypeCheckTester(s.Init(c), BtMachinePlatformPattern)
vt.Varname("ONLY_FOR_PLATFORM")
vt.Op(opUseMatch)
@@ -916,7 +989,7 @@ func (s *Suite) Test_VartypeCheck_Machin
}
func (s *Suite) Test_VartypeCheck_MailAddress(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).MailAddress)
+ vt := NewVartypeCheckTester(s.Init(c), BtMailAddress)
vt.Varname("MAINTAINER")
vt.Values(
@@ -933,7 +1006,7 @@ func (s *Suite) Test_VartypeCheck_MailAd
}
func (s *Suite) Test_VartypeCheck_Message(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Message)
+ vt := NewVartypeCheckTester(s.Init(c), BtMessage)
vt.Varname("SUBST_MESSAGE.id")
vt.Values(
@@ -945,7 +1018,7 @@ func (s *Suite) Test_VartypeCheck_Messag
}
func (s *Suite) Test_VartypeCheck_Option(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Option)
+ vt := NewVartypeCheckTester(s.Init(c), BtOption)
G.Pkgsrc.PkgOptions["documented"] = "Option description"
G.Pkgsrc.PkgOptions["undocumented"] = ""
@@ -966,7 +1039,7 @@ func (s *Suite) Test_VartypeCheck_Option
}
func (s *Suite) Test_VartypeCheck_Pathlist(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Pathlist)
+ vt := NewVartypeCheckTester(s.Init(c), BtPathlist)
vt.Varname("PATH")
vt.Values(
@@ -980,8 +1053,8 @@ func (s *Suite) Test_VartypeCheck_Pathli
"WARN: filename.mk:2: \"/directory with spaces\" is not a valid pathname.")
}
-func (s *Suite) Test_VartypeCheck_PathMask(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).PathMask)
+func (s *Suite) Test_VartypeCheck_PathPattern(c *check.C) {
+ vt := NewVartypeCheckTester(s.Init(c), BtPathPattern)
vt.Varname("DISTDIRS")
vt.Values(
@@ -999,7 +1072,7 @@ func (s *Suite) Test_VartypeCheck_PathMa
}
func (s *Suite) Test_VartypeCheck_Pathname(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Pathname)
+ vt := NewVartypeCheckTester(s.Init(c), BtPathname)
vt.Varname("EGDIR")
vt.Values(
@@ -1016,7 +1089,7 @@ func (s *Suite) Test_VartypeCheck_Pathna
}
func (s *Suite) Test_VartypeCheck_Perl5Packlist(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Perl5Packlist)
+ vt := NewVartypeCheckTester(s.Init(c), BtPerl5Packlist)
vt.Varname("PERL5_PACKLIST")
vt.Values(
@@ -1028,7 +1101,7 @@ func (s *Suite) Test_VartypeCheck_Perl5P
}
func (s *Suite) Test_VartypeCheck_Perms(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Perms)
+ vt := NewVartypeCheckTester(s.Init(c), BtPerms)
vt.Varname("CONF_FILES_PERMS")
vt.Op(opAssignAppend)
@@ -1046,7 +1119,7 @@ func (s *Suite) Test_VartypeCheck_Perms(
}
func (s *Suite) Test_VartypeCheck_Pkgname(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Pkgname)
+ vt := NewVartypeCheckTester(s.Init(c), BtPkgname)
vt.Varname("PKGNAME")
vt.Values(
@@ -1077,9 +1150,9 @@ func (s *Suite) Test_VartypeCheck_Pkgnam
}
func (s *Suite) Test_VartypeCheck_PkgOptionsVar(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).PkgOptionsVar)
+ vt := NewVartypeCheckTester(s.Init(c), BtPkgOptionsVar)
- vt.Varname("PKG_OPTIONS_VAR.screen")
+ vt.Varname("PKG_OPTIONS_VAR")
vt.Values(
"PKG_OPTIONS.${PKGBASE}",
"PKG_OPTIONS.anypkgbase",
@@ -1091,11 +1164,13 @@ func (s *Suite) Test_VartypeCheck_PkgOpt
"of the form \"PKG_OPTIONS.*\", not \"PKG_OPTS.mc\".")
}
-func (s *Suite) Test_VartypeCheck_PkgPath(c *check.C) {
+func (s *Suite) Test_VartypeCheck_Pkgpath(c *check.C) {
t := s.Init(c)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).PkgPath)
+ vt := NewVartypeCheckTester(t, BtPkgpath)
+ t.CreateFileLines("category/Makefile")
t.CreateFileLines("category/other-package/Makefile")
+ t.CreateFileLines("wip/package/Makefile")
t.Chdir("category/package")
vt.Varname("PKGPATH")
@@ -1103,17 +1178,38 @@ func (s *Suite) Test_VartypeCheck_PkgPat
"category/other-package",
"${OTHER_VAR}",
"invalid",
- "../../invalid/relative")
+ "../../invalid/relative",
+ "wip/package",
+ "category",
+ "&&")
vt.Output(
- "ERROR: filename.mk:3: Relative path \"../../invalid/Makefile\" does not exist.",
- "WARN: filename.mk:3: \"../../invalid\" is not a valid relative package directory.",
- "ERROR: filename.mk:4: Relative path \"../../../../invalid/relative/Makefile\" does not exist.",
- "WARN: filename.mk:4: \"../../../../invalid/relative\" is not a valid relative package directory.")
+ "ERROR: filename.mk:3: There is no package in \"../../invalid\".",
+ "ERROR: filename.mk:4: There is no package in \"../../../../invalid/relative\".",
+ "ERROR: filename.mk:5: A main pkgsrc package must not depend on a pkgsrc-wip package.",
+ "ERROR: filename.mk:6: \"category\" is not a valid path to a package.",
+ "WARN: filename.mk:7: The pathname \"&&\" contains the invalid characters \"&&\".",
+ "ERROR: filename.mk:7: There is no package in \"../../&&\".")
+
+ G.Wip = true
+
+ vt.Values(
+ "wip/package")
+
+ vt.OutputEmpty()
+
+ vt.Op(opUseMatch)
+
+ vt.Values(
+ "pattern",
+ "&special&")
+
+ vt.Output(
+ "WARN: filename.mk:22: The pathname pattern \"&special&\" contains the invalid characters \"&&\".")
}
-func (s *Suite) Test_VartypeCheck_PkgRevision(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).PkgRevision)
+func (s *Suite) Test_VartypeCheck_Pkgrevision(c *check.C) {
+ vt := NewVartypeCheckTester(s.Init(c), BtPkgrevision)
vt.Varname("PKGREVISION")
vt.Values(
@@ -1131,7 +1227,7 @@ func (s *Suite) Test_VartypeCheck_PkgRev
}
func (s *Suite) Test_VartypeCheck_PrefixPathname(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).PrefixPathname)
+ vt := NewVartypeCheckTester(s.Init(c), BtPrefixPathname)
vt.Varname("PKGMANDIR")
vt.Values(
@@ -1143,7 +1239,7 @@ func (s *Suite) Test_VartypeCheck_Prefix
}
func (s *Suite) Test_VartypeCheck_PythonDependency(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).PythonDependency)
+ vt := NewVartypeCheckTester(s.Init(c), BtPythonDependency)
vt.Varname("PYTHON_VERSIONED_DEPENDENCIES")
vt.Values(
@@ -1157,7 +1253,7 @@ func (s *Suite) Test_VartypeCheck_Python
}
func (s *Suite) Test_VartypeCheck_RPkgName(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).RPkgName)
+ vt := NewVartypeCheckTester(s.Init(c), BtRPkgName)
vt.Varname("R_PKGNAME")
vt.Values(
@@ -1180,7 +1276,7 @@ func (s *Suite) Test_VartypeCheck_RPkgNa
}
func (s *Suite) Test_VartypeCheck_RPkgVer(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).RPkgVer)
+ vt := NewVartypeCheckTester(s.Init(c), BtRPkgVer)
vt.Varname("R_PKGVER")
vt.Values(
@@ -1201,7 +1297,7 @@ func (s *Suite) Test_VartypeCheck_RPkgVe
func (s *Suite) Test_VartypeCheck_RelativePkgPath(c *check.C) {
t := s.Init(c)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).RelativePkgPath)
+ vt := NewVartypeCheckTester(t, BtRelativePkgPath)
t.CreateFileLines("category/other-package/Makefile")
t.Chdir("category/package")
@@ -1221,7 +1317,7 @@ func (s *Suite) Test_VartypeCheck_Relati
}
func (s *Suite) Test_VartypeCheck_Restricted(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Restricted)
+ vt := NewVartypeCheckTester(s.Init(c), BtRestricted)
vt.Varname("NO_BIN_ON_CDROM")
vt.Values(
@@ -1232,7 +1328,7 @@ func (s *Suite) Test_VartypeCheck_Restri
}
func (s *Suite) Test_VartypeCheck_SedCommands(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).SedCommands)
+ vt := NewVartypeCheckTester(s.Init(c), BtSedCommands)
vt.Varname("SUBST_SED.dummy")
vt.Values(
@@ -1262,10 +1358,49 @@ func (s *Suite) Test_VartypeCheck_SedCom
"WARN: filename.mk:11: Unclosed shell variable starting at \"$${unclosedShellVar\".")
}
+func (s *Suite) Test_VartypeCheck_SedCommands__experimental(c *check.C) {
+ vt := NewVartypeCheckTester(s.Init(c), BtSedCommands)
+ G.Experimental = true
+
+ vt.Varname("SUBST_SED.dummy")
+
+ vt.Values(
+ "-e s,???,questions,",
+ "-e 's?from?to?g'",
+ "-E -e 's,from,to,g'")
+
+ vt.Output(
+ "WARN: filename.mk:1: The \"?\" in the word \"s,???,questions,\" may lead to unintended file globbing.")
+
+ vt.Values(
+ "-e s,?,replacement,",
+ "-e s,\\?,replacement,",
+ "-e s,\\\\?,replacement,",
+ "-e s,\\\\\\?,replacement,")
+
+ vt.Output(
+ "WARN: filename.mk:11: The \"?\" in the word \"s,?,replacement,\" may lead to unintended file globbing.",
+ "WARN: filename.mk:13: The \"?\" in the word \"s,\\\\\\\\?,replacement,\" may lead to unintended file globbing.",
+ "WARN: filename.mk:13: In a basic regular expression, a backslash followed by \"?\" is undefined.",
+ "WARN: filename.mk:14: In a basic regular expression, a backslash followed by \"?\" is undefined.")
+
+ vt.Values(
+ "-e s/dir\\\\/file/other-file/")
+
+ // No warning about backslash followed by "/" being undefined.
+ vt.OutputEmpty()
+
+ vt.Values(
+ "-e 's, ,space,g'",
+ "-e 's,\t,tab,g'")
+
+ vt.OutputEmpty()
+}
+
func (s *Suite) Test_VartypeCheck_ShellCommand(c *check.C) {
t := s.Init(c)
t.SetUpVartypes()
- vt := NewVartypeCheckTester(t, (*VartypeCheck).ShellCommand)
+ vt := NewVartypeCheckTester(t, BtShellCommand)
vt.Varname("INSTALL_CMD")
vt.Values(
@@ -1287,7 +1422,7 @@ func (s *Suite) Test_VartypeCheck_ShellC
t := s.Init(c)
t.SetUpVartypes()
t.SetUpTool("echo", "ECHO", AtRunTime)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).ShellCommands)
+ vt := NewVartypeCheckTester(t, BtShellCommands)
vt.Varname("GENERATE_PLIST")
vt.Values(
@@ -1299,7 +1434,7 @@ func (s *Suite) Test_VartypeCheck_ShellC
}
func (s *Suite) Test_VartypeCheck_Stage(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Stage)
+ vt := NewVartypeCheckTester(s.Init(c), BtStage)
vt.Varname("SUBST_STAGE.dummy")
vt.Values(
@@ -1314,7 +1449,7 @@ func (s *Suite) Test_VartypeCheck_Stage(
func (s *Suite) Test_VartypeCheck_Tool(c *check.C) {
t := s.Init(c)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).Tool)
+ vt := NewVartypeCheckTester(t, BtTool)
t.SetUpTool("tool1", "", AtRunTime)
t.SetUpTool("tool2", "", AtRunTime)
@@ -1371,9 +1506,9 @@ func (s *Suite) Test_VartypeCheck_Tool(c
func (s *Suite) Test_VartypeCheck_URL(c *check.C) {
t := s.Init(c)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).URL)
+ vt := NewVartypeCheckTester(t, BtURL)
- vt.Varname("HOMEPAGE")
+ vt.Varname("LATEX2HTML_ICONPATH")
vt.Values(
"# none",
"${OTHER_VAR}",
@@ -1417,7 +1552,7 @@ func (s *Suite) Test_VartypeCheck_URL(c
func (s *Suite) Test_VartypeCheck_UserGroupName(c *check.C) {
t := s.Init(c)
- vt := NewVartypeCheckTester(t, (*VartypeCheck).UserGroupName)
+ vt := NewVartypeCheckTester(t, BtUserGroupName)
vt.Varname("APACHE_USER")
vt.Values(
@@ -1433,7 +1568,7 @@ func (s *Suite) Test_VartypeCheck_UserGr
}
func (s *Suite) Test_VartypeCheck_VariableName(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).VariableName)
+ vt := NewVartypeCheckTester(s.Init(c), BtVariableName)
vt.Varname("BUILD_DEFS")
vt.Values(
@@ -1447,7 +1582,7 @@ func (s *Suite) Test_VartypeCheck_Variab
}
func (s *Suite) Test_VartypeCheck_VariableNamePattern(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).VariableNamePattern)
+ vt := NewVartypeCheckTester(s.Init(c), BtVariableNamePattern)
vt.Varname("_SORTED_VARS.group")
vt.Values(
@@ -1464,7 +1599,7 @@ func (s *Suite) Test_VartypeCheck_Variab
}
func (s *Suite) Test_VartypeCheck_Version(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Version)
+ vt := NewVartypeCheckTester(s.Init(c), BtVersion)
vt.Varname("PERL5_REQD")
vt.Op(opAssignAppend)
@@ -1495,9 +1630,9 @@ func (s *Suite) Test_VartypeCheck_Versio
}
func (s *Suite) Test_VartypeCheck_WrapperReorder(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).WrapperReorder)
+ vt := NewVartypeCheckTester(s.Init(c), BtWrapperReorder)
- vt.Varname("WRAPPER_REORDER")
+ vt.Varname("WRAPPER_REORDER_CMDS")
vt.Op(opAssignAppend)
vt.Values(
"reorder:l:first:second",
@@ -1509,7 +1644,7 @@ func (s *Suite) Test_VartypeCheck_Wrappe
}
func (s *Suite) Test_VartypeCheck_WrapperTransform(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).WrapperTransform)
+ vt := NewVartypeCheckTester(s.Init(c), BtWrapperTransform)
vt.Varname("WRAPPER_TRANSFORM_CMDS")
vt.Op(opAssignAppend)
@@ -1529,7 +1664,7 @@ func (s *Suite) Test_VartypeCheck_Wrappe
}
func (s *Suite) Test_VartypeCheck_WrksrcSubdirectory(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).WrksrcSubdirectory)
+ vt := NewVartypeCheckTester(s.Init(c), BtWrksrcSubdirectory)
vt.Varname("BUILD_DIRS")
vt.Op(opAssignAppend)
@@ -1556,7 +1691,7 @@ func (s *Suite) Test_VartypeCheck_Wrksrc
}
func (s *Suite) Test_VartypeCheck_Yes(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).Yes)
+ vt := NewVartypeCheckTester(s.Init(c), BtYes)
vt.Varname("APACHE_MODULE")
vt.Values(
@@ -1568,7 +1703,7 @@ func (s *Suite) Test_VartypeCheck_Yes(c
"WARN: filename.mk:2: APACHE_MODULE should be set to YES or yes.",
"WARN: filename.mk:3: APACHE_MODULE should be set to YES or yes.")
- vt.Varname("PKG_DEVELOPER")
+ vt.Varname("BUILD_USES_MSGFMT")
vt.Op(opUseMatch)
vt.Values(
"yes",
@@ -1576,15 +1711,15 @@ func (s *Suite) Test_VartypeCheck_Yes(c
"${YESVAR}")
vt.Output(
- "WARN: filename.mk:11: PKG_DEVELOPER should only be used in a \".if defined(...)\" condition.",
- "WARN: filename.mk:12: PKG_DEVELOPER should only be used in a \".if defined(...)\" condition.",
- "WARN: filename.mk:13: PKG_DEVELOPER should only be used in a \".if defined(...)\" condition.")
+ "WARN: filename.mk:11: BUILD_USES_MSGFMT should only be used in a \".if defined(...)\" condition.",
+ "WARN: filename.mk:12: BUILD_USES_MSGFMT should only be used in a \".if defined(...)\" condition.",
+ "WARN: filename.mk:13: BUILD_USES_MSGFMT should only be used in a \".if defined(...)\" condition.")
}
func (s *Suite) Test_VartypeCheck_YesNo(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).YesNo)
+ vt := NewVartypeCheckTester(s.Init(c), BtYesNo)
- vt.Varname("GNU_CONFIGURE")
+ vt.Varname("PKG_DEVELOPER")
vt.Values(
"yes",
"no",
@@ -1592,14 +1727,14 @@ func (s *Suite) Test_VartypeCheck_YesNo(
"${YESVAR}")
vt.Output(
- "WARN: filename.mk:3: GNU_CONFIGURE should be set to YES, yes, NO, or no.",
- "WARN: filename.mk:4: GNU_CONFIGURE should be set to YES, yes, NO, or no.")
+ "WARN: filename.mk:3: PKG_DEVELOPER should be set to YES, yes, NO, or no.",
+ "WARN: filename.mk:4: PKG_DEVELOPER should be set to YES, yes, NO, or no.")
}
func (s *Suite) Test_VartypeCheck_YesNoIndirectly(c *check.C) {
- vt := NewVartypeCheckTester(s.Init(c), (*VartypeCheck).YesNoIndirectly)
+ vt := NewVartypeCheckTester(s.Init(c), BtYesNoIndirectly)
- vt.Varname("GNU_CONFIGURE")
+ vt.Varname("IS_BUILTIN.pkgbase")
vt.Values(
"yes",
"no",
@@ -1607,24 +1742,24 @@ func (s *Suite) Test_VartypeCheck_YesNoI
"${YESVAR}")
vt.Output(
- "WARN: filename.mk:3: GNU_CONFIGURE should be set to YES, yes, NO, or no.")
+ "WARN: filename.mk:3: IS_BUILTIN.pkgbase should be set to YES, yes, NO, or no.")
}
// VartypeCheckTester helps to test the many different checks in VartypeCheck.
// It keeps track of the current variable, operator, filename, line number,
// so that the test can focus on the interesting details.
type VartypeCheckTester struct {
- tester *Tester
- checker func(cv *VartypeCheck)
- filename string
- lineno int
- varname string
- op MkOperator
+ tester *Tester
+ basicType *BasicType
+ filename string
+ lineno int
+ varname string
+ op MkOperator
}
// NewVartypeCheckTester starts the test with a filename of "filename", at line 1,
// with "=" as the operator. The variable has to be initialized explicitly.
-func NewVartypeCheckTester(t *Tester, checker func(cv *VartypeCheck)) *VartypeCheckTester {
+func NewVartypeCheckTester(t *Tester, basicType *BasicType) *VartypeCheckTester {
// This is necessary to know whether the variable name is a list type
// since in such a case each value is split into the list elements.
@@ -1632,16 +1767,14 @@ func NewVartypeCheckTester(t *Tester, ch
t.SetUpVartypes()
}
- return &VartypeCheckTester{
- t,
- checker,
- "filename.mk",
- 1,
- "",
- opAssign}
+ return &VartypeCheckTester{t, basicType, "filename.mk", 1, "", opAssign}
}
func (vt *VartypeCheckTester) Varname(varname string) {
+ vartype := G.Pkgsrc.VariableType(nil, varname)
+ assertNotNil(vartype)
+ assert(vartype.basicType == vt.basicType)
+
vt.varname = varname
vt.nextSection()
}
@@ -1708,7 +1841,7 @@ func (vt *VartypeCheckTester) Values(val
for _, lineValue := range lineValues {
valueNovar := mkline.WithoutMakeVariables(lineValue)
vc := VartypeCheck{mklines, mkline, varname, vt.op, lineValue, valueNovar, comment, false}
- vt.checker(&vc)
+ vt.basicType.checker(&vc)
}
}
Index: pkgsrc/pkgtools/pkglint/files/textproc/lexer.go
diff -u pkgsrc/pkgtools/pkglint/files/textproc/lexer.go:1.5 pkgsrc/pkgtools/pkglint/files/textproc/lexer.go:1.6
--- pkgsrc/pkgtools/pkglint/files/textproc/lexer.go:1.5 Sun Mar 10 19:01:50 2019
+++ pkgsrc/pkgtools/pkglint/files/textproc/lexer.go Tue Oct 1 21:38:00 2019
@@ -130,6 +130,13 @@ func (l *Lexer) SkipByte(b byte) bool {
return false
}
+// NextByte returns the next byte.
+func (l *Lexer) NextByte() byte {
+ b := l.rest[0]
+ l.rest = l.rest[1:]
+ return b
+}
+
// NextBytesFunc chops off the longest prefix (possibly empty) consisting
// solely of bytes for which fn returns true.
func (l *Lexer) NextBytesFunc(fn func(b byte) bool) string {
Index: pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go
diff -u pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go:1.5 pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go:1.6
--- pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go:1.5 Sun Jul 14 21:25:47 2019
+++ pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go Tue Oct 1 21:38:00 2019
@@ -143,6 +143,16 @@ func (s *Suite) Test_Lexer_SkipByte(c *c
c.Check(lexer.SkipByte(0), equals, false) // This is not a C string.
}
+func (s *Suite) Test_Lexer_NextByte(c *check.C) {
+ lexer := NewLexer("byte")
+
+ c.Check(lexer.NextByte(), equals, byte('b'))
+ c.Check(lexer.NextByte(), equals, byte('y'))
+ c.Check(lexer.NextByte(), equals, byte('t'))
+ c.Check(lexer.NextByte(), equals, byte('e'))
+ c.Check(lexer.NextByte, check.PanicMatches, "^runtime error: index out of range.*")
+}
+
func (s *Suite) Test_Lexer_NextBytesFunc(c *check.C) {
lexer := NewLexer("an alphanumerical string")
Home |
Main Index |
Thread Index |
Old Index