diff options
author | rillig <rillig@pkgsrc.org> | 2019-04-28 18:13:53 +0000 |
---|---|---|
committer | rillig <rillig@pkgsrc.org> | 2019-04-28 18:13:53 +0000 |
commit | 1b3d34fc36aee840c2d0bb7b6f54a6b2e76fe891 (patch) | |
tree | 503130917798c206081351cb2ecf1217856244c7 /pkgtools | |
parent | d580ad228a3bf226a9abc1a3c396451dcc057d31 (diff) | |
download | pkgsrc-1b3d34fc36aee840c2d0bb7b6f54a6b2e76fe891.tar.gz |
pkgtools/pkglint: update to 5.7.8
Changes since 5.7.7:
Warn about definitions of NOT_FOR_* and ONLY_FOR_* which are missing a
rationale. When maintaining such packages it helps a lot to know why the
package cannot be built on a particular platform or with a particular
compiler or Python version.
Diffstat (limited to 'pkgtools')
-rw-r--r-- | pkgtools/pkglint/Makefile | 4 | ||||
-rw-r--r-- | pkgtools/pkglint/files/logging.go | 5 | ||||
-rw-r--r-- | pkgtools/pkglint/files/mklinechecker.go | 58 | ||||
-rw-r--r-- | pkgtools/pkglint/files/mklinechecker_test.go | 42 | ||||
-rw-r--r-- | pkgtools/pkglint/files/pkgsrc_test.go | 11 | ||||
-rw-r--r-- | pkgtools/pkglint/files/vardefs.go | 81 | ||||
-rw-r--r-- | pkgtools/pkglint/files/vartype.go | 6 |
7 files changed, 170 insertions, 37 deletions
diff --git a/pkgtools/pkglint/Makefile b/pkgtools/pkglint/Makefile index 674122e96b3..6ed3b685cfe 100644 --- a/pkgtools/pkglint/Makefile +++ b/pkgtools/pkglint/Makefile @@ -1,6 +1,6 @@ -# $NetBSD: Makefile,v 1.577 2019/04/27 19:33:56 rillig Exp $ +# $NetBSD: Makefile,v 1.578 2019/04/28 18:13:53 rillig Exp $ -PKGNAME= pkglint-5.7.7 +PKGNAME= pkglint-5.7.8 CATEGORIES= pkgtools DISTNAME= tools MASTER_SITES= ${MASTER_SITE_GITHUB:=golang/} diff --git a/pkgtools/pkglint/files/logging.go b/pkgtools/pkglint/files/logging.go index b229f51ceef..bd3070f1c9b 100644 --- a/pkgtools/pkglint/files/logging.go +++ b/pkgtools/pkglint/files/logging.go @@ -236,9 +236,8 @@ func (l *Logger) Logf(level *LogLevel, filename, lineno, format, msg string) { // Errorf logs a technical error on the error output. // -// location must be either an empty string or a slash-separated filename, -// such as the one in Location.Filename. It may be followed by the usual -// ":123" for line numbers. +// location must be a slash-separated filename, such as the one in +// Location.Filename. It may be followed by the usual ":123" for line numbers. // // For diagnostics, use Logf instead. func (l *Logger) Errorf(location string, format string, args ...interface{}) { diff --git a/pkgtools/pkglint/files/mklinechecker.go b/pkgtools/pkglint/files/mklinechecker.go index dbf33d24c70..3fdae86723f 100644 --- a/pkgtools/pkglint/files/mklinechecker.go +++ b/pkgtools/pkglint/files/mklinechecker.go @@ -402,6 +402,63 @@ func (ck MkLineChecker) explainPermissions(varname string, vartype *Vartype, int ck.MkLine.Explain(expl...) } +func (ck MkLineChecker) checkVarassignLeftRationale() { + + isRationale := func(mkline MkLine) bool { + if mkline.IsVarassign() || mkline.IsCommentedVarassign() { + return mkline.VarassignComment() != "" + } + return mkline.IsComment() && !hasPrefix(mkline.Text, "# $") + } + + needsRationale := func(mkline MkLine) bool { + if !mkline.IsVarassign() && !mkline.IsCommentedVarassign() { + return false + } + vartype := G.Pkgsrc.VariableType(ck.MkLines, mkline.Varname()) + return vartype != nil && vartype.NeedsRationale() + } + + mkline := ck.MkLine + if !needsRationale(mkline) { + return + } + + if mkline.VarassignComment() != "" { + return + } + + // Check whether there is a comment directly above. + for i, other := range ck.MkLines.mklines { + if other == mkline && i > 0 { + aboveIndex := i - 1 + for aboveIndex > 0 && needsRationale(ck.MkLines.mklines[aboveIndex]) { + aboveIndex-- + } + + if isRationale(ck.MkLines.mklines[aboveIndex]) { + return + } + } + } + + mkline.Warnf("Setting variable %s should have a rationale.", mkline.Varname()) + mkline.Explain( + "Since this variable prevents the package from being built in some situations,", + "the reasons for this restriction should be documented.", + "Otherwise it becomes too difficult to check whether these restrictions still apply", + "when the package is updated by someone else later.", + "", + "To add the rationale, put it in a comment at the end of this line,", + "or in a separate comment in the line above.", + "The rationale should try to answer these questions:", + "", + "* which specific aspects of the package are affected?", + "* if it's a dependency, is the dependency too old or too new?", + "* in which situations does a crash occur, if any?", + "* has it been reported upstream?") +} + // CheckVaruse checks a single use of a variable in a specific context. func (ck MkLineChecker) CheckVaruse(varuse *MkVarUse, vuc *VarUseContext) { mkline := ck.MkLine @@ -932,6 +989,7 @@ func (ck MkLineChecker) checkVarassignLeft() { if !ck.checkVarassignLeftUserSettable() { ck.checkVarassignLeftPermissions() } + ck.checkVarassignLeftRationale() ck.checkTextVarUse( ck.MkLine.Varname(), diff --git a/pkgtools/pkglint/files/mklinechecker_test.go b/pkgtools/pkglint/files/mklinechecker_test.go index 2c03a01b22e..406468d8252 100644 --- a/pkgtools/pkglint/files/mklinechecker_test.go +++ b/pkgtools/pkglint/files/mklinechecker_test.go @@ -736,6 +736,38 @@ func (s *Suite) Test_MkLineChecker_checkVarassignLeftPermissions__infrastructure t.CheckOutputEmpty() } +func (s *Suite) Test_MkLineChecker_checkVarassignLeftRationale(c *check.C) { + t := s.Init(c) + + t.SetUpVartypes() + mklines := t.NewMkLines("filename.mk", + MkRcsID, + "ONLY_FOR_PLATFORM=\t*-*-*", // The CVS Id above is not a rationale. + "NOT_FOR_PLATFORM=\t*-*-*", // Neither does this line have a rationale. + "", + "ONLY_FOR_PLATFORM+=\t*-*-* # rationale", + "", + "# rationale in the line above", + "ONLY_FOR_PLATFORM+=\t*-*-*", + "", + "#VAR=\tvalue", // This comment is not a rationale. + "ONLY_FOR_PLATFORM+=\t*-*-*", // Needs a rationale. + "", + "# rationale", + "BROKEN_ON_PLATFORM+=\t*-*-*", + "BROKEN_ON_PLATFORM+=\t*-*-*", // The rationale applies to this line, too. + "", + "PKGNAME=\tpackage-1.0", // Does not need a rationale. + "UNKNOWN=\t${UNKNOWN}") // Unknown type, does not need a rationale. + + mklines.Check() + + t.CheckOutputLines( + "WARN: filename.mk:2: Setting variable ONLY_FOR_PLATFORM should have a rationale.", + "WARN: filename.mk:3: Setting variable NOT_FOR_PLATFORM should have a rationale.", + "WARN: filename.mk:11: Setting variable ONLY_FOR_PLATFORM should have a rationale.") +} + func (s *Suite) Test_MkLineChecker_checkVarassignOpShell(c *check.C) { t := s.Init(c) @@ -1225,11 +1257,11 @@ func (s *Suite) Test_MkLineChecker_checkVarassignDecreasingVersions(c *check.C) t.SetUpVartypes() mklines := t.NewMkLines("Makefile", MkRcsID, - "PYTHON_VERSIONS_ACCEPTED=\t36 __future__", - "PYTHON_VERSIONS_ACCEPTED=\t36 -13", - "PYTHON_VERSIONS_ACCEPTED=\t36 ${PKGVERSION_NOREV}", - "PYTHON_VERSIONS_ACCEPTED=\t36 37", - "PYTHON_VERSIONS_ACCEPTED=\t37 36 27 25") + "PYTHON_VERSIONS_ACCEPTED=\t36 __future__ # rationale", + "PYTHON_VERSIONS_ACCEPTED=\t36 -13 # rationale", + "PYTHON_VERSIONS_ACCEPTED=\t36 ${PKGVERSION_NOREV} # rationale", + "PYTHON_VERSIONS_ACCEPTED=\t36 37 # rationale", + "PYTHON_VERSIONS_ACCEPTED=\t37 36 27 25 # rationale") // TODO: All but the last of the above assignments should be flagged as // redundant by RedundantScope; as of March 2019, that check is only diff --git a/pkgtools/pkglint/files/pkgsrc_test.go b/pkgtools/pkglint/files/pkgsrc_test.go index 6892d9f96c4..741b0473050 100644 --- a/pkgtools/pkglint/files/pkgsrc_test.go +++ b/pkgtools/pkglint/files/pkgsrc_test.go @@ -199,6 +199,12 @@ func (s *Suite) Test_Pkgsrc_loadTools__BUILD_DEFS(c *check.C) { t.CreateFileLines("mk/bsd.pkg.mk", MkRcsID, "_BUILD_DEFS+=\tPKG_SYSCONFBASEDIR PKG_SYSCONFDIR") + t.CreateFileLines("mk/defaults/mk.conf", + MkRcsID, + "", + "VARBASE=\t\t/var/pkg", + "PKG_SYSCONFBASEDIR=\t/usr/pkg/etc", + "PKG_SYSCONFDIR=\t/usr/pkg/etc") t.FinishSetUp() G.Check(pkg) @@ -206,8 +212,9 @@ func (s *Suite) Test_Pkgsrc_loadTools__BUILD_DEFS(c *check.C) { c.Check(G.Pkgsrc.IsBuildDef("PKG_SYSCONFDIR"), equals, true) c.Check(G.Pkgsrc.IsBuildDef("VARBASE"), equals, false) - // FIXME: There should be a warning for VARBASE, but G.Pkgsrc.UserDefinedVars - // does not contain anything at mklinechecker.go:/UserDefinedVars/. + t.CheckOutputLines( + "WARN: ~/category/package/Makefile:21: " + + "The user-defined variable VARBASE is used but not added to BUILD_DEFS.") } func (s *Suite) Test_Pkgsrc_loadDocChanges__not_found(c *check.C) { diff --git a/pkgtools/pkglint/files/vardefs.go b/pkgtools/pkglint/files/vardefs.go index 0b55fce1f1d..735f6539cba 100644 --- a/pkgtools/pkglint/files/vardefs.go +++ b/pkgtools/pkglint/files/vardefs.go @@ -124,6 +124,14 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { "Makefile, Makefile.*, *.mk: default, set, use") } + // Like pkg, but always needs a rationale. + pkgrat := func(varname string, basicType *BasicType) { + acl(varname, basicType, + PackageSettable|NeedsRationale, + "buildlink3.mk, builtin.mk: none", + "Makefile, Makefile.*, *.mk: default, set, use") + } + // pkgload is the same as pkg, except that the variable may be accessed at load time. pkgload := func(varname string, basicType *BasicType) { acl(varname, basicType, @@ -145,6 +153,14 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { "Makefile, Makefile.*, *.mk: default, set, append, use") } + // Like pkglist, but always needs a rationale. + pkglistrat := func(varname string, basicType *BasicType) { + acllist(varname, basicType, + List|PackageSettable|NeedsRationale, + "buildlink3.mk, builtin.mk: none", + "Makefile, Makefile.*, *.mk: default, set, append, use") + } + // pkgappend declares a variable that may use the += operator, // even though it is not a list where each item can be interpreted // on its own. @@ -168,6 +184,14 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { "Makefile, Makefile.*, *.mk: default, set, append, use") } + // Like pkgappend, but always needs a rationale. + pkgappendrat := func(varname string, basicType *BasicType) { + acl(varname, basicType, + PackageSettable|NeedsRationale, + "buildlink3.mk, builtin.mk: none", + "Makefile, Makefile.*, *.mk: default, set, append, use") + } + // Some package-defined variables may be modified in buildlink3.mk files. // These variables are typically related to compiling and linking files // from C and related languages. @@ -184,6 +208,13 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { "Makefile, Makefile.*, *.mk: default, set, append, use") } + // Like pkglistbl3, but always needs a rationale. + pkglistbl3rat := func(varname string, basicType *BasicType) { + acl(varname, basicType, + List|PackageSettable|NeedsRationale, + "Makefile, Makefile.*, *.mk: default, set, append, use") + } + // sys declares a user-defined or system-defined variable that must not // be modified by packages. // @@ -776,10 +807,10 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { pkglist("BOOTSTRAP_DEPENDS", BtDependencyWithPath) pkg("BOOTSTRAP_PKG", BtYesNo) // BROKEN should better be a list of messages instead of a simple string. - pkgappend("BROKEN", BtMessage) + pkgappendrat("BROKEN", BtMessage) pkg("BROKEN_GETTEXT_DETECTION", BtYesNo) - pkglist("BROKEN_EXCEPT_ON_PLATFORM", BtMachinePlatformPattern) - pkglist("BROKEN_ON_PLATFORM", BtMachinePlatformPattern) + pkglistrat("BROKEN_EXCEPT_ON_PLATFORM", BtMachinePlatformPattern) + pkglistrat("BROKEN_ON_PLATFORM", BtMachinePlatformPattern) syslist("BSD_MAKE_ENV", BtShellWord) // TODO: Align the permissions of the various BUILDLINK_*.* variables with each other. acllist("BUILDLINK_ABI_DEPENDS.*", BtDependency, @@ -1026,7 +1057,7 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { pkglist("EMACS_VERSIONS_ACCEPTED", emacsVersions) sys("EMACS_VERSION_MAJOR", BtInteger) sys("EMACS_VERSION_MINOR", BtInteger) - pkglist("EMACS_VERSION_REQD", emacsVersions) + pkglistrat("EMACS_VERSION_REQD", emacsVersions) sys("EMULDIR", BtPathname) sys("EMULSUBDIR", BtPathname) sys("OPSYS_EMULDIR", BtPathname) @@ -1070,17 +1101,17 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { pkglist("FILES_SUBST", BtShellWord) syslist("FILES_SUBST_SED", BtShellWord) pkglist("FIX_RPATH", BtVariableName) - pkglist("FLEX_REQD", BtVersion) + pkglistrat("FLEX_REQD", BtVersion) pkglist("FONTS_DIRS.*", BtPathname) syslist("GAMEDATA_PERMS", BtPerms) syslist("GAMEDIR_PERMS", BtPerms) - pkglistbl3("GCC_REQD", BtGccReqd) + pkglistbl3rat("GCC_REQD", BtGccReqd) pkgappend("GENERATE_PLIST", BtShellCommands) pkg("GITHUB_PROJECT", BtIdentifier) pkg("GITHUB_TAG", BtIdentifier) pkg("GITHUB_RELEASE", BtFileName) pkg("GITHUB_TYPE", enum("tag release")) - pkg("GMAKE_REQD", BtVersion) + pkgrat("GMAKE_REQD", BtVersion) // Some packages need to set GNU_ARCH.i386 to either i486 or i586. pkg("GNU_ARCH.*", BtIdentifier) // GNU_CONFIGURE needs to be tested in some buildlink3.mk files, @@ -1104,7 +1135,7 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { PackageSettable, "*: set, use-loadtime") sys("IMAKE", BtShellCommand) - pkglistbl3("INCOMPAT_CURSES", BtMachinePlatformPattern) + pkglistbl3rat("INCOMPAT_CURSES", BtMachinePlatformPattern) sys("INFO_DIR", BtPathname) // relative to PREFIX pkg("INFO_FILES", BtYes) sys("INSTALL", BtShellCommand) @@ -1163,7 +1194,7 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { pkglist("LIBS.*", BtLdFlag) sys("LIBTOOL", BtShellCommand) pkglist("LIBTOOL_OVERRIDE", BtPathmask) - pkglist("LIBTOOL_REQD", BtVersion) + pkglistrat("LIBTOOL_REQD", BtVersion) pkgappend("LICENCE", BtLicense) pkgappend("LICENSE", BtLicense) pkg("LICENSE_FILE", BtPathname) @@ -1244,12 +1275,12 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { sys("NATIVE_CC", BtShellCommand) // See mk/platform/tools.NetBSD.mk (and some others). sys("NM", BtShellCommand) sys("NONBINMODE", BtFileMode) - pkglist("NOT_FOR_COMPILER", compilers) - pkglist("NOT_FOR_BULK_PLATFORM", BtMachinePlatformPattern) - pkglist("NOT_FOR_PLATFORM", BtMachinePlatformPattern) - pkg("NOT_FOR_UNPRIVILEGED", BtYesNo) - pkglist("NOT_PAX_ASLR_SAFE", BtPathmask) - pkglist("NOT_PAX_MPROTECT_SAFE", BtPathmask) + pkglistrat("NOT_FOR_COMPILER", compilers) + pkglistrat("NOT_FOR_BULK_PLATFORM", BtMachinePlatformPattern) + pkglistrat("NOT_FOR_PLATFORM", BtMachinePlatformPattern) + pkgrat("NOT_FOR_UNPRIVILEGED", BtYesNo) + pkglistrat("NOT_PAX_ASLR_SAFE", BtPathmask) + pkglistrat("NOT_PAX_MPROTECT_SAFE", BtPathmask) pkg("NO_BIN_ON_CDROM", BtRestricted) pkg("NO_BIN_ON_FTP", BtRestricted) pkgload("NO_BUILD", BtYes) @@ -1262,9 +1293,9 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { pkg("NO_SRC_ON_CDROM", BtRestricted) pkg("NO_SRC_ON_FTP", BtRestricted) sysload("OBJECT_FMT", enum("COFF ECOFF ELF SOM XCOFF Mach-O PE a.out")) - pkglist("ONLY_FOR_COMPILER", compilers) - pkglist("ONLY_FOR_PLATFORM", BtMachinePlatformPattern) - pkg("ONLY_FOR_UNPRIVILEGED", BtYesNo) + pkglistrat("ONLY_FOR_COMPILER", compilers) + pkglistrat("ONLY_FOR_PLATFORM", BtMachinePlatformPattern) + pkgrat("ONLY_FOR_UNPRIVILEGED", BtYesNo) sysload("OPSYS", enumFromFiles("mk/platform", `(.*)\.mk$`, "$1", "Cygwin DragonFly FreeBSD Linux NetBSD SunOS")) pkglistbl3("OPSYSVARS", BtVariableName) @@ -1290,7 +1321,7 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { sys("PAXCTL", BtShellCommand) // See mk/pax.mk. pkglist("PERL5_PACKLIST", BtPerl5Packlist) pkg("PERL5_PACKLIST_DIR", BtPathname) - pkglist("PERL5_REQD", BtVersion) + pkglistrat("PERL5_REQD", BtVersion) sysbl3("PERL5_INSTALLARCHLIB", BtPathname) // See lang/perl5/vars.mk sysbl3("PERL5_INSTALLSCRIPT", BtPathname) sysbl3("PERL5_INSTALLVENDORBIN", BtPathname) @@ -1310,7 +1341,7 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { pkg("PERL5_USE_PACKLIST", BtYesNo) sys("PGSQL_PREFIX", BtPathname) acllist("PGSQL_VERSIONS_ACCEPTED", pgsqlVersions, - PackageSettable, + PackageSettable|NeedsRationale, // The "set" is necessary for databases/postgresql-postgis2. "Makefile, Makefile.*, *.mk: default, set, append, use") usr("PGSQL_VERSION_DEFAULT", BtVersion) @@ -1359,7 +1390,7 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { sys("PKGWILDCARD", BtFileMask) sysload("PKG_ADMIN", BtShellCommand) sys("PKG_APACHE", enum("apache24")) - pkglist("PKG_APACHE_ACCEPTED", enum("apache24")) + pkglistrat("PKG_APACHE_ACCEPTED", enum("apache24")) usr("PKG_APACHE_DEFAULT", enum("apache24")) sysloadlist("PKG_BUILD_OPTIONS.*", BtOption) usr("PKG_CONFIG", BtYes) @@ -1391,7 +1422,7 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { sys("PKG_INFO", BtShellCommand) sys("PKG_JAVA_HOME", BtPathname) sys("PKG_JVM", jvms) - pkglist("PKG_JVMS_ACCEPTED", jvms) + pkglistrat("PKG_JVMS_ACCEPTED", jvms) pkg("PKG_LIBTOOL", BtPathname) // begin PKG_OPTIONS section @@ -1469,8 +1500,8 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { "*: use, use-loadtime") // See lang/python/pyversion.mk pkg("PYTHON_FOR_BUILD_ONLY", enum("yes no test tool YES")) - pkglist("PYTHON_VERSIONS_ACCEPTED", BtVersion) - pkglist("PYTHON_VERSIONS_INCOMPATIBLE", BtVersion) + pkglistrat("PYTHON_VERSIONS_ACCEPTED", BtVersion) + pkglistrat("PYTHON_VERSIONS_INCOMPATIBLE", BtVersion) usr("PYTHON_VERSION_DEFAULT", BtVersion) usr("PYTHON_VERSION_REQD", BtVersion) pkglist("PYTHON_VERSIONED_DEPENDENCIES", BtPythonDependency) @@ -1568,7 +1599,7 @@ func (reg *VarTypeRegistry) Init(src *Pkgsrc) { pkglist("TEST_DIRS", BtWrksrcSubdirectory) pkglist("TEST_ENV", BtShellWord) pkglist("TEST_TARGET", BtIdentifier) - pkglist("TEXINFO_REQD", BtVersion) + pkglistrat("TEXINFO_REQD", BtVersion) pkglistbl3("TOOL_DEPENDS", BtDependencyWithPath) syslist("TOOLS_ALIASES", BtFileName) syslist("TOOLS_BROKEN", BtTool) diff --git a/pkgtools/pkglint/files/vartype.go b/pkgtools/pkglint/files/vartype.go index 19f304ffa23..e2eb7727ec9 100644 --- a/pkgtools/pkglint/files/vartype.go +++ b/pkgtools/pkglint/files/vartype.go @@ -29,6 +29,11 @@ const ( UserSettable SystemProvided CommandLineProvided + + // NeedsRationale marks variables that should always contain a comment + // describing why they are set. Typical examples are NOT_FOR_* variables. + NeedsRationale + NoVartypeOptions = 0 ) @@ -87,6 +92,7 @@ func (vt *Vartype) PackageSettable() bool { return vt.options&PackageSettabl func (vt *Vartype) UserSettable() bool { return vt.options&UserSettable != 0 } func (vt *Vartype) SystemProvided() bool { return vt.options&SystemProvided != 0 } func (vt *Vartype) CommandLineProvided() bool { return vt.options&CommandLineProvided != 0 } +func (vt *Vartype) NeedsRationale() bool { return vt.options&NeedsRationale != 0 } func (vt *Vartype) EffectivePermissions(basename string) ACLPermissions { for _, aclEntry := range vt.aclEntries { |