summaryrefslogtreecommitdiff
path: root/pkgtools/pkglint/files/package.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkgtools/pkglint/files/package.go')
-rw-r--r--pkgtools/pkglint/files/package.go576
1 files changed, 413 insertions, 163 deletions
diff --git a/pkgtools/pkglint/files/package.go b/pkgtools/pkglint/files/package.go
index 57bdd429e7d..75b0d972abd 100644
--- a/pkgtools/pkglint/files/package.go
+++ b/pkgtools/pkglint/files/package.go
@@ -1,87 +1,146 @@
package main
import (
+ "fmt"
"path"
"regexp"
"strconv"
"strings"
)
-func checkpackagePossibleDowngrade() {
- defer tracecall("checkpackagePossibleDowngrade")()
+// Package contains data for the pkgsrc package that is currently checked.
+type Package struct {
+ Pkgpath string // e.g. "category/pkgdir"
+ Pkgdir string // PKGDIR from the package Makefile
+ Filesdir string // FILESDIR from the package Makefile
+ Patchdir string // PATCHDIR from the package Makefile
+ DistinfoFile string // DISTINFO_FILE from the package Makefile
+ EffectivePkgname string // PKGNAME or DISTNAME from the package Makefile, including nb13
+ EffectivePkgbase string // The effective PKGNAME without the version
+ EffectivePkgversion string // The version part of the effective PKGNAME, excluding nb13
+ EffectivePkgnameLine *MkLine // The origin of the three effective_* values
+ SeenBsdPrefsMk bool // Has bsd.prefs.mk already been included?
+
+ vardef map[string]*MkLine // (varname, varcanon) => line
+ varuse map[string]*MkLine // (varname, varcanon) => line
+ bl3 map[string]*Line // buildlink3.mk name => line; contains only buildlink3.mk files that are directly included.
+ plistSubstCond map[string]bool // varname => true; list of all variables that are used as conditionals (@comment or nothing) in PLISTs.
+ included map[string]*Line // fname => line
+ seenMakefileCommon bool // Does the package have any .includes?
+}
+
+func NewPackage(pkgpath string) *Package {
+ pkg := &Package{
+ Pkgpath: pkgpath,
+ vardef: make(map[string]*MkLine),
+ varuse: make(map[string]*MkLine),
+ bl3: make(map[string]*Line),
+ plistSubstCond: make(map[string]bool),
+ included: make(map[string]*Line),
+ }
+ for varname, line := range G.globalData.UserDefinedVars {
+ pkg.vardef[varname] = line
+ }
+ return pkg
+}
- m, _, pkgversion := match2(G.pkgContext.effectivePkgname, rePkgname)
+func (pkg *Package) defineVar(mkline *MkLine, varname string) {
+ if pkg.vardef[varname] == nil {
+ pkg.vardef[varname] = mkline
+ }
+ varcanon := varnameCanon(varname)
+ if pkg.vardef[varcanon] == nil {
+ pkg.vardef[varcanon] = mkline
+ }
+}
+
+func (pkg *Package) varValue(varname string) (string, bool) {
+ if mkline := pkg.vardef[varname]; mkline != nil {
+ return mkline.Value(), true
+ }
+ return "", false
+}
+
+func (pkg *Package) checkPossibleDowngrade() {
+ if G.opts.DebugTrace {
+ defer tracecall0()()
+ }
+
+ m, _, pkgversion := match2(pkg.EffectivePkgname, rePkgname)
if !m {
return
}
- line := G.pkgContext.effectivePkgnameLine
+ mkline := pkg.EffectivePkgnameLine
- change := G.globalData.lastChange[G.pkgContext.pkgpath]
+ change := G.globalData.LastChange[pkg.Pkgpath]
if change == nil {
- _ = G.opts.DebugMisc && line.debugf("No change log for package %q", G.pkgContext.pkgpath)
+ if G.opts.DebugMisc {
+ mkline.Debug1("No change log for package %q", pkg.Pkgpath)
+ }
return
}
- if change.action == "Updated" {
- if pkgverCmp(pkgversion, change.version) < 0 {
- line.warnf("The package is being downgraded from %s to %s", change.version, pkgversion)
+ if change.Action == "Updated" {
+ if pkgverCmp(pkgversion, change.Version) < 0 {
+ mkline.Warn2("The package is being downgraded from %s to %s", change.Version, pkgversion)
}
}
}
-func checklinesBuildlink3Inclusion(lines []*Line) {
- defer tracecall("checklinesbuildlink3Inclusion")()
-
- if G.pkgContext == nil {
- return
+func (pkg *Package) checklinesBuildlink3Inclusion(mklines *MkLines) {
+ if G.opts.DebugTrace {
+ defer tracecall0()()
}
// Collect all the included buildlink3.mk files from the file.
- includedFiles := make(map[string]*Line)
- for _, line := range lines {
- if m, _, file := match2(line.text, reMkInclude); m {
+ includedFiles := make(map[string]*MkLine)
+ for _, mkline := range mklines.mklines {
+ if mkline.IsInclude() {
+ file := mkline.Includefile()
if m, bl3 := match1(file, `^\.\./\.\./(.*)/buildlink3\.mk`); m {
- includedFiles[bl3] = line
- if G.pkgContext.bl3[bl3] == nil {
- line.warnf("%s/buildlink3.mk is included by this file but not by the package.", bl3)
+ includedFiles[bl3] = mkline
+ if pkg.bl3[bl3] == nil {
+ mkline.Warn1("%s/buildlink3.mk is included by this file but not by the package.", bl3)
}
}
}
}
if G.opts.DebugMisc {
- for packageBl3, line := range G.pkgContext.bl3 {
+ for packageBl3, line := range pkg.bl3 {
if includedFiles[packageBl3] == nil {
- line.debugf("%s/buildlink3.mk is included by the package but not by the buildlink3.mk file.", packageBl3)
+ line.Debug1("%s/buildlink3.mk is included by the package but not by the buildlink3.mk file.", packageBl3)
}
}
}
}
func checkdirPackage(pkgpath string) {
- defer tracecall("checkdirPackage", pkgpath)()
- ctx := newPkgContext(pkgpath)
- G.pkgContext = ctx
- defer func() { G.pkgContext = nil }()
+ if G.opts.DebugTrace {
+ defer tracecall1(pkgpath)()
+ }
+
+ G.Pkg = NewPackage(pkgpath)
+ defer func() { G.Pkg = nil }()
+ pkg := G.Pkg
// we need to handle the Makefile first to get some variables
- lines := loadPackageMakefile(G.currentDir + "/Makefile")
+ lines := pkg.loadPackageMakefile(G.CurrentDir + "/Makefile")
if lines == nil {
- errorf(G.currentDir+"/Makefile", noLines, "Cannot be read.")
return
}
- files := dirglob(G.currentDir)
- if ctx.pkgdir != "." {
- files = append(files, dirglob(G.currentDir+"/"+ctx.pkgdir)...)
+ files := dirglob(G.CurrentDir)
+ if pkg.Pkgdir != "." {
+ files = append(files, dirglob(G.CurrentDir+"/"+pkg.Pkgdir)...)
}
if G.opts.CheckExtra {
- files = append(files, dirglob(G.currentDir+"/"+ctx.filesdir)...)
+ files = append(files, dirglob(G.CurrentDir+"/"+pkg.Filesdir)...)
}
- files = append(files, dirglob(G.currentDir+"/"+ctx.patchdir)...)
- if ctx.distinfoFile != "distinfo" && ctx.distinfoFile != "./distinfo" {
- files = append(files, G.currentDir+"/"+ctx.distinfoFile)
+ files = append(files, dirglob(G.CurrentDir+"/"+pkg.Patchdir)...)
+ if pkg.DistinfoFile != "distinfo" && pkg.DistinfoFile != "./distinfo" {
+ files = append(files, G.CurrentDir+"/"+pkg.DistinfoFile)
}
haveDistinfo := false
havePatches := false
@@ -90,24 +149,23 @@ func checkdirPackage(pkgpath string) {
for _, fname := range files {
if (hasPrefix(path.Base(fname), "Makefile.") || hasSuffix(fname, ".mk")) &&
!matches(fname, `patch-`) &&
- !contains(fname, G.pkgContext.pkgdir+"/") &&
- !contains(fname, G.pkgContext.filesdir+"/") {
+ !contains(fname, pkg.Pkgdir+"/") &&
+ !contains(fname, pkg.Filesdir+"/") {
if lines, err := readLines(fname, true); err == nil && lines != nil {
- ParselinesMk(lines)
- determineUsedVariables(lines)
+ NewMkLines(lines).DetermineUsedVariables()
}
}
}
for _, fname := range files {
- if fname == G.currentDir+"/Makefile" {
+ if fname == G.CurrentDir+"/Makefile" {
if G.opts.CheckMakefile {
- checkfilePackageMakefile(fname, lines)
+ pkg.checkfilePackageMakefile(fname, lines)
}
} else {
- checkfile(fname)
+ Checkfile(fname)
}
- if matches(fname, `/patches/patch-*$`) {
+ if contains(fname, "/patches/patch-") {
havePatches = true
} else if hasSuffix(fname, "/distinfo") {
haveDistinfo = true
@@ -116,186 +174,345 @@ func checkdirPackage(pkgpath string) {
if G.opts.CheckDistinfo && G.opts.CheckPatches {
if havePatches && !haveDistinfo {
- warnf(G.currentDir+"/"+ctx.distinfoFile, noLines, "File not found. Please run \"%s makepatchsum\".", confMake)
+ Warnf(G.CurrentDir+"/"+pkg.DistinfoFile, noLines, "File not found. Please run \"%s makepatchsum\".", confMake)
}
}
- if !isEmptyDir(G.currentDir + "/scripts") {
- warnf(G.currentDir+"/scripts", noLines, "This directory and its contents are deprecated! Please call the script(s) explicitly from the corresponding target(s) in the pkg's Makefile.")
+ if !isEmptyDir(G.CurrentDir + "/scripts") {
+ Warnf(G.CurrentDir+"/scripts", noLines, "This directory and its contents are deprecated! Please call the script(s) explicitly from the corresponding target(s) in the pkg's Makefile.")
}
}
-func checkfilePackageMakefile(fname string, lines []*Line) {
- defer tracecall("checkfilePackageMakefile", fname, len(lines))()
+func (pkg *Package) loadPackageMakefile(fname string) *MkLines {
+ if G.opts.DebugTrace {
+ defer tracecall1(fname)()
+ }
+
+ mainLines, allLines := NewMkLines(nil), NewMkLines(nil)
+ if !readMakefile(fname, mainLines, allLines, "") {
+ return nil
+ }
- vardef := G.pkgContext.vardef
- if vardef["PLIST_SRC"] == nil &&
- vardef["GENERATE_PLIST"] == nil &&
- vardef["META_PACKAGE"] == nil &&
- !fileExists(G.currentDir+"/"+G.pkgContext.pkgdir+"/PLIST") &&
- !fileExists(G.currentDir+"/"+G.pkgContext.pkgdir+"/PLIST.common") {
- warnf(fname, noLines, "Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?")
+ if G.opts.DumpMakefile {
+ Debugf(G.CurrentDir, noLines, "Whole Makefile (with all included files) follows:")
+ for _, line := range allLines.lines {
+ fmt.Printf("%s\n", line.String())
+ }
}
- if (vardef["NO_CHECKSUM"] != nil || vardef["META_PACKAGE"] != nil) && isEmptyDir(G.currentDir+"/"+G.pkgContext.patchdir) {
- if distinfoFile := G.currentDir + "/" + G.pkgContext.distinfoFile; fileExists(distinfoFile) {
- warnf(distinfoFile, noLines, "This file should not exist if NO_CHECKSUM or META_PACKAGE is set.")
+ allLines.DetermineUsedVariables()
+
+ pkg.Pkgdir = expandVariableWithDefault("PKGDIR", ".")
+ pkg.DistinfoFile = expandVariableWithDefault("DISTINFO_FILE", "distinfo")
+ pkg.Filesdir = expandVariableWithDefault("FILESDIR", "files")
+ pkg.Patchdir = expandVariableWithDefault("PATCHDIR", "patches")
+
+ if varIsDefined("PHPEXT_MK") {
+ if !varIsDefined("USE_PHP_EXT_PATCHES") {
+ pkg.Patchdir = "patches"
}
- } else {
- if distinfoFile := G.currentDir + "/" + G.pkgContext.distinfoFile; !containsVarRef(distinfoFile) && !fileExists(distinfoFile) {
- warnf(distinfoFile, noLines, "File not found. Please run \"%s makesum\".", confMake)
+ if varIsDefined("PECL_VERSION") {
+ pkg.DistinfoFile = "distinfo"
}
}
- if vardef["REPLACE_PERL"] != nil && vardef["NO_CONFIGURE"] != nil {
- vardef["REPLACE_PERL"].warnf("REPLACE_PERL is ignored when ...")
- vardef["NO_CONFIGURE"].warnf("... NO_CONFIGURE is set.")
+ if G.opts.DebugMisc {
+ dummyLine.Debug1("DISTINFO_FILE=%s", pkg.DistinfoFile)
+ dummyLine.Debug1("FILESDIR=%s", pkg.Filesdir)
+ dummyLine.Debug1("PATCHDIR=%s", pkg.Patchdir)
+ dummyLine.Debug1("PKGDIR=%s", pkg.Pkgdir)
}
- if vardef["LICENSE"] == nil {
- errorf(fname, noLines, "Each package must define its LICENSE.")
+ return mainLines
+}
+
+func readMakefile(fname string, mainLines *MkLines, allLines *MkLines, includingFnameForUsedCheck string) bool {
+ if G.opts.DebugTrace {
+ defer tracecall1(fname)()
}
- if vardef["GNU_CONFIGURE"] != nil && vardef["USE_LANGUAGES"] != nil {
- languagesLine := vardef["USE_LANGUAGES"]
- value := languagesLine.extra["value"].(string)
+ fileLines := LoadNonemptyLines(fname, true)
+ if fileLines == nil {
+ return false
+ }
+ fileMklines := NewMkLines(fileLines)
- if languagesLine.extra["comment"] != nil && matches(languagesLine.extra["comment"].(string), `(?-i)\b(?:c|empty|none)\b`) {
- // Don't emit a warning, since the comment
- // probably contains a statement that C is
- // really not needed.
+ isMainMakefile := len(mainLines.mklines) == 0
+
+ for _, mkline := range fileMklines.mklines {
+ line := mkline.Line
- } else if !matches(value, `(?:^|\s+)(?:c|c99|objc)(?:\s+|$)`) {
- vardef["GNU_CONFIGURE"].warnf("GNU_CONFIGURE almost always needs a C compiler, ...")
- languagesLine.warnf("... but \"c\" is not added to USE_LANGUAGES.")
+ if isMainMakefile {
+ mainLines.mklines = append(mainLines.mklines, mkline)
+ mainLines.lines = append(mainLines.lines, line)
+ }
+ allLines.mklines = append(allLines.mklines, mkline)
+ allLines.lines = append(allLines.lines, line)
+
+ var includeFile, incDir, incBase string
+ if mkline.IsInclude() {
+ inc := mkline.Includefile()
+ includeFile = resolveVariableRefs(resolveVarsInRelativePath(inc, true))
+ if containsVarRef(includeFile) {
+ if !contains(fname, "/mk/") {
+ line.Note1("Skipping include file %q. This may result in false warnings.", includeFile)
+ }
+ includeFile = ""
+ }
+ incDir, incBase = path.Split(includeFile)
}
- }
- distnameLine := vardef["DISTNAME"]
- pkgnameLine := vardef["PKGNAME"]
+ if includeFile != "" {
+ if path.Base(fname) != "buildlink3.mk" {
+ if m, bl3File := match1(includeFile, `^\.\./\.\./(.*)/buildlink3\.mk$`); m {
+ G.Pkg.bl3[bl3File] = line
+ if G.opts.DebugMisc {
+ line.Debug1("Buildlink3 file in package: %q", bl3File)
+ }
+ }
+ }
+ }
- distname := ""
- if distnameLine != nil {
- distname = distnameLine.extra["value"].(string)
+ if includeFile != "" && G.Pkg.included[includeFile] == nil {
+ G.Pkg.included[includeFile] = line
+
+ if matches(includeFile, `^\.\./[^./][^/]*/[^/]+`) {
+ mkline.Warn0("References to other packages should look like \"../../category/package\", not \"../package\".")
+ mkline.explainRelativeDirs()
+ }
+
+ if path.Base(fname) == "Makefile" && !hasPrefix(incDir, "../../mk/") && incBase != "buildlink3.mk" && incBase != "builtin.mk" && incBase != "options.mk" {
+ if G.opts.DebugInclude {
+ line.Debug1("Including %q sets seenMakefileCommon.", includeFile)
+ }
+ G.Pkg.seenMakefileCommon = true
+ }
+
+ if !contains(incDir, "/mk/") || strings.HasSuffix(includeFile, "/mk/haskell.mk") {
+ dirname, _ := path.Split(fname)
+ dirname = cleanpath(dirname)
+
+ // Only look in the directory relative to the
+ // current file and in the current working directory.
+ // Pkglint doesn’t have an include dir list, like make(1) does.
+ if !fileExists(dirname + "/" + includeFile) {
+ dirname = G.CurrentDir
+ }
+ if !fileExists(dirname + "/" + includeFile) {
+ line.Error1("Cannot read %q.", dirname+"/"+includeFile)
+ return false
+ }
+
+ if G.opts.DebugInclude {
+ line.Debug1("Including %q.", dirname+"/"+includeFile)
+ }
+ includingFname := ifelseStr(incBase == "Makefile.common" && incDir != "", fname, "")
+ if !readMakefile(dirname+"/"+includeFile, mainLines, allLines, includingFname) {
+ return false
+ }
+ }
+ }
+
+ if mkline.IsVarassign() {
+ varname, op, value := mkline.Varname(), mkline.Op(), mkline.Value()
+
+ if op != opAssignDefault || G.Pkg.vardef[varname] == nil {
+ if G.opts.DebugMisc {
+ line.Debugf("varassign(%q, %q, %q)", varname, op, value)
+ }
+ G.Pkg.vardef[varname] = mkline
+ }
+ }
}
- pkgname := ""
- if pkgnameLine != nil {
- pkgname = pkgnameLine.extra["value"].(string)
+
+ if includingFnameForUsedCheck != "" {
+ fileMklines.checkForUsedComment(relpath(G.globalData.Pkgsrcdir, includingFnameForUsedCheck))
}
- if distname != "" && pkgname != "" {
- pkgname = pkgnameFromDistname(pkgname, distname)
+ return true
+}
+
+func (pkg *Package) checkfilePackageMakefile(fname string, mklines *MkLines) {
+ if G.opts.DebugTrace {
+ defer tracecall1(fname)()
}
- if pkgname != "" && pkgname == distname && pkgnameLine.extra["comment"].(string) == "" {
- pkgnameLine.notef("PKGNAME is ${DISTNAME} by default. You probably don't need to define PKGNAME.")
+ vardef := pkg.vardef
+ if vardef["PLIST_SRC"] == nil &&
+ vardef["GENERATE_PLIST"] == nil &&
+ vardef["META_PACKAGE"] == nil &&
+ !fileExists(G.CurrentDir+"/"+pkg.Pkgdir+"/PLIST") &&
+ !fileExists(G.CurrentDir+"/"+pkg.Pkgdir+"/PLIST.common") {
+ Warnf(fname, noLines, "Neither PLIST nor PLIST.common exist, and PLIST_SRC is unset. Are you sure PLIST handling is ok?")
}
- if pkgname == "" && distname != "" && !containsVarRef(distname) && !matches(distname, rePkgname) {
- distnameLine.warnf("As DISTNAME is not a valid package name, please define the PKGNAME explicitly.")
+ if (vardef["NO_CHECKSUM"] != nil || vardef["META_PACKAGE"] != nil) && isEmptyDir(G.CurrentDir+"/"+pkg.Patchdir) {
+ if distinfoFile := G.CurrentDir + "/" + pkg.DistinfoFile; fileExists(distinfoFile) {
+ Warnf(distinfoFile, noLines, "This file should not exist if NO_CHECKSUM or META_PACKAGE is set.")
+ }
+ } else {
+ if distinfoFile := G.CurrentDir + "/" + pkg.DistinfoFile; !containsVarRef(distinfoFile) && !fileExists(distinfoFile) {
+ Warnf(distinfoFile, noLines, "File not found. Please run \"%s makesum\".", confMake)
+ }
}
- G.pkgContext.effectivePkgname,
- G.pkgContext.effectivePkgnameLine,
- G.pkgContext.effectivePkgbase,
- G.pkgContext.effectivePkgversion = determineEffectivePkgVars(pkgname, pkgnameLine, distname, distnameLine)
+ if vardef["REPLACE_PERL"] != nil && vardef["NO_CONFIGURE"] != nil {
+ vardef["REPLACE_PERL"].Warn0("REPLACE_PERL is ignored when ...")
+ vardef["NO_CONFIGURE"].Warn0("... NO_CONFIGURE is set.")
+ }
- if G.pkgContext.effectivePkgnameLine != nil {
- _ = G.opts.DebugMisc && G.pkgContext.effectivePkgnameLine.debugf("Effective name=%q base=%q version=%q",
- G.pkgContext.effectivePkgname, G.pkgContext.effectivePkgbase, G.pkgContext.effectivePkgversion)
+ if vardef["LICENSE"] == nil {
+ Errorf(fname, noLines, "Each package must define its LICENSE.")
}
- checkpackagePossibleDowngrade()
+ if vardef["GNU_CONFIGURE"] != nil && vardef["USE_LANGUAGES"] != nil {
+ languagesLine := vardef["USE_LANGUAGES"]
- if vardef["COMMENT"] == nil {
- warnf(fname, noLines, "No COMMENT given.")
- }
+ if matches(languagesLine.Comment(), `(?-i)\b(?:c|empty|none)\b`) {
+ // Don't emit a warning, since the comment
+ // probably contains a statement that C is
+ // really not needed.
- if vardef["USE_IMAKE"] != nil && vardef["USE_X11"] != nil {
- vardef["USE_IMAKE"].notef("USE_IMAKE makes ...")
- vardef["USE_X11"].notef("... USE_X11 superfluous.")
+ } else if !matches(languagesLine.Value(), `(?:^|\s+)(?:c|c99|objc)(?:\s+|$)`) {
+ vardef["GNU_CONFIGURE"].Warn0("GNU_CONFIGURE almost always needs a C compiler, ...")
+ languagesLine.Warn0("... but \"c\" is not added to USE_LANGUAGES.")
+ }
}
- if G.pkgContext.effectivePkgbase != "" {
- for _, sugg := range G.globalData.getSuggestedPackageUpdates() {
- if G.pkgContext.effectivePkgbase != sugg.pkgname {
- continue
- }
+ pkg.determineEffectivePkgVars()
+ pkg.checkPossibleDowngrade()
- suggver, comment := sugg.version, sugg.comment
- if comment != "" {
- comment = " (" + comment + ")"
- }
+ if vardef["COMMENT"] == nil {
+ Warnf(fname, noLines, "No COMMENT given.")
+ }
- pkgnameLine := G.pkgContext.effectivePkgnameLine
- cmp := pkgverCmp(G.pkgContext.effectivePkgversion, suggver)
- switch {
- case cmp < 0:
- pkgnameLine.warnf("This package should be updated to %s%s.", sugg.version, comment)
- pkgnameLine.explain(
- "The wishlist for package updates in doc/TODO mentions that a newer",
- "version of this package is available.")
- case cmp > 0:
- pkgnameLine.notef("This package is newer than the update request to %s%s.", suggver, comment)
- default:
- pkgnameLine.notef("The update request to %s from doc/TODO%s has been done.", suggver, comment)
- }
- }
+ if vardef["USE_IMAKE"] != nil && vardef["USE_X11"] != nil {
+ vardef["USE_IMAKE"].Note0("USE_IMAKE makes ...")
+ vardef["USE_X11"].Note0("... USE_X11 superfluous.")
}
- ChecklinesMk(lines)
- ChecklinesPackageMakefileVarorder(lines)
- saveAutofixChanges(lines)
+ pkg.checkUpdate()
+ mklines.Check()
+ pkg.ChecklinesPackageMakefileVarorder(mklines)
+ SaveAutofixChanges(mklines.lines)
}
-func getNbpart() string {
- line := G.pkgContext.vardef["PKGREVISION"]
+func (pkg *Package) getNbpart() string {
+ line := pkg.vardef["PKGREVISION"]
if line == nil {
return ""
}
- pkgrevision := line.extra["value"].(string)
+ pkgrevision := line.Value()
if rev, err := strconv.Atoi(pkgrevision); err == nil {
- return sprintf("nb%d", rev)
+ return "nb" + strconv.Itoa(rev)
}
return ""
}
-func determineEffectivePkgVars(pkgname string, pkgnameLine *Line, distname string, distnameLine *Line) (string, *Line, string, string) {
+func (pkg *Package) determineEffectivePkgVars() {
+ distnameLine := pkg.vardef["DISTNAME"]
+ pkgnameLine := pkg.vardef["PKGNAME"]
+
+ distname := ""
+ if distnameLine != nil {
+ distname = distnameLine.Value()
+ }
+ pkgname := ""
+ if pkgnameLine != nil {
+ pkgname = pkgnameLine.Value()
+ }
+
+ if distname != "" && pkgname != "" {
+ pkgname = pkg.pkgnameFromDistname(pkgname, distname)
+ }
+
+ if pkgname != "" && pkgname == distname && pkgnameLine.Comment() == "" {
+ pkgnameLine.Note0("PKGNAME is ${DISTNAME} by default. You probably don't need to define PKGNAME.")
+ }
+
+ if pkgname == "" && distname != "" && !containsVarRef(distname) && !matches(distname, rePkgname) {
+ distnameLine.Warn0("As DISTNAME is not a valid package name, please define the PKGNAME explicitly.")
+ }
+
if pkgname != "" && !containsVarRef(pkgname) {
if m, m1, m2 := match2(pkgname, rePkgname); m {
- return pkgname + getNbpart(), pkgnameLine, m1, m2
+ pkg.EffectivePkgname = pkgname + pkg.getNbpart()
+ pkg.EffectivePkgnameLine = pkgnameLine
+ pkg.EffectivePkgbase = m1
+ pkg.EffectivePkgversion = m2
}
}
- if distname != "" && !containsVarRef(distname) {
+ if pkg.EffectivePkgnameLine == nil && distname != "" && !containsVarRef(distname) {
if m, m1, m2 := match2(distname, rePkgname); m {
- return distname + getNbpart(), distnameLine, m1, m2
+ pkg.EffectivePkgname = distname + pkg.getNbpart()
+ pkg.EffectivePkgnameLine = distnameLine
+ pkg.EffectivePkgbase = m1
+ pkg.EffectivePkgversion = m2
+ }
+ }
+ if pkg.EffectivePkgnameLine != nil {
+ if G.opts.DebugMisc {
+ pkg.EffectivePkgnameLine.Line.Debugf("Effective name=%q base=%q version=%q",
+ pkg.EffectivePkgname, pkg.EffectivePkgbase, pkg.EffectivePkgversion)
}
}
- return "", nil, "", ""
}
-func pkgnameFromDistname(pkgname, distname string) string {
+func (pkg *Package) pkgnameFromDistname(pkgname, distname string) string {
pkgname = strings.Replace(pkgname, "${DISTNAME}", distname, -1)
if m, before, sep, subst, after := match4(pkgname, `^(.*)\$\{DISTNAME:S(.)([^\\}:]+)\}(.*)$`); m {
qsep := regexp.QuoteMeta(sep)
if m, left, from, right, to, mod := match5(subst, `^(\^?)([^:]*)(\$?)`+qsep+`([^:]*)`+qsep+`(g?)$`); m {
newPkgname := before + mkopSubst(distname, left != "", from, right != "", to, mod != "") + after
- _ = G.opts.DebugMisc && G.pkgContext.vardef["PKGNAME"].debugf("pkgnameFromDistname %q => %q", pkgname, newPkgname)
+ if G.opts.DebugMisc {
+ pkg.vardef["PKGNAME"].Debug2("pkgnameFromDistname %q => %q", pkgname, newPkgname)
+ }
pkgname = newPkgname
}
}
return pkgname
}
-func ChecklinesPackageMakefileVarorder(lines []*Line) {
- defer tracecall("ChecklinesPackageMakefileVarorder", len(lines))
+func (pkg *Package) checkUpdate() {
+ if pkg.EffectivePkgbase != "" {
+ for _, sugg := range G.globalData.GetSuggestedPackageUpdates() {
+ if pkg.EffectivePkgbase != sugg.Pkgname {
+ continue
+ }
+
+ suggver, comment := sugg.Version, sugg.Comment
+ if comment != "" {
+ comment = " (" + comment + ")"
+ }
- if !G.opts.WarnOrder {
+ pkgnameLine := pkg.EffectivePkgnameLine
+ cmp := pkgverCmp(pkg.EffectivePkgversion, suggver)
+ switch {
+ case cmp < 0:
+ pkgnameLine.Warn2("This package should be updated to %s%s.", sugg.Version, comment)
+ Explain2(
+ "The wishlist for package updates in doc/TODO mentions that a newer",
+ "version of this package is available.")
+ case cmp > 0:
+ pkgnameLine.Note2("This package is newer than the update request to %s%s.", suggver, comment)
+ default:
+ pkgnameLine.Note2("The update request to %s from doc/TODO%s has been done.", suggver, comment)
+ }
+ }
+ }
+}
+
+func (pkg *Package) ChecklinesPackageMakefileVarorder(mklines *MkLines) {
+ if G.opts.DebugTrace {
+ defer tracecall0()()
+ }
+
+ if !G.opts.WarnOrder || pkg.seenMakefileCommon {
return
}
- type OccCount int
+ type OccCount uint8
const (
once OccCount = iota
optional
@@ -378,10 +595,6 @@ func ChecklinesPackageMakefileVarorder(lines []*Line) {
},
}
- if G.pkgContext == nil || G.pkgContext.seenMakefileCommon {
- return
- }
-
lineno := 0
sectindex := -1
varindex := 0
@@ -399,12 +612,15 @@ func ChecklinesPackageMakefileVarorder(lines []*Line) {
// - new lineno > old lineno
// - new sectindex > old sectindex
// - new sectindex == old sectindex && new varindex > old varindex
- // - new next_section == true && old next_section == false
- for lineno <= len(lines) {
- line := lines[lineno]
- text := line.text
-
- _ = G.opts.DebugMisc && line.debugf("[varorder] section %d variable %d", sectindex, varindex)
+ // - new nextSection == true && old nextSection == false
+ for lineno < len(mklines.lines) {
+ mkline := mklines.mklines[lineno]
+ line := mklines.lines[lineno]
+ text := line.Text
+
+ if G.opts.DebugMisc {
+ line.Debugf("[varorder] section %d variable %d vars %v", sectindex, varindex, vars)
+ }
if nextSection {
nextSection = false
@@ -421,14 +637,14 @@ func ChecklinesPackageMakefileVarorder(lines []*Line) {
case hasPrefix(text, "#"):
lineno++
- case line.extra["varcanon"] != nil:
- varcanon := line.extra["varcanon"].(string)
+ case mkline.IsVarassign():
+ varcanon := mkline.Varcanon()
if belowText, exists := below[varcanon]; exists {
if belowText != "" {
- line.warnf("%s appears too late. Please put it below %s.", varcanon, belowText)
+ line.Warn2("%s appears too late. Please put it below %s.", varcanon, belowText)
} else {
- line.warnf("%s appears too late. It should be the very first definition.", varcanon)
+ line.Warn1("%s appears too late. It should be the very first definition.", varcanon)
}
lineno++
continue
@@ -444,12 +660,12 @@ func ChecklinesPackageMakefileVarorder(lines []*Line) {
switch {
case !(varindex < len(vars)):
if sections[sectindex].count != optional {
- line.warnf("Empty line expected.")
+ line.Warn0("Empty line expected.")
}
nextSection = true
case varcanon != vars[varindex].varname:
- line.warnf("Expected %s, but found %s.", vars[varindex].varname, varcanon)
+ line.Warn2("Expected %s, but found %s.", vars[varindex].varname, varcanon)
lineno++
default:
@@ -464,7 +680,7 @@ func ChecklinesPackageMakefileVarorder(lines []*Line) {
default:
for varindex < len(vars) {
if vars[varindex].count == once && !maySkipSection {
- line.warnf("%s should be set here.", vars[varindex].varname)
+ line.Warn1("%s should be set here.", vars[varindex].varname)
}
below[vars[varindex].varname] = belowWhat
varindex++
@@ -477,3 +693,37 @@ func ChecklinesPackageMakefileVarorder(lines []*Line) {
}
}
}
+
+func (mklines *MkLines) checkForUsedComment(relativeName string) {
+ lines := mklines.lines
+ if len(lines) < 3 {
+ return
+ }
+
+ expected := "# used by " + relativeName
+ for _, line := range lines {
+ if line.Text == expected {
+ return
+ }
+ }
+
+ i := 0
+ for i < 2 && hasPrefix(lines[i].Text, "#") {
+ i++
+ }
+
+ insertLine := lines[i]
+ if !insertLine.AutofixInsertBefore(expected) {
+ insertLine.Warn1("Please add a line %q here.", expected)
+ Explain(
+ "Since Makefile.common files usually don't have any comments and",
+ "therefore not a clearly defined interface, they should at least",
+ "contain references to all files that include them, so that it is",
+ "easier to see what effects future changes may have.",
+ "",
+ "If there are more than five packages that use a Makefile.common,",
+ "you should think about giving it a proper name (maybe plugin.mk) and",
+ "documenting its interface.")
+ }
+ SaveAutofixChanges(lines)
+}