summaryrefslogtreecommitdiff
path: root/pkgtools
diff options
context:
space:
mode:
authorrillig <rillig@pkgsrc.org>2021-06-06 07:41:34 +0000
committerrillig <rillig@pkgsrc.org>2021-06-06 07:41:34 +0000
commit13aa7c90adaf414a78421a3b7c944174eece680b (patch)
tree0b5d104e4beaaff46970cd7afe69c61ff3f0c39e /pkgtools
parent771977eeb11e067dac802faab483ef00f2678c5a (diff)
downloadpkgsrc-13aa7c90adaf414a78421a3b7c944174eece680b.tar.gz
pkgtools/pkglint: update to 21.1.3
Changes since 21.1.2: The entries in doc/CHANGES are checked more strictly, they must always consist of 4 words (for removed packages) or 6 words (for all other changes). Packages that include curses.buildlink3.mk may use all buildlink3 variables with the identifier "curses". The previous pkglint warnings had been wrong. Python packages that directly contain .egg-info in their PLIST files should include egg.mk instead. Pkglint can now fix these packages automatically.
Diffstat (limited to 'pkgtools')
-rw-r--r--pkgtools/pkglint/Makefile4
-rw-r--r--pkgtools/pkglint/files/autofix.go9
-rw-r--r--pkgtools/pkglint/files/autofix_test.go17
-rw-r--r--pkgtools/pkglint/files/line.go1
-rw-r--r--pkgtools/pkglint/files/mkvarusechecker.go6
-rw-r--r--pkgtools/pkglint/files/mkvarusechecker_test.go36
-rw-r--r--pkgtools/pkglint/files/package.go46
-rw-r--r--pkgtools/pkglint/files/pkgsrc.go10
-rw-r--r--pkgtools/pkglint/files/pkgsrc_test.go5
-rw-r--r--pkgtools/pkglint/files/plist.go15
-rw-r--r--pkgtools/pkglint/files/plist_test.go29
11 files changed, 169 insertions, 9 deletions
diff --git a/pkgtools/pkglint/Makefile b/pkgtools/pkglint/Makefile
index 5c757d14f16..a07ef51c265 100644
--- a/pkgtools/pkglint/Makefile
+++ b/pkgtools/pkglint/Makefile
@@ -1,6 +1,6 @@
-# $NetBSD: Makefile,v 1.686 2021/05/25 21:48:46 rillig Exp $
+# $NetBSD: Makefile,v 1.687 2021/06/06 07:41:34 rillig Exp $
-PKGNAME= pkglint-21.1.2
+PKGNAME= pkglint-21.1.3
CATEGORIES= pkgtools
DISTNAME= tools
MASTER_SITES= ${MASTER_SITE_GITHUB:=golang/}
diff --git a/pkgtools/pkglint/files/autofix.go b/pkgtools/pkglint/files/autofix.go
index c1d177876d9..6522bc92d75 100644
--- a/pkgtools/pkglint/files/autofix.go
+++ b/pkgtools/pkglint/files/autofix.go
@@ -84,6 +84,15 @@ func (fix *Autofix) Notef(format string, args ...interface{}) {
fix.setDiag(Note, format, args)
}
+// Silent removes the need to specify the diagnostic that most fixes need.
+//
+// When a fix is part of a larger "transaction", the diagnostic may already be
+// printed by another fix, and no further diagnostic is needed to inform the
+// pkglint user about all changes that happen.
+func (fix *Autofix) Silent() {
+ fix.setDiag(Note, SilentAutofixFormat, nil)
+}
+
// Explain remembers the explanation for logging it later when Apply is called.
func (fix *Autofix) Explain(explanation ...string) {
// Since a silent fix doesn't have a diagnostic, its explanation would
diff --git a/pkgtools/pkglint/files/autofix_test.go b/pkgtools/pkglint/files/autofix_test.go
index 290f998c1b9..6f49477878c 100644
--- a/pkgtools/pkglint/files/autofix_test.go
+++ b/pkgtools/pkglint/files/autofix_test.go
@@ -401,6 +401,23 @@ func (s *Suite) Test_Autofix_Notef(c *check.C) {
"NOTE: DESCR:1: Note.")
}
+func (s *Suite) Test_Autofix_Silent(c *check.C) {
+ t := s.Init(c)
+
+ t.SetUpCommandLine("--show-autofix")
+
+ line := t.NewLine("DESCR", 1, "Description of the package")
+
+ fix := line.Autofix()
+ fix.Silent()
+ fix.Replace("package", "replaced package")
+ fix.Apply()
+
+ t.CheckOutputLines(
+ "AUTOFIX: DESCR:1: Replacing \"package\" with \"replaced package\".")
+ t.CheckEquals(line.fix.texts[0], "Description of the replaced package\n")
+}
+
func (s *Suite) Test_Autofix_Explain__without_explain_option(c *check.C) {
t := s.Init(c)
diff --git a/pkgtools/pkglint/files/line.go b/pkgtools/pkglint/files/line.go
index 6313ce374e3..1e0c9fabee8 100644
--- a/pkgtools/pkglint/files/line.go
+++ b/pkgtools/pkglint/files/line.go
@@ -182,6 +182,7 @@ func (line *Line) String() string {
// fix.Errorf("Must not be ...")
// fix.Warnf("Should not be ...")
// fix.Notef("It is also possible ...")
+// fix.Silent()
//
// fix.Explain(
// "Explanation ...",
diff --git a/pkgtools/pkglint/files/mkvarusechecker.go b/pkgtools/pkglint/files/mkvarusechecker.go
index 0e67e704e81..2c8e31e8ca8 100644
--- a/pkgtools/pkglint/files/mkvarusechecker.go
+++ b/pkgtools/pkglint/files/mkvarusechecker.go
@@ -19,7 +19,7 @@ func NewMkVarUseChecker(use *MkVarUse, mklines *MkLines, mkline *MkLine) *MkVarU
return &MkVarUseChecker{use, vartype, mklines, mkline}
}
-// CheckVaruse checks a single use of a variable in a specific context.
+// Check checks a single use of a variable in a specific context.
func (ck *MkVarUseChecker) Check(vuc *VarUseContext) {
if ck.use.IsExpression() {
return
@@ -242,6 +242,10 @@ func (ck *MkVarUseChecker) checkVarnameBuildlink(varname string) {
}
}
+ // TODO: Generalize the following paragraphs
+ if id == "curses" && pkg.Includes("../../mk/curses.buildlink3.mk") != nil {
+ return
+ }
if id == "mysql-client" && pkg.Includes("../../mk/mysql.buildlink3.mk") != nil {
return
}
diff --git a/pkgtools/pkglint/files/mkvarusechecker_test.go b/pkgtools/pkglint/files/mkvarusechecker_test.go
index 85141e1ee15..bf504733b80 100644
--- a/pkgtools/pkglint/files/mkvarusechecker_test.go
+++ b/pkgtools/pkglint/files/mkvarusechecker_test.go
@@ -524,6 +524,42 @@ func (s *Suite) Test_MkVarUseChecker_checkVarnameBuildlink__no_buildlink3_data(c
"WARN: module.mk:2: Buildlink identifier \"package\" is not known in this package.")
}
+func (s *Suite) Test_MkVarUseChecker_checkVarnameBuildlink__curses_ok(c *check.C) {
+ t := s.Init(c)
+
+ t.SetUpPackage("category/package")
+ t.CreateFileLines("mk/curses.buildlink3.mk")
+ t.CreateFileLines("category/package/module.mk",
+ MkCvsID,
+ "CONFIGURE_ARGS+=\t--prefix=${BUILDLINK_PREFIX.curses}",
+ ".include \"../../mk/curses.buildlink3.mk\"")
+ t.Chdir("category/package")
+ t.FinishSetUp()
+
+ G.Check(".")
+
+ t.CheckOutputEmpty()
+}
+
+func (s *Suite) Test_MkVarUseChecker_checkVarnameBuildlink__curses_bad(c *check.C) {
+ t := s.Init(c)
+
+ t.SetUpPackage("category/package")
+ t.CreateFileLines("mk/curses.buildlink3.mk")
+ t.CreateFileLines("category/package/module.mk",
+ MkCvsID,
+ "CONFIGURE_ARGS+=\t--prefix=${BUILDLINK_PREFIX.curses}",
+ // does not include mk/curses.buildlink3.mk
+ )
+ t.Chdir("category/package")
+ t.FinishSetUp()
+
+ G.Check(".")
+
+ t.CheckOutputLines(
+ "WARN: module.mk:2: Buildlink identifier \"curses\" is not known in this package.")
+}
+
func (s *Suite) Test_MkVarUseChecker_checkVarnameBuildlink__mysql_ok(c *check.C) {
t := s.Init(c)
diff --git a/pkgtools/pkglint/files/package.go b/pkgtools/pkglint/files/package.go
index f1b53c3fb49..0e922768b36 100644
--- a/pkgtools/pkglint/files/package.go
+++ b/pkgtools/pkglint/files/package.go
@@ -20,6 +20,8 @@ type Package struct {
dir CurrPath // The directory of the package, for resolving files
Pkgpath PkgsrcPath // e.g. "category/pkgdir"
+ Makefile *MkLines
+
EffectivePkgname string // PKGNAME or DISTNAME from the package Makefile, including nb13, can be empty
EffectivePkgbase string // EffectivePkgname without the version
EffectivePkgversion string // The version part of the effective PKGNAME, excluding nb13
@@ -216,6 +218,7 @@ func (pkg *Package) loadPackageMakefile() (*MkLines, *MkLines) {
if mainLines == nil {
return nil, nil
}
+ pkg.Makefile = mainLines
G.checkRegCvsSubst(filename)
allLines := NewMkLines(NewLines("", nil), pkg, &pkg.vars)
@@ -1729,6 +1732,49 @@ func (pkg *Package) Includes(filename PackagePath) *MkLine {
return mkline
}
+// CanFixAddInclude tests whether the package Makefile follows the standard
+// form and thus allows to add additional '.include' directives.
+func (pkg *Package) CanFixAddInclude() bool {
+ mklines := pkg.Makefile
+ lastLine := mklines.mklines[len(mklines.mklines)-1]
+ return lastLine.Text == ".include \"../../mk/bsd.pkg.mk\""
+}
+
+// FixAddInclude adds an '.include' directive at the end of the package
+// Makefile.
+func (pkg *Package) FixAddInclude(includedFile PackagePath) {
+ mklines := pkg.Makefile
+
+ alreadyThere := false
+ mklines.ForEach(func(mkline *MkLine) {
+ if mkline.IsInclude() && mkline.IncludedFile() == includedFile.AsRelPath() {
+ alreadyThere = true
+ }
+
+ // XXX: This low-level code should not be necessary.
+ // Instead, the added '.include' line should be a MkLine of its own.
+ if mkline.fix != nil {
+ expected := ".include \"" + includedFile.String() + "\"\n"
+ for _, rawLine := range mkline.fix.above {
+ if rawLine == expected {
+ alreadyThere = true
+ }
+ }
+ }
+ })
+ if alreadyThere {
+ return
+ }
+
+ lastLine := mklines.mklines[len(mklines.mklines)-1]
+ fix := lastLine.Autofix()
+ fix.Silent()
+ fix.InsertAbove(".include \"" + includedFile.String() + "\"")
+ fix.Apply()
+
+ mklines.SaveAutofixChanges()
+}
+
// PlistContent lists the directories and files that appear in the
// package's PLIST files. It serves two purposes:
//
diff --git a/pkgtools/pkglint/files/pkgsrc.go b/pkgtools/pkglint/files/pkgsrc.go
index 4fba0459d77..cbd3bb73e96 100644
--- a/pkgtools/pkglint/files/pkgsrc.go
+++ b/pkgtools/pkglint/files/pkgsrc.go
@@ -399,11 +399,11 @@ func (*Pkgsrc) parseDocChange(line *Line, warn bool) *Change {
switch {
case
- action == Added && f[2] == "version",
- action == Updated && f[2] == "to",
- action == Downgraded && f[2] == "to",
- action == Removed && (f[2] == "successor" || f[2] == "version" || n == 4),
- (action == Renamed || action == Moved) && f[2] == "to":
+ action == Added && f[2] == "version" && n == 6,
+ action == Updated && f[2] == "to" && n == 6,
+ action == Downgraded && f[2] == "to" && n == 6,
+ action == Removed && ((f[2] == "successor" || f[2] == "version") && n == 6 || n == 4),
+ (action == Renamed || action == Moved) && f[2] == "to" && n == 6:
return &Change{
Location: line.Location,
Action: action,
diff --git a/pkgtools/pkglint/files/pkgsrc_test.go b/pkgtools/pkglint/files/pkgsrc_test.go
index 77701052826..7e9c4f8f2bc 100644
--- a/pkgtools/pkglint/files/pkgsrc_test.go
+++ b/pkgtools/pkglint/files/pkgsrc_test.go
@@ -514,6 +514,11 @@ func (s *Suite) Test_Pkgsrc_parseDocChange(c *check.C) {
test("\tAdded category/pkgpath version 1.0 [author-dash 2019-01-01]",
"WARN: doc/CHANGES-2019:123: Invalid doc/CHANGES line: "+
"\tAdded category/pkgpath version 1.0 [author-dash 2019-01-01]")
+
+ // The word 'version' must only appear with 'Added', not with 'Updated'.
+ test("\tUpdated category/pkgpath to version 1.0 [author 2019-01-01]",
+ "WARN: doc/CHANGES-2019:123: Invalid doc/CHANGES line: "+
+ "\tUpdated category/pkgpath to version 1.0 [author 2019-01-01]")
}
func (s *Suite) Test_Pkgsrc_checkRemovedAfterLastFreeze(c *check.C) {
diff --git a/pkgtools/pkglint/files/plist.go b/pkgtools/pkglint/files/plist.go
index 9263b4e1e96..40ab5519953 100644
--- a/pkgtools/pkglint/files/plist.go
+++ b/pkgtools/pkglint/files/plist.go
@@ -228,7 +228,17 @@ func (ck *PlistChecker) checkPathMisc(rel RelPath, pline *PlistLine) {
"since its contents depends on more than one package.")
}
if rel.ContainsText(".egg-info/") {
- pline.Warnf("Include \"../../lang/python/egg.mk\" instead of listing .egg-info files directly.")
+ canFix := ck.pkg != nil && ck.pkg.CanFixAddInclude()
+ fix := pline.Autofix()
+ fix.Warnf("Include \"../../lang/python/egg.mk\" " +
+ "instead of listing .egg-info files directly.")
+ if canFix {
+ fix.Replace(pline.Path().Dir().String(), "${PYSITELIB}/${EGG_INFODIR}")
+ }
+ fix.Apply()
+ if canFix {
+ ck.pkg.FixAddInclude("../../lang/python/egg.mk")
+ }
}
if rel.ContainsPath("..") {
pline.Errorf("Paths in PLIST files must not contain \"..\".")
@@ -534,6 +544,9 @@ type PlistLine struct {
text string // Line.Text without any conditions of the form ${PLIST.cond}
}
+// Autofix returns the autofix instance belonging to the line.
+//
+// See Line.Autofix for usage details.
func (pline *PlistLine) Autofix() *Autofix { return pline.Line.Autofix() }
func (pline *PlistLine) Errorf(format string, args ...interface{}) {
diff --git a/pkgtools/pkglint/files/plist_test.go b/pkgtools/pkglint/files/plist_test.go
index 6a6e410a958..3df3b869483 100644
--- a/pkgtools/pkglint/files/plist_test.go
+++ b/pkgtools/pkglint/files/plist_test.go
@@ -624,6 +624,35 @@ func (s *Suite) Test_PlistChecker_checkPathMisc__python_egg(c *check.C) {
"WARN: PLIST:2: Include \"../../lang/python/egg.mk\" instead of listing .egg-info files directly.")
}
+func (s *Suite) Test_PlistChecker_checkPathMisc__python_egg_autofix(c *check.C) {
+ t := s.Init(c)
+
+ t.SetUpCommandLine("--show-autofix")
+ t.SetUpPackage("category/package")
+ t.Chdir("category/package")
+ t.CreateFileLines("PLIST",
+ PlistCvsID,
+ "${PYSITELIB}/gdspy-${PKGVERSION}-py${PYVERSSUFFIX}.egg-info/PKG-INFO",
+ "${PYSITELIB}/gdspy-${PKGVERSION}-py${PYVERSSUFFIX}.egg-info/SOURCES.txt")
+ t.FinishSetUp()
+
+ G.Check(".")
+
+ t.CheckOutputLines(
+ "WARN: PLIST:2: Include \"../../lang/python/egg.mk\" "+
+ "instead of listing .egg-info files directly.",
+ "AUTOFIX: PLIST:2: Replacing "+
+ "\"${PYSITELIB}/gdspy-${PKGVERSION}-py${PYVERSSUFFIX}.egg-info\" "+
+ "with \"${PYSITELIB}/${EGG_INFODIR}\".",
+ "AUTOFIX: Makefile:21: Inserting a line "+
+ "\".include \\\"../../lang/python/egg.mk\\\"\" above this line.",
+ "WARN: PLIST:3: Include \"../../lang/python/egg.mk\" "+
+ "instead of listing .egg-info files directly.",
+ "AUTOFIX: PLIST:3: Replacing "+
+ "\"${PYSITELIB}/gdspy-${PKGVERSION}-py${PYVERSSUFFIX}.egg-info\" "+
+ "with \"${PYSITELIB}/${EGG_INFODIR}\".")
+}
+
func (s *Suite) Test_PlistChecker_checkPathMisc__unwanted_entries(c *check.C) {
t := s.Init(c)