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: Sat Mar 24 14:32:49 UTC 2018
Modified Files:
pkgsrc/pkgtools/pkglint: Makefile
pkgsrc/pkgtools/pkglint/files: autofix.go autofix_test.go
buildlink3_test.go category_test.go check_test.go distinfo.go
licenses.go licenses_test.go line.go linechecker.go mkline.go
mkline_test.go mklinechecker.go mklinechecker_test.go mklines.go
mklines_test.go mkparser_test.go package.go package_test.go
pkglint.go pkglint_test.go plist.go plist_test.go shell.go
shell_test.go toplevel_test.go util.go vardefs.go vartype_test.go
vartypecheck.go vartypecheck_test.go
Added Files:
pkgsrc/pkgtools/pkglint/files: pkgsrc.go pkgsrc_test.go tools.go
Log Message:
Update pkglint to 5.5.7
Changes since 5.5.6:
* When pkglint warns about files that are accidentally executable, it
offers to fix the file permissions.
* Warn about ${HOMEPAGE:=repository/}, since the := modifier should
only be used with MASTER_SITES.
* When the distinfo file is missing, suggest setting NO_CHECKSUM.
* Several refactorings.
To generate a diff of this commit:
cvs rdiff -u -r1.531 -r1.532 pkgsrc/pkgtools/pkglint/Makefile
cvs rdiff -u -r1.5 -r1.6 pkgsrc/pkgtools/pkglint/files/autofix.go \
pkgsrc/pkgtools/pkglint/files/vartype_test.go
cvs rdiff -u -r1.4 -r1.5 pkgsrc/pkgtools/pkglint/files/autofix_test.go
cvs rdiff -u -r1.12 -r1.13 pkgsrc/pkgtools/pkglint/files/buildlink3_test.go
cvs rdiff -u -r1.8 -r1.9 pkgsrc/pkgtools/pkglint/files/category_test.go \
pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go
cvs rdiff -u -r1.18 -r1.19 pkgsrc/pkgtools/pkglint/files/check_test.go \
pkgsrc/pkgtools/pkglint/files/distinfo.go \
pkgsrc/pkgtools/pkglint/files/mklines_test.go
cvs rdiff -u -r1.10 -r1.11 pkgsrc/pkgtools/pkglint/files/licenses.go \
pkgsrc/pkgtools/pkglint/files/licenses_test.go \
pkgsrc/pkgtools/pkglint/files/mklinechecker.go
cvs rdiff -u -r1.21 -r1.22 pkgsrc/pkgtools/pkglint/files/line.go \
pkgsrc/pkgtools/pkglint/files/mklines.go
cvs rdiff -u -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/linechecker.go
cvs rdiff -u -r1.29 -r1.30 pkgsrc/pkgtools/pkglint/files/mkline.go
cvs rdiff -u -r1.31 -r1.32 pkgsrc/pkgtools/pkglint/files/mkline_test.go
cvs rdiff -u -r1.9 -r1.10 pkgsrc/pkgtools/pkglint/files/mkparser_test.go \
pkgsrc/pkgtools/pkglint/files/toplevel_test.go
cvs rdiff -u -r1.26 -r1.27 pkgsrc/pkgtools/pkglint/files/package.go
cvs rdiff -u -r1.19 -r1.20 pkgsrc/pkgtools/pkglint/files/package_test.go
cvs rdiff -u -r1.28 -r1.29 pkgsrc/pkgtools/pkglint/files/pkglint.go
cvs rdiff -u -r1.16 -r1.17 pkgsrc/pkgtools/pkglint/files/pkglint_test.go
cvs rdiff -u -r0 -r1.1 pkgsrc/pkgtools/pkglint/files/pkgsrc.go \
pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go \
pkgsrc/pkgtools/pkglint/files/tools.go
cvs rdiff -u -r1.23 -r1.24 pkgsrc/pkgtools/pkglint/files/plist.go
cvs rdiff -u -r1.22 -r1.23 pkgsrc/pkgtools/pkglint/files/plist_test.go \
pkgsrc/pkgtools/pkglint/files/shell.go \
pkgsrc/pkgtools/pkglint/files/shell_test.go \
pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go
cvs rdiff -u -r1.20 -r1.21 pkgsrc/pkgtools/pkglint/files/util.go
cvs rdiff -u -r1.37 -r1.38 pkgsrc/pkgtools/pkglint/files/vardefs.go
cvs rdiff -u -r1.30 -r1.31 pkgsrc/pkgtools/pkglint/files/vartypecheck.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.531 pkgsrc/pkgtools/pkglint/Makefile:1.532
--- pkgsrc/pkgtools/pkglint/Makefile:1.531 Sun Mar 4 20:34:32 2018
+++ pkgsrc/pkgtools/pkglint/Makefile Sat Mar 24 14:32:49 2018
@@ -1,6 +1,6 @@
-# $NetBSD: Makefile,v 1.531 2018/03/04 20:34:32 rillig Exp $
+# $NetBSD: Makefile,v 1.532 2018/03/24 14:32:49 rillig Exp $
-PKGNAME= pkglint-5.5.6
+PKGNAME= pkglint-5.5.7
DISTFILES= # none
CATEGORIES= pkgtools
Index: pkgsrc/pkgtools/pkglint/files/autofix.go
diff -u pkgsrc/pkgtools/pkglint/files/autofix.go:1.5 pkgsrc/pkgtools/pkglint/files/autofix.go:1.6
--- pkgsrc/pkgtools/pkglint/files/autofix.go:1.5 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/autofix.go Sat Mar 24 14:32:49 2018
@@ -38,6 +38,22 @@ func NewAutofix(line Line) *Autofix {
lines: append([]*RawLine{}, line.raw...)}
}
+// Custom runs a custom fix action, unless the fix is skipped anyway
+// because of the --only option.
+//
+// The fixer function must always call Describef.
+// If printAutofix or autofix is true, the fix should be done in
+// memory as far as possible (e.g. changes to the text of the line).
+// If autofix is true, the fix should be done permanently
+// (e.g. direct changes to the file system).
+func (fix *Autofix) Custom(fixer func(printAutofix, autofix bool)) {
+ if fix.skip() {
+ return
+ }
+
+ fixer(G.opts.PrintAutofix, G.opts.Autofix)
+}
+
func (fix *Autofix) Replace(from string, to string) {
fix.ReplaceAfter("", from, to)
}
@@ -62,8 +78,10 @@ func (fix *Autofix) ReplaceAfter(prefix,
}
}
-// ReplaceRegex replaces the first or all occurrences of the `from` pattern
-// with the fixed string `toText`. Placeholders like `$1` are _not_ expanded.
+// ReplaceRegex replaces the first howOften or all occurrences (if negative)
+// of the `from` pattern with the fixed string `toText`.
+//
+// Placeholders like `$1` are _not_ expanded in the `toText`.
// (If you know how to do the expansion correctly, feel free to implement it.)
func (fix *Autofix) ReplaceRegex(from regex.Pattern, toText string, howOften int) {
if fix.skip() {
@@ -223,10 +241,10 @@ func (fix *Autofix) Explain(explanation
// * records the fixes in the line (--autofix)
func (fix *Autofix) Apply() {
line := fix.line
- if line.firstLine < 1 {
- return
- }
+ if fix.diagFormat == "" {
+ panic("Each autofix must have a diagnostic.")
+ }
G.explainNext = shallBeLogged(fix.diagFormat)
if G.explainNext {
logDiagnostic := fix.level != nil && fix.diagFormat != "Silent-Magic-Diagnostic" &&
@@ -239,7 +257,11 @@ func (fix *Autofix) Apply() {
logRepair := len(fix.actions) > 0 && (G.opts.Autofix || G.opts.PrintAutofix)
if logRepair {
for _, action := range fix.actions {
- logs(llAutofix, line.Filename, strconv.Itoa(action.lineno), "", action.description)
+ lineno := ""
+ if action.lineno != 0 {
+ lineno = strconv.Itoa(action.lineno)
+ }
+ logs(llAutofix, line.Filename, lineno, "", action.description)
}
}
Index: pkgsrc/pkgtools/pkglint/files/vartype_test.go
diff -u pkgsrc/pkgtools/pkglint/files/vartype_test.go:1.5 pkgsrc/pkgtools/pkglint/files/vartype_test.go:1.6
--- pkgsrc/pkgtools/pkglint/files/vartype_test.go:1.5 Mon Feb 19 12:40:38 2018
+++ pkgsrc/pkgtools/pkglint/files/vartype_test.go Sat Mar 24 14:32:49 2018
@@ -5,15 +5,17 @@ import (
)
func (s *Suite) Test_Vartype_EffectivePermissions(c *check.C) {
- G.globalData.InitVartypes()
+ t := s.Init(c)
- if t := G.globalData.vartypes["PREFIX"]; c.Check(t, check.NotNil) {
+ t.SetupVartypes()
+
+ if t := G.Pkgsrc.vartypes["PREFIX"]; c.Check(t, check.NotNil) {
c.Check(t.basicType.name, equals, "Pathname")
c.Check(t.aclEntries, check.DeepEquals, []ACLEntry{{glob: "*", permissions: aclpUse}})
c.Check(t.EffectivePermissions("Makefile"), equals, aclpUse)
}
- if t := G.globalData.vartypes["EXTRACT_OPTS"]; c.Check(t, check.NotNil) {
+ if t := G.Pkgsrc.vartypes["EXTRACT_OPTS"]; c.Check(t, check.NotNil) {
c.Check(t.basicType.name, equals, "ShellWord")
c.Check(t.EffectivePermissions("Makefile"), equals, aclpAppend|aclpSet)
c.Check(t.EffectivePermissions("../Makefile"), equals, aclpAppend|aclpSet)
Index: pkgsrc/pkgtools/pkglint/files/autofix_test.go
diff -u pkgsrc/pkgtools/pkglint/files/autofix_test.go:1.4 pkgsrc/pkgtools/pkglint/files/autofix_test.go:1.5
--- pkgsrc/pkgtools/pkglint/files/autofix_test.go:1.4 Mon Feb 19 12:40:38 2018
+++ pkgsrc/pkgtools/pkglint/files/autofix_test.go Sat Mar 24 14:32:49 2018
@@ -1,6 +1,9 @@
package main
-import "gopkg.in/check.v1"
+import (
+ "gopkg.in/check.v1"
+ "strings"
+)
func (s *Suite) Test_Autofix_ReplaceRegex(c *check.C) {
t := s.Init(c)
@@ -387,3 +390,46 @@ func (s *Suite) Test_SaveAutofixChanges(
// And therefore, no AUTOFIX action must appear in the log.
t.CheckOutputEmpty()
}
+
+func (s *Suite) Test_Autofix_CustomFix(c *check.C) {
+ t := s.Init(c)
+
+ lines := t.NewLines("Makefile",
+ "line1",
+ "line2",
+ "line3")
+
+ doFix := func(line Line) {
+ fix := line.Autofix()
+ fix.Warnf("Please write in ALL-UPPERCASE")
+ fix.Custom(func(printAutofix, autofix bool) {
+ fix.Describef(int(line.firstLine), "Converting to uppercase")
+ if printAutofix || autofix {
+ line.Text = strings.ToUpper(line.Text)
+ }
+ })
+ fix.Apply()
+ }
+
+ doFix(lines[0])
+
+ t.CheckOutputLines(
+ "WARN: Makefile:1: Please write in ALL-UPPERCASE")
+
+ t.SetupCommandLine("--show-autofix")
+
+ doFix(lines[1])
+
+ t.CheckOutputLines(
+ "WARN: Makefile:2: Please write in ALL-UPPERCASE",
+ "AUTOFIX: Makefile:2: Converting to uppercase")
+ c.Check(lines[1].Text, equals, "LINE2")
+
+ t.SetupCommandLine("--autofix")
+
+ doFix(lines[2])
+
+ t.CheckOutputLines(
+ "AUTOFIX: Makefile:3: Converting to uppercase")
+ c.Check(lines[2].Text, equals, "LINE3")
+}
Index: pkgsrc/pkgtools/pkglint/files/buildlink3_test.go
diff -u pkgsrc/pkgtools/pkglint/files/buildlink3_test.go:1.12 pkgsrc/pkgtools/pkglint/files/buildlink3_test.go:1.13
--- pkgsrc/pkgtools/pkglint/files/buildlink3_test.go:1.12 Mon Feb 19 12:40:38 2018
+++ pkgsrc/pkgtools/pkglint/files/buildlink3_test.go Sat Mar 24 14:32:49 2018
@@ -5,7 +5,7 @@ import "gopkg.in/check.v1"
func (s *Suite) Test_ChecklinesBuildlink3Mk(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("buildlink3.mk",
MkRcsID,
"# XXX This file was created automatically using createbuildlink-@PKGVERSION@",
@@ -40,7 +40,7 @@ func (s *Suite) Test_ChecklinesBuildlink
func (s *Suite) Test_ChecklinesBuildlink3Mk_name_mismatch(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Pkg = NewPackage("x11/hs-X11")
G.Pkg.EffectivePkgbase = "X11"
G.Pkg.EffectivePkgnameLine = t.NewMkLine("Makefile", 3, "DISTNAME=\tX11-1.0")
@@ -68,7 +68,7 @@ func (s *Suite) Test_ChecklinesBuildlink
func (s *Suite) Test_ChecklinesBuildlink3Mk_name_mismatch_multiple_inclusion(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("buildlink3.mk",
MkRcsID,
"",
@@ -91,7 +91,7 @@ func (s *Suite) Test_ChecklinesBuildlink
func (s *Suite) Test_ChecklinesBuildlink3Mk_name_mismatch_abi_api(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("buildlink3.mk",
MkRcsID,
"",
@@ -116,7 +116,7 @@ func (s *Suite) Test_ChecklinesBuildlink
func (s *Suite) Test_ChecklinesBuildlink3Mk_abi_api_versions(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("buildlink3.mk",
MkRcsID,
"",
@@ -141,7 +141,7 @@ func (s *Suite) Test_ChecklinesBuildlink
func (s *Suite) Test_ChecklinesBuildlink3Mk_no_BUILDLINK_TREE_at_beginning(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("buildlink3.mk",
MkRcsID,
"",
@@ -165,7 +165,7 @@ func (s *Suite) Test_ChecklinesBuildlink
func (s *Suite) Test_ChecklinesBuildlink3Mk_no_BUILDLINK_TREE_at_end(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("buildlink3.mk",
MkRcsID,
"",
@@ -194,7 +194,7 @@ func (s *Suite) Test_ChecklinesBuildlink
func (s *Suite) Test_ChecklinesBuildlink3Mk_multiple_inclusion_wrong(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("buildlink3.mk",
MkRcsID,
"",
@@ -213,7 +213,7 @@ func (s *Suite) Test_ChecklinesBuildlink
func (s *Suite) Test_ChecklinesBuildlink3Mk_missing_endif(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("buildlink3.mk",
MkRcsID,
"",
@@ -231,7 +231,7 @@ func (s *Suite) Test_ChecklinesBuildlink
func (s *Suite) Test_ChecklinesBuildlink3Mk_unknown_dependency_patterns(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("buildlink3.mk",
MkRcsID,
"",
@@ -258,7 +258,7 @@ func (s *Suite) Test_ChecklinesBuildlink
func (s *Suite) Test_ChecklinesBuildlink3Mk_PKGBASE_with_variable(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("buildlink3.mk",
MkRcsID,
"",
@@ -283,7 +283,7 @@ func (s *Suite) Test_ChecklinesBuildlink
func (s *Suite) Test_ChecklinesBuildlink3Mk_PKGBASE_with_unknown_variable(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("buildlink3.mk",
MkRcsID,
"",
@@ -314,7 +314,7 @@ func (s *Suite) Test_ChecklinesBuildlink
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("buildlink3.mk",
MkRcsID,
"",
Index: pkgsrc/pkgtools/pkglint/files/category_test.go
diff -u pkgsrc/pkgtools/pkglint/files/category_test.go:1.8 pkgsrc/pkgtools/pkglint/files/category_test.go:1.9
--- pkgsrc/pkgtools/pkglint/files/category_test.go:1.8 Mon Feb 19 12:40:38 2018
+++ pkgsrc/pkgtools/pkglint/files/category_test.go Sat Mar 24 14:32:49 2018
@@ -5,7 +5,7 @@ import "gopkg.in/check.v1"
func (s *Suite) Test_CheckdirCategory_totally_broken(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
t.SetupFileLines("archivers/Makefile",
"# $",
"SUBDIR+=pkg1",
@@ -36,7 +36,7 @@ func (s *Suite) Test_CheckdirCategory_to
func (s *Suite) Test_CheckdirCategory_invalid_comment(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
t.SetupFileLines("archivers/Makefile",
MkRcsID,
"COMMENT=\t\\Make $$$$ fast\"",
Index: pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go:1.8 pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go:1.9
--- pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go:1.8 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go Sat Mar 24 14:32:49 2018
@@ -6,10 +6,10 @@ func (s *Suite) Test_MkLineChecker_Check
t := s.Init(c)
t.SetupCommandLine("-Wtypes")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mkline := t.NewMkLine("fname", 1, "COMMENT=\tA nice package")
- vartype1 := G.globalData.vartypes["COMMENT"]
+ vartype1 := G.Pkgsrc.vartypes["COMMENT"]
c.Assert(vartype1, check.NotNil)
c.Check(vartype1.guessed, equals, false)
@@ -29,7 +29,7 @@ func (s *Suite) Test_MkLineChecker_Check
func (s *Suite) Test_MkLineChecker_CheckVartype(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mkline := t.NewMkLine("fname", 1, "DISTNAME=gcc-${GCC_VERSION}")
MkLineChecker{mkline}.CheckVartype("DISTNAME", opAssign, "gcc-${GCC_VERSION}", "")
@@ -43,7 +43,7 @@ func (s *Suite) Test_MkLineChecker_check
t := s.Init(c)
G.Pkg = NewPackage("graphics/gimp-fix-ca")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mkline := t.NewMkLine("fname", 10, "MASTER_SITES=http://registry.gimp.org/file/fix-ca.c?action=download&id=9884&file=")
MkLineChecker{mkline}.checkVarassign()
@@ -55,7 +55,7 @@ func (s *Suite) Test_MkLineChecker_Check
t := s.Init(c)
t.SetupCommandLine("-Wtypes")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
MkLineChecker{t.NewMkLine("fname", 1, ".if !empty(PKGSRC_COMPILER:Mmycc)")}.CheckCond()
@@ -133,7 +133,7 @@ func (s *Suite) Test_MkLineChecker_Check
func (s *Suite) Test_MkLineChecker_checkVarassign(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("Makefile",
MkRcsID,
@@ -149,7 +149,7 @@ func (s *Suite) Test_MkLineChecker_check
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mkline := t.NewMkLine("options.mk", 2, "PKG_DEVELOPER?=\tyes")
MkLineChecker{mkline}.checkVarassignDefPermissions()
@@ -162,20 +162,19 @@ func (s *Suite) Test_MkLineChecker_Check
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("options.mk",
MkRcsID,
"COMMENT=\t${GAMES_USER}",
"COMMENT:=\t${PKGBASE}",
"PYPKGPREFIX=${PKGBASE}")
- G.globalData.UserDefinedVars = map[string]MkLine{
+ G.Pkgsrc.UserDefinedVars = map[string]MkLine{
"GAMES_USER": mklines.mklines[0],
}
mklines.Check()
t.CheckOutputLines(
- "WARN: options.mk:2: The user-defined variable GAMES_USER is used but not added to BUILD_DEFS.",
"WARN: options.mk:3: PKGBASE should not be evaluated at load time.",
"WARN: options.mk:4: The variable PYPKGPREFIX may not be set in this file; it would be ok in pyversion.mk.",
"WARN: options.mk:4: PKGBASE should not be evaluated indirectly at load time.",
@@ -186,7 +185,7 @@ func (s *Suite) Test_MkLineChecker_Check
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("options.mk",
MkRcsID,
"WRKSRC:=${.CURDIR}")
@@ -242,7 +241,7 @@ func (s *Suite) Test_MkLineChecker__Varu
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("x11/xkeyboard-config/Makefile",
"FILES_SUBST+=XKBCOMP_SYMLINK=${${XKBBASE}/xkbcomp:L:Q}")
@@ -256,7 +255,7 @@ func (s *Suite) Test_MkLineChecker_Check
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("security/openssl/Makefile",
MkRcsID,
".if ${PKGSRC_COMPILER} == \"gcc\" && ${CC} == \"cc\"",
@@ -273,7 +272,7 @@ func (s *Suite) Test_MkLine_CheckCond_co
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("audio/pulseaudio/Makefile",
MkRcsID,
".if ${OPSYS} == \"Darwin\" && ${PKGSRC_COMPILER} == \"clang\"",
@@ -289,7 +288,7 @@ func (s *Suite) Test_MkLineChecker_Check
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("chat/pidgin-icb/Makefile",
MkRcsID,
"CFLAGS+=\t`pkg-config pidgin --cflags`")
@@ -312,7 +311,7 @@ func (s *Suite) Test_MkLineChecker_Check
func (s *Suite) Test_MkLineChecker_CheckVartype_CFLAGS(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("Makefile",
MkRcsID,
"CPPFLAGS.SunOS+=\t-DPIPECOMMAND=\\\"/usr/sbin/sendmail -bs %s\\\"")
@@ -330,7 +329,7 @@ func (s *Suite) Test_MkLineChecker_check
t := s.Init(c)
t.SetupCommandLine("-Wall", "--autofix")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
lines := t.SetupFileLinesContinuation("options.mk",
MkRcsID,
".if ${PKGNAME} == pkgname",
@@ -359,7 +358,7 @@ func (s *Suite) Test_MkLineChecker_Check
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
lines := t.SetupFileLinesContinuation("options.mk",
MkRcsID,
"GOPATH=\t${WRKDIR}",
@@ -379,3 +378,23 @@ func (s *Suite) Test_MkLineChecker_Check
t.CheckOutputLines(
"WARN: ~/options.mk:4: The variable PATH should be quoted as part of a shell word.")
}
+
+// The ${VARNAME:=suffix} should only be used with lists.
+// It typically appears in MASTER_SITE definitions.
+func (s *Suite) Test_MkLineChecker_CheckVaruse_eq_nonlist(c *check.C) {
+ t := s.Init(c)
+
+ t.SetupCommandLine("-Wall")
+ t.SetupVartypes()
+ t.SetupMasterSite("MASTER_SITE_GITHUB", "https://github.com/")
+ lines := t.SetupFileLinesContinuation("options.mk",
+ MkRcsID,
+ "WRKSRC=\t\t${WRKDIR:=/subdir}",
+ "MASTER_SITES=\t${MASTER_SITE_GITHUB:=organization/}")
+ mklines := NewMkLines(lines)
+
+ mklines.Check()
+
+ t.CheckOutputLines(
+ "WARN: ~/options.mk:2: The :from=to modifier should only be used with lists.")
+}
Index: pkgsrc/pkgtools/pkglint/files/check_test.go
diff -u pkgsrc/pkgtools/pkglint/files/check_test.go:1.18 pkgsrc/pkgtools/pkglint/files/check_test.go:1.19
--- pkgsrc/pkgtools/pkglint/files/check_test.go:1.18 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/check_test.go Sat Mar 24 14:32:49 2018
@@ -50,6 +50,7 @@ func (s *Suite) SetUpTest(c *check.C) {
G.logOut = NewSeparatorWriter(&t.stdout)
G.logErr = NewSeparatorWriter(&t.stderr)
trace.Out = &t.stdout
+ G.Pkgsrc = NewPkgsrc(t.TmpDir())
t.checkC = c
t.SetupCommandLine( /* no arguments */ )
@@ -104,9 +105,15 @@ func (t *Tester) SetupCommandLine(args .
G.opts.LogVerbose = true // See SetUpTest
}
+// SetupVartypes registers a few hundred variables like MASTER_SITES,
+// WRKSRC, SUBST_SED.*, so that their data types are known to pkglint.
+func (t *Tester) SetupVartypes() {
+ G.Pkgsrc.InitVartypes()
+}
+
func (t *Tester) SetupMasterSite(varname string, urls ...string) {
- name2url := &G.globalData.MasterSiteVarToURL
- url2name := &G.globalData.MasterSiteURLToVar
+ name2url := &G.Pkgsrc.MasterSiteVarToURL
+ url2name := &G.Pkgsrc.MasterSiteURLToVar
if *name2url == nil {
*name2url = make(map[string]string)
*url2name = make(map[string]string)
@@ -118,11 +125,11 @@ func (t *Tester) SetupMasterSite(varname
}
func (t *Tester) SetupTool(tool *Tool) {
- reg := G.globalData.Tools
+ reg := G.Pkgsrc.Tools
if len(reg.byName) == 0 && len(reg.byVarname) == 0 {
reg = NewToolRegistry()
- G.globalData.Tools = reg
+ G.Pkgsrc.Tools = reg
}
if tool.Name != "" {
reg.byName[tool.Name] = tool
Index: pkgsrc/pkgtools/pkglint/files/distinfo.go
diff -u pkgsrc/pkgtools/pkglint/files/distinfo.go:1.18 pkgsrc/pkgtools/pkglint/files/distinfo.go:1.19
--- pkgsrc/pkgtools/pkglint/files/distinfo.go:1.18 Sat Jan 27 18:50:36 2018
+++ pkgsrc/pkgtools/pkglint/files/distinfo.go Sat Mar 24 14:32:49 2018
@@ -18,7 +18,7 @@ func ChecklinesDistinfo(lines []Line) {
patchesDir := "patches"
patchesDirSet := false
if G.Pkg != nil && contains(fname, "lang/php") {
- phpdir := G.globalData.Latest("lang", `^php[0-9]+$`, "/lang/$0")
+ phpdir := G.Pkgsrc.Latest("lang", `^php[0-9]+$`, "/lang/$0")
if hasSuffix(fname, phpdir+"/distinfo") {
patchesDir = G.CurPkgsrcdir + phpdir + "/patches"
patchesDirSet = true
Index: pkgsrc/pkgtools/pkglint/files/mklines_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.18 pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.19
--- pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.18 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/mklines_test.go Sat Mar 24 14:32:49 2018
@@ -68,7 +68,7 @@ func (s *Suite) Test_MkLines_quoting_LDF
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Pkg = NewPackage("category/pkgbase")
mklines := t.NewMkLines("Makefile",
MkRcsID,
@@ -109,7 +109,7 @@ func (s *Suite) Test_MkLines__comparing_
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("databases/gdbm_compat/builtin.mk",
MkRcsID,
".if ${USE_BUILTIN.gdbm} == \"no\"",
@@ -128,7 +128,7 @@ func (s *Suite) Test_MkLines__varuse_sh_
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("lang/qore/module.mk",
MkRcsID,
"qore-version=\tqore --short-version | ${SED} -e s/-.*//",
@@ -152,7 +152,7 @@ func (s *Suite) Test_MkLines__varuse_par
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("converters/wv2/Makefile",
MkRcsID,
"CONFIGURE_ARGS+=\t\t${CONFIGURE_ARGS.${ICONV_TYPE}-iconv}",
@@ -172,7 +172,7 @@ func (s *Suite) Test_MkLines__loop_modif
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("chat/xchat/Makefile",
MkRcsID,
"GCONF_SCHEMAS=\tapps_xchat_url_handler.schemas",
@@ -190,7 +190,7 @@ func (s *Suite) Test_MkLines__loop_modif
func (s *Suite) Test_MkLines__PKG_SKIP_REASON_depending_on_OPSYS(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("Makefile",
MkRcsID,
"PKG_SKIP_REASON+=\t\"Fails everywhere\"",
@@ -243,7 +243,7 @@ func (s *Suite) Test_MkLines_Check__abso
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("games/heretic2-demo/Makefile",
MkRcsID,
".if ${OPSYS} == \"DragonFly\"",
@@ -347,7 +347,7 @@ func (s *Suite) Test_MkLines_PrivateTool
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("fname",
MkRcsID,
"",
@@ -363,7 +363,7 @@ func (s *Suite) Test_MkLines_PrivateTool
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("fname",
MkRcsID,
"TOOLS_CREATE+=\tmd5sum",
@@ -423,7 +423,7 @@ func (s *Suite) Test_MkLines_wip_categor
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
t.SetupTool(&Tool{Name: "rm", Varname: "RM", Predefined: true})
mklines := t.NewMkLines("Makefile",
MkRcsID,
@@ -451,7 +451,7 @@ func (s *Suite) Test_MkLines_ExtractDocu
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
t.SetupTool(&Tool{Name: "rm", Varname: "RM", Predefined: true})
mklines := t.NewMkLines("Makefile",
MkRcsID,
Index: pkgsrc/pkgtools/pkglint/files/licenses.go
diff -u pkgsrc/pkgtools/pkglint/files/licenses.go:1.10 pkgsrc/pkgtools/pkglint/files/licenses.go:1.11
--- pkgsrc/pkgtools/pkglint/files/licenses.go:1.10 Sun Jan 29 14:27:48 2017
+++ pkgsrc/pkgtools/pkglint/files/licenses.go Sat Mar 24 14:32:49 2018
@@ -10,7 +10,7 @@ func checkToplevelUnusedLicenses() {
return
}
- licensedir := G.globalData.Pkgsrcdir + "/licenses"
+ licensedir := G.Pkgsrc.File("licenses")
files, _ := ioutil.ReadDir(licensedir)
for _, licensefile := range files {
licensename := licensefile.Name()
@@ -51,7 +51,7 @@ func (lc *LicenseChecker) checkLicenseNa
}
}
if licenseFile == "" {
- licenseFile = G.globalData.Pkgsrcdir + "/licenses/" + license
+ licenseFile = G.Pkgsrc.File("licenses/" + license)
if G.UsedLicenses != nil {
G.UsedLicenses[license] = true
}
Index: pkgsrc/pkgtools/pkglint/files/licenses_test.go
diff -u pkgsrc/pkgtools/pkglint/files/licenses_test.go:1.10 pkgsrc/pkgtools/pkglint/files/licenses_test.go:1.11
--- pkgsrc/pkgtools/pkglint/files/licenses_test.go:1.10 Sat Jan 27 18:50:36 2018
+++ pkgsrc/pkgtools/pkglint/files/licenses_test.go Sat Mar 24 14:32:49 2018
@@ -10,7 +10,6 @@ func (s *Suite) Test_checklineLicense(c
t.SetupFileLines("licenses/gnu-gpl-v2",
"Most software \u2026")
mkline := t.NewMkLine("Makefile", 7, "LICENSE=dummy")
- G.globalData.Pkgsrcdir = t.TmpDir()
G.CurrentDir = t.TmpDir()
licenseChecker := &LicenseChecker{mkline}
Index: pkgsrc/pkgtools/pkglint/files/mklinechecker.go
diff -u pkgsrc/pkgtools/pkglint/files/mklinechecker.go:1.10 pkgsrc/pkgtools/pkglint/files/mklinechecker.go:1.11
--- pkgsrc/pkgtools/pkglint/files/mklinechecker.go:1.10 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/mklinechecker.go Sat Mar 24 14:32:49 2018
@@ -318,6 +318,18 @@ func (ck MkLineChecker) CheckVaruse(varu
mkline.Warnf("%s is used but not defined. Spelling mistake?", varname)
}
+ if hasPrefix(varuse.Mod(), ":=") && vartype != nil && !vartype.IsConsideredList() {
+ mkline.Warnf("The :from=to modifier should only be used with lists.")
+ Explain(
+ "Instead of:",
+ "\tMASTER_SITES=\t${HOMEPAGE:=repository/}",
+ "",
+ "Write:",
+ "\tMASTER_SITES=\t${HOMEPAGE}repository/",
+ "",
+ "This is a much clearer expression of the same thought.")
+ }
+
ck.CheckVarusePermissions(varname, vartype, vuc)
if varname == "LOCALBASE" && !G.Infrastructure {
@@ -334,7 +346,7 @@ func (ck MkLineChecker) CheckVaruse(varu
ck.CheckVaruseShellword(varname, vartype, vuc, varuse.Mod(), needsQuoting)
}
- if G.globalData.UserDefinedVars[varname] != nil && !G.globalData.SystemBuildDefs[varname] && !G.Mk.buildDefs[varname] {
+ if G.Pkgsrc.UserDefinedVars[varname] != nil && !G.Pkgsrc.IsBuildDef(varname) && !G.Mk.buildDefs[varname] {
mkline.Warnf("The user-defined variable %s is used but not added to BUILD_DEFS.", varname)
Explain(
"When a pkgsrc package is built, many things can be configured by the",
@@ -386,7 +398,7 @@ func (ck MkLineChecker) CheckVarusePermi
}
done := false
- tool := G.globalData.Tools.byVarname[varname]
+ tool := G.Pkgsrc.Tools.ByVarname(varname)
if isLoadTime && tool != nil {
done = tool.Predefined && (G.Mk == nil || G.Mk.SeenBsdPrefsMk || G.Pkg == nil || G.Pkg.SeenBsdPrefsMk)
@@ -663,9 +675,9 @@ func (ck MkLineChecker) checkVarassign()
}
} else if !varIsUsed(varname) {
- if vartypes := G.globalData.vartypes; vartypes[varname] != nil || vartypes[varcanon] != nil {
+ if vartypes := G.Pkgsrc.vartypes; vartypes[varname] != nil || vartypes[varcanon] != nil {
// Ok
- } else if deprecated := G.globalData.Deprecated; deprecated[varname] != "" || deprecated[varcanon] != "" {
+ } else if deprecated := G.Pkgsrc.Deprecated; deprecated[varname] != "" || deprecated[varcanon] != "" {
// Ok
} else {
mkline.Warnf("%s is defined but not used. Spelling mistake?", varname)
@@ -703,9 +715,9 @@ func (ck MkLineChecker) checkVarassign()
}
}
- if fix := G.globalData.Deprecated[varname]; fix != "" {
+ if fix := G.Pkgsrc.Deprecated[varname]; fix != "" {
mkline.Warnf("Definition of %s is deprecated. %s", varname, fix)
- } else if fix := G.globalData.Deprecated[varcanon]; fix != "" {
+ } else if fix := G.Pkgsrc.Deprecated[varcanon]; fix != "" {
mkline.Warnf("Definition of %s is deprecated. %s", varname, fix)
}
@@ -972,9 +984,9 @@ func (ck MkLineChecker) checkText(text s
varbase, varext := m[1], m[2]
varname := varbase + varext
varcanon := varnameCanon(varname)
- instead := G.globalData.Deprecated[varname]
+ instead := G.Pkgsrc.Deprecated[varname]
if instead == "" {
- instead = G.globalData.Deprecated[varcanon]
+ instead = G.Pkgsrc.Deprecated[varcanon]
}
if instead != "" {
mkline.Warnf("Use of %q is deprecated. %s", varname, instead)
@@ -1071,7 +1083,7 @@ func (ck MkLineChecker) CheckRelativePkg
pkgdir = mkline.ResolveVarsInRelativePath(pkgdir, false)
if m, otherpkgpath := match1(pkgdir, `^(?:\./)?\.\./\.\./([^/]+/[^/]+)$`); m {
- if !fileExists(G.globalData.Pkgsrcdir + "/" + otherpkgpath + "/Makefile") {
+ if !fileExists(G.Pkgsrc.File(otherpkgpath + "/Makefile")) {
mkline.Errorf("There is no package in %q.", otherpkgpath)
}
Index: pkgsrc/pkgtools/pkglint/files/line.go
diff -u pkgsrc/pkgtools/pkglint/files/line.go:1.21 pkgsrc/pkgtools/pkglint/files/line.go:1.22
--- pkgsrc/pkgtools/pkglint/files/line.go:1.21 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/line.go Sat Mar 24 14:32:49 2018
@@ -160,6 +160,27 @@ func (line *LineImpl) String() string {
return line.Filename + ":" + line.Linenos() + ": " + line.Text
}
+// Usage:
+//
+// fix := mkline.Line.Autofix()
+//
+// fix.Errorf("Must not be ...")
+// fix.Warnf("Should not be ...")
+// fix.Notef("It is also possible ...")
+//
+// fix.Explain(
+// "Explanation ...",
+// "... end of explanation.")
+//
+// fix.Replace("from", "to")
+// fix.ReplaceAfter("prefix", "from", "to")
+// fix.ReplaceRegex(`\s+`, "space", "from", "to")
+// fix.InsertBefore("new line")
+// fix.InsertAfter("new line")
+// fix.Delete()
+// fix.Custom(func(...))
+//
+// fix.Apply()
func (line *LineImpl) Autofix() *Autofix {
if line.autofix == nil {
line.autofix = NewAutofix(line)
Index: pkgsrc/pkgtools/pkglint/files/mklines.go
diff -u pkgsrc/pkgtools/pkglint/files/mklines.go:1.21 pkgsrc/pkgtools/pkglint/files/mklines.go:1.22
--- pkgsrc/pkgtools/pkglint/files/mklines.go:1.21 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/mklines.go Sat Mar 24 14:32:49 2018
@@ -27,11 +27,11 @@ func NewMkLines(lines []Line) *MkLines {
mklines[i] = NewMkLine(line)
}
tools := make(map[string]bool)
- for toolname, tool := range G.globalData.Tools.byName {
+ G.Pkgsrc.Tools.ForEach(func(tool *Tool) {
if tool.Predefined {
- tools[toolname] = true
+ tools[tool.Name] = true
}
- }
+ })
return &MkLines{
mklines,
Index: pkgsrc/pkgtools/pkglint/files/linechecker.go
diff -u pkgsrc/pkgtools/pkglint/files/linechecker.go:1.6 pkgsrc/pkgtools/pkglint/files/linechecker.go:1.7
--- pkgsrc/pkgtools/pkglint/files/linechecker.go:1.6 Sun Jan 28 23:21:16 2018
+++ pkgsrc/pkgtools/pkglint/files/linechecker.go Sat Mar 24 14:32:49 2018
@@ -95,15 +95,22 @@ func CheckwordAbsolutePathname(line Line
case regex.Matches(word, `^/(?:[a-z]|\$[({])`):
// Absolute paths probably start with a lowercase letter.
line.Warnf("Found absolute pathname: %s", word)
- Explain(
- "Absolute pathnames are often an indicator for unportable code. As",
- "pkgsrc aims to be a portable system, absolute pathnames should be",
- "avoided whenever possible.",
- "",
- "A special variable in this context is ${DESTDIR}, which is used in",
- "GNU projects to specify a different directory for installation than",
- "what the programs see later when they are executed. Usually it is",
- "empty, so if anything after that variable starts with a slash, it is",
- "considered an absolute pathname.")
+ if contains(line.Text, "DESTDIR") {
+ Explain(
+ "Absolute pathnames are often an indicator for unportable code. As",
+ "pkgsrc aims to be a portable system, absolute pathnames should be",
+ "avoided whenever possible.",
+ "",
+ "A special variable in this context is ${DESTDIR}, which is used in",
+ "GNU projects to specify a different directory for installation than",
+ "what the programs see later when they are executed. Usually it is",
+ "empty, so if anything after that variable starts with a slash, it is",
+ "considered an absolute pathname.")
+ } else {
+ Explain(
+ "Absolute pathnames are often an indicator for unportable code. As",
+ "pkgsrc aims to be a portable system, absolute pathnames should be",
+ "avoided whenever possible.")
+ }
}
}
Index: pkgsrc/pkgtools/pkglint/files/mkline.go
diff -u pkgsrc/pkgtools/pkglint/files/mkline.go:1.29 pkgsrc/pkgtools/pkglint/files/mkline.go:1.30
--- pkgsrc/pkgtools/pkglint/files/mkline.go:1.29 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/mkline.go Sat Mar 24 14:32:49 2018
@@ -195,7 +195,11 @@ func (mkline *MkLineImpl) IsDependency()
return ok
}
-// Varname applies to variable assignments and returns the variable name, exactly as given in the Makefile.
+// Varname applies to variable assignments and returns the name
+// of the variable that is assigned or appended to.
+//
+// Example:
+// VARNAME?= value
func (mkline *MkLineImpl) Varname() string { return mkline.data.(mkLineAssign).varname }
// Varcanon applies to variable assignments and returns the canonicalized variable name for parameterized variables.
@@ -276,20 +280,20 @@ func (mkline *MkLineImpl) ResolveVarsInR
tmp = strings.Replace(tmp, "${.CURDIR}", ".", -1)
tmp = strings.Replace(tmp, "${.PARSEDIR}", ".", -1)
if contains(tmp, "${LUA_PKGSRCDIR}") {
- tmp = strings.Replace(tmp, "${LUA_PKGSRCDIR}", G.globalData.Latest("lang", `^lua[0-9]+$`, "../../lang/$0"), -1)
+ tmp = strings.Replace(tmp, "${LUA_PKGSRCDIR}", G.Pkgsrc.Latest("lang", `^lua[0-9]+$`, "../../lang/$0"), -1)
}
if contains(tmp, "${PHPPKGSRCDIR}") {
- tmp = strings.Replace(tmp, "${PHPPKGSRCDIR}", G.globalData.Latest("lang", `^php[0-9]+$`, "../../lang/$0"), -1)
+ tmp = strings.Replace(tmp, "${PHPPKGSRCDIR}", G.Pkgsrc.Latest("lang", `^php[0-9]+$`, "../../lang/$0"), -1)
}
if contains(tmp, "${SUSE_DIR_PREFIX}") {
- suseDirPrefix := G.globalData.Latest("emulators", `^(suse[0-9]+)_base`, "$1")
+ suseDirPrefix := G.Pkgsrc.Latest("emulators", `^(suse[0-9]+)_base`, "$1")
tmp = strings.Replace(tmp, "${SUSE_DIR_PREFIX}", suseDirPrefix, -1)
}
if contains(tmp, "${PYPKGSRCDIR}") {
- tmp = strings.Replace(tmp, "${PYPKGSRCDIR}", G.globalData.Latest("lang", `^python[0-9]+$`, "../../lang/$0"), -1)
+ tmp = strings.Replace(tmp, "${PYPKGSRCDIR}", G.Pkgsrc.Latest("lang", `^python[0-9]+$`, "../../lang/$0"), -1)
}
if contains(tmp, "${PYPACKAGE}") {
- tmp = strings.Replace(tmp, "${PYPACKAGE}", G.globalData.Latest("lang", `^python[0-9]+$`, "$0"), -1)
+ tmp = strings.Replace(tmp, "${PYPACKAGE}", G.Pkgsrc.Latest("lang", `^python[0-9]+$`, "$0"), -1)
}
if G.Pkg != nil {
tmp = strings.Replace(tmp, "${FILESDIR}", G.Pkg.Filesdir, -1)
@@ -446,9 +450,9 @@ func (mkline *MkLineImpl) VariableNeedsQ
}
}
- // Assuming the tool definitions don't include very special characters,
- // so they can safely be used inside any quotes.
- if G.globalData.Tools.byVarname[varname] != nil {
+ // Pkglint assumes that the tool definitions don't include very
+ // special characters, so they can safely be used inside any quotes.
+ if G.Pkgsrc.Tools.ByVarname(varname) != nil {
switch vuc.quoting {
case vucQuotPlain:
if !vuc.IsWordPart {
@@ -512,14 +516,14 @@ func (mkline *MkLineImpl) VariableType(v
defer trace.Call1(varname)()
}
- if vartype := G.globalData.vartypes[varname]; vartype != nil {
+ if vartype := G.Pkgsrc.vartypes[varname]; vartype != nil {
return vartype
}
- if vartype := G.globalData.vartypes[varnameCanon(varname)]; vartype != nil {
+ if vartype := G.Pkgsrc.vartypes[varnameCanon(varname)]; vartype != nil {
return vartype
}
- if tool := G.globalData.Tools.byVarname[varname]; tool != nil {
+ if tool := G.Pkgsrc.Tools.ByVarname(varname); tool != nil {
perms := aclpUse
if trace.Tracing {
trace.Stepf("Use of tool %+v", tool)
@@ -532,14 +536,15 @@ func (mkline *MkLineImpl) VariableType(v
return &Vartype{lkNone, BtShellCommand, []ACLEntry{{"*", perms}}, false}
}
- if m, toolvarname := match1(varname, `^TOOLS_(.*)`); m && G.globalData.Tools.byVarname[toolvarname] != nil {
+ m, toolvarname := match1(varname, `^TOOLS_(.*)`)
+ if m && G.Pkgsrc.Tools.ByVarname(toolvarname) != nil {
return &Vartype{lkNone, BtPathname, []ACLEntry{{"*", aclpUse}}, false}
}
allowAll := []ACLEntry{{"*", aclpAll}}
allowRuntime := []ACLEntry{{"*", aclpAllRuntime}}
- // Guess the datatype of the variable based on naming conventions.
+ // Guess the data type of the variable based on naming conventions.
varbase := varnameBase(varname)
var gtype *Vartype
switch {
Index: pkgsrc/pkgtools/pkglint/files/mkline_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mkline_test.go:1.31 pkgsrc/pkgtools/pkglint/files/mkline_test.go:1.32
--- pkgsrc/pkgtools/pkglint/files/mkline_test.go:1.31 Mon Feb 19 12:40:38 2018
+++ pkgsrc/pkgtools/pkglint/files/mkline_test.go Sat Mar 24 14:32:49 2018
@@ -210,7 +210,7 @@ func (s *Suite) Test_MkLine_VariableType
t := s.Init(c)
mkline := t.NewMkLine("fname", 1, "# dummy")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
t1 := mkline.VariableType("FONT_DIRS")
@@ -226,7 +226,7 @@ func (s *Suite) Test_MkLine_VariableType
func (s *Suite) Test_VarUseContext_String(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mkline := t.NewMkLine("fname", 1, "# dummy")
vartype := mkline.VariableType("PKGNAME")
vuc := &VarUseContext{vartype, vucTimeUnknown, vucQuotBackt, false}
@@ -275,7 +275,7 @@ func (s *Suite) Test_MkLines_Check__extr
t := s.Init(c)
t.SetupCommandLine("-Wextra")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Pkg = NewPackage("category/pkgbase")
G.Mk = t.NewMkLines("options.mk",
MkRcsID,
@@ -303,9 +303,9 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
mkline := t.NewMkLine("fname", 1, "PKGNAME := ${UNKNOWN}")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
- vuc := &VarUseContext{G.globalData.vartypes["PKGNAME"], vucTimeParse, vucQuotUnknown, false}
+ vuc := &VarUseContext{G.Pkgsrc.vartypes["PKGNAME"], vucTimeParse, vucQuotUnknown, false}
nq := mkline.VariableNeedsQuoting("UNKNOWN", nil, vuc)
c.Check(nq, equals, nqDontKnow)
@@ -315,12 +315,12 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
t.SetupMasterSite("MASTER_SITE_SOURCEFORGE", "http://downloads.sourceforge.net/sourceforge/")
mkline := t.NewMkLine("Makefile", 95, "MASTER_SITES=\t${HOMEPAGE}")
- vuc := &VarUseContext{G.globalData.vartypes["MASTER_SITES"], vucTimeRun, vucQuotPlain, false}
- nq := mkline.VariableNeedsQuoting("HOMEPAGE", G.globalData.vartypes["HOMEPAGE"], vuc)
+ vuc := &VarUseContext{G.Pkgsrc.vartypes["MASTER_SITES"], vucTimeRun, vucQuotPlain, false}
+ nq := mkline.VariableNeedsQuoting("HOMEPAGE", G.Pkgsrc.vartypes["HOMEPAGE"], vuc)
c.Check(nq, equals, nqNo)
@@ -333,7 +333,7 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
t.SetupMasterSite("MASTER_SITE_SOURCEFORGE", "http://downloads.sourceforge.net/sourceforge/")
mkline := t.NewMkLine("Makefile", 96, "MASTER_SITES=\t${MASTER_SITE_SOURCEFORGE:=squirrel-sql/}")
@@ -347,7 +347,7 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mkline := t.NewMkLine("builtin.mk", 3, "USE_BUILTIN.Xfixes!=\t${PKG_ADMIN} pmatch 'pkg-[0-9]*' ${BUILTIN_PKG.Xfixes:Q}")
MkLineChecker{mkline}.checkVarassign()
@@ -361,7 +361,7 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mkline := t.NewMkLine("Makefile", 3, "SUBST_SED.hpath=\t-e 's|^\\(INSTALL[\t:]*=\\).*|\\1${INSTALL}|'")
MkLineChecker{mkline}.checkVarassign()
@@ -374,7 +374,7 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
t.SetupTool(&Tool{Name: "find", Varname: "FIND", Predefined: true})
t.SetupTool(&Tool{Name: "sort", Varname: "SORT", Predefined: true})
G.Pkg = NewPackage("category/pkgbase")
@@ -393,7 +393,7 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("Makefile",
MkRcsID,
"EGDIR=\t${EGDIR}/${MACHINE_GNU_PLATFORM}")
@@ -415,7 +415,7 @@ func (s *Suite) Test_MkLine_variableNeed
t.SetupCommandLine("-Wall")
t.SetupTool(&Tool{Name: "perl", Varname: "PERL5", Predefined: true})
t.SetupTool(&Tool{Name: "bash", Varname: "BASH", Predefined: true})
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("Makefile",
MkRcsID,
"\t${RUN} cd ${WRKSRC} && ( ${ECHO} ${PERL5:Q} ; ${ECHO} ) | ${BASH} ./install",
@@ -434,7 +434,7 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("Makefile",
MkRcsID,
"MASTER_SITES=${HOMEPAGE}archive/")
@@ -453,7 +453,7 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
t.SetupTool(&Tool{Name: "awk", Varname: "AWK", Predefined: true})
t.SetupTool(&Tool{Name: "echo", Varname: "ECHO", Predefined: true})
G.Mk = t.NewMkLines("xpi.mk",
@@ -476,7 +476,7 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("x11/mlterm/Makefile",
MkRcsID,
"SUBST_SED.link=-e 's|(LIBTOOL_LINK).*(LIBS)|& ${LDFLAGS:M*:Q}|g'",
@@ -499,7 +499,7 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("Makefile",
MkRcsID,
"PKG_SUGGESTED_OPTIONS+=\t${PKG_DEFAULT_OPTIONS:Mcdecimal} ${PKG_OPTIONS.py-trytond:Mcdecimal}")
@@ -514,7 +514,7 @@ func (s *Suite) Test_MkLines_Check__MAST
t.SetupCommandLine("-Wall")
t.SetupMasterSite("MASTER_SITE_GITHUB", "https://github.com/")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("devel/catch/Makefile",
MkRcsID,
"HOMEPAGE=\t${MASTER_SITE_GITHUB:=philsquared/Catch/}",
@@ -537,7 +537,7 @@ func (s *Suite) Test_MkLine_variableNeed
t.SetupCommandLine("-Wall")
t.SetupTool(&Tool{Name: "echo", Varname: "ECHO", Predefined: true})
t.SetupTool(&Tool{Name: "sh", Varname: "SH", Predefined: true})
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("x11/labltk/Makefile",
MkRcsID,
"CONFIGURE_ARGS+=\t-tklibs \"`${SH} -c '${ECHO} $$TK_LD_FLAGS'`\"")
@@ -552,7 +552,7 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("x11/qt5-qtbase/Makefile.common",
"BUILDLINK_TRANSFORM+=opt:-ldl:${BUILDLINK_LDADD.dl:M*}")
@@ -567,7 +567,7 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("benchmarks/iozone/Makefile",
"SUBST_MESSAGE.crlf=\tStripping EOL CR in ${REPLACE_PERL}")
@@ -581,7 +581,7 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("audio/jack-rack/Makefile",
MkRcsID,
"LADSPA_PLUGIN_PATH?=\t${PREFIX}/lib/ladspa",
@@ -597,7 +597,7 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("x11/eterm/Makefile",
MkRcsID,
"DISTFILES=\t${DEFAULT_DISTFILES} ${PIXMAP_FILES}")
@@ -612,7 +612,7 @@ func (s *Suite) Test_MkLine_variableNeed
t.SetupCommandLine("-Wall")
t.SetupMasterSite("MASTER_SITE_GNOME", "http://ftp.gnome.org/")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("x11/gtk3/Makefile",
MkRcsID,
"MASTER_SITES=\tftp://ftp.gtk.org/${PKGNAME}/ ${MASTER_SITE_GNOME:=subdir/}")
@@ -626,9 +626,8 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
- G.globalData.Tools = NewToolRegistry()
- G.globalData.Tools.RegisterVarname("tar", "TAR")
+ t.SetupVartypes()
+ G.Pkgsrc.Tools.RegisterVarname("tar", "TAR")
mklines := t.NewMkLines("Makefile",
MkRcsID,
"",
@@ -648,9 +647,8 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
- G.globalData.Tools = NewToolRegistry()
- G.globalData.Tools.RegisterVarname("cat", "CAT")
+ t.SetupVartypes()
+ G.Pkgsrc.Tools.RegisterVarname("cat", "CAT")
mklines := t.NewMkLines("Makefile",
MkRcsID,
"",
@@ -677,7 +675,7 @@ func (s *Suite) Test_MkLine_variableNeed
t := s.Init(c)
t.SetupCommandLine("-Wall", "--autofix")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
lines := t.SetupFileLinesContinuation("Makefile",
MkRcsID,
@@ -703,7 +701,7 @@ func (s *Suite) Test_MkLine_Pkgmandir(c
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("chat/ircII/Makefile",
MkRcsID,
"CONFIGURE_ARGS+=--mandir=${DESTDIR}${PREFIX}/man",
@@ -721,7 +719,7 @@ func (s *Suite) Test_MkLines_Check__VERS
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("geography/viking/Makefile",
MkRcsID,
"MASTER_SITES=\t${MASTER_SITE_SOURCEFORGE:=viking/}${VERSION}/")
@@ -737,7 +735,7 @@ func (s *Suite) Test_MkLines_Check__shel
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("x11/lablgtk1/Makefile",
MkRcsID,
"CONFIGURE_ENV+=\tCC=${CC}")
@@ -753,7 +751,7 @@ func (s *Suite) Test_MkLine_shell_varuse
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("x11/motif/Makefile",
MkRcsID,
"post-patch:",
@@ -779,7 +777,7 @@ func (s *Suite) Test_MkLine_VariableType
func (s *Suite) Test_MkLine__comment_in_comment(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("Makefile",
MkRcsID,
"COMMENT=\tPKCS#5 v2.0 PBKDF2 Module")
Index: pkgsrc/pkgtools/pkglint/files/mkparser_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mkparser_test.go:1.9 pkgsrc/pkgtools/pkglint/files/mkparser_test.go:1.10
--- pkgsrc/pkgtools/pkglint/files/mkparser_test.go:1.9 Mon Feb 19 12:40:38 2018
+++ pkgsrc/pkgtools/pkglint/files/mkparser_test.go Sat Mar 24 14:32:49 2018
@@ -221,7 +221,7 @@ func (s *Suite) Test_MkParser__varuse_pa
t := s.Init(c)
t.SetupCommandLine("--autofix")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
lines := t.SetupFileLines("Makefile",
MkRcsID,
"COMMENT=$(P1) $(P2)) $(P3:Q) ${BRACES}")
Index: pkgsrc/pkgtools/pkglint/files/toplevel_test.go
diff -u pkgsrc/pkgtools/pkglint/files/toplevel_test.go:1.9 pkgsrc/pkgtools/pkglint/files/toplevel_test.go:1.10
--- pkgsrc/pkgtools/pkglint/files/toplevel_test.go:1.9 Mon Feb 19 12:40:38 2018
+++ pkgsrc/pkgtools/pkglint/files/toplevel_test.go Sat Mar 24 14:32:49 2018
@@ -19,7 +19,7 @@ func (s *Suite) Test_CheckdirToplevel(c
t.SetupFileLines("bbb/Makefile")
t.SetupFileLines("ccc/Makefile")
t.SetupFileLines("x11/Makefile")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.CurrentDir = t.TmpDir()
CheckdirToplevel()
Index: pkgsrc/pkgtools/pkglint/files/package.go
diff -u pkgsrc/pkgtools/pkglint/files/package.go:1.26 pkgsrc/pkgtools/pkglint/files/package.go:1.27
--- pkgsrc/pkgtools/pkglint/files/package.go:1.26 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/package.go Sat Mar 24 14:32:49 2018
@@ -4,6 +4,7 @@ import (
"netbsd.org/pkglint/pkgver"
"netbsd.org/pkglint/regex"
"netbsd.org/pkglint/trace"
+ "os"
"path"
"regexp"
"strconv"
@@ -49,7 +50,7 @@ func NewPackage(pkgpath string) *Package
conditionalIncludes: make(map[string]MkLine),
unconditionalIncludes: make(map[string]MkLine),
}
- for varname, line := range G.globalData.UserDefinedVars {
+ for varname, line := range G.Pkgsrc.UserDefinedVars {
pkg.vars.Define(varname, line)
}
return pkg
@@ -89,7 +90,7 @@ func (pkg *Package) checkPossibleDowngra
mkline := pkg.EffectivePkgnameLine
- change := G.globalData.LastChange[pkg.Pkgpath]
+ change := G.Pkgsrc.LastChange[pkg.Pkgpath]
if change == nil {
if trace.Tracing {
trace.Step1("No change log for package %q", pkg.Pkgpath)
@@ -138,6 +139,11 @@ func (pkg *Package) checklinesBuildlink3
}
}
+// Given the package path relative to the pkgsrc top directory,
+// checks a complete pkgsrc package.
+//
+// Example:
+// checkdirPackage("category/pkgbase")
func (pkglint *Pkglint) checkdirPackage(pkgpath string) {
if trace.Tracing {
defer trace.Call1(pkgpath)()
@@ -187,6 +193,9 @@ func (pkglint *Pkglint) checkdirPackage(
continue
}
if fname == G.CurrentDir+"/Makefile" {
+ if st, err := os.Lstat(fname); err == nil {
+ pkglint.checkExecutable(st, fname)
+ }
if G.opts.CheckMakefile {
pkg.checkfilePackageMakefile(fname, lines)
}
@@ -357,7 +366,7 @@ func (pkg *Package) readMakefile(fname s
}
if includingFnameForUsedCheck != "" {
- fileMklines.checkForUsedComment(relpath(G.globalData.Pkgsrcdir, includingFnameForUsedCheck))
+ fileMklines.checkForUsedComment(G.Pkgsrc.ToRel(includingFnameForUsedCheck))
}
return true
@@ -383,7 +392,7 @@ func (pkg *Package) checkfilePackageMake
}
} else {
if distinfoFile := G.CurrentDir + "/" + pkg.DistinfoFile; !containsVarRef(distinfoFile) && !fileExists(distinfoFile) {
- NewLineWhole(distinfoFile).Warnf("File not found. Please run \"%s makesum\".", confMake)
+ NewLineWhole(distinfoFile).Warnf("File not found. Please run \"%s makesum\" or define NO_CHECKSUM=yes in the package Makefile.", confMake)
}
}
@@ -549,7 +558,7 @@ func (pkg *Package) expandVariableWithDe
func (pkg *Package) checkUpdate() {
if pkg.EffectivePkgbase != "" {
- for _, sugg := range G.globalData.GetSuggestedPackageUpdates() {
+ for _, sugg := range G.Pkgsrc.GetSuggestedPackageUpdates() {
if pkg.EffectivePkgbase != sugg.Pkgname {
continue
}
Index: pkgsrc/pkgtools/pkglint/files/package_test.go
diff -u pkgsrc/pkgtools/pkglint/files/package_test.go:1.19 pkgsrc/pkgtools/pkglint/files/package_test.go:1.20
--- pkgsrc/pkgtools/pkglint/files/package_test.go:1.19 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/package_test.go Sat Mar 24 14:32:49 2018
@@ -158,8 +158,7 @@ func (s *Suite) Test_Package_varorder_li
"",
".include \"../../mk/bsd.pkg.mk\"")
- G.globalData.InitVartypes()
- G.globalData.Pkgsrcdir = t.TmpDir()
+ t.SetupVartypes()
G.CurrentDir = t.TmpDir()
G.CheckDirent(t.TmpDir() + "/x11/9term")
@@ -197,7 +196,7 @@ func (s *Suite) Test_Package_CheckVarord
t := s.Init(c)
t.SetupCommandLine("-Worder")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
pkg := NewPackage("category/package")
pkg.CheckVarorder(t.NewMkLines("Makefile",
@@ -285,7 +284,7 @@ func (s *Suite) Test_Package_checkPossib
G.CurPkgsrcdir = "../.."
G.Pkg.EffectivePkgname = "package-1.0nb15"
G.Pkg.EffectivePkgnameLine = t.NewMkLine("category/pkgbase/Makefile", 5, "PKGNAME=dummy")
- G.globalData.LastChange = map[string]*Change{
+ G.Pkgsrc.LastChange = map[string]*Change{
"category/pkgbase": {
Action: "Updated",
Version: "1.8",
@@ -298,7 +297,7 @@ func (s *Suite) Test_Package_checkPossib
t.CheckOutputLines(
"WARN: category/pkgbase/Makefile:5: The package is being downgraded from 1.8 (see ../../doc/CHANGES:116) to 1.0nb15")
- G.globalData.LastChange["category/pkgbase"].Version = "1.0nb22"
+ G.Pkgsrc.LastChange["category/pkgbase"].Version = "1.0nb22"
G.Pkg.checkPossibleDowngrade()
@@ -316,7 +315,7 @@ func (s *Suite) Test_checkdirPackage(c *
t.CheckOutputLines(
"WARN: ~/Makefile: Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?",
- "WARN: ~/distinfo: File not found. Please run \""+confMake+" makesum\".",
+ "WARN: ~/distinfo: File not found. Please run \""+confMake+" makesum\" or define NO_CHECKSUM=yes in the package Makefile.",
"ERROR: ~/Makefile: Each package must define its LICENSE.",
"WARN: ~/Makefile: No COMMENT given.")
}
@@ -329,7 +328,7 @@ func (s *Suite) Test_checkdirPackage__me
"",
"META_PACKAGE=\tyes")
G.CurrentDir = t.TmpDir()
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.checkdirPackage(t.TmpDir())
@@ -425,7 +424,7 @@ func (s *Suite) Test_Package_loadPackage
func (s *Suite) Test_Package_conditionalAndUnconditionalInclude(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
t.CreateFileLines("category/package/Makefile",
MkRcsID,
"",
@@ -455,7 +454,6 @@ func (s *Suite) Test_Package_conditional
t.CreateFileLines("sysutils/coreutils/buildlink3.mk", "")
pkg := NewPackage("category/package")
- G.globalData.Pkgsrcdir = t.TmpDir()
G.CurrentDir = t.TmpDir() + "/category/package"
G.CurPkgsrcdir = "../.."
G.Pkg = pkg
Index: pkgsrc/pkgtools/pkglint/files/pkglint.go
diff -u pkgsrc/pkgtools/pkglint/files/pkglint.go:1.28 pkgsrc/pkgtools/pkglint/files/pkglint.go:1.29
--- pkgsrc/pkgtools/pkglint/files/pkglint.go:1.28 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/pkglint.go Sat Mar 24 14:32:49 2018
@@ -26,10 +26,10 @@ const confVersion = "@VERSION@"
// tracing.Out (not thread-safe)
// tracing.traceDepth (not thread-safe)
type Pkglint struct {
- opts CmdOpts //
- globalData GlobalData //
- Pkg *Package // The package that is currently checked.
- Mk *MkLines // The Makefile (or fragment) that is currently checked.
+ opts CmdOpts // Command line options.
+ Pkgsrc Pkgsrc // Global data, mostly extracted from mk/*.
+ Pkg *Package // The package that is currently checked.
+ Mk *MkLines // The Makefile (or fragment) that is currently checked.
Todo []string // The files or directories that still need to be checked.
CurrentDir string // The currently checked directory, relative to the cwd
@@ -159,7 +159,17 @@ func (pkglint *Pkglint) Main(args ...str
pkglint.Todo = []string{"."}
}
- pkglint.globalData.Initialize()
+ firstArg := G.Todo[0]
+ if fileExists(firstArg) {
+ firstArg = path.Dir(firstArg)
+ }
+ relTopdir := findPkgsrcTopdir(firstArg)
+ if relTopdir == "" {
+ dummyLine.Fatalf("%q is not inside a pkgsrc tree.", firstArg)
+ }
+
+ pkglint.Pkgsrc = NewPkgsrc(firstArg + "/" + relTopdir)
+ pkglint.Pkgsrc.Load()
currentUser, err := user.Current()
if err == nil {
@@ -307,7 +317,7 @@ func (pkglint *Pkglint) CheckDirent(fnam
switch pkglint.CurPkgsrcdir {
case "../..":
- pkglint.checkdirPackage(relpath(pkglint.globalData.Pkgsrcdir, currentDir))
+ pkglint.checkdirPackage(pkglint.Pkgsrc.ToRel(currentDir))
case "..":
CheckdirCategory()
case ".":
@@ -477,15 +487,7 @@ func (pkglint *Pkglint) Checkfile(fname
return
}
- if st.Mode().IsRegular() && st.Mode().Perm()&0111 != 0 && !isCommitted(fname) {
- line := NewLine(fname, 0, "", nil)
- line.Warnf("Should not be executable.")
- Explain(
- "No package file should ever be executable. Even the INSTALL and",
- "DEINSTALL scripts are usually not usable in the form they have in",
- "the package, as the pathnames get adjusted during installation.",
- "So there is no need to have any file executable.")
- }
+ pkglint.checkExecutable(st, fname)
switch {
case st.Mode().IsDir():
@@ -576,7 +578,7 @@ func (pkglint *Pkglint) Checkfile(fname
case hasPrefix(basename, "CHANGES-"):
// This only checks the file, but doesn't register the changes globally.
- _ = pkglint.globalData.loadDocChangesFromFile(fname)
+ _ = pkglint.Pkgsrc.loadDocChangesFromFile(fname)
case matches(fname, `(?:^|/)files/[^/]*$`):
// Skip
@@ -592,6 +594,28 @@ func (pkglint *Pkglint) Checkfile(fname
}
}
+func (pkglint *Pkglint) checkExecutable(st os.FileInfo, fname string) {
+ if st.Mode().IsRegular() && st.Mode().Perm()&0111 != 0 && !isCommitted(fname) {
+ line := NewLine(fname, 0, "", nil)
+ fix := line.Autofix()
+ fix.Warnf("Should not be executable.")
+ fix.Explain(
+ "No package file should ever be executable. Even the INSTALL and",
+ "DEINSTALL scripts are usually not usable in the form they have in",
+ "the package, as the pathnames get adjusted during installation.",
+ "So there is no need to have any file executable.")
+ fix.Custom(func(printAutofix, autofix bool) {
+ fix.Describef(0, "Clearing executable bits")
+ if autofix {
+ if err := os.Chmod(line.Filename, st.Mode()&^0111); err != nil {
+ line.Errorf("Cannot clear executable bits: %s", err)
+ }
+ }
+ })
+ fix.Apply()
+ }
+}
+
func ChecklinesTrailingEmptyLines(lines []Line) {
max := len(lines)
last := max
Index: pkgsrc/pkgtools/pkglint/files/pkglint_test.go
diff -u pkgsrc/pkgtools/pkglint/files/pkglint_test.go:1.16 pkgsrc/pkgtools/pkglint/files/pkglint_test.go:1.17
--- pkgsrc/pkgtools/pkglint/files/pkglint_test.go:1.16 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/pkglint_test.go Sat Mar 24 14:32:49 2018
@@ -151,7 +151,7 @@ func (s *Suite) Test_Pkglint_Main__compl
"# dummy")
// The MASTER_SITES in the package Makefile are searched here.
- // See GlobalData.loadDistSites.
+ // See Pkgsrc.loadMasterSites.
t.CreateFileLines("mk/fetch/sites.mk",
MkRcsID,
"",
@@ -288,7 +288,6 @@ func (s *Suite) Test_Pkglint_CheckDirent
t.SetupFileLines("category/package/Makefile")
t.SetupFileLines("category/Makefile")
t.SetupFileLines("Makefile")
- G.globalData.Pkgsrcdir = t.TmpDir()
G.CheckDirent(t.TmpDir())
@@ -434,39 +433,60 @@ func (s *Suite) Test_ChecklinesMessage__
"===========================================================================")
}
-func (s *Suite) Test_GlobalData_Latest(c *check.C) {
+func (s *Suite) Test_GlobalData_Latest_no_basedir(c *check.C) {
t := s.Init(c)
- G.globalData.Pkgsrcdir = t.TmpDir()
-
- latest1 := G.globalData.Latest("lang", `^python[0-9]+$`, "../../lang/$0")
+ latest1 := G.Pkgsrc.Latest("lang", `^python[0-9]+$`, "../../lang/$0")
c.Check(latest1, equals, "")
t.CheckOutputLines(
- "ERROR: Cannot find latest version of \"^python[0-9]+$\" in \"~\".")
+ "ERROR: Cannot find latest version of \"^python[0-9]+$\" in \"~/lang\".")
+}
+
+func (s *Suite) Test_GlobalData_Latest_no_subdirs(c *check.C) {
+ t := s.Init(c)
t.SetupFileLines("lang/Makefile")
- G.globalData.latest = nil
- latest2 := G.globalData.Latest("lang", `^python[0-9]+$`, "../../lang/$0")
+ latest2 := G.Pkgsrc.Latest("lang", `^python[0-9]+$`, "../../lang/$0")
c.Check(latest2, equals, "")
t.CheckOutputLines(
- "ERROR: Cannot find latest version of \"^python[0-9]+$\" in \"~\".")
+ "ERROR: Cannot find latest version of \"^python[0-9]+$\" in \"~/lang\".")
+}
+func (s *Suite) Test_GlobalData_Latest_single(c *check.C) {
+ t := s.Init(c)
+
+ t.SetupFileLines("lang/Makefile")
t.SetupFileLines("lang/python27/Makefile")
- G.globalData.latest = nil
- latest3 := G.globalData.Latest("lang", `^python[0-9]+$`, "../../lang/$0")
+ latest3 := G.Pkgsrc.Latest("lang", `^python[0-9]+$`, "../../lang/$0")
c.Check(latest3, equals, "../../lang/python27")
- t.CheckOutputEmpty()
+}
+func (s *Suite) Test_GlobalData_Latest_multi(c *check.C) {
+ t := s.Init(c)
+
+ t.SetupFileLines("lang/Makefile")
+ t.SetupFileLines("lang/python27/Makefile")
t.SetupFileLines("lang/python35/Makefile")
- G.globalData.latest = nil
- latest4 := G.globalData.Latest("lang", `^python[0-9]+$`, "../../lang/$0")
+ latest4 := G.Pkgsrc.Latest("lang", `^python[0-9]+$`, "../../lang/$0")
c.Check(latest4, equals, "../../lang/python35")
- t.CheckOutputEmpty()
+}
+
+func (s *Suite) Test_GlobalData_Latest_numeric(c *check.C) {
+ t := s.Init(c)
+
+ t.SetupFileLines("databases/postgresql95/Makefile")
+ t.SetupFileLines("databases/postgresql97/Makefile")
+ t.SetupFileLines("databases/postgresql100/Makefile")
+ t.SetupFileLines("databases/postgresql104/Makefile")
+
+ latest := G.Pkgsrc.Latest("databases", `^postgresql[0-9]+$`, "$0")
+
+ c.Check(latest, equals, "postgresql104")
}
Index: pkgsrc/pkgtools/pkglint/files/plist.go
diff -u pkgsrc/pkgtools/pkglint/files/plist.go:1.23 pkgsrc/pkgtools/pkglint/files/plist.go:1.24
--- pkgsrc/pkgtools/pkglint/files/plist.go:1.23 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/plist.go Sat Mar 24 14:32:49 2018
@@ -501,6 +501,9 @@ func (s *plistLineSorter) Sort() {
return
}
+ if !shallBeLogged("%q should be sorted before %q.") {
+ return
+ }
if len(s.middle) == 0 {
return
}
@@ -522,6 +525,7 @@ func (s *plistLineSorter) Sort() {
}
fix := firstLine.Autofix()
+ fix.Notef("Silent-Magic-Diagnostic")
fix.Describef(int(firstLine.firstLine), "Sorting the whole file.")
fix.Apply()
Index: pkgsrc/pkgtools/pkglint/files/plist_test.go
diff -u pkgsrc/pkgtools/pkglint/files/plist_test.go:1.22 pkgsrc/pkgtools/pkglint/files/plist_test.go:1.23
--- pkgsrc/pkgtools/pkglint/files/plist_test.go:1.22 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/plist_test.go Sat Mar 24 14:32:49 2018
@@ -317,3 +317,25 @@ func (s *Suite) Test_PlistChecker__remov
"${PLIST.option3}bin/false",
"bin/true")
}
+
+// When pkglint is run with the --only option, only the matched
+// diagnostics must be autofixed. Up to 2018-03-12, the PLIST was
+// sorted even if it didn't match the --only pattern.
+func (s *Suite) Test_PlistChecker__autofix_with_only(c *check.C) {
+ t := s.Init(c)
+
+ t.SetupCommandLine("-Wall", "--autofix", "--only", "matches nothing")
+
+ lines := t.SetupFileLines("PLIST",
+ PlistRcsID,
+ "sbin/program",
+ "bin/program")
+
+ ChecklinesPlist(lines)
+
+ t.CheckOutputEmpty()
+ t.CheckFileLines("PLIST",
+ PlistRcsID,
+ "sbin/program",
+ "bin/program")
+}
Index: pkgsrc/pkgtools/pkglint/files/shell.go
diff -u pkgsrc/pkgtools/pkglint/files/shell.go:1.22 pkgsrc/pkgtools/pkglint/files/shell.go:1.23
--- pkgsrc/pkgtools/pkglint/files/shell.go:1.22 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/shell.go Sat Mar 24 14:32:49 2018
@@ -476,7 +476,7 @@ func (scc *SimpleCommandChecker) handleT
}
shellword := scc.strcmd.Name
- tool, localTool := G.globalData.Tools.byName[shellword], false
+ tool, localTool := G.Pkgsrc.Tools.ByName(shellword), false
if tool == nil && G.Mk != nil {
tool, localTool = G.Mk.toolRegistry.byName[shellword], true
}
@@ -524,7 +524,7 @@ func (scc *SimpleCommandChecker) handleC
if varuse := parser.VarUse(); varuse != nil && parser.EOF() {
varname := varuse.varname
- if tool := G.globalData.Tools.byVarname[varname]; tool != nil {
+ if tool := G.Pkgsrc.Tools.ByVarname(varname); tool != nil {
if !G.Mk.tools[tool.Name] {
scc.shline.mkline.Warnf("The %q tool is used but not added to USE_TOOLS.", tool.Name)
}
@@ -791,6 +791,12 @@ func (spc *ShellProgramChecker) checkPip
return false
}
+ // canFail tests whether one of the left-hand side commands of a
+ // shell pipeline can fail.
+ //
+ // Examples:
+ // echo "hello" | sed 's,$, world,,' => cannot fail
+ // find . -print | xargs cat | wc -l => can fail
canFail := func() (bool, string) {
for _, cmd := range pipeline.Cmds[:len(pipeline.Cmds)-1] {
simple := cmd.Simple
@@ -800,7 +806,7 @@ func (spc *ShellProgramChecker) checkPip
if len(simple.Redirections) != 0 {
return true, simple.Name.MkText
}
- tool := G.globalData.Tools.FindByCommand(simple.Name)
+ tool := G.Pkgsrc.Tools.FindByCommand(simple.Name)
switch {
case tool == nil:
return true, simple.Name.MkText
Index: pkgsrc/pkgtools/pkglint/files/shell_test.go
diff -u pkgsrc/pkgtools/pkglint/files/shell_test.go:1.22 pkgsrc/pkgtools/pkglint/files/shell_test.go:1.23
--- pkgsrc/pkgtools/pkglint/files/shell_test.go:1.22 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/shell_test.go Sat Mar 24 14:32:49 2018
@@ -109,7 +109,7 @@ func (s *Suite) Test_ShellLine_CheckShel
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
checkShellCommandLine := func(shellCommand string) {
G.Mk = t.NewMkLines("fname",
@@ -131,7 +131,7 @@ func (s *Suite) Test_ShellLine_CheckShel
"WARN: fname:1: Unknown shell command \"echo\".")
t.SetupTool(&Tool{Name: "echo", Predefined: true})
- G.globalData.InitVartypes()
+ t.SetupVartypes()
checkShellCommandLine("echo ${PKGNAME:Q}") // vucQuotPlain
@@ -258,7 +258,7 @@ func (s *Suite) Test_ShellLine_CheckShel
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
t.SetupTool(&Tool{Name: "echo", Predefined: true})
G.Mk = t.NewMkLines("Makefile",
"\techo ${PKGNAME:Q}")
@@ -274,7 +274,7 @@ func (s *Suite) Test_ShellLine_CheckShel
t := s.Init(c)
t.SetupCommandLine("-Wall", "--show-autofix")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
t.SetupTool(&Tool{Name: "echo", Predefined: true})
G.Mk = t.NewMkLines("Makefile",
"\techo ${PKGNAME:Q}")
@@ -292,7 +292,7 @@ func (s *Suite) Test_ShellLine_CheckShel
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
t.SetupTool(&Tool{Name: "cat", Predefined: true})
t.SetupTool(&Tool{Name: "echo", Predefined: true})
t.SetupTool(&Tool{Name: "printf", Predefined: true})
@@ -325,7 +325,7 @@ func (s *Suite) Test_ShellLine_CheckShel
t := s.Init(c)
t.SetupCommandLine("-Wall", "--autofix")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
t.SetupTool(&Tool{Name: "echo", Predefined: true})
G.Mk = t.NewMkLines("Makefile",
"\techo ${PKGNAME:Q}")
@@ -341,7 +341,7 @@ func (s *Suite) Test_ShellLine_CheckShel
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("fname",
"# dummy")
shline := NewShellLine(G.Mk.mklines[0])
@@ -369,7 +369,7 @@ func (s *Suite) Test_ShellLine_CheckShel
func (s *Suite) Test_ShellLine_CheckShelltext__dollar_without_variable(c *check.C) {
t := s.Init(c)
- G.globalData.InitVartypes()
+ t.SetupVartypes()
G.Mk = t.NewMkLines("fname",
"# dummy")
shline := NewShellLine(G.Mk.mklines[0])
@@ -385,7 +385,7 @@ func (s *Suite) Test_ShellLine_CheckWord
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
checkWord := func(shellWord string, checkQuoting bool) {
shline := t.NewShellLine("dummy.mk", 1, "\t echo "+shellWord)
@@ -622,7 +622,7 @@ func (s *Suite) Test_ShellLine__variable
t := s.Init(c)
t.SetupCommandLine("-Wall")
- G.globalData.InitVartypes()
+ t.SetupVartypes()
mklines := t.NewMkLines("dummy.mk",
MkRcsID,
"GZIP=\t${ECHO} $$comment")
Index: pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go
diff -u pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go:1.22 pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go:1.23
--- pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go:1.22 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go Sat Mar 24 14:32:49 2018
@@ -172,7 +172,6 @@ func (s *Suite) Test_VartypeCheck_Depend
"# empty")
t.SetupFileLines("category/package/Makefile",
"# empty")
- G.globalData.Pkgsrcdir = t.TmpDir()
G.CurrentDir = t.TmpDir() + "/category/package"
G.CurPkgsrcdir = "../.."
@@ -323,7 +322,7 @@ func (s *Suite) Test_VartypeCheck_Licens
"AND mit")
t.CheckOutputLines(
- "WARN: fname:1: License file /licenses/gnu-gpl-v2 does not exist.",
+ "WARN: fname:1: License file ~/licenses/gnu-gpl-v2 does not exist.",
"ERROR: fname:2: Parse error for license condition \"AND mit\".")
runVartypeChecks(t, "LICENSE", opAssignAppend, (*VartypeCheck).License,
@@ -332,7 +331,7 @@ func (s *Suite) Test_VartypeCheck_Licens
t.CheckOutputLines(
"ERROR: fname:1: Parse error for appended license condition \"gnu-gpl-v2\".",
- "WARN: fname:2: License file /licenses/mit does not exist.")
+ "WARN: fname:2: License file ~/licenses/mit does not exist.")
}
func (s *Suite) Test_VartypeCheck_MachineGnuPlatform(c *check.C) {
@@ -379,10 +378,8 @@ func (s *Suite) Test_VartypeCheck_Messag
func (s *Suite) Test_VartypeCheck_Option(c *check.C) {
t := s.Init(c)
- G.globalData.PkgOptions = map[string]string{
- "documented": "Option description",
- "undocumented": "",
- }
+ G.Pkgsrc.PkgOptions["documented"] = "Option description"
+ G.Pkgsrc.PkgOptions["undocumented"] = ""
runVartypeChecks(t, "PKG_OPTIONS.pkgbase", opAssign, (*VartypeCheck).Option,
"documented",
Index: pkgsrc/pkgtools/pkglint/files/util.go
diff -u pkgsrc/pkgtools/pkglint/files/util.go:1.20 pkgsrc/pkgtools/pkglint/files/util.go:1.21
--- pkgsrc/pkgtools/pkglint/files/util.go:1.20 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/util.go Sat Mar 24 14:32:49 2018
@@ -302,13 +302,15 @@ func mkopSubst(s string, left bool, from
})
}
+// relpath returns the relative path from `from` to `to`.
+// If `to` is not within `from`, it panics.
func relpath(from, to string) string {
absFrom, err1 := filepath.Abs(from)
absTo, err2 := filepath.Abs(to)
rel, err3 := filepath.Rel(absFrom, absTo)
if err1 != nil || err2 != nil || err3 != nil {
trace.Stepf("relpath.panic", from, to, err1, err2, err3)
- panic("relpath")
+ panic(fmt.Sprintf("relpath %q, %q", from, to))
}
result := filepath.ToSlash(rel)
if trace.Tracing {
@@ -471,3 +473,81 @@ func (s *Scope) FirstDefinition(varname
func (s *Scope) FirstUse(varname string) MkLine {
return s.used[varname]
}
+
+// The MIT License (MIT)
+//
+// Copyright (c) 2015 Frits van Bommel
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+// Taken from https://github.com/fvbommel/util/blob/11997822f8/sortorder/natsort.go
+func naturalLess(str1, str2 string) bool {
+
+ isDigit := func(b byte) bool { return '0' <= b && b <= '9' }
+
+ idx := 0
+ len1, len2 := len(str1), len(str2)
+ len := len1 + len2 - imax(len1, len2)
+ for idx < len {
+ c1, c2 := str1[idx], str2[idx]
+ dig1, dig2 := isDigit(c1), isDigit(c2)
+ switch {
+ case dig1 != dig2: // Digits before other characters.
+ return dig1 // True if LHS is a digit, false if the RHS is one.
+ case !dig1: // && !dig2, because dig1 == dig2
+ // UTF-8 compares bytewise-lexicographically, no need to decode
+ // codepoints.
+ if c1 != c2 {
+ return c1 < c2
+ }
+ idx++
+ default: // Digits
+ // Eat zeros.
+ idx1, idx2 := idx, idx
+ for ; idx1 < len1 && str1[idx1] == '0'; idx1++ {
+ }
+ for ; idx2 < len2 && str2[idx2] == '0'; idx2++ {
+ }
+ // Eat all digits.
+ nonZero1, nonZero2 := idx1, idx2
+ for ; idx1 < len1 && isDigit(str1[idx1]); idx1++ {
+ }
+ for ; idx2 < len2 && isDigit(str2[idx2]); idx2++ {
+ }
+ // If lengths of numbers with non-zero prefix differ, the shorter
+ // one is less.
+ if len1, len2 := idx1-nonZero1, idx2-nonZero2; len1 != len2 {
+ return len1 < len2
+ }
+ // If they're not equal, string comparison is correct.
+ if nr1, nr2 := str1[nonZero1:idx1], str2[nonZero2:idx2]; nr1 != nr2 {
+ return nr1 < nr2
+ }
+ // Otherwise, the one with less zeros is less.
+ // Because everything up to the number is equal, comparing the index
+ // after the zeros is sufficient.
+ if nonZero1 != nonZero2 {
+ return nonZero1 < nonZero2
+ }
+ idx = idx1
+ }
+ // They're identical so far, so continue comparing.
+ }
+ // So far they are identical. At least one is ended. If the other continues,
+ // it sorts last.
+ return len1 < len2
+}
Index: pkgsrc/pkgtools/pkglint/files/vardefs.go
diff -u pkgsrc/pkgtools/pkglint/files/vardefs.go:1.37 pkgsrc/pkgtools/pkglint/files/vardefs.go:1.38
--- pkgsrc/pkgtools/pkglint/files/vardefs.go:1.37 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/vardefs.go Sat Mar 24 14:32:49 2018
@@ -17,17 +17,40 @@ import (
// InitVartypes initializes the long list of predefined pkgsrc variables.
// After this is done, ${PKGNAME}, ${MAKE_ENV} and all the other variables
// can be used in Makefiles without triggering warnings about typos.
-func (gd *GlobalData) InitVartypes() {
+func (src *PkgsrcImpl) InitVartypes() {
+
+ acl := func(varname string, kindOfList KindOfList, checker *BasicType, aclentries string) {
+ m := mustMatch(varname, `^([A-Z_.][A-Z0-9_]*)(|\*|\.\*)$`)
+ varbase, varparam := m[1], m[2]
+
+ vtype := &Vartype{kindOfList, checker, parseACLEntries(varname, aclentries), false}
+
+ if src.vartypes == nil {
+ src.vartypes = make(map[string]*Vartype)
+ }
+ if varparam == "" || varparam == "*" {
+ src.vartypes[varbase] = vtype
+ }
+ if varparam == "*" || varparam == ".*" {
+ src.vartypes[varbase+".*"] = vtype
+ }
+ }
// A package-defined variable may be set in all Makefiles except buildlink3.mk and builtin.mk.
pkg := func(varname string, kindOfList KindOfList, checker *BasicType) {
- acl(varname, kindOfList, checker, "Makefile: set, use; buildlink3.mk, builtin.mk:; Makefile.*, *.mk: default, set, use")
+ acl(varname, kindOfList, checker, ""+
+ "Makefile: set, use; "+
+ "buildlink3.mk, builtin.mk:; "+
+ "Makefile.*, *.mk: default, set, use")
}
// A package-defined list may be appended to in all Makefiles except buildlink3.mk and builtin.mk.
// Simple assignment (instead of appending) is only allowed in Makefile and Makefile.common.
pkglist := func(varname string, kindOfList KindOfList, checker *BasicType) {
- acl(varname, kindOfList, checker, "Makefile, Makefile.common, options.mk: append, default, set, use; buildlink3.mk, builtin.mk:; *.mk: append, default, use")
+ acl(varname, kindOfList, checker, ""+
+ "Makefile, Makefile.common, options.mk: append, default, set, use; "+
+ "buildlink3.mk, builtin.mk:; "+
+ "*.mk: append, default, use")
}
// A user-defined or system-defined variable must not be set by any
@@ -1023,23 +1046,6 @@ func enum(values string) *BasicType {
}}
}
-func acl(varname string, kindOfList KindOfList, checker *BasicType, aclentries string) {
- m := mustMatch(varname, `^([A-Z_.][A-Z0-9_]*)(|\*|\.\*)$`)
- varbase, varparam := m[1], m[2]
-
- vtype := &Vartype{kindOfList, checker, parseACLEntries(varname, aclentries), false}
-
- if G.globalData.vartypes == nil {
- G.globalData.vartypes = make(map[string]*Vartype)
- }
- if varparam == "" || varparam == "*" {
- G.globalData.vartypes[varbase] = vtype
- }
- if varparam == "*" || varparam == ".*" {
- G.globalData.vartypes[varbase+".*"] = vtype
- }
-}
-
func parseACLEntries(varname string, aclentries string) []ACLEntry {
if aclentries == "" {
return nil
Index: pkgsrc/pkgtools/pkglint/files/vartypecheck.go
diff -u pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.30 pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.31
--- pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.30 Sun Mar 4 20:34:33 2018
+++ pkgsrc/pkgtools/pkglint/files/vartypecheck.go Sat Mar 24 14:32:49 2018
@@ -396,7 +396,7 @@ func (cv *VartypeCheck) EmulPlatform() {
func (cv *VartypeCheck) FetchURL() {
MkLineChecker{cv.MkLine}.CheckVartypePrimitive(cv.Varname, BtURL, cv.Op, cv.Value, cv.MkComment, cv.Guessed)
- for siteURL, siteName := range G.globalData.MasterSiteURLToVar {
+ for siteURL, siteName := range G.Pkgsrc.MasterSiteURLToVar {
if hasPrefix(cv.Value, siteURL) {
subdir := cv.Value[len(siteURL):]
if hasPrefix(cv.Value, "https://github.com/") {
@@ -411,7 +411,7 @@ func (cv *VartypeCheck) FetchURL() {
}
if m, name, subdir := match2(cv.Value, `\$\{(MASTER_SITE_[^:]*).*:=(.*)\}$`); m {
- if G.globalData.MasterSiteVarToURL[name] == "" {
+ if G.Pkgsrc.MasterSiteVarToURL[name] == "" {
cv.Line.Errorf("The site %s does not exist.", name)
}
if !hasSuffix(subdir, "/") {
@@ -457,7 +457,7 @@ func (cv *VartypeCheck) Homepage() {
MkLineChecker{cv.MkLine}.CheckVartypePrimitive(cv.Varname, BtURL, cv.Op, cv.Value, cv.MkComment, cv.Guessed)
if m, wrong, sitename, subdir := match3(cv.Value, `^(\$\{(MASTER_SITE\w+)(?::=([\w\-/]+))?\})`); m {
- baseURL := G.globalData.MasterSiteVarToURL[sitename]
+ baseURL := G.Pkgsrc.MasterSiteVarToURL[sitename]
if sitename == "MASTER_SITES" && G.Pkg != nil {
masterSites, _ := G.Pkg.varValue("MASTER_SITES")
if !containsVarRef(masterSites) {
@@ -638,7 +638,7 @@ func (cv *VartypeCheck) Option() {
}
if m, optname := match1(value, `^-?([a-z][-0-9a-z+]*)$`); m {
- if _, found := G.globalData.PkgOptions[optname]; !found { // There's a difference between empty and absent here.
+ if _, found := G.Pkgsrc.PkgOptions[optname]; !found { // There's a difference between empty and absent here.
line.Warnf("Unknown option \"%s\".", optname)
Explain(
"This option is not documented in the mk/defaults/options.description",
@@ -945,7 +945,7 @@ func (cv *VartypeCheck) Tool() {
// no warning for package-defined tool definitions
} else if m, toolname, tooldep := match2(cv.Value, `^([-\w]+|\[)(?::(\w+))?$`); m {
- if G.globalData.Tools.byName[toolname] == nil && (G.Mk == nil || G.Mk.toolRegistry.byName[toolname] == nil) {
+ if G.Pkgsrc.Tools.ByName(toolname) == nil && (G.Mk == nil || G.Mk.toolRegistry.byName[toolname] == nil) {
cv.Line.Errorf("Unknown tool %q.", toolname)
}
switch tooldep {
Added files:
Index: pkgsrc/pkgtools/pkglint/files/pkgsrc.go
diff -u /dev/null pkgsrc/pkgtools/pkglint/files/pkgsrc.go:1.1
--- /dev/null Sat Mar 24 14:32:50 2018
+++ pkgsrc/pkgtools/pkglint/files/pkgsrc.go Sat Mar 24 14:32:49 2018
@@ -0,0 +1,605 @@
+package main
+
+import (
+ "io/ioutil"
+ "netbsd.org/pkglint/regex"
+ "netbsd.org/pkglint/trace"
+ "sort"
+ "strings"
+)
+
+// 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.
+type Pkgsrc = *PkgsrcImpl
+
+type PkgsrcImpl struct {
+
+ // The top directory (PKGSRCDIR), either absolute or relative to
+ // the current working directory.
+ topdir string
+
+ // The set of user-defined variables that are added to BUILD_DEFS
+ // within the bsd.pkg.mk file.
+ buildDefs map[string]bool
+
+ Tools ToolRegistry
+
+ MasterSiteURLToVar map[string]string // "https://github.com/" => "MASTER_SITE_GITHUB"
+ MasterSiteVarToURL map[string]string // "MASTER_SITE_GITHUB" => "https://github.com/"
+
+ PkgOptions map[string]string // "x11" => "Provides X11 support"
+
+ suggestedUpdates []SuggestedUpdate //
+ suggestedWipUpdates []SuggestedUpdate //
+ LastChange map[string]*Change //
+ latest map[string]string // "lang/php[0-9]*" => "lang/php70"
+
+ UserDefinedVars map[string]MkLine // varname => line; used for checking BUILD_DEFS
+ Deprecated map[string]string //
+ vartypes map[string]*Vartype // varcanon => type
+}
+
+func NewPkgsrc(dir string) Pkgsrc {
+ src := &PkgsrcImpl{
+ dir,
+ make(map[string]bool),
+ NewToolRegistry(),
+ make(map[string]string),
+ make(map[string]string),
+ make(map[string]string),
+ nil,
+ nil,
+ make(map[string]*Change),
+ make(map[string]string),
+ make(map[string]MkLine),
+ make(map[string]string),
+ make(map[string]*Vartype)}
+
+ // Some user-defined variables do not influence the binary
+ // package at all and therefore do not have to be added to
+ // BUILD_DEFS; therefore they are marked as "already added".
+ src.AddBuildDef("DISTDIR")
+ src.AddBuildDef("FETCH_CMD")
+ src.AddBuildDef("FETCH_OUTPUT_ARGS")
+
+ // The following variables are not expected to be modified
+ // by the pkgsrc user. They are added here to prevent unnecessary
+ // warnings by pkglint.
+ src.AddBuildDef("GAMES_USER")
+ src.AddBuildDef("GAMES_GROUP")
+ src.AddBuildDef("GAMEDATAMODE")
+ src.AddBuildDef("GAMEDIRMODE")
+ src.AddBuildDef("GAMEMODE")
+ src.AddBuildDef("GAMEOWN")
+ src.AddBuildDef("GAMEGRP")
+
+ return src
+}
+
+// Load reads the pkgsrc infrastructure files to
+// extract information like the tools, packages to update,
+// user-defined variables.
+//
+// This work is not done in the constructor to keep the tests
+// simple, since setting up a realistic pkgsrc environment requires
+// a lot of files.
+func (src *PkgsrcImpl) Load() {
+ src.InitVartypes()
+ src.loadMasterSites()
+ src.loadPkgOptions()
+ src.loadDocChanges()
+ src.loadSuggestedUpdates()
+ src.loadUserDefinedVars()
+ src.loadTools()
+ src.initDeprecatedVars()
+}
+
+// Latest returns the latest package matching the given pattern.
+// It searches the `category` for subdirectories matching the given
+// regular expression, and returns the `repl` string, in which the
+// placeholder is filled with the best result.
+//
+// Example:
+// Latest("lang", `^php[0-9]+$`, "../../lang/$0") => "../../lang/php72"
+func (src *PkgsrcImpl) Latest(category string, re regex.Pattern, repl string) string {
+ key := category + "/" + string(re) + " => " + repl
+ if latest, found := src.latest[key]; found {
+ return latest
+ }
+
+ if src.latest == nil {
+ src.latest = make(map[string]string)
+ }
+
+ categoryDir := src.File(category)
+ error := func() string {
+ dummyLine.Errorf("Cannot find latest version of %q in %q.", re, categoryDir)
+ src.latest[key] = ""
+ return ""
+ }
+
+ all, err := ioutil.ReadDir(categoryDir)
+ sort.SliceStable(all, func(i, j int) bool {
+ return naturalLess(all[i].Name(), all[j].Name())
+ })
+ if err != nil {
+ return error()
+ }
+
+ latest := ""
+ for _, fileInfo := range all {
+ if matches(fileInfo.Name(), re) {
+ latest = regex.Compile(re).ReplaceAllString(fileInfo.Name(), repl)
+ }
+ }
+ if latest == "" {
+ return error()
+ }
+
+ src.latest[key] = latest
+ return latest
+}
+
+// loadTools loads the tool definitions from `mk/tools/*`.
+func (src *PkgsrcImpl) loadTools() {
+ toolFiles := []string{"defaults.mk"}
+ {
+ lines := G.Pkgsrc.LoadExistingLines("mk/tools/bsd.tools.mk", true)
+ for _, line := range lines {
+ if m, _, _, includefile := MatchMkInclude(line.Text); m {
+ if !contains(includefile, "/") {
+ toolFiles = append(toolFiles, includefile)
+ }
+ }
+ }
+ if len(toolFiles) <= 1 {
+ lines[0].Fatalf("Too few tool files.")
+ }
+ }
+
+ reg := src.Tools
+ reg.RegisterTool(&Tool{"echo", "ECHO", true, true, true})
+ reg.RegisterTool(&Tool{"echo -n", "ECHO_N", true, true, true})
+ reg.RegisterTool(&Tool{"false", "FALSE", true /*why?*/, true, false})
+ reg.RegisterTool(&Tool{"test", "TEST", true, true, true})
+ reg.RegisterTool(&Tool{"true", "TRUE", true /*why?*/, true, true})
+
+ for _, basename := range toolFiles {
+ lines := G.Pkgsrc.LoadExistingLines("mk/tools/"+basename, true)
+ for _, line := range lines {
+ reg.ParseToolLine(line)
+ }
+ }
+
+ for _, relativeName := range [...]string{"mk/bsd.prefs.mk", "mk/bsd.pkg.mk"} {
+ condDepth := 0
+
+ lines := G.Pkgsrc.LoadExistingLines(relativeName, true)
+ for _, line := range lines {
+ text := line.Text
+ if hasPrefix(text, "#") {
+ continue
+ }
+
+ if m, _, varname, _, _, _, value, _, _ := MatchVarassign(text); m {
+ if varname == "USE_TOOLS" {
+ if trace.Tracing {
+ trace.Stepf("[condDepth=%d] %s", condDepth, value)
+ }
+ if condDepth == 0 || condDepth == 1 && relativeName == "mk/bsd.prefs.mk" {
+ for _, toolname := range splitOnSpace(value) {
+ if !containsVarRef(toolname) {
+ for _, tool := range [...]*Tool{reg.Register(toolname), reg.Register("TOOLS_" + toolname)} {
+ tool.Predefined = true
+ if relativeName == "mk/bsd.prefs.mk" {
+ tool.UsableAtLoadtime = true
+ }
+ }
+ }
+ }
+ }
+
+ } else if varname == "_BUILD_DEFS" {
+ for _, bdvar := range splitOnSpace(value) {
+ src.AddBuildDef(bdvar)
+ }
+ }
+
+ } else if m, _, cond, _ := matchMkCond(text); m {
+ switch cond {
+ case "if", "ifdef", "ifndef", "for":
+ condDepth++
+ case "endif", "endfor":
+ condDepth--
+ }
+ }
+ }
+ }
+
+ if trace.Tracing {
+ reg.Trace()
+ }
+}
+
+func (src *PkgsrcImpl) loadSuggestedUpdatesFile(fname string) []SuggestedUpdate {
+ lines := LoadExistingLines(fname, false)
+ return src.parseSuggestedUpdates(lines)
+}
+
+func (src *PkgsrcImpl) parseSuggestedUpdates(lines []Line) []SuggestedUpdate {
+ var updates []SuggestedUpdate
+ state := 0
+ for _, line := range lines {
+ text := line.Text
+
+ if state == 0 && text == "Suggested package updates" {
+ state = 1
+ } else if state == 1 && text == "" {
+ state = 2
+ } else if state == 2 {
+ state = 3
+ } else if state == 3 && text == "" {
+ state = 4
+ }
+
+ if state == 3 {
+ if m, pkgname, comment := match2(text, `^\to\s(\S+)(?:\s*(.+))?$`); m {
+ if m, pkgbase, pkgversion := match2(pkgname, rePkgname); m {
+ updates = append(updates, SuggestedUpdate{line, pkgbase, pkgversion, comment})
+ } else {
+ line.Warnf("Invalid package name %q", pkgname)
+ }
+ } else {
+ line.Warnf("Invalid line format %q", text)
+ }
+ }
+ }
+ return updates
+}
+
+func (src *PkgsrcImpl) loadSuggestedUpdates() {
+ src.suggestedUpdates = src.loadSuggestedUpdatesFile(G.Pkgsrc.File("doc/TODO"))
+ if wipFilename := G.Pkgsrc.File("wip/TODO"); fileExists(wipFilename) {
+ src.suggestedWipUpdates = src.loadSuggestedUpdatesFile(wipFilename)
+ }
+}
+
+func (src *PkgsrcImpl) loadDocChangesFromFile(fname string) []*Change {
+ lines := LoadExistingLines(fname, false)
+
+ parseChange := func(line Line) *Change {
+ text := line.Text
+ if !hasPrefix(text, "\t") {
+ return nil
+ }
+
+ f := strings.Fields(text)
+ n := len(f)
+ if n != 4 && n != 6 {
+ return nil
+ }
+
+ action, pkgpath, author, date := f[0], f[1], f[len(f)-2], f[len(f)-1]
+ if !hasPrefix(author, "[") || !hasSuffix(date, "]") {
+ return nil
+ }
+ author, date = author[1:], date[:len(date)-1]
+
+ switch {
+ case action == "Added" && f[2] == "version" && n == 6:
+ return &Change{line, action, pkgpath, f[3], author, date}
+ case (action == "Updated" || action == "Downgraded") && f[2] == "to" && n == 6:
+ return &Change{line, action, pkgpath, f[3], author, date}
+ case action == "Removed" && (n == 6 && f[2] == "successor" || n == 4):
+ return &Change{line, action, pkgpath, "", author, date}
+ case (action == "Renamed" || action == "Moved") && f[2] == "to" && n == 6:
+ return &Change{line, action, pkgpath, "", author, date}
+ }
+ return nil
+ }
+
+ var changes []*Change
+ for _, line := range lines {
+ if change := parseChange(line); change != nil {
+ changes = append(changes, change)
+ } else if text := line.Text; len(text) >= 2 && text[0] == '\t' && 'A' <= text[1] && text[1] <= 'Z' {
+ line.Warnf("Unknown doc/CHANGES line: %q", text)
+ Explain("See mk/misc/developer.mk for the rules.")
+ }
+ }
+ return changes
+}
+
+func (src *PkgsrcImpl) GetSuggestedPackageUpdates() []SuggestedUpdate {
+ if G.Wip {
+ return src.suggestedWipUpdates
+ } else {
+ return src.suggestedUpdates
+ }
+}
+
+func (src *PkgsrcImpl) loadDocChanges() {
+ docdir := G.Pkgsrc.File("doc")
+ files, err := ioutil.ReadDir(docdir)
+ if err != nil {
+ NewLineWhole(docdir).Fatalf("Cannot be read.")
+ }
+
+ var fnames []string
+ for _, file := range files {
+ fname := file.Name()
+ if matches(fname, `^CHANGES-20\d\d$`) && fname >= "CHANGES-2011" {
+ fnames = append(fnames, fname)
+ }
+ }
+
+ sort.Strings(fnames)
+ src.LastChange = make(map[string]*Change)
+ for _, fname := range fnames {
+ changes := src.loadDocChangesFromFile(docdir + "/" + fname)
+ for _, change := range changes {
+ src.LastChange[change.Pkgpath] = change
+ }
+ }
+}
+
+func (src *PkgsrcImpl) loadUserDefinedVars() {
+ lines := G.Pkgsrc.LoadExistingLines("mk/defaults/mk.conf", true)
+ mklines := NewMkLines(lines)
+
+ for _, mkline := range mklines.mklines {
+ if mkline.IsVarassign() {
+ src.UserDefinedVars[mkline.Varname()] = mkline
+ }
+ }
+}
+
+func (src *PkgsrcImpl) initDeprecatedVars() {
+ src.Deprecated = map[string]string{
+
+ // December 2003
+ "FIX_RPATH": "It has been removed from pkgsrc in 2003.",
+
+ // February 2005
+ "LIB_DEPENDS": "Use DEPENDS instead.",
+ "ONLY_FOR_ARCHS": "Use ONLY_FOR_PLATFORM instead.",
+ "NOT_FOR_ARCHS": "Use NOT_FOR_PLATFORM instead.",
+ "ONLY_FOR_OPSYS": "Use ONLY_FOR_PLATFORM instead.",
+ "NOT_FOR_OPSYS": "Use NOT_FOR_PLATFORM instead.",
+
+ // May 2005
+ "ALL_TARGET": "Use BUILD_TARGET instead.",
+ "DIGEST_FILE": "Use DISTINFO_FILE instead.",
+ "IGNORE": "Use PKG_FAIL_REASON or PKG_SKIP_REASON instead.",
+ "IS_INTERACTIVE": "Use INTERACTIVE_STAGE instead.",
+ "KERBEROS": "Use the PKG_OPTIONS framework instead.",
+ "MASTER_SITE_SUBDIR": "Use some form of MASTER_SITES instead.",
+ "MD5_FILE": "Use DISTINFO_FILE instead.",
+ "MIRROR_DISTFILE": "Use NO_BIN_ON_FTP and/or NO_SRC_ON_FTP instead.",
+ "NO_CDROM": "Use NO_BIN_ON_CDROM and/or NO_SRC_ON_CDROM instead.",
+ "NO_PATCH": "You can just remove it.",
+ "NO_WRKSUBDIR": "Use WRKSRC=${WRKDIR} instead.",
+ "PATCH_SITE_SUBDIR": "Use some form of PATCHES_SITES instead.",
+ "PATCH_SUM_FILE": "Use DISTINFO_FILE instead.",
+ "PKG_JVM": "Use PKG_DEFAULT_JVM instead.",
+ "USE_BUILDLINK2": "You can just remove it.",
+ "USE_BUILDLINK3": "You can just remove it.",
+ "USE_CANNA": "Use the PKG_OPTIONS framework instead.",
+ "USE_DB4": "Use the PKG_OPTIONS framework instead.",
+ "USE_DIRS": "You can just remove it.",
+ "USE_ESOUND": "Use the PKG_OPTIONS framework instead.",
+ "USE_GIF": "Use the PKG_OPTIONS framework instead.",
+ "USE_GMAKE": "Use USE_TOOLS+=gmake instead.",
+ "USE_GNU_TOOLS": "Use USE_TOOLS instead.",
+ "USE_IDEA": "Use the PKG_OPTIONS framework instead.",
+ "USE_LIBCRACK": "Use the PKG_OPTIONS framework instead.",
+ "USE_MMX": "Use the PKG_OPTIONS framework instead.",
+ "USE_PKGLIBTOOL": "Use USE_LIBTOOL instead.",
+ "USE_SSL": "Include \"../../security/openssl/buildlink3.mk\" instead.",
+
+ // July 2005
+ "USE_PERL5": "Use USE_TOOLS+=perl or USE_TOOLS+=perl:run instead.",
+
+ // October 2005
+ "NO_TOOLS": "You can just remove it.",
+ "NO_WRAPPER": "You can just remove it.",
+
+ // November 2005
+ "ALLFILES": "Use CKSUMFILES instead.",
+ "DEPENDS_TARGET": "Use DEPENDS instead.",
+ "FETCH_DEPENDS": "Use DEPENDS instead.",
+ "RUN_DEPENDS": "Use DEPENDS instead.",
+
+ // December 2005
+ "USE_CUPS": "Use the PKG_OPTIONS framework (option cups) instead.",
+ "USE_I586": "Use the PKG_OPTIONS framework (option i586) instead.",
+ "USE_INN": "Use the PKG_OPTIONS framework instead.",
+ "USE_OPENLDAP": "Use the PKG_OPTIONS framework (option openldap) instead.",
+ "USE_OSS": "Use the PKG_OPTIONS framework (option oss) instead.",
+ "USE_RSAREF2": "Use the PKG_OPTIONS framework (option rsaref) instead.",
+ "USE_SASL": "Use the PKG_OPTIONS framework (option sasl) instead.",
+ "USE_SASL2": "Use the PKG_OPTIONS framework (option sasl) instead.",
+ "USE_SJ3": "Use the PKG_OPTIONS framework (option sj3) instead.",
+ "USE_SOCKS": "Use the PKG_OPTIONS framework (socks4 and socks5 options) instead.",
+ "USE_WNN4": "Use the PKG_OPTIONS framework (option wnn4) instead.",
+ "USE_XFACE": "Use the PKG_OPTIONS framework instead.",
+
+ // February 2006
+ "TOOLS_DEPMETHOD": "Use the :build or :run modifiers in USE_TOOLS instead.",
+ "MANDIR": "Please use ${PREFIX}/${PKGMANDIR} instead.",
+ "DOWNLOADED_DISTFILE": "Use the shell variable $$extract_file instead.",
+ "DECOMPRESS_CMD": "Use EXTRACT_CMD instead.",
+
+ // March 2006
+ "INSTALL_EXTRA_TMPL": "Use INSTALL_TEMPLATE instead.",
+ "DEINSTALL_EXTRA_TMPL": "Use DEINSTALL_TEMPLATE instead.",
+
+ // April 2006
+ "RECOMMENDED": "Use ABI_DEPENDS instead.",
+ "BUILD_USES_MSGFMT": "Use USE_TOOLS+=msgfmt instead.",
+ "USE_MSGFMT_PLURALS": "Use USE_TOOLS+=msgfmt instead.",
+
+ // May 2006
+ "EXTRACT_USING_PAX": "Use \"EXTRACT_OPTS=-t pax\" instead.",
+ "NO_EXTRACT": "It doesn't exist anymore.",
+ "_FETCH_MESSAGE": "Use FETCH_MESSAGE (different format) instead.",
+ "BUILDLINK_DEPENDS.*": "Use BUILDLINK_API_DEPENDS.* instead.",
+ "BUILDLINK_RECOMMENDED.*": "Use BUILDLINK_ABI_DEPENDS.* instead.",
+ "SHLIB_HANDLING": "Use CHECK_SHLIBS_SUPPORTED instead.",
+ "USE_RMAN": "It has been removed.",
+
+ // June 2006
+ "DEINSTALL_SRC": "Use the pkginstall framework instead.",
+ "INSTALL_SRC": "Use the pkginstall framework instead.",
+ "DEINSTALL_TEMPLATE": "Use DEINSTALL_TEMPLATES instead.",
+ "INSTALL_TEMPLATE": "Use INSTALL_TEMPLATES instead.",
+ "HEADER_TEMPLATE": "Use HEADER_TEMPLATES instead.",
+ "_REPLACE.*": "Use REPLACE.* instead.",
+ "_REPLACE_FILES.*": "Use REPLACE_FILES.* instead.",
+ "MESSAGE": "Use MESSAGE_SRC instead.",
+ "INSTALL_FILE": "It may only be used internally by pkgsrc.",
+ "DEINSTALL_FILE": "It may only be used internally by pkgsrc.",
+
+ // July 2006
+ "USE_DIGEST": "You can just remove it.",
+ "LTCONFIG_OVERRIDE": "You can just remove it.",
+ "USE_GNU_GETTEXT": "You can just remove it.",
+ "BUILD_ENV": "Use PKGSRC_MAKE_ENV instead.",
+ "DYNAMIC_MASTER_SITES": "You can just remove it.",
+
+ // September 2006
+ "MAKEFILE": "Use MAKE_FILE instead.",
+
+ // November 2006
+ "SKIP_PORTABILITY_CHECK": "Use CHECK_PORTABILITY_SKIP (a list of patterns) instead.",
+
+ // January 2007
+ "BUILDLINK_TRANSFORM.*": "Use BUILDLINK_FNAME_TRANSFORM.* instead.",
+
+ // March 2007
+ "SCRIPTDIR": "You can just remove it.",
+ "NO_PKG_REGISTER": "You can just remove it.",
+ "NO_DEPENDS": "You can just remove it.",
+
+ // October 2007
+ "_PKG_SILENT": "Use RUN (with more error checking) instead.",
+ "_PKG_DEBUG": "Use RUN (with more error checking) instead.",
+ "LICENCE": "Use LICENSE instead.",
+
+ // November 2007
+ //USE_NCURSES Include "../../devel/ncurses/buildlink3.mk" instead.
+
+ // December 2007
+ "INSTALLATION_DIRS_FROM_PLIST": "Use AUTO_MKDIRS instead.",
+
+ // April 2009
+ "NO_PACKAGE": "It doesn't exist anymore.",
+ "NO_MTREE": "You can just remove it.",
+
+ // July 2012
+ "SETGIDGAME": "Use USE_GAMESGROUP instead.",
+ "GAMEGRP": "Use GAMES_GROUP instead.",
+ "GAMEOWN": "Use GAMES_USER instead.",
+
+ // July 2013
+ "USE_GNU_READLINE": "Include \"../../devel/readline/buildlink3.mk\" instead.",
+
+ // October 2014
+ "SVR4_PKGNAME": "Just remove it.",
+ "PKG_INSTALLATION_TYPES": "Just remove it.",
+
+ // January 2016
+ "SUBST_POSTCMD.*": "Has been removed, as it seemed unused.",
+
+ // June 2016
+ "USE_CROSSBASE": "Has been removed.",
+ }
+}
+
+// LoadExistingLines loads the file relative to the pkgsrc top directory.
+func (src *PkgsrcImpl) LoadExistingLines(fileName string, joinBackslashLines bool) []Line {
+ return LoadExistingLines(src.topdir+"/"+fileName, joinBackslashLines)
+}
+
+// File resolves a file name relative to the pkgsrc top directory.
+//
+// Example:
+// NewPkgsrc("/usr/pkgsrc").File("distfiles") => "/usr/pkgsrc/distfiles"
+func (src *PkgsrcImpl) File(relativeName string) string {
+ return src.topdir + "/" + relativeName
+}
+
+// ToRel returns the path of `fileName`, relative to the pkgsrc top directory.
+//
+// Example:
+// NewPkgsrc("/usr/pkgsrc").ToRel("/usr/pkgsrc/distfiles") => "distfiles"
+func (src *PkgsrcImpl) ToRel(fileName string) string {
+ return relpath(src.topdir, fileName)
+}
+
+func (src *PkgsrcImpl) AddBuildDef(varname string) {
+ src.buildDefs[varname] = true
+}
+
+func (src *PkgsrcImpl) IsBuildDef(varname string) bool {
+ return src.buildDefs[varname]
+}
+
+func (src *PkgsrcImpl) loadMasterSites() {
+ lines := src.LoadExistingLines("mk/fetch/sites.mk", true)
+
+ nameToUrl := src.MasterSiteVarToURL
+ urlToName := src.MasterSiteURLToVar
+ for _, line := range lines {
+ if m, commented, varname, _, _, _, urls, _, _ := MatchVarassign(line.Text); m {
+ if !commented && hasPrefix(varname, "MASTER_SITE_") && varname != "MASTER_SITE_BACKUP" {
+ for _, url := range splitOnSpace(urls) {
+ if matches(url, `^(?:http://|https://|ftp://)`) {
+ if nameToUrl[varname] == "" {
+ nameToUrl[varname] = url
+ }
+ urlToName[url] = varname
+ }
+ }
+ }
+ }
+ }
+
+ // Explicitly allowed, although not defined in mk/fetch/sites.mk.
+ nameToUrl["MASTER_SITE_LOCAL"] = "ftp://ftp.NetBSD.org/pub/pkgsrc/distfiles/LOCAL_PORTS/"
+
+ if trace.Tracing {
+ trace.Stepf("Loaded %d MASTER_SITE_* URLs.", len(urlToName))
+ }
+}
+
+func (src *PkgsrcImpl) loadPkgOptions() {
+ lines := src.LoadExistingLines("mk/defaults/options.description", false)
+
+ for _, line := range lines {
+ if m, optname, optdescr := match2(line.Text, `^([-0-9a-z_+]+)(?:\s+(.*))?$`); m {
+ src.PkgOptions[optname] = optdescr
+ } else {
+ line.Fatalf("Unknown line format.")
+ }
+ }
+}
+
+// Change is a change entry from the `doc/CHANGES-*` files.
+type Change struct {
+ Line Line
+ Action string
+ Pkgpath string
+ Version string
+ Author string
+ Date string
+}
+
+// SuggestedUpdate is from the `doc/TODO` file.
+type SuggestedUpdate struct {
+ Line Line
+ Pkgname string
+ Version string
+ Comment string
+}
Index: pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go
diff -u /dev/null pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go:1.1
--- /dev/null Sat Mar 24 14:32:50 2018
+++ pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go Sat Mar 24 14:32:49 2018
@@ -0,0 +1,143 @@
+package main
+
+import (
+ "gopkg.in/check.v1"
+ "netbsd.org/pkglint/trace"
+)
+
+// Ensures that pkglint can handle MASTER_SITES definitions with and
+// without line continuations.
+//
+// See https://mail-index.netbsd.org/tech-pkg/2017/01/18/msg017698.html.
+func (s *Suite) Test_Pkgsrc_loadMasterSites(c *check.C) {
+ t := s.Init(c)
+
+ t.CreateFileLines("mk/fetch/sites.mk",
+ MkRcsID,
+ "",
+ "MASTER_SITE_A+= https://example.org/distfiles/",
+ "MASTER_SITE_B+= https://b.example.org/distfiles/ \\",
+ " https://b2.example.org/distfiles/",
+ "MASTER_SITE_A+= https://a.example.org/distfiles/")
+
+ G.Pkgsrc.loadMasterSites()
+
+ c.Check(G.Pkgsrc.MasterSiteURLToVar["https://example.org/distfiles/"], equals, "MASTER_SITE_A")
+ c.Check(G.Pkgsrc.MasterSiteURLToVar["https://b.example.org/distfiles/"], equals, "MASTER_SITE_B")
+ c.Check(G.Pkgsrc.MasterSiteURLToVar["https://b2.example.org/distfiles/"], equals, "MASTER_SITE_B")
+ c.Check(G.Pkgsrc.MasterSiteURLToVar["https://a.example.org/distfiles/"], equals, "MASTER_SITE_A")
+ c.Check(G.Pkgsrc.MasterSiteVarToURL["MASTER_SITE_A"], equals, "https://example.org/distfiles/")
+ c.Check(G.Pkgsrc.MasterSiteVarToURL["MASTER_SITE_B"], equals, "https://b.example.org/distfiles/")
+}
+
+func (s *Suite) Test_Pkgsrc_InitVartypes(c *check.C) {
+ t := s.Init(c)
+
+ src := NewPkgsrc(t.TmpDir())
+ src.InitVartypes()
+
+ c.Check(src.vartypes["BSD_MAKE_ENV"].basicType.name, equals, "ShellWord")
+ c.Check(src.vartypes["USE_BUILTIN.*"].basicType.name, equals, "YesNoIndirectly")
+}
+
+func (s *Suite) Test_Pkgsrc_parseSuggestedUpdates(c *check.C) {
+ t := s.Init(c)
+
+ lines := t.NewLines("doc/TODO",
+ "",
+ "Suggested package updates",
+ "==============",
+ "For Perl updates \u2026",
+ "",
+ "\t"+"o CSP-0.34",
+ "\t"+"o freeciv-client-2.5.0 (urgent)",
+ "",
+ "\t"+"o ignored-0.0")
+
+ todo := G.Pkgsrc.parseSuggestedUpdates(lines)
+
+ c.Check(todo, check.DeepEquals, []SuggestedUpdate{
+ {lines[5], "CSP", "0.34", ""},
+ {lines[6], "freeciv-client", "2.5.0", "(urgent)"}})
+}
+
+func (s *Suite) Test_GlobalData_loadTools(c *check.C) {
+ t := s.Init(c)
+
+ t.SetupFileLines("mk/tools/bsd.tools.mk",
+ ".include \"flex.mk\"",
+ ".include \"gettext.mk\"")
+ t.SetupFileLines("mk/tools/defaults.mk",
+ "_TOOLS_VARNAME.chown=CHOWN",
+ "_TOOLS_VARNAME.gawk=AWK",
+ "_TOOLS_VARNAME.mv=MV",
+ "_TOOLS_VARNAME.pwd=PWD")
+ t.SetupFileLines("mk/tools/flex.mk",
+ "# empty")
+ t.SetupFileLines("mk/tools/gettext.mk",
+ "USE_TOOLS+=msgfmt",
+ "TOOLS_CREATE+=msgfmt")
+ t.SetupFileLines("mk/bsd.prefs.mk",
+ "USE_TOOLS+=\tpwd")
+ t.SetupFileLines("mk/bsd.pkg.mk",
+ "USE_TOOLS+=\tmv")
+ G.CurrentDir = t.TmpDir()
+ G.CurPkgsrcdir = "."
+
+ G.Pkgsrc.loadTools()
+
+ trace.Tracing = true
+ G.Pkgsrc.Tools.Trace()
+
+ t.CheckOutputLines(
+ "TRACE: + (*ToolRegistry).Trace()",
+ "TRACE: 1 tool &{Name:TOOLS_mv Varname: MustUseVarForm:false Predefined:true UsableAtLoadtime:false}",
+ "TRACE: 1 tool &{Name:TOOLS_pwd Varname: MustUseVarForm:false Predefined:true UsableAtLoadtime:true}",
+ "TRACE: 1 tool &{Name:chown Varname:CHOWN MustUseVarForm:false Predefined:false UsableAtLoadtime:false}",
+ "TRACE: 1 tool &{Name:echo Varname:ECHO MustUseVarForm:true Predefined:true UsableAtLoadtime:true}",
+ "TRACE: 1 tool &{Name:echo -n Varname:ECHO_N MustUseVarForm:true Predefined:true UsableAtLoadtime:true}",
+ "TRACE: 1 tool &{Name:false Varname:FALSE MustUseVarForm:true Predefined:true UsableAtLoadtime:false}",
+ "TRACE: 1 tool &{Name:gawk Varname:AWK MustUseVarForm:false Predefined:false UsableAtLoadtime:false}",
+ "TRACE: 1 tool &{Name:msgfmt Varname: MustUseVarForm:false Predefined:false UsableAtLoadtime:false}",
+ "TRACE: 1 tool &{Name:mv Varname:MV MustUseVarForm:false Predefined:true UsableAtLoadtime:false}",
+ "TRACE: 1 tool &{Name:pwd Varname:PWD MustUseVarForm:false Predefined:true UsableAtLoadtime:true}",
+ "TRACE: 1 tool &{Name:test Varname:TEST MustUseVarForm:true Predefined:true UsableAtLoadtime:true}",
+ "TRACE: 1 tool &{Name:true Varname:TRUE MustUseVarForm:true Predefined:true UsableAtLoadtime:true}",
+ "TRACE: - (*ToolRegistry).Trace()")
+}
+
+func (s *Suite) Test_GlobalData_loadDocChangesFromFile(c *check.C) {
+ t := s.Init(c)
+
+ t.SetupFileLines("doc/CHANGES-2015",
+ "\tAdded category/package version 1.0 [author1 2015-01-01]",
+ "\tUpdated category/package to 1.5 [author2 2015-01-02]",
+ "\tRenamed category/package to category/pkg [author3 2015-01-03]",
+ "\tMoved category/package to other/package [author4 2015-01-04]",
+ "\tRemoved category/package [author5 2015-01-05]",
+ "\tRemoved category/package successor category/package2 [author6 2015-01-06]",
+ "\tDowngraded category/package to 1.2 [author7 2015-01-07]")
+
+ changes := G.Pkgsrc.loadDocChangesFromFile(t.TmpDir() + "/doc/CHANGES-2015")
+
+ c.Assert(len(changes), equals, 7)
+ c.Check(*changes[0], equals, Change{changes[0].Line, "Added", "category/package", "1.0", "author1", "2015-01-01"})
+ c.Check(*changes[1], equals, Change{changes[1].Line, "Updated", "category/package", "1.5", "author2", "2015-01-02"})
+ c.Check(*changes[2], equals, Change{changes[2].Line, "Renamed", "category/package", "", "author3", "2015-01-03"})
+ c.Check(*changes[3], equals, Change{changes[3].Line, "Moved", "category/package", "", "author4", "2015-01-04"})
+ c.Check(*changes[4], equals, Change{changes[4].Line, "Removed", "category/package", "", "author5", "2015-01-05"})
+ c.Check(*changes[5], equals, Change{changes[5].Line, "Removed", "category/package", "", "author6", "2015-01-06"})
+ c.Check(*changes[6], equals, Change{changes[6].Line, "Downgraded", "category/package", "1.2", "author7", "2015-01-07"})
+}
+
+func (s *Suite) Test_GlobalData_deprecated(c *check.C) {
+ t := s.Init(c)
+
+ G.Pkgsrc.initDeprecatedVars()
+ mkline := t.NewMkLine("Makefile", 5, "USE_PERL5=\tyes")
+
+ MkLineChecker{mkline}.checkVarassign()
+
+ t.CheckOutputLines(
+ "WARN: Makefile:5: Definition of USE_PERL5 is deprecated. Use USE_TOOLS+=perl or USE_TOOLS+=perl:run instead.")
+}
Index: pkgsrc/pkgtools/pkglint/files/tools.go
diff -u /dev/null pkgsrc/pkgtools/pkglint/files/tools.go:1.1
--- /dev/null Sat Mar 24 14:32:50 2018
+++ pkgsrc/pkgtools/pkglint/files/tools.go Sat Mar 24 14:32:49 2018
@@ -0,0 +1,116 @@
+package main
+
+import (
+ "netbsd.org/pkglint/trace"
+ "sort"
+)
+
+// See `mk/tools/`.
+type Tool struct {
+ Name string // e.g. "sed", "gzip"
+ Varname string // e.g. "SED", "GZIP_CMD"
+ MustUseVarForm bool // True for `echo`, because of many differing implementations.
+ Predefined bool // This tool is used by the pkgsrc infrastructure, therefore the package does not need to add it to `USE_TOOLS` explicitly.
+ UsableAtLoadtime bool // May be used after including `bsd.prefs.mk`.
+}
+
+type ToolRegistry struct {
+ byName map[string]*Tool
+ byVarname map[string]*Tool
+}
+
+func NewToolRegistry() ToolRegistry {
+ return ToolRegistry{make(map[string]*Tool), make(map[string]*Tool)}
+}
+
+func (tr *ToolRegistry) Register(toolname string) *Tool {
+ tool := tr.byName[toolname]
+ if tool == nil {
+ tool = &Tool{Name: toolname}
+ tr.byName[toolname] = tool
+ }
+ return tool
+}
+
+func (tr *ToolRegistry) RegisterVarname(toolname, varname string) *Tool {
+ tool := tr.Register(toolname)
+ tool.Varname = varname
+ tr.byVarname[varname] = tool
+ return tool
+}
+
+func (tr *ToolRegistry) RegisterTool(tool *Tool) {
+ if tool.Name != "" && tr.byName[tool.Name] == nil {
+ tr.byName[tool.Name] = tool
+ }
+ if tool.Varname != "" && tr.byVarname[tool.Varname] == nil {
+ tr.byVarname[tool.Varname] = tool
+ }
+}
+
+func (tr *ToolRegistry) FindByCommand(cmd *ShToken) *Tool {
+ if tool := tr.byName[cmd.MkText]; tool != nil {
+ return tool
+ }
+ if len(cmd.Atoms) == 1 {
+ if varuse := cmd.Atoms[0].VarUse(); varuse != nil {
+ if tool := tr.byVarname[varuse.varname]; tool != nil {
+ return tool
+ }
+ }
+ }
+ return nil
+}
+
+func (tr *ToolRegistry) Trace() {
+ if trace.Tracing {
+ defer trace.Call0()()
+ }
+
+ var keys []string
+ for k := range tr.byName {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+
+ for _, toolname := range keys {
+ trace.Stepf("tool %+v", tr.byName[toolname])
+ }
+}
+
+func (tr *ToolRegistry) ParseToolLine(line Line) {
+ if m, commented, varname, _, _, _, value, _, _ := MatchVarassign(line.Text); m {
+ if commented {
+ return
+ }
+ if varname == "TOOLS_CREATE" && (value == "[" || matches(value, `^?[-\w.]+$`)) {
+ tr.Register(value)
+
+ } else if m, toolname := match1(varname, `^_TOOLS_VARNAME\.([-\w.]+|\[)$`); m {
+ tr.RegisterVarname(toolname, value)
+
+ } else if m, toolname := match1(varname, `^(?:TOOLS_PATH|_TOOLS_DEPMETHOD)\.([-\w.]+|\[)$`); m {
+ tr.Register(toolname)
+
+ } else if m, toolname := match1(varname, `_TOOLS\.(.*)`); m {
+ tr.Register(toolname)
+ for _, tool := range splitOnSpace(value) {
+ tr.Register(tool)
+ }
+ }
+ }
+}
+
+func (tr *ToolRegistry) ByVarname(varname string) *Tool {
+ return tr.byVarname[varname]
+}
+
+func (tr *ToolRegistry) ByName(name string) *Tool {
+ return tr.byName[name]
+}
+
+func (tr *ToolRegistry) ForEach(action func(tool *Tool)) {
+ for _, tool := range tr.byName {
+ action(tool)
+ }
+}
Home |
Main Index |
Thread Index |
Old Index