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: Mon May 6 20:27:17 UTC 2019
Modified Files:
pkgsrc/pkgtools/pkglint: Makefile
pkgsrc/pkgtools/pkglint/files: buildlink3.go buildlink3_test.go
check_test.go distinfo.go distinfo_test.go licenses.go
mklinechecker.go mklinechecker_test.go mklines_test.go package.go
package_test.go pkglint.go pkglint_test.go pkgsrc.go
redundantscope_test.go shell.go shell_test.go toplevel.go util.go
vardefs.go
Log Message:
pkgtools/pkglint: update to 5.7.9
Changes since 5.7.8:
* Buildlink3.mk files are checked for typos in the identifier that is
used for BUILDLINK_TREE, to detect copy-and-paste mistakes.
* Having a rationale is recommended for some variables, especially those
that make a package fail to build or crash at runtime. This check is
only active when -Wextra is given, since it is still actively debated
whether such a check is actually useful.
* Files called Makefile.php can easily be mistaken to be PHP files.
Therefore the recommended naming convention is to have auxiliary files
called *.mk. There are already many more files called *.mk than those
being called Makefile.*.
* The check for unquoted sed substitution commands has been made more
detailed, but since it is completely disabled, there's nothing to see
for now.
* The definitions for MASTER_SITE_* are loaded directly from the pkgsrc
infrastructure instead of hard-coding them in pkglint.
To generate a diff of this commit:
cvs rdiff -u -r1.578 -r1.579 pkgsrc/pkgtools/pkglint/Makefile
cvs rdiff -u -r1.21 -r1.22 pkgsrc/pkgtools/pkglint/files/buildlink3.go
cvs rdiff -u -r1.30 -r1.31 pkgsrc/pkgtools/pkglint/files/buildlink3_test.go
cvs rdiff -u -r1.40 -r1.41 pkgsrc/pkgtools/pkglint/files/check_test.go \
pkgsrc/pkgtools/pkglint/files/pkglint_test.go
cvs rdiff -u -r1.32 -r1.33 pkgsrc/pkgtools/pkglint/files/distinfo.go
cvs rdiff -u -r1.29 -r1.30 pkgsrc/pkgtools/pkglint/files/distinfo_test.go
cvs rdiff -u -r1.23 -r1.24 pkgsrc/pkgtools/pkglint/files/licenses.go
cvs rdiff -u -r1.37 -r1.38 pkgsrc/pkgtools/pkglint/files/mklinechecker.go
cvs rdiff -u -r1.33 -r1.34 \
pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go
cvs rdiff -u -r1.42 -r1.43 pkgsrc/pkgtools/pkglint/files/mklines_test.go
cvs rdiff -u -r1.52 -r1.53 pkgsrc/pkgtools/pkglint/files/package.go
cvs rdiff -u -r1.45 -r1.46 pkgsrc/pkgtools/pkglint/files/package_test.go \
pkgsrc/pkgtools/pkglint/files/shell_test.go
cvs rdiff -u -r1.53 -r1.54 pkgsrc/pkgtools/pkglint/files/pkglint.go
cvs rdiff -u -r1.25 -r1.26 pkgsrc/pkgtools/pkglint/files/pkgsrc.go
cvs rdiff -u -r1.3 -r1.4 pkgsrc/pkgtools/pkglint/files/redundantscope_test.go
cvs rdiff -u -r1.39 -r1.40 pkgsrc/pkgtools/pkglint/files/shell.go
cvs rdiff -u -r1.17 -r1.18 pkgsrc/pkgtools/pkglint/files/toplevel.go
cvs rdiff -u -r1.43 -r1.44 pkgsrc/pkgtools/pkglint/files/util.go
cvs rdiff -u -r1.63 -r1.64 pkgsrc/pkgtools/pkglint/files/vardefs.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.578 pkgsrc/pkgtools/pkglint/Makefile:1.579
--- pkgsrc/pkgtools/pkglint/Makefile:1.578 Sun Apr 28 18:13:53 2019
+++ pkgsrc/pkgtools/pkglint/Makefile Mon May 6 20:27:17 2019
@@ -1,6 +1,6 @@
-# $NetBSD: Makefile,v 1.578 2019/04/28 18:13:53 rillig Exp $
+# $NetBSD: Makefile,v 1.579 2019/05/06 20:27:17 rillig Exp $
-PKGNAME= pkglint-5.7.8
+PKGNAME= pkglint-5.7.9
CATEGORIES= pkgtools
DISTNAME= tools
MASTER_SITES= ${MASTER_SITE_GITHUB:=golang/}
Index: pkgsrc/pkgtools/pkglint/files/buildlink3.go
diff -u pkgsrc/pkgtools/pkglint/files/buildlink3.go:1.21 pkgsrc/pkgtools/pkglint/files/buildlink3.go:1.22
--- pkgsrc/pkgtools/pkglint/files/buildlink3.go:1.21 Sat Apr 20 17:43:24 2019
+++ pkgsrc/pkgtools/pkglint/files/buildlink3.go Mon May 6 20:27:17 2019
@@ -2,6 +2,7 @@ package pkglint
import (
"netbsd.org/pkglint/pkgver"
+ "path"
"strings"
)
@@ -84,12 +85,36 @@ func (ck *Buildlink3Checker) checkFirstP
if containsVarRef(pkgbase) {
ck.checkVaruseInPkgbase(pkgbase, pkgbaseLine)
}
+
+ ck.checkUniquePkgbase(pkgbase, pkgbaseLine)
+
mlex.SkipEmptyOrNote()
ck.pkgbase = pkgbase
ck.pkgbaseLine = pkgbaseLine
return true
}
+func (ck *Buildlink3Checker) checkUniquePkgbase(pkgbase string, mkline MkLine) {
+ prev := G.InterPackage.Bl3(pkgbase, &mkline.Location)
+ if prev == nil {
+ return
+ }
+
+ base, name := trimCommon(pkgbase, path.Base(path.Dir(mkline.Filename)))
+ if base == "" && matches(name, `^(\d*|-cvs|-fossil|-git|-hg|-svn|-devel|-snapshot)$`) {
+ return
+ }
+
+ mkline.Errorf("Duplicate package identifier %q already appeared in %s.",
+ pkgbase, mkline.RefToLocation(*prev))
+ mkline.Explain(
+ "Each buildlink3.mk file must have a unique identifier.",
+ "These identifiers are used for multiple-inclusion guards,",
+ "and using the same identifier for different packages",
+ "(often by copy-and-paste) may change the dependencies",
+ "of a package in subtle and unexpected ways.")
+}
+
// checkSecondParagraph checks the multiple inclusion protection and
// introduces the uppercase package identifier.
func (ck *Buildlink3Checker) checkSecondParagraph(mlex *MkLinesLexer) bool {
Index: pkgsrc/pkgtools/pkglint/files/buildlink3_test.go
diff -u pkgsrc/pkgtools/pkglint/files/buildlink3_test.go:1.30 pkgsrc/pkgtools/pkglint/files/buildlink3_test.go:1.31
--- pkgsrc/pkgtools/pkglint/files/buildlink3_test.go:1.30 Sat Apr 20 17:43:24 2019
+++ pkgsrc/pkgtools/pkglint/files/buildlink3_test.go Mon May 6 20:27:17 2019
@@ -520,6 +520,59 @@ func (s *Suite) Test_CheckLinesBuildlink
"(also in other variables in this file).")
}
+func (s *Suite) Test_Buildlink3Checker_checkUniquePkgbase(c *check.C) {
+ t := s.Init(c)
+
+ G.InterPackage.Enable()
+
+ test := func(pkgbase, pkgpath string, diagnostics ...string) {
+ mkline := t.NewMkLine(t.File(pkgpath+"/buildlink3.mk"), 123, "")
+
+ (*Buildlink3Checker).checkUniquePkgbase(nil, pkgbase, mkline)
+
+ t.CheckOutput(diagnostics)
+ }
+
+ // From now on, the pkgbase "php" may only be used for "php\d+".
+ test("php", "lang/php56",
+ nil...)
+
+ // No warning since "php" is a valid buildlink3 basename for "php56".
+ test("php", "lang/php72",
+ nil...)
+
+ // But this is a clear typo.
+ test("php", "security/pgp",
+ "ERROR: ~/security/pgp/buildlink3.mk:123: "+
+ "Duplicate package identifier \"php\" already appeared "+
+ "in ../../lang/php56/buildlink3.mk:123.")
+
+ // This combination is not allowed because the names "php" and "php-pcre"
+ // differ too much. The only allowed inexact match is that the pkgname
+ // has one more number than the pkgbase, no matter at which position.
+ test("php", "textproc/php-pcre",
+ "ERROR: ~/textproc/php-pcre/buildlink3.mk:123: "+
+ "Duplicate package identifier \"php\" already appeared "+
+ "in ../../lang/php56/buildlink3.mk:123.")
+
+ test("ruby-module", "net/ruby24-module",
+ nil...)
+
+ test("ruby-module", "net/ruby26-module",
+ nil...)
+
+ test("ruby-module", "net/ruby26-module12",
+ "ERROR: ~/net/ruby26-module12/buildlink3.mk:123: "+
+ "Duplicate package identifier \"ruby-module\" already appeared "+
+ "in ../../net/ruby24-module/buildlink3.mk:123.")
+
+ test("package", "devel/package",
+ nil...)
+
+ test("package", "wip/package",
+ nil...)
+}
+
func (s *Suite) Test_Buildlink3Checker_checkMainPart__if_else_endif(c *check.C) {
t := s.Init(c)
Index: pkgsrc/pkgtools/pkglint/files/check_test.go
diff -u pkgsrc/pkgtools/pkglint/files/check_test.go:1.40 pkgsrc/pkgtools/pkglint/files/check_test.go:1.41
--- pkgsrc/pkgtools/pkglint/files/check_test.go:1.40 Sat Apr 27 19:33:57 2019
+++ pkgsrc/pkgtools/pkglint/files/check_test.go Mon May 6 20:27:17 2019
@@ -177,6 +177,13 @@ func (t *Tester) SetUpVartypes() {
}
func (t *Tester) SetUpMasterSite(varname string, urls ...string) {
+ if !G.Pkgsrc.vartypes.DefinedExact(varname) {
+ G.Pkgsrc.vartypes.DefineParse(varname, BtFetchURL,
+ List|SystemProvided,
+ "buildlink3.mk: none",
+ "*: use")
+ }
+
for _, url := range urls {
G.Pkgsrc.registerMasterSite(varname, url)
}
@@ -272,6 +279,8 @@ func (t *Tester) SetUpPkgsrc() {
// The various MASTER_SITE_* variables for use in the
// MASTER_SITES are defined in this file.
//
+ // To define a MASTER_SITE for a pkglint test, call t.SetUpMasterSite.
+ //
// See Pkgsrc.loadMasterSites.
t.CreateFileLines("mk/fetch/sites.mk",
MkRcsID)
@@ -497,6 +506,14 @@ func (t *Tester) File(relativeFileName s
return path.Clean(t.tmpdir + "/" + relativeFileName)
}
+// Copy copies a file inside the temporary directory.
+func (t *Tester) Copy(relativeSrc, relativeDst string) {
+ data, err := ioutil.ReadFile(t.File(relativeSrc))
+ G.AssertNil(err, "Copy.Read")
+ err = ioutil.WriteFile(t.File(relativeDst), data, 0777)
+ G.AssertNil(err, "Copy.Write")
+}
+
// Chdir changes the current working directory to the given subdirectory
// of the temporary directory, creating it if necessary.
//
@@ -552,7 +569,7 @@ func (t *Tester) Remove(relativeFileName
// "VAR= env")))
//
// mklines := get("including.mk")
-// module := get("module.mk")
+// module := get("subdir/module.mk")
//
// The filenames passed to the include function are all relative to the
// same location, but that location is irrelevant in practice. The generated
Index: pkgsrc/pkgtools/pkglint/files/pkglint_test.go
diff -u pkgsrc/pkgtools/pkglint/files/pkglint_test.go:1.40 pkgsrc/pkgtools/pkglint/files/pkglint_test.go:1.41
--- pkgsrc/pkgtools/pkglint/files/pkglint_test.go:1.40 Sat Apr 27 19:33:57 2019
+++ pkgsrc/pkgtools/pkglint/files/pkglint_test.go Mon May 6 20:27:17 2019
@@ -1187,3 +1187,24 @@ func (s *Suite) Test_Main(c *check.C) {
"Looks fine.")
// outProfiling is not checked because it contains timing information.
}
+
+func (s *Suite) Test_InterPackage_Bl3__same_identifier(c *check.C) {
+ t := s.Init(c)
+
+ t.SetUpPackage("category/package1",
+ "PKGNAME=\t${DISTNAME:@v@${v}@}") // Make the package name non-obvious.
+ t.SetUpPackage("category/package2",
+ "PKGNAME=\t${DISTNAME:@v@${v}@}") // Make the package name non-obvious.
+ t.CreateFileDummyBuildlink3("category/package1/buildlink3.mk")
+ t.Copy("category/package1/buildlink3.mk", "category/package2/buildlink3.mk")
+ t.Chdir(".")
+ t.FinishSetUp()
+
+ G.InterPackage.Enable()
+ G.Check("category/package1")
+ G.Check("category/package2")
+
+ t.CheckOutputLines(
+ "ERROR: category/package2/buildlink3.mk:3: Duplicate package identifier " +
+ "\"package1\" already appeared in ../../category/package1/buildlink3.mk:3.")
+}
Index: pkgsrc/pkgtools/pkglint/files/distinfo.go
diff -u pkgsrc/pkgtools/pkglint/files/distinfo.go:1.32 pkgsrc/pkgtools/pkglint/files/distinfo.go:1.33
--- pkgsrc/pkgtools/pkglint/files/distinfo.go:1.32 Tue Apr 23 21:20:49 2019
+++ pkgsrc/pkgtools/pkglint/files/distinfo.go Mon May 6 20:27:17 2019
@@ -323,8 +323,8 @@ func (ck *distinfoLinesChecker) checkUnr
// Inter-package check for differing distfile checksums.
func (ck *distinfoLinesChecker) checkGlobalDistfileMismatch(info distinfoHash) {
- hashes := G.Hashes
- if hashes == nil {
+
+ if !G.InterPackage.Enabled() {
return
}
@@ -348,23 +348,20 @@ func (ck *distinfoLinesChecker) checkGlo
return
}
- key := alg + ":" + filename
- otherHash := hashes[key]
-
// See https://github.com/golang/go/issues/29802
hashBytes := make([]byte, hex.DecodedLen(len(hash)))
_, err := hex.Decode(hashBytes, []byte(hash))
if err != nil {
line.Errorf("The %s hash for %s contains a non-hex character.", alg, filename)
+ return
}
+ otherHash := G.InterPackage.Hash(alg, filename, hashBytes, &line.Location)
if otherHash != nil {
if !bytes.Equal(otherHash.hash, hashBytes) {
line.Errorf("The %s hash for %s is %s, which conflicts with %s in %s.",
alg, filename, hash, hex.EncodeToString(otherHash.hash), line.RefToLocation(otherHash.location))
}
- } else {
- hashes[key] = &Hash{hashBytes, line.Location}
}
}
Index: pkgsrc/pkgtools/pkglint/files/distinfo_test.go
diff -u pkgsrc/pkgtools/pkglint/files/distinfo_test.go:1.29 pkgsrc/pkgtools/pkglint/files/distinfo_test.go:1.30
--- pkgsrc/pkgtools/pkglint/files/distinfo_test.go:1.29 Tue Apr 23 21:20:49 2019
+++ pkgsrc/pkgtools/pkglint/files/distinfo_test.go Mon May 6 20:27:17 2019
@@ -204,8 +204,8 @@ func (s *Suite) Test_distinfoLinesChecke
"(Run \"pkglint -e\" to show explanations.)")
// Ensure that hex.DecodeString does not waste memory here.
- t.Check(len(G.Hashes["SHA512:distfile-1.0.tar.gz"].hash), equals, 8)
- t.Check(cap(G.Hashes["SHA512:distfile-1.0.tar.gz"].hash), equals, 8)
+ t.Check(len(G.InterPackage.hashes["SHA512:distfile-1.0.tar.gz"].hash), equals, 8)
+ t.Check(cap(G.InterPackage.hashes["SHA512:distfile-1.0.tar.gz"].hash), equals, 8)
}
func (s *Suite) Test_distinfoLinesChecker_checkAlgorithms__missing_patch_with_distfile_checksums(c *check.C) {
Index: pkgsrc/pkgtools/pkglint/files/licenses.go
diff -u pkgsrc/pkgtools/pkglint/files/licenses.go:1.23 pkgsrc/pkgtools/pkglint/files/licenses.go:1.24
--- pkgsrc/pkgtools/pkglint/files/licenses.go:1.23 Sat Apr 20 17:43:24 2019
+++ pkgsrc/pkgtools/pkglint/files/licenses.go Mon May 6 20:27:17 2019
@@ -32,9 +32,7 @@ func (lc *LicenseChecker) checkName(lice
}
if licenseFile == "" {
licenseFile = G.Pkgsrc.File("licenses/" + license)
- if G.UsedLicenses != nil {
- G.UsedLicenses[intern(license)] = true
- }
+ G.InterPackage.UseLicense(license)
}
if !fileExists(licenseFile) {
Index: pkgsrc/pkgtools/pkglint/files/mklinechecker.go
diff -u pkgsrc/pkgtools/pkglint/files/mklinechecker.go:1.37 pkgsrc/pkgtools/pkglint/files/mklinechecker.go:1.38
--- pkgsrc/pkgtools/pkglint/files/mklinechecker.go:1.37 Sun Apr 28 18:13:53 2019
+++ pkgsrc/pkgtools/pkglint/files/mklinechecker.go Mon May 6 20:27:17 2019
@@ -403,6 +403,9 @@ func (ck MkLineChecker) explainPermissio
}
func (ck MkLineChecker) checkVarassignLeftRationale() {
+ if !G.Opts.WarnExtra {
+ return
+ }
isRationale := func(mkline MkLine) bool {
if mkline.IsVarassign() || mkline.IsCommentedVarassign() {
Index: pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go:1.33 pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go:1.34
--- pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go:1.33 Sun Apr 28 18:13:53 2019
+++ pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go Mon May 6 20:27:17 2019
@@ -766,6 +766,13 @@ func (s *Suite) Test_MkLineChecker_check
"WARN: filename.mk:2: Setting variable ONLY_FOR_PLATFORM should have a rationale.",
"WARN: filename.mk:3: Setting variable NOT_FOR_PLATFORM should have a rationale.",
"WARN: filename.mk:11: Setting variable ONLY_FOR_PLATFORM should have a rationale.")
+
+ // This check is only enabled when -Wextra is given.
+ t.SetUpCommandLine()
+
+ mklines.Check()
+
+ t.CheckOutputEmpty()
}
func (s *Suite) Test_MkLineChecker_checkVarassignOpShell(c *check.C) {
@@ -2150,6 +2157,7 @@ func (s *Suite) Test_MkLineChecker_check
t := s.Init(c)
t.SetUpPkgsrc()
+ t.SetUpMasterSite("MASTER_SITE_GITHUB", "https://download.github.com/")
t.SetUpCommandLine("-Wall,no-space")
mklines := t.SetUpFileMkLines("module.mk",
MkRcsID,
Index: pkgsrc/pkgtools/pkglint/files/mklines_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.42 pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.43
--- pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.42 Sat Apr 27 19:33:57 2019
+++ pkgsrc/pkgtools/pkglint/files/mklines_test.go Mon May 6 20:27:17 2019
@@ -903,6 +903,7 @@ func (s *Suite) Test_MkLines_Check__VERS
t := s.Init(c)
t.SetUpVartypes()
+ t.SetUpMasterSite("MASTER_SITE_SOURCEFORGE", "https://download.sf.net/")
mklines := t.NewMkLines("geography/viking/Makefile",
MkRcsID,
"MASTER_SITES=\t${MASTER_SITE_SOURCEFORGE:=viking/}${VERSION}/")
Index: pkgsrc/pkgtools/pkglint/files/package.go
diff -u pkgsrc/pkgtools/pkglint/files/package.go:1.52 pkgsrc/pkgtools/pkglint/files/package.go:1.53
--- pkgsrc/pkgtools/pkglint/files/package.go:1.52 Sat Apr 27 19:33:57 2019
+++ pkgsrc/pkgtools/pkglint/files/package.go Mon May 6 20:27:17 2019
@@ -218,11 +218,11 @@ func (pkg *Package) load() ([]string, Mk
return files, mklines, allLines
}
-func (pkg *Package) check(files []string, mklines, allLines MkLines) {
+func (pkg *Package) check(filenames []string, mklines, allLines MkLines) {
haveDistinfo := false
havePatches := false
- for _, filename := range files {
+ for _, filename := range filenames {
if containsVarRef(filename) {
if trace.Tracing {
trace.Stepf("Skipping file %q because the name contains an unresolved variable.", filename)
@@ -1013,6 +1013,28 @@ func (pkg *Package) CheckVarorder(mkline
seeGuide("Package components, Makefile", "components.Makefile"))
}
+func (pkg *Package) checkFileMakefileExt(filename string) {
+ base := path.Base(filename)
+ if !hasPrefix(base, "Makefile.") || base == "Makefile.common" {
+ return
+ }
+ ext := strings.TrimPrefix(base, "Makefile.")
+
+ line := NewLineWhole(filename)
+ line.Notef("Consider renaming %q to %q.", base, ext+".mk")
+ line.Explain(
+ "The main definition of a pkgsrc package should be in the Makefile.",
+ "Common definitions for a few very closely related packages can be",
+ "placed in a Makefile.common, these may cover various topics.",
+ "",
+ "All other definitions should be grouped by topics and implemented",
+ "in separate files named *.mk after their topics. Typical examples",
+ "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")))
+}
+
// checkLocallyModified checks files that are about to be committed.
// Depending on whether the package has a MAINTAINER or an OWNER,
// the wording differs.
Index: pkgsrc/pkgtools/pkglint/files/package_test.go
diff -u pkgsrc/pkgtools/pkglint/files/package_test.go:1.45 pkgsrc/pkgtools/pkglint/files/package_test.go:1.46
--- pkgsrc/pkgtools/pkglint/files/package_test.go:1.45 Sat Apr 27 19:33:57 2019
+++ pkgsrc/pkgtools/pkglint/files/package_test.go Mon May 6 20:27:17 2019
@@ -1445,3 +1445,32 @@ func (s *Suite) Test_Package_readMakefil
"~/category/package/Makefile:22: ",
"~/category/package/Makefile:23: .include \"../../mk/bsd.pkg.mk\"")
}
+
+// As of April 2019, there are only a few files in the whole pkgsrc tree
+// that are called Makefile.*, except Makefile.common, which occurs more
+// often.
+//
+// Using the file extension for variants of that Makefile is confusing,
+// therefore they should be renamed to *.mk.
+func (s *Suite) Test_Package__Makefile_files(c *check.C) {
+ t := s.Init(c)
+
+ t.SetUpPackage("category/package")
+ t.CreateFileLines("category/package/Makefile.common",
+ MkRcsID)
+ t.CreateFileLines("category/package/Makefile.orig",
+ MkRcsID)
+ t.CreateFileLines("category/package/Makefile.php",
+ MkRcsID)
+ t.CreateFileLines("category/package/ext.mk",
+ MkRcsID)
+ t.FinishSetUp()
+
+ G.Check(t.File("category/package"))
+
+ // No warning for the Makefile.orig since the package is not
+ // being imported at the moment; see Pkglint.checkReg.
+ t.CheckOutputLines(
+ "NOTE: ~/category/package/Makefile.php: " +
+ "Consider renaming \"Makefile.php\" to \"php.mk\".")
+}
Index: pkgsrc/pkgtools/pkglint/files/shell_test.go
diff -u pkgsrc/pkgtools/pkglint/files/shell_test.go:1.45 pkgsrc/pkgtools/pkglint/files/shell_test.go:1.46
--- pkgsrc/pkgtools/pkglint/files/shell_test.go:1.45 Sat Apr 27 19:33:57 2019
+++ pkgsrc/pkgtools/pkglint/files/shell_test.go Mon May 6 20:27:17 2019
@@ -409,7 +409,8 @@ func (s *Suite) Test_ShellLineChecker_Ch
ck.CheckShellCommandLine("pax -rwpp -s /.*~$$//g . ${DESTDIR}${PREFIX}")
- t.CheckOutputEmpty()
+ t.CheckOutputLines(
+ "WARN: filename.mk:1: Substitution commands like \"/.*~$$//g\" should always be quoted.")
}
func (s *Suite) Test_ShellLineChecker_CheckWord(c *check.C) {
@@ -1188,30 +1189,39 @@ func (s *Suite) Test_ShellProgramChecker
func (s *Suite) Test_SimpleCommandChecker_checkRegexReplace(c *check.C) {
t := s.Init(c)
- t.SetUpTool("pax", "PAX", AtRunTime)
- t.SetUpTool("sed", "SED", AtRunTime)
- mklines := t.NewMkLines("Makefile",
- MkRcsID,
- "pre-configure:",
- "\t${PAX} -s s,.*,, src dst",
- "\tpax -s s,.*,, src dst",
- "\t${SED} -e s,.*,, src dst",
- "\tsed -e s,.*,, src dst",
- "\tpax -s s,\\.orig,, src dst",
- "\tsed -e s,a,b,g src dst")
+ test := func(cmd string, diagnostics ...string) {
+ t.SetUpTool("pax", "PAX", AtRunTime)
+ t.SetUpTool("sed", "SED", AtRunTime)
+ mklines := t.NewMkLines("Makefile",
+ MkRcsID,
+ "pre-configure:",
+ "\t"+cmd)
- mklines.Check()
+ mklines.Check()
+
+ t.CheckOutput(diagnostics)
+ }
+
+ test("${PAX} -s s,.*,, src dst",
+ "WARN: Makefile:3: Substitution commands like \"s,.*,,\" should always be quoted.")
+
+ test("pax -s s,.*,, src dst",
+ "WARN: Makefile:3: Substitution commands like \"s,.*,,\" should always be quoted.")
+
+ test("${SED} -e s,.*,, src dst",
+ "WARN: Makefile:3: Substitution commands like \"s,.*,,\" should always be quoted.")
+
+ test("sed -e s,.*,, src dst",
+ "WARN: Makefile:3: Substitution commands like \"s,.*,,\" should always be quoted.")
+
+ test("pax -s s,\\.orig,, src dst",
+ nil...)
+
+ test("sed -e s,a,b,g src dst",
+ nil...)
- // FIXME: warn for "pax -s".
- // FIXME: warn for "sed -e".
- // TODO: don't warn for "pax .orig".
- // TODO: don't warn for "s,a,b,g".
// TODO: Merge the code with BtSedCommands.
// TODO: Finally, remove the G.Testing from the main code.
- t.CheckOutputLines(
- "WARN: Makefile:3: Substitution commands like \"s,.*,,\" should always be quoted.",
- "WARN: Makefile:5: Substitution commands like \"s,.*,,\" should always be quoted.")
-
}
func (s *Suite) Test_ShellProgramChecker_checkSetE__simple_commands(c *check.C) {
Index: pkgsrc/pkgtools/pkglint/files/pkglint.go
diff -u pkgsrc/pkgtools/pkglint/files/pkglint.go:1.53 pkgsrc/pkgtools/pkglint/files/pkglint.go:1.54
--- pkgsrc/pkgtools/pkglint/files/pkglint.go:1.53 Sat Apr 27 19:33:57 2019
+++ pkgsrc/pkgtools/pkglint/files/pkglint.go Mon May 6 20:27:17 2019
@@ -45,8 +45,7 @@ type Pkglint struct {
// There is no other use for it.
cwd string
- Hashes map[string]*Hash // Maps "alg:filename" => hash (inter-package check).
- UsedLicenses map[string]bool // Maps "license name" => true (inter-package check).
+ InterPackage InterPackage
}
func NewPkglint() Pkglint {
@@ -60,6 +59,58 @@ func NewPkglint() Pkglint {
interner: NewStringInterner()}
}
+type InterPackage struct {
+ hashes map[string]*Hash // Maps "alg:filename" => hash (inter-package check).
+ usedLicenses map[string]struct{} // Maps "license name" => true (inter-package check).
+ bl3Names map[string]Location // Maps buildlink3 identifiers to their first occurrence.
+}
+
+func (ip *InterPackage) Enable() {
+ *ip = InterPackage{
+ make(map[string]*Hash),
+ make(map[string]struct{}),
+ make(map[string]Location)}
+}
+
+func (ip *InterPackage) Enabled() bool { return ip.hashes != nil }
+
+func (ip *InterPackage) Hash(alg, filename string, hashBytes []byte, loc *Location) *Hash {
+ key := alg + ":" + filename
+ if otherHash := ip.hashes[key]; otherHash != nil {
+ return otherHash
+ }
+
+ ip.hashes[key] = &Hash{hashBytes, *loc}
+ return nil
+}
+
+func (ip *InterPackage) UseLicense(name string) {
+ if ip.usedLicenses != nil {
+ ip.usedLicenses[intern(name)] = struct{}{}
+ }
+}
+
+func (ip *InterPackage) LicenseUsed(name string) bool {
+ _, used := ip.usedLicenses[name]
+ return used
+}
+
+// Bl3 remembers that the given buildlink3 name is used at the given location.
+// Since these names must be unique, there should be no other location where
+// the same name is used.
+func (ip *InterPackage) Bl3(name string, loc *Location) *Location {
+ if ip.bl3Names == nil {
+ return nil
+ }
+
+ if prev, found := ip.bl3Names[name]; found {
+ return &prev
+ }
+
+ ip.bl3Names[name] = *loc
+ return nil
+}
+
type CmdOpts struct {
CheckExtra,
CheckGlobal bool
@@ -575,6 +626,10 @@ func CheckFileMk(filename string) {
return
}
+ if G.Pkg != nil {
+ G.Pkg.checkFileMakefileExt(filename)
+ }
+
mklines.Check()
mklines.SaveAutofixChanges()
}
Index: pkgsrc/pkgtools/pkglint/files/pkgsrc.go
diff -u pkgsrc/pkgtools/pkglint/files/pkgsrc.go:1.25 pkgsrc/pkgtools/pkglint/files/pkgsrc.go:1.26
--- pkgsrc/pkgtools/pkglint/files/pkgsrc.go:1.25 Sat Apr 27 19:33:57 2019
+++ pkgsrc/pkgtools/pkglint/files/pkgsrc.go Mon May 6 20:27:17 2019
@@ -13,6 +13,10 @@ import (
// Pkgsrc describes a pkgsrc installation.
// In each pkglint run, only a single pkgsrc installation is ever loaded.
// It just doesn't make sense to check multiple pkgsrc installations at once.
+//
+// This type only contains data that is loaded once and then stays constant.
+// Everything else (distfile hashes, package names) is recorded in the Pkglint
+// type instead.
type Pkgsrc struct {
// The top directory (PKGSRCDIR), either absolute or relative to
// the current working directory.
@@ -249,15 +253,14 @@ func (src *Pkgsrc) ListVersions(category
}
func (src *Pkgsrc) checkToplevelUnusedLicenses() {
- usedLicenses := G.UsedLicenses
- if usedLicenses == nil {
+ if !G.InterPackage.Enabled() {
return
}
licensesDir := src.File("licenses")
for _, licenseFile := range src.ReadDir("licenses") {
licenseName := licenseFile.Name()
- if !usedLicenses[licenseName] {
+ if !G.InterPackage.LicenseUsed(licenseName) {
licensePath := licensesDir + "/" + licenseName
if fileExists(licensePath) {
NewLineWhole(licensePath).Warnf("This license seems to be unused.")
@@ -387,6 +390,7 @@ func (src *Pkgsrc) loadUntypedVars() {
}
handleFile := func(pathName string, info os.FileInfo, err error) error {
+ G.AssertNil(err, "handleFile %q", pathName)
baseName := info.Name()
if hasSuffix(baseName, ".mk") || baseName == "mk.conf" {
handleMkFile(filepath.ToSlash(pathName))
Index: pkgsrc/pkgtools/pkglint/files/redundantscope_test.go
diff -u pkgsrc/pkgtools/pkglint/files/redundantscope_test.go:1.3 pkgsrc/pkgtools/pkglint/files/redundantscope_test.go:1.4
--- pkgsrc/pkgtools/pkglint/files/redundantscope_test.go:1.3 Sat Apr 20 17:43:24 2019
+++ pkgsrc/pkgtools/pkglint/files/redundantscope_test.go Mon May 6 20:27:17 2019
@@ -730,10 +730,118 @@ func (s *Suite) Test_RedundantScope__var
"NOTE: filename.mk:4: Definition of VAR is redundant because of line 2.")
}
+func (s *Suite) Test_RedundantScope__incomplete_then_default(c *check.C) {
+ t := s.Init(c)
+
+ include, get := t.SetUpHierarchy()
+
+ include("including.mk",
+ ".if ${OPSYS} == NetBSD",
+ "VAR=\tNetBSD",
+ ".elif ${OPSYS} == FreeBSD",
+ "VAR=\tFreeBSD",
+ ".endif",
+ "",
+ "VAR?=\tdefault")
+
+ mklines := get("including.mk")
+
+ NewRedundantScope().Check(mklines)
+
+ t.CheckOutputEmpty()
+}
+
+func (s *Suite) Test_RedundantScope__complete_then_default(c *check.C) {
+ t := s.Init(c)
+
+ include, get := t.SetUpHierarchy()
+
+ include("including.mk",
+ ".if ${OPSYS} == NetBSD",
+ "VAR=\tNetBSD",
+ ".else",
+ "VAR=\tFreeBSD",
+ ".endif",
+ "",
+ "VAR?=\tdefault")
+
+ mklines := get("including.mk")
+
+ NewRedundantScope().Check(mklines)
+
+ // TODO: Pkglint could know that the ?= is redundant because VAR is
+ // definitely assigned.
+ t.CheckOutputEmpty()
+}
+
+func (s *Suite) Test_RedundantScope__conditional_then_override(c *check.C) {
+ t := s.Init(c)
+
+ include, get := t.SetUpHierarchy()
+
+ include("including.mk",
+ ".if ${OPSYS} == NetBSD",
+ "VAR=\tNetBSD",
+ ".else",
+ "VAR=\tFreeBSD",
+ ".endif",
+ "",
+ "VAR=\tdefault")
+
+ mklines := get("including.mk")
+
+ NewRedundantScope().Check(mklines)
+
+ // TODO: Pkglint could know that no matter which branch is taken,
+ // the variable will be overwritten in the last line.
+ t.CheckOutputEmpty()
+}
+
+func (s *Suite) Test_RedundantScope__set_then_conditional(c *check.C) {
+ t := s.Init(c)
+
+ include, get := t.SetUpHierarchy()
+
+ include("including.mk",
+ "VAR=\tdefault",
+ "",
+ ".if ${OPSYS} == NetBSD",
+ "VAR=\tNetBSD",
+ ".else",
+ "VAR=\tFreeBSD",
+ ".endif")
+
+ mklines := get("including.mk")
+
+ NewRedundantScope().Check(mklines)
+
+ // TODO: Pkglint could know that no matter which branch is taken,
+ // one of the branches will overwrite the assignment from line 1.
+ t.CheckOutputEmpty()
+}
+
+func (s *Suite) Test_RedundantScope__branch_with_set_then_set(c *check.C) {
+ t := s.Init(c)
+
+ include, get := t.SetUpHierarchy()
+
+ include("including.mk",
+ ".if ${OPSYS} == NetBSD",
+ "VAR=\tfirst",
+ "VAR=\tsecond",
+ ".endif")
+
+ mklines := get("including.mk")
+
+ NewRedundantScope().Check(mklines)
+
+ // TODO: Pkglint could know that the second assignment overwrites the
+ // first assignment since they are in the same basic block.
+ t.CheckOutputEmpty()
+}
+
// FIXME: Continue the systematic redundancy tests.
//
-// Tests where the variables are defined conditionally using .if, .else, .endif.
-//
// Tests where the variables are defined in a .for loop that might not be
// evaluated at all.
//
Index: pkgsrc/pkgtools/pkglint/files/shell.go
diff -u pkgsrc/pkgtools/pkglint/files/shell.go:1.39 pkgsrc/pkgtools/pkglint/files/shell.go:1.40
--- pkgsrc/pkgtools/pkglint/files/shell.go:1.39 Tue Apr 23 21:20:49 2019
+++ pkgsrc/pkgtools/pkglint/files/shell.go Mon May 6 20:27:17 2019
@@ -189,10 +189,30 @@ func (ck *ShellLineChecker) checkVaruseT
// This is ok as long as these variables don't have embedded [$\\"'`].
case quoting == shqDquot && varuse.IsQ():
- ck.mkline.Warnf("The :Q modifier should not be used inside double quotes.")
- ck.mkline.Explain(
+ ck.Warnf("The :Q modifier should not be used inside double 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.",
+ "It only works correctly when it appears outside of \"double\" or 'single'",
+ "quotes or `backticks`.",
+ "",
+ "When it is used inside double quotes or backticks, the resulting string may",
+ "contain more backslashes than intended.",
+ "",
+ "When it is used inside single quotes and the string contains a single quote",
+ "itself, it produces syntax errors in the shell.",
+ "",
"To fix this warning, either remove the :Q or the double quotes.",
- "In most cases, it is more appropriate to remove the double quotes.")
+ "In most cases, it is more appropriate to remove the double quotes.",
+ "",
+ "A special case is for empty strings.",
+ "If the empty string should be preserved as an empty string,",
+ "the correct form is ${VAR:Q}'' with either leading or trailing single or double quotes.",
+ "If the empty string should just be skipped,",
+ "a simple ${VAR:Q} without any surrounding quotes is correct.")
+
+ // TODO: What about single quotes?
+ // TODO: What about backticks?
}
if ck.checkVarUse {
@@ -623,17 +643,42 @@ func (scc *SimpleCommandChecker) checkRe
defer trace.Call0()()
}
- cmdname := scc.strcmd.Name
- isSubst := false
- for _, arg := range scc.strcmd.Args {
- if G.Testing && isSubst && !matches(arg, `"^[\"\'].*[\"\']$`) {
- scc.Warnf("Substitution commands like %q should always be quoted.", arg)
- scc.Explain(
- "Usually these substitution commands contain characters like '*' or",
- "other shell metacharacters that might lead to lookup of matching",
- "filenames and then expand to more than one word.")
+ if !G.Testing {
+ return
+ }
+
+ checkArg := func(arg string) {
+ if matches(arg, `"^[\"\'].*[\"\']$`) {
+ return
}
- isSubst = cmdname == "${PAX}" && arg == "-s" || cmdname == "${SED}" && arg == "-e"
+
+ // Substitution commands that consist only of safe characters cannot
+ // have any side effects, therefore they don't need to be quoted.
+ if matches(arg, `^([\w,.]|\\[.])+$`) {
+ return
+ }
+
+ scc.Warnf("Substitution commands like %q should always be quoted.", arg)
+ scc.Explain(
+ "Usually these substitution commands contain characters like '*' or",
+ "other shell metacharacters that might lead to lookup of matching",
+ "filenames and then expand to more than one word.")
+ }
+
+ checkArgAfter := func(opt string) {
+ args := scc.strcmd.Args
+ for i, arg := range args {
+ if i > 0 && args[i-1] == opt {
+ checkArg(arg)
+ }
+ }
+ }
+
+ switch scc.strcmd.Name {
+ case "${PAX}", "pax":
+ checkArgAfter("-s")
+ case "${SED}", "sed":
+ checkArgAfter("-e")
}
}
Index: pkgsrc/pkgtools/pkglint/files/toplevel.go
diff -u pkgsrc/pkgtools/pkglint/files/toplevel.go:1.17 pkgsrc/pkgtools/pkglint/files/toplevel.go:1.18
--- pkgsrc/pkgtools/pkglint/files/toplevel.go:1.17 Thu Feb 21 22:49:03 2019
+++ pkgsrc/pkgtools/pkglint/files/toplevel.go Mon May 6 20:27:17 2019
@@ -29,8 +29,7 @@ func CheckdirToplevel(dir string) {
if G.Opts.Recursive {
if G.Opts.CheckGlobal {
- G.UsedLicenses = make(map[string]bool)
- G.Hashes = make(map[string]*Hash)
+ G.InterPackage.Enable()
}
G.Todo = append(append([]string(nil), ctx.subdirs...), G.Todo...)
}
Index: pkgsrc/pkgtools/pkglint/files/util.go
diff -u pkgsrc/pkgtools/pkglint/files/util.go:1.43 pkgsrc/pkgtools/pkglint/files/util.go:1.44
--- pkgsrc/pkgtools/pkglint/files/util.go:1.43 Sat Apr 27 19:33:57 2019
+++ pkgsrc/pkgtools/pkglint/files/util.go Mon May 6 20:27:17 2019
@@ -91,6 +91,22 @@ func trimHspace(str string) string {
return str[start:end]
}
+func trimCommon(a, b string) (string, string) {
+ // trim common prefix
+ for len(a) > 0 && len(b) > 0 && a[0] == b[0] {
+ a = a[1:]
+ b = b[1:]
+ }
+
+ // trim common suffix
+ for len(a) > 0 && len(b) > 0 && a[len(a)-1] == b[len(b)-1] {
+ a = a[:len(a)-1]
+ b = b[:len(b)-1]
+ }
+
+ return a, b
+}
+
func isHspace(ch byte) bool {
return ch == ' ' || ch == '\t'
}
Index: pkgsrc/pkgtools/pkglint/files/vardefs.go
diff -u pkgsrc/pkgtools/pkglint/files/vardefs.go:1.63 pkgsrc/pkgtools/pkglint/files/vardefs.go:1.64
--- pkgsrc/pkgtools/pkglint/files/vardefs.go:1.63 Thu May 2 08:36:10 2019
+++ pkgsrc/pkgtools/pkglint/files/vardefs.go Mon May 6 20:27:17 2019
@@ -1220,7 +1220,7 @@ func (reg *VarTypeRegistry) Init(src *Pk
pkg("MAKE_FILE", BtPathname)
pkglist("MAKE_FLAGS", BtShellWord)
pkglist("MAKE_FLAGS.*", BtShellWord)
- pkg("MAKE_JOBS_SAFE", BtYesNo)
+ pkgrat("MAKE_JOBS_SAFE", BtYesNo)
pkg("MAKE_PROGRAM", BtShellCommand)
pkg("MANCOMPRESSED", BtYesNo)
pkg("MANCOMPRESSED_IF_MANZ", BtYes)
@@ -1228,44 +1228,20 @@ func (reg *VarTypeRegistry) Init(src *Pk
sys("MANMODE", BtFileMode)
sys("MANOWN", BtUserGroupName)
pkglist("MASTER_SITES", BtFetchURL)
- // TODO: Extract the MASTER_SITE_* definitions from mk/fetch/sites.mk
- // instead of listing them here.
- syslist("MASTER_SITE_APACHE", BtFetchURL)
- syslist("MASTER_SITE_BACKUP", BtFetchURL)
- syslist("MASTER_SITE_CRATESIO", BtFetchURL)
- syslist("MASTER_SITE_CYGWIN", BtFetchURL)
- syslist("MASTER_SITE_DEBIAN", BtFetchURL)
- syslist("MASTER_SITE_FREEBSD", BtFetchURL)
- syslist("MASTER_SITE_FREEBSD_LOCAL", BtFetchURL)
- syslist("MASTER_SITE_GENTOO", BtFetchURL)
- syslist("MASTER_SITE_GITHUB", BtFetchURL)
- syslist("MASTER_SITE_GNOME", BtFetchURL)
- syslist("MASTER_SITE_GNU", BtFetchURL)
- syslist("MASTER_SITE_GNUSTEP", BtFetchURL)
- syslist("MASTER_SITE_IFARCHIVE", BtFetchURL)
- syslist("MASTER_SITE_HASKELL_HACKAGE", BtFetchURL)
- syslist("MASTER_SITE_KDE", BtFetchURL)
- syslist("MASTER_SITE_LOCAL", BtFetchURL)
- syslist("MASTER_SITE_MOZILLA", BtFetchURL)
- syslist("MASTER_SITE_MOZILLA_ALL", BtFetchURL)
- syslist("MASTER_SITE_MOZILLA_ESR", BtFetchURL)
- syslist("MASTER_SITE_MYSQL", BtFetchURL)
- syslist("MASTER_SITE_NETLIB", BtFetchURL)
- syslist("MASTER_SITE_OPENBSD", BtFetchURL)
- syslist("MASTER_SITE_OPENOFFICE", BtFetchURL)
- syslist("MASTER_SITE_OSDN", BtFetchURL)
- syslist("MASTER_SITE_PERL_CPAN", BtFetchURL)
- syslist("MASTER_SITE_PGSQL", BtFetchURL)
- syslist("MASTER_SITE_PYPI", BtFetchURL)
- syslist("MASTER_SITE_R_CRAN", BtFetchURL)
- syslist("MASTER_SITE_RUBYGEMS", BtFetchURL)
- syslist("MASTER_SITE_SOURCEFORGE", BtFetchURL)
- syslist("MASTER_SITE_SUNSITE", BtFetchURL)
- syslist("MASTER_SITE_SUSE", BtFetchURL)
- syslist("MASTER_SITE_TEX_CTAN", BtFetchURL)
- syslist("MASTER_SITE_XCONTRIB", BtFetchURL)
- syslist("MASTER_SITE_XEMACS", BtFetchURL)
- syslist("MASTER_SITE_XORG", BtFetchURL)
+
+ for _, filename := range []string{"mk/fetch/sites.mk", "mk/fetch/fetch.mk"} {
+ sitesMk := LoadMk(src.File(filename), NotEmpty)
+ if sitesMk != nil {
+ sitesMk.ForEach(func(mkline MkLine) {
+ if mkline.IsVarassign() && hasPrefix(mkline.Varname(), "MASTER_SITE_") {
+ syslist(mkline.Varname(), BtFetchURL)
+ }
+ })
+ } else {
+ // During tests, use t.SetUpMasterSite instead to declare these variables.
+ }
+ }
+
pkglist("MESSAGE_SRC", BtPathname)
pkglist("MESSAGE_SUBST", BtShellWord)
pkg("META_PACKAGE", BtYes)
Home |
Main Index |
Thread Index |
Old Index