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 Nov 23 23:35:56 UTC 2019
Modified Files:
pkgsrc/pkgtools/pkglint: Makefile PLIST
pkgsrc/pkgtools/pkglint/files: alternatives.go autofix.go
autofix_test.go buildlink3.go buildlink3_test.go category.go
category_test.go check_test.go distinfo.go files.go fuzzer_test.go
licenses.go licenses_test.go line.go linelexer.go lines.go
logging.go mkline.go mkline_test.go mklinechecker.go
mklinechecker_test.go mklineparser.go mklineparser_test.go
mklines.go mklines_test.go mkparser.go package.go package_test.go
patches.go pkglint.go pkglint_test.go pkgsrc.go pkgsrc_test.go
plist.go redundantscope.go redundantscope_test.go shell.go
shell_test.go shtokenizer.go testnames_test.go tools.go
tools_test.go toplevel.go util.go util_test.go vardefs.go
vardefs_test.go vartypecheck.go vartypecheck_test.go
pkgsrc/pkgtools/pkglint/files/textproc: lexer.go
pkgsrc/pkgtools/pkglint/files/trace: tracing.go
Log Message:
pkgtools/pkglint: update to 19.3.10
Changes since 19.3.9:
In diagnostics for suggested package updates, the exact line of doc/TODO
is mentioned. If a suggested update has an additional comment, the
brackets around that comment are not output anymore.
The check for defined but not used variables has been improved for the
edge case of defining a variable in the package Makefile and using it
in the buildlink3.mk file of the same package, which just doesn't work.
Makefile fragments in patches/ directories are now completely ignored.
It was a hypothetical case anyway.
Comparing PKGSRC_COMPILER using the == or != operators is now considered
an error instead of a warning. The common cases can be autofixed.
To generate a diff of this commit:
cvs rdiff -u -r1.609 -r1.610 pkgsrc/pkgtools/pkglint/Makefile
cvs rdiff -u -r1.16 -r1.17 pkgsrc/pkgtools/pkglint/PLIST
cvs rdiff -u -r1.16 -r1.17 pkgsrc/pkgtools/pkglint/files/alternatives.go
cvs rdiff -u -r1.29 -r1.30 pkgsrc/pkgtools/pkglint/files/autofix.go \
pkgsrc/pkgtools/pkglint/files/logging.go
cvs rdiff -u -r1.30 -r1.31 pkgsrc/pkgtools/pkglint/files/autofix_test.go
cvs rdiff -u -r1.25 -r1.26 pkgsrc/pkgtools/pkglint/files/buildlink3.go
cvs rdiff -u -r1.35 -r1.36 pkgsrc/pkgtools/pkglint/files/buildlink3_test.go \
pkgsrc/pkgtools/pkglint/files/mkparser.go \
pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go \
pkgsrc/pkgtools/pkglint/files/util_test.go
cvs rdiff -u -r1.24 -r1.25 pkgsrc/pkgtools/pkglint/files/category.go \
pkgsrc/pkgtools/pkglint/files/licenses_test.go
cvs rdiff -u -r1.26 -r1.27 pkgsrc/pkgtools/pkglint/files/category_test.go \
pkgsrc/pkgtools/pkglint/files/licenses.go
cvs rdiff -u -r1.54 -r1.55 pkgsrc/pkgtools/pkglint/files/check_test.go
cvs rdiff -u -r1.36 -r1.37 pkgsrc/pkgtools/pkglint/files/distinfo.go
cvs rdiff -u -r1.27 -r1.28 pkgsrc/pkgtools/pkglint/files/files.go
cvs rdiff -u -r1.4 -r1.5 pkgsrc/pkgtools/pkglint/files/fuzzer_test.go
cvs rdiff -u -r1.38 -r1.39 pkgsrc/pkgtools/pkglint/files/line.go
cvs rdiff -u -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/linelexer.go
cvs rdiff -u -r1.9 -r1.10 pkgsrc/pkgtools/pkglint/files/lines.go
cvs rdiff -u -r1.63 -r1.64 pkgsrc/pkgtools/pkglint/files/mkline.go
cvs rdiff -u -r1.71 -r1.72 pkgsrc/pkgtools/pkglint/files/mkline_test.go
cvs rdiff -u -r1.53 -r1.54 pkgsrc/pkgtools/pkglint/files/mklinechecker.go
cvs rdiff -u -r1.48 -r1.49 \
pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go \
pkgsrc/pkgtools/pkglint/files/shell.go
cvs rdiff -u -r1.3 -r1.4 pkgsrc/pkgtools/pkglint/files/mklineparser.go \
pkgsrc/pkgtools/pkglint/files/mklineparser_test.go
cvs rdiff -u -r1.59 -r1.60 pkgsrc/pkgtools/pkglint/files/mklines.go \
pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go
cvs rdiff -u -r1.51 -r1.52 pkgsrc/pkgtools/pkglint/files/mklines_test.go
cvs rdiff -u -r1.68 -r1.69 pkgsrc/pkgtools/pkglint/files/package.go
cvs rdiff -u -r1.58 -r1.59 pkgsrc/pkgtools/pkglint/files/package_test.go \
pkgsrc/pkgtools/pkglint/files/util.go
cvs rdiff -u -r1.32 -r1.33 pkgsrc/pkgtools/pkglint/files/patches.go
cvs rdiff -u -r1.64 -r1.65 pkgsrc/pkgtools/pkglint/files/pkglint.go
cvs rdiff -u -r1.49 -r1.50 pkgsrc/pkgtools/pkglint/files/pkglint_test.go
cvs rdiff -u -r1.41 -r1.42 pkgsrc/pkgtools/pkglint/files/pkgsrc.go
cvs rdiff -u -r1.44 -r1.45 pkgsrc/pkgtools/pkglint/files/plist.go
cvs rdiff -u -r1.7 -r1.8 pkgsrc/pkgtools/pkglint/files/redundantscope.go \
pkgsrc/pkgtools/pkglint/files/redundantscope_test.go
cvs rdiff -u -r1.56 -r1.57 pkgsrc/pkgtools/pkglint/files/shell_test.go
cvs rdiff -u -r1.19 -r1.20 pkgsrc/pkgtools/pkglint/files/shtokenizer.go \
pkgsrc/pkgtools/pkglint/files/tools.go
cvs rdiff -u -r1.8 -r1.9 pkgsrc/pkgtools/pkglint/files/testnames_test.go
cvs rdiff -u -r1.21 -r1.22 pkgsrc/pkgtools/pkglint/files/tools_test.go
cvs rdiff -u -r1.23 -r1.24 pkgsrc/pkgtools/pkglint/files/toplevel.go \
pkgsrc/pkgtools/pkglint/files/vardefs_test.go
cvs rdiff -u -r1.77 -r1.78 pkgsrc/pkgtools/pkglint/files/vardefs.go
cvs rdiff -u -r1.66 -r1.67 pkgsrc/pkgtools/pkglint/files/vartypecheck.go
cvs rdiff -u -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/textproc/lexer.go
cvs rdiff -u -r1.10 -r1.11 pkgsrc/pkgtools/pkglint/files/trace/tracing.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.609 pkgsrc/pkgtools/pkglint/Makefile:1.610
--- pkgsrc/pkgtools/pkglint/Makefile:1.609 Tue Nov 19 06:51:38 2019
+++ pkgsrc/pkgtools/pkglint/Makefile Sat Nov 23 23:35:55 2019
@@ -1,6 +1,6 @@
-# $NetBSD: Makefile,v 1.609 2019/11/19 06:51:38 rillig Exp $
+# $NetBSD: Makefile,v 1.610 2019/11/23 23:35:55 rillig Exp $
-PKGNAME= pkglint-19.3.9
+PKGNAME= pkglint-19.3.10
CATEGORIES= pkgtools
DISTNAME= tools
MASTER_SITES= ${MASTER_SITE_GITHUB:=golang/}
Index: pkgsrc/pkgtools/pkglint/PLIST
diff -u pkgsrc/pkgtools/pkglint/PLIST:1.16 pkgsrc/pkgtools/pkglint/PLIST:1.17
--- pkgsrc/pkgtools/pkglint/PLIST:1.16 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/PLIST Sat Nov 23 23:35:55 2019
@@ -1,4 +1,4 @@
-@comment $NetBSD: PLIST,v 1.16 2019/11/17 01:26:25 rillig Exp $
+@comment $NetBSD: PLIST,v 1.17 2019/11/23 23:35:55 rillig Exp $
bin/pkglint
gopkg/pkg/${GO_PLATFORM}/netbsd.org/pkglint.a
gopkg/pkg/${GO_PLATFORM}/netbsd.org/pkglint/getopt.a
@@ -77,6 +77,8 @@ gopkg/src/netbsd.org/pkglint/paragraph.g
gopkg/src/netbsd.org/pkglint/paragraph_test.go
gopkg/src/netbsd.org/pkglint/patches.go
gopkg/src/netbsd.org/pkglint/patches_test.go
+gopkg/src/netbsd.org/pkglint/path.go
+gopkg/src/netbsd.org/pkglint/path_test.go
gopkg/src/netbsd.org/pkglint/pkglint.0
gopkg/src/netbsd.org/pkglint/pkglint.1
gopkg/src/netbsd.org/pkglint/pkglint.go
Index: pkgsrc/pkgtools/pkglint/files/alternatives.go
diff -u pkgsrc/pkgtools/pkglint/files/alternatives.go:1.16 pkgsrc/pkgtools/pkglint/files/alternatives.go:1.17
--- pkgsrc/pkgtools/pkglint/files/alternatives.go:1.16 Tue Nov 19 06:51:38 2019
+++ pkgsrc/pkgtools/pkglint/files/alternatives.go Sat Nov 23 23:35:56 2019
@@ -5,7 +5,7 @@ import (
"strings"
)
-func CheckFileAlternatives(filename string) {
+func CheckFileAlternatives(filename Path) {
lines := Load(filename, NotEmpty|LogErrors)
if lines == nil {
return
@@ -16,7 +16,7 @@ func CheckFileAlternatives(filename stri
plist = G.Pkg.Plist
}
- checkPlistWrapper := func(line *Line, wrapper string) {
+ checkPlistWrapper := func(line *Line, wrapper Path) {
if plist.Files[wrapper] != nil {
line.Errorf("Alternative wrapper %q must not appear in the PLIST.", wrapper)
}
@@ -25,10 +25,10 @@ func CheckFileAlternatives(filename stri
checkPlistAlternative := func(line *Line, alternative string) {
relImplementation := strings.Replace(alternative, "@PREFIX@/", "", 1)
plistName := replaceAll(relImplementation, `@(\w+)@`, "${$1}")
- if plist.Files[plistName] != nil || G.Pkg.vars.IsDefined("ALTERNATIVES_SRC") {
+ if plist.Files[NewPath(plistName)] != nil || G.Pkg.vars.IsDefined("ALTERNATIVES_SRC") {
return
}
- if plist.Files[strings.Replace(plistName, "${PKGMANDIR}", "man", 1)] != nil {
+ if plist.Files[NewPath(strings.Replace(plistName, "${PKGMANDIR}", "man", 1))] != nil {
return
}
@@ -57,7 +57,7 @@ func CheckFileAlternatives(filename stri
}
if plist.Files != nil {
- checkPlistWrapper(line, wrapper)
+ checkPlistWrapper(line, NewPath(wrapper))
checkPlistAlternative(line, alternative)
}
Index: pkgsrc/pkgtools/pkglint/files/autofix.go
diff -u pkgsrc/pkgtools/pkglint/files/autofix.go:1.29 pkgsrc/pkgtools/pkglint/files/autofix.go:1.30
--- pkgsrc/pkgtools/pkglint/files/autofix.go:1.29 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/autofix.go Sat Nov 23 23:35:56 2019
@@ -1,10 +1,8 @@
package pkglint
import (
- "io/ioutil"
"netbsd.org/pkglint/regex"
"os"
- "path/filepath"
"strconv"
"strings"
)
@@ -455,12 +453,12 @@ func SaveAutofixChanges(lines *Lines) (a
if G.Testing {
abs := abspath(lines.Filename)
- absTmp := abspath(filepath.ToSlash(os.TempDir()))
- assertf(hasPrefix(abs, absTmp), "%q must be inside %q", abs, absTmp)
+ absTmp := abspath(NewPathSlash(os.TempDir()))
+ assertf(abs.HasPrefixPath(absTmp), "%q must be inside %q", abs, absTmp)
}
- changes := make(map[string][]string)
- changed := make(map[string]bool)
+ changes := make(map[Path][]string)
+ changed := make(map[Path]bool)
for _, line := range lines.Lines {
chlines := changes[line.Filename]
if fix := line.autofix; fix != nil {
@@ -488,12 +486,12 @@ func SaveAutofixChanges(lines *Lines) (a
for _, changedLine := range changedLines {
text.WriteString(changedLine)
}
- err := ioutil.WriteFile(tmpName, []byte(text.String()), 0666)
+ err := tmpName.WriteString(text.String())
if err != nil {
G.Logger.Errorf(tmpName, "Cannot write: %s", err)
continue
}
- err = os.Rename(tmpName, filename)
+ err = tmpName.Rename(filename)
if err != nil {
G.Logger.Errorf(tmpName, "Cannot overwrite with autofixed content: %s", err)
continue
Index: pkgsrc/pkgtools/pkglint/files/logging.go
diff -u pkgsrc/pkgtools/pkglint/files/logging.go:1.29 pkgsrc/pkgtools/pkglint/files/logging.go:1.30
--- pkgsrc/pkgtools/pkglint/files/logging.go:1.29 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/logging.go Sat Nov 23 23:35:56 2019
@@ -5,7 +5,6 @@ import (
"io"
"netbsd.org/pkglint/histogram"
"netbsd.org/pkglint/textproc"
- "path"
"strings"
)
@@ -126,12 +125,12 @@ func (l *Logger) Diag(line *Line, level
l.Logf(level, filename, linenos, format, msg)
}
-func (l *Logger) FirstTime(filename, linenos, msg string) bool {
+func (l *Logger) FirstTime(filename Path, linenos, msg string) bool {
if l.Opts.LogVerbose {
return true
}
- if !l.logged.FirstTimeSlice(path.Clean(filename), linenos, msg) {
+ if !l.logged.FirstTimeSlice(filename.Clean().String(), linenos, msg) {
l.suppressDiag = true
l.suppressExpl = true
return false
@@ -230,7 +229,7 @@ func (l *Logger) showSource(line *Line)
// IsAutofix returns whether one of the --show-autofix or --autofix options is active.
func (l *Logger) IsAutofix() bool { return l.Opts.Autofix || l.Opts.ShowAutofix }
-func (l *Logger) Logf(level *LogLevel, filename, lineno, format, msg string) {
+func (l *Logger) Logf(level *LogLevel, filename Path, lineno, format, msg string) {
if l.suppressDiag {
l.suppressDiag = false
return
@@ -290,7 +289,7 @@ func (l *Logger) Logf(level *LogLevel, f
// 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{}) {
+func (l *Logger) Errorf(location Path, format string, args ...interface{}) {
msg := sprintf(format, args...)
var diag string
if l.Opts.GccOutput {
Index: pkgsrc/pkgtools/pkglint/files/autofix_test.go
diff -u pkgsrc/pkgtools/pkglint/files/autofix_test.go:1.30 pkgsrc/pkgtools/pkglint/files/autofix_test.go:1.31
--- pkgsrc/pkgtools/pkglint/files/autofix_test.go:1.30 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/autofix_test.go Sat Nov 23 23:35:56 2019
@@ -1282,7 +1282,7 @@ func (s *Suite) Test_SaveAutofixChanges_
t.SetUpCommandLine("--autofix")
lines := t.SetUpFileLines("subdir/file.txt",
"line 1")
- _ = os.RemoveAll(t.File("subdir"))
+ _ = os.RemoveAll(t.File("subdir").String())
fix := lines.Lines[0].Autofix()
fix.Warnf("Should start with an uppercase letter.")
@@ -1308,7 +1308,7 @@ func (s *Suite) Test_SaveAutofixChanges_
"line 1")
// As long as the file is kept open, it cannot be overwritten or deleted.
- openFile, err := os.OpenFile(t.File("subdir/file.txt"), 0, 0666)
+ openFile, err := os.OpenFile(t.File("subdir/file.txt").String(), 0, 0666) // TODO: replace with Path.Open
defer func() { assertNil(openFile.Close(), "") }()
c.Check(err, check.IsNil)
@@ -1336,8 +1336,8 @@ func (s *Suite) Test_SaveAutofixChanges_
lines := t.SetUpFileLines("file.txt",
"line 1")
- c.Check(os.RemoveAll(t.File("file.txt")), check.IsNil)
- c.Check(os.MkdirAll(t.File("file.txt"), 0777), check.IsNil)
+ c.Check(os.RemoveAll(t.File("file.txt").String()), check.IsNil)
+ c.Check(os.MkdirAll(t.File("file.txt").String(), 0777), check.IsNil)
fix := lines.Lines[0].Autofix()
fix.Warnf("Should start with an uppercase letter.")
Index: pkgsrc/pkgtools/pkglint/files/buildlink3.go
diff -u pkgsrc/pkgtools/pkglint/files/buildlink3.go:1.25 pkgsrc/pkgtools/pkglint/files/buildlink3.go:1.26
--- pkgsrc/pkgtools/pkglint/files/buildlink3.go:1.25 Fri Oct 11 23:30:02 2019
+++ pkgsrc/pkgtools/pkglint/files/buildlink3.go Sat Nov 23 23:35:56 2019
@@ -2,7 +2,6 @@ package pkglint
import (
"netbsd.org/pkglint/pkgver"
- "path"
"strings"
)
@@ -21,7 +20,7 @@ func CheckLinesBuildlink3Mk(mklines *MkL
func (ck *Buildlink3Checker) Check() {
mklines := ck.mklines
if trace.Tracing {
- defer trace.Call1(mklines.lines.Filename)()
+ defer trace.Call(mklines.lines.Filename)()
}
mklines.Check()
@@ -40,7 +39,7 @@ func (ck *Buildlink3Checker) Check() {
if llex.SkipRegexp(`^BUILDLINK_DEPMETHOD\.([^\t ]+)\?=.*$`) {
llex.PreviousLine().Warnf("This line belongs inside the .ifdef block.")
- for llex.SkipString("") {
+ for llex.SkipText("") {
}
}
@@ -100,7 +99,7 @@ func (ck *Buildlink3Checker) checkUnique
return
}
- base, name := trimCommon(pkgbase, path.Base(path.Dir(mkline.Filename)))
+ base, name := trimCommon(pkgbase, mkline.Filename.Dir().Base())
if base == "" && matches(name, `^(\d*|-cvs|-fossil|-git|-hg|-svn|-devel|-snapshot)$`) {
return
}
Index: pkgsrc/pkgtools/pkglint/files/buildlink3_test.go
diff -u pkgsrc/pkgtools/pkglint/files/buildlink3_test.go:1.35 pkgsrc/pkgtools/pkglint/files/buildlink3_test.go:1.36
--- pkgsrc/pkgtools/pkglint/files/buildlink3_test.go:1.35 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/buildlink3_test.go Sat Nov 23 23:35:56 2019
@@ -599,7 +599,7 @@ func (s *Suite) Test_Buildlink3Checker_c
G.InterPackage.Enable()
- test := func(pkgbase, pkgpath string, diagnostics ...string) {
+ test := func(pkgbase string, pkgpath Path, diagnostics ...string) {
mkline := t.NewMkLine(t.File(pkgpath+"/buildlink3.mk"), 123, "")
(*Buildlink3Checker).checkUniquePkgbase(nil, pkgbase, mkline)
Index: pkgsrc/pkgtools/pkglint/files/mkparser.go
diff -u pkgsrc/pkgtools/pkglint/files/mkparser.go:1.35 pkgsrc/pkgtools/pkglint/files/mkparser.go:1.36
--- pkgsrc/pkgtools/pkglint/files/mkparser.go:1.35 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/mkparser.go Sat Nov 23 23:35:56 2019
@@ -410,6 +410,8 @@ func (p *MkParser) varUseModifierAt(lexe
// MkCond parses a condition like ${OPSYS} == "NetBSD".
//
// See devel/bmake/files/cond.c.
+//
+// FIXME: Move over to MkTokensParser
func (p *MkParser) MkCond() *MkCond {
and := p.mkCondAnd()
if and == nil {
Index: pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go
diff -u pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go:1.35 pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go:1.36
--- pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go:1.35 Tue Nov 19 06:51:38 2019
+++ pkgsrc/pkgtools/pkglint/files/pkgsrc_test.go Sat Nov 23 23:35:56 2019
@@ -292,7 +292,7 @@ func (s *Suite) Test_Pkgsrc_loadDocChang
"\t\tdistfile directly from GitHub [rillig 2018-01-01]",
"\tmk/bsd.pkg.mk: Another infrastructure change [rillig 2018-01-02]")
- t.Main(t.File("category/package"))
+ t.Main("category/package")
// For pkglint's purpose, the infrastructure entries are simply ignored
// since they do not belong to a single package.
@@ -543,6 +543,7 @@ func (s *Suite) Test_Pkgsrc_parseSuggest
t := s.Init(c)
lines := t.NewLines("doc/TODO",
+ CvsID,
"",
"Suggested package updates",
"==============",
@@ -556,8 +557,8 @@ func (s *Suite) Test_Pkgsrc_parseSuggest
todo := G.Pkgsrc.parseSuggestedUpdates(lines)
t.CheckDeepEquals(todo, []SuggestedUpdate{
- {lines.Lines[5].Location, "CSP", "0.34", ""},
- {lines.Lines[6].Location, "freeciv-client", "2.5.0", "(urgent)"}})
+ {lines.Lines[6].Location, "CSP", "0.34", ""},
+ {lines.Lines[7].Location, "freeciv-client", "2.5.0", "(urgent)"}})
}
func (s *Suite) Test_Pkgsrc_parseSuggestedUpdates__wip(c *check.C) {
@@ -577,7 +578,36 @@ func (s *Suite) Test_Pkgsrc_parseSuggest
t.CheckOutputLines(
"WARN: ~/wip/package/Makefile:3: " +
- "This package should be updated to 1.13 ([cool new features]).")
+ "This package should be updated to 1.13 (cool new features; see ../../wip/TODO:5).")
+}
+
+func (s *Suite) Test_Pkgsrc_parseSuggestedUpdates__parse_errors(c *check.C) {
+ t := s.Init(c)
+
+ lines := t.NewLines("doc/TODO",
+ "", // missing CvsID
+ "Suggested package updates",
+ "==============", // usually this line is a bit longer
+ "",
+ "", // usually there's only a single empty line
+ "\t"+"O wrong bullet",
+ "\t"+"o package-without-version",
+ "\t"+"o CSP-0.34",
+ "\t"+"o freeciv-client-2.5.0 (urgent)", // missing [brackets]
+ "\t"+"o mix-2.5.0 [urgent)", // bracket + parenthesis
+ "",
+ "\t"+"o ignored-0.0")
+
+ todo := G.Pkgsrc.parseSuggestedUpdates(lines)
+
+ t.CheckDeepEquals(todo, []SuggestedUpdate{
+ {lines.Lines[7].Location, "CSP", "0.34", ""},
+ {lines.Lines[8].Location, "freeciv-client", "2.5.0", "(urgent)"},
+ {lines.Lines[9].Location, "mix", "2.5.0", "[urgent)"}})
+
+ t.CheckOutputLines(
+ "WARN: doc/TODO:6: Invalid line format \"\\tO wrong bullet\".",
+ "WARN: doc/TODO:7: Invalid package name \"package-without-version\".")
}
func (s *Suite) Test_Pkgsrc_loadTools(c *check.C) {
@@ -1025,12 +1055,12 @@ func (s *Suite) Test_Pkgsrc_VariableType
"PKGSRC_MAKE_ENV?=\t# none",
"CPPPATH?=\tcpp",
"OSNAME.Linux?=\tLinux")
- pkg := t.SetUpPackage("category/package",
+ t.SetUpPackage("category/package",
"PKGSRC_MAKE_ENV+=\tCPP=${CPPPATH:Q}",
"PKGSRC_UNKNOWN_ENV+=\tCPP=${ABCPATH:Q}",
"OSNAME.SunOS=\t\t${OSNAME.Other}")
- t.Main("-Wall", pkg)
+ t.Main("-Wall", "category/package")
if typ := G.Pkgsrc.VariableType(nil, "PKGSRC_MAKE_ENV"); c.Check(typ, check.NotNil) {
t.CheckEquals(typ.String(), "ShellWord (list, guessed)")
@@ -1110,7 +1140,7 @@ func (s *Suite) Test_Pkgsrc_checkTopleve
t.SetUpPackage("category/package2",
"LICENSE=\tmissing")
- t.Main("-r", "-Cglobal", t.File("."))
+ t.Main("-r", "-Cglobal", ".")
t.CheckOutputLines(
"WARN: ~/category/package2/Makefile:11: License file ~/licenses/missing does not exist.",
@@ -1162,8 +1192,8 @@ func (s *Suite) Test_Change_Target(c *ch
moved := Change{loc, Moved, "category/path", "category/other", "author", "2019-01-01"}
downgraded := Change{loc, Downgraded, "category/path", "1.0", "author", "2019-01-01"}
- t.CheckEquals(renamed.Target(), "category/other")
- t.CheckEquals(moved.Target(), "category/other")
+ t.CheckEquals(renamed.Target(), NewPath("category/other"))
+ t.CheckEquals(moved.Target(), NewPath("category/other"))
t.ExpectAssert(func() { downgraded.Target() })
}
Index: pkgsrc/pkgtools/pkglint/files/util_test.go
diff -u pkgsrc/pkgtools/pkglint/files/util_test.go:1.35 pkgsrc/pkgtools/pkglint/files/util_test.go:1.36
--- pkgsrc/pkgtools/pkglint/files/util_test.go:1.35 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/util_test.go Sat Nov 23 23:35:56 2019
@@ -99,12 +99,12 @@ func (s *Suite) Test_isEmptyDir__and_get
if dir := t.File("."); true {
t.CheckEquals(isEmptyDir(dir), true)
- t.CheckDeepEquals(getSubdirs(dir), []string(nil))
+ t.CheckDeepEquals(getSubdirs(dir), []Path(nil))
t.CreateFileLines("somedir/file")
t.CheckEquals(isEmptyDir(dir), false)
- t.CheckDeepEquals(getSubdirs(dir), []string{"somedir"})
+ t.CheckDeepEquals(getSubdirs(dir), []Path{"somedir"})
}
if absent := t.File("nonexistent"); true {
@@ -122,9 +122,9 @@ func (s *Suite) Test_getSubdirs(c *check
t.CreateFileLines("subdir/file")
t.CreateFileLines("empty/file")
- c.Check(os.Remove(t.File("empty/file")), check.IsNil)
+ c.Check(os.Remove(t.File("empty/file").String()), check.IsNil)
- t.CheckDeepEquals(getSubdirs(t.File(".")), []string{"subdir"})
+ t.CheckDeepEquals(getSubdirs(t.File(".")), []Path{"subdir"})
}
func (s *Suite) Test_isLocallyModified(c *check.C) {
@@ -133,10 +133,10 @@ func (s *Suite) Test_isLocallyModified(c
unmodified := t.CreateFileLines("unmodified")
modTime := time.Unix(1136239445, 0).UTC()
- err := os.Chtimes(unmodified, modTime, modTime)
+ err := os.Chtimes(unmodified.String(), modTime, modTime)
c.Check(err, check.IsNil)
- st, err := os.Lstat(unmodified)
+ st, err := os.Lstat(unmodified.String())
c.Check(err, check.IsNil)
// Make sure that the file system has second precision and accuracy.
@@ -284,28 +284,6 @@ func (s *Suite) Test_varnameParam(c *che
t.CheckEquals(varnameParam(".CURDIR"), "")
}
-func (s *Suite) Test_fileExists(c *check.C) {
- t := s.Init(c)
-
- t.CreateFileLines("dir/file")
-
- t.CheckEquals(fileExists(t.File("nonexistent")), false)
- t.CheckEquals(fileExists(t.File("dir")), false)
- t.CheckEquals(fileExists(t.File("dir/nonexistent")), false)
- t.CheckEquals(fileExists(t.File("dir/file")), true)
-}
-
-func (s *Suite) Test_dirExists(c *check.C) {
- t := s.Init(c)
-
- t.CreateFileLines("dir/file")
-
- t.CheckEquals(dirExists(t.File("nonexistent")), false)
- t.CheckEquals(dirExists(t.File("dir")), true)
- t.CheckEquals(dirExists(t.File("dir/nonexistent")), false)
- t.CheckEquals(dirExists(t.File("dir/file")), false)
-}
-
func (s *Suite) Test_mkopSubst__middle(c *check.C) {
t := s.Init(c)
@@ -360,7 +338,7 @@ func (s *Suite) Test_relpath(c *check.C)
t.Chdir(".")
t.CheckEquals(G.Pkgsrc.topdir, t.tmpdir)
- test := func(from, to, result string) {
+ test := func(from, to Path, result Path) {
t.CheckEquals(relpath(from, to), result)
}
@@ -396,7 +374,7 @@ func (s *Suite) Test_relpath(c *check.C)
func (s *Suite) Test_relpath__quick(c *check.C) {
t := s.Init(c)
- test := func(from, to, result string) {
+ test := func(from, to Path, result Path) {
t.CheckEquals(relpath(from, to), result)
}
@@ -411,7 +389,7 @@ func (s *Suite) Test_relpath__quick(c *c
func (s *Suite) Test_cleanpath(c *check.C) {
t := s.Init(c)
- test := func(from, to string) {
+ test := func(from, to Path) {
t.CheckEquals(cleanpath(from), to)
}
@@ -498,12 +476,12 @@ func (s *Suite) Test_pathContains(c *che
func (s *Suite) Test_pathContainsDir(c *check.C) {
t := s.Init(c)
- test := func(haystack, needle string, expected bool) {
+ test := func(haystack, needle Path, expected bool) {
actual := pathContainsDir(haystack, needle)
t.CheckEquals(actual, expected)
}
- testPanic := func(haystack, needle string) {
+ testPanic := func(haystack, needle Path) {
t.c.Check(
func() { _ = pathContainsDir(haystack, needle) },
check.PanicMatches,
@@ -850,15 +828,15 @@ func (s *Suite) Test_FileCache(c *check.
c.Check(cache.Get("Makefile", MustSucceed|LogErrors), check.IsNil) // Wrong LoadOptions.
linesFromCache := cache.Get("Makefile", 0)
- t.CheckEquals(linesFromCache.Filename, "Makefile")
+ t.CheckEquals(linesFromCache.Filename, NewPath("Makefile"))
c.Check(linesFromCache.Lines, check.HasLen, 2)
- t.CheckEquals(linesFromCache.Lines[0].Filename, "Makefile")
+ t.CheckEquals(linesFromCache.Lines[0].Filename, NewPath("Makefile"))
// Cache keys are normalized using path.Clean.
linesFromCache2 := cache.Get("./Makefile", 0)
- t.CheckEquals(linesFromCache2.Filename, "./Makefile")
+ t.CheckEquals(linesFromCache2.Filename, NewPath("./Makefile"))
c.Check(linesFromCache2.Lines, check.HasLen, 2)
- t.CheckEquals(linesFromCache2.Lines[0].Filename, "./Makefile")
+ t.CheckEquals(linesFromCache2.Lines[0].Filename, NewPath("./Makefile"))
cache.Put("file1.mk", 0, lines)
cache.Put("file2.mk", 0, lines)
Index: pkgsrc/pkgtools/pkglint/files/category.go
diff -u pkgsrc/pkgtools/pkglint/files/category.go:1.24 pkgsrc/pkgtools/pkglint/files/category.go:1.25
--- pkgsrc/pkgtools/pkglint/files/category.go:1.24 Fri Nov 1 19:56:53 2019
+++ pkgsrc/pkgtools/pkglint/files/category.go Sat Nov 23 23:35:56 2019
@@ -6,12 +6,12 @@ import (
"strings"
)
-func CheckdirCategory(dir string) {
+func CheckdirCategory(dir Path) {
if trace.Tracing {
- defer trace.Call1(dir)()
+ defer trace.Call(dir)()
}
- mklines := LoadMk(dir+"/Makefile", NotEmpty|LogErrors)
+ mklines := LoadMk(dir.JoinNoClean("Makefile"), NotEmpty|LogErrors) // TODO: Remove the "./" here already
if mklines == nil {
return
}
@@ -49,7 +49,7 @@ func CheckdirCategory(dir string) {
mlex.SkipEmptyOrNote()
type subdir struct {
- name string
+ name Path
line *MkLine
}
@@ -67,7 +67,7 @@ func CheckdirCategory(dir string) {
if (mkline.IsVarassignMaybeCommented()) && mkline.Varname() == "SUBDIR" {
mlex.Skip()
- name := mkline.Value()
+ name := mkline.Value() // TODO: Maybe NewPath here already
if mkline.IsCommentedVarassign() && !mkline.HasComment() {
mkline.Warnf("%q commented out without giving a reason.", name)
}
@@ -78,12 +78,12 @@ func CheckdirCategory(dir string) {
seen[name] = mkline
if len(mSubdirs) > 0 {
- if prev := mSubdirs[len(mSubdirs)-1].name; name < prev {
+ if prev := mSubdirs[len(mSubdirs)-1].name; name < prev.String() {
mkline.Warnf("%q should come before %q.", name, prev)
}
}
- mSubdirs = append(mSubdirs, subdir{name, mkline})
+ mSubdirs = append(mSubdirs, subdir{NewPath(name), mkline})
} else {
if !mkline.IsEmpty() {
@@ -96,8 +96,8 @@ func CheckdirCategory(dir string) {
// To prevent unnecessary warnings about subdirectories that are
// in one list but not in the other, generate the sets of
// subdirs of each list.
- fCheck := make(map[string]bool)
- mCheck := make(map[string]bool)
+ fCheck := make(map[Path]bool)
+ mCheck := make(map[Path]bool)
for _, fsub := range fSubdirs {
fCheck[fsub] = true
}
@@ -122,7 +122,7 @@ func CheckdirCategory(dir string) {
fix := line.Autofix()
fix.Errorf("%q exists in the file system but not in the Makefile.", fCurrent)
- fix.InsertBefore("SUBDIR+=\t" + fCurrent)
+ fix.InsertBefore("SUBDIR+=\t" + fCurrent.String())
fix.Apply()
}
fRest = fRest[1:]
@@ -155,7 +155,7 @@ func CheckdirCategory(dir string) {
mklines.SaveAutofixChanges()
if G.Opts.Recursive {
- var recurseInto []string
+ var recurseInto []Path
for _, msub := range mSubdirs {
if !msub.line.IsCommentedVarassign() {
recurseInto = append(recurseInto, joinPath(dir, msub.name))
Index: pkgsrc/pkgtools/pkglint/files/licenses_test.go
diff -u pkgsrc/pkgtools/pkglint/files/licenses_test.go:1.24 pkgsrc/pkgtools/pkglint/files/licenses_test.go:1.25
--- pkgsrc/pkgtools/pkglint/files/licenses_test.go:1.24 Tue Oct 1 21:37:59 2019
+++ pkgsrc/pkgtools/pkglint/files/licenses_test.go Sat Nov 23 23:35:56 2019
@@ -54,7 +54,7 @@ func (s *Suite) Test_LicenseChecker_chec
t.CreateFileLines("category/package/my-license",
"An individual license file.")
- t.Main(t.File("category/package"))
+ t.Main("category/package")
// There is no warning about the unusual file name in the package directory.
// If it were not mentioned in LICENSE_FILE, the file named my-license
Index: pkgsrc/pkgtools/pkglint/files/category_test.go
diff -u pkgsrc/pkgtools/pkglint/files/category_test.go:1.26 pkgsrc/pkgtools/pkglint/files/category_test.go:1.27
--- pkgsrc/pkgtools/pkglint/files/category_test.go:1.26 Fri Nov 1 19:56:53 2019
+++ pkgsrc/pkgtools/pkglint/files/category_test.go Sat Nov 23 23:35:56 2019
@@ -208,12 +208,12 @@ func (s *Suite) Test_CheckdirCategory__r
// It is only removed in Pkglint.Main, therefore it stays there even
// after the call to CheckdirCategory. This is a bit unrealistic,
// but close enough for this test.
- t.CheckDeepEquals(G.Todo.entries, []string{"."})
+ t.CheckDeepEquals(G.Todo.entries, []Path{"."})
CheckdirCategory(".")
t.CheckOutputEmpty()
- t.CheckDeepEquals(G.Todo.entries, []string{"./package", "."})
+ t.CheckDeepEquals(G.Todo.entries, []Path{"./package", "."})
}
// Ensures that a directory in the file system can be added at the very
Index: pkgsrc/pkgtools/pkglint/files/licenses.go
diff -u pkgsrc/pkgtools/pkglint/files/licenses.go:1.26 pkgsrc/pkgtools/pkglint/files/licenses.go:1.27
--- pkgsrc/pkgtools/pkglint/files/licenses.go:1.26 Sun Jul 14 21:25:47 2019
+++ pkgsrc/pkgtools/pkglint/files/licenses.go Sat Nov 23 23:35:56 2019
@@ -24,18 +24,18 @@ func (lc *LicenseChecker) Check(value st
}
func (lc *LicenseChecker) checkName(license string) {
- licenseFile := ""
+ licenseFile := NewPath("")
if G.Pkg != nil {
if mkline := G.Pkg.vars.FirstDefinition("LICENSE_FILE"); mkline != nil {
- licenseFile = G.Pkg.File(mkline.ResolveVarsInRelativePath(mkline.Value()))
+ licenseFile = G.Pkg.File(mkline.ResolveVarsInRelativePath(NewPath(mkline.Value())))
}
}
if licenseFile == "" {
- licenseFile = G.Pkgsrc.File("licenses/" + license)
+ licenseFile = G.Pkgsrc.File("licenses").JoinNoClean(NewPath(license))
G.InterPackage.UseLicense(license)
}
- if !fileExists(licenseFile) {
+ if !licenseFile.IsFile() {
lc.MkLine.Warnf("License file %s does not exist.", cleanpath(licenseFile))
}
Index: pkgsrc/pkgtools/pkglint/files/check_test.go
diff -u pkgsrc/pkgtools/pkglint/files/check_test.go:1.54 pkgsrc/pkgtools/pkglint/files/check_test.go:1.55
--- pkgsrc/pkgtools/pkglint/files/check_test.go:1.54 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/check_test.go Sat Nov 23 23:35:56 2019
@@ -7,8 +7,6 @@ import (
"io/ioutil"
"netbsd.org/pkglint/regex"
"os"
- "path"
- "path/filepath"
"regexp"
"strings"
"testing"
@@ -128,9 +126,9 @@ type Tester struct {
stdout bytes.Buffer
stderr bytes.Buffer
- tmpdir string
+ tmpdir Path
prevdir string // The current working directory before the test started
- relCwd string // See Tester.Chdir
+ relCwd Path // See Tester.Chdir
seenSetUpCommandLine bool
seenSetupPkgsrc int
@@ -206,7 +204,7 @@ func (t *Tester) SetUpTool(name, varname
// The file is then read in, without interpreting line continuations.
//
// See SetUpFileMkLines for loading a Makefile fragment.
-func (t *Tester) SetUpFileLines(relativeFileName string, lines ...string) *Lines {
+func (t *Tester) SetUpFileLines(relativeFileName Path, lines ...string) *Lines {
filename := t.CreateFileLines(relativeFileName, lines...)
return Load(filename, MustSucceed)
}
@@ -215,7 +213,7 @@ func (t *Tester) SetUpFileLines(relative
// The file is then read in, handling line continuations for Makefiles.
//
// See SetUpFileLines for loading an ordinary file.
-func (t *Tester) SetUpFileMkLines(relativeFileName string, lines ...string) *MkLines {
+func (t *Tester) SetUpFileMkLines(relativeFileName Path, lines ...string) *MkLines {
filename := t.CreateFileLines(relativeFileName, lines...)
return LoadMk(filename, MustSucceed)
}
@@ -224,15 +222,15 @@ func (t *Tester) SetUpFileMkLines(relati
// merging all the lines into a single MkLines object.
//
// This is useful for testing code related to Package.readMakefile.
-func (t *Tester) LoadMkInclude(relativeFileName string) *MkLines {
+func (t *Tester) LoadMkInclude(relativeFileName Path) *MkLines {
var lines []*Line
// TODO: Include files with multiple-inclusion guard only once.
// TODO: Include files without multiple-inclusion guard as often as needed.
// TODO: Set an upper limit, to prevent denial of service.
- var load func(filename string)
- load = func(filename string) {
+ var load func(filename Path)
+ load = func(filename Path) {
for _, mkline := range NewMkLines(Load(filename, MustSucceed)).mklines {
lines = append(lines, mkline.Line)
@@ -332,11 +330,12 @@ func (t *Tester) SetUpPkgsrc() {
// SetUpCategory makes the given category valid by creating a dummy Makefile.
// After that, it can be mentioned in the CATEGORIES variable of a package.
-func (t *Tester) SetUpCategory(name string) {
- assert(!contains(name, "/")) // Category must not contain a slash.
+func (t *Tester) SetUpCategory(name Path) {
+ assert(name.Count() == 1)
- if _, err := os.Stat(t.File(name + "/Makefile")); os.IsNotExist(err) {
- t.CreateFileLines(name+"/Makefile",
+ makefile := name.JoinNoClean("Makefile")
+ if !t.File(makefile).IsFile() {
+ t.CreateFileLines(makefile,
MkCvsID)
}
}
@@ -352,11 +351,11 @@ func (t *Tester) SetUpCategory(name stri
// After calling this method, individual files can be overwritten as necessary.
// At the end of the setup phase, t.FinishSetUp() must be called to load all
// the files.
-func (t *Tester) SetUpPackage(pkgpath string, makefileLines ...string) string {
- assertf(matches(pkgpath, `^[^/]+/[^/]+$`), "pkgpath %q must have the form \"category/package\"", pkgpath)
+func (t *Tester) SetUpPackage(pkgpath Path, makefileLines ...string) Path {
+ assertf(matches(pkgpath.String(), `^[^/]+/[^/]+$`), "pkgpath %q must have the form \"category/package\"", pkgpath)
- distname := path.Base(pkgpath)
- category := path.Dir(pkgpath)
+ distname := pkgpath.Base()
+ category := pkgpath.Dir()
if category == "wip" {
// To avoid boilerplate CATEGORIES definitions for wip packages.
category = "local"
@@ -365,9 +364,9 @@ func (t *Tester) SetUpPackage(pkgpath st
t.SetUpPkgsrc()
t.SetUpCategory(category)
- t.CreateFileLines(pkgpath+"/DESCR",
+ t.CreateFileLines(pkgpath.JoinNoClean("DESCR"),
"Package description")
- t.CreateFileLines(pkgpath+"/PLIST",
+ t.CreateFileLines(pkgpath.JoinNoClean("PLIST"),
PlistCvsID,
"bin/program")
@@ -377,12 +376,12 @@ func (t *Tester) SetUpPackage(pkgpath st
// correct position. To prevent the tests from having to mention the
// unrelated warnings about the variable order, that check is suppressed
// here.
- t.CreateFileLines(pkgpath+"/suppress-varorder.mk",
+ t.CreateFileLines(pkgpath.JoinNoClean("suppress-varorder.mk"),
MkCvsID)
// This distinfo file contains dummy hashes since pkglint cannot check the
// distfiles hashes anyway. It can only check the hashes for the patches.
- t.CreateFileLines(pkgpath+"/distinfo",
+ t.CreateFileLines(pkgpath.JoinNoClean("distinfo"),
CvsID,
"",
"SHA1 (distfile-1.0.tar.gz) = 12341234",
@@ -395,7 +394,7 @@ func (t *Tester) SetUpPackage(pkgpath st
"",
"DISTNAME=\t" + distname + "-1.0",
"#PKGNAME=\tpackage-1.0",
- "CATEGORIES=\t" + category,
+ "CATEGORIES=\t" + category.String(),
"MASTER_SITES=\t# none",
"",
"MAINTAINER=\tpkgsrc-users%NetBSD.org@localhost",
@@ -433,7 +432,7 @@ line:
"",
".include \"../../mk/bsd.pkg.mk\"")
- t.CreateFileLines(pkgpath+"/Makefile",
+ t.CreateFileLines(pkgpath.JoinNoClean("Makefile"),
mlines...)
return t.File(pkgpath)
@@ -443,18 +442,18 @@ line:
// given lines to it.
//
// It returns the full path to the created file.
-func (t *Tester) CreateFileLines(relativeFileName string, lines ...string) (filename string) {
- var content bytes.Buffer
+func (t *Tester) CreateFileLines(relativeFileName Path, lines ...string) (filename Path) {
+ var content strings.Builder
for _, line := range lines {
content.WriteString(line)
content.WriteString("\n")
}
filename = t.File(relativeFileName)
- err := os.MkdirAll(path.Dir(filename), 0777)
+ err := os.MkdirAll(filename.Dir().String(), 0777)
t.c.Assert(err, check.IsNil)
- err = ioutil.WriteFile(filename, content.Bytes(), 0666)
+ err = filename.WriteString(content.String())
t.c.Assert(err, check.IsNil)
G.fileCache.Evict(filename)
@@ -464,7 +463,7 @@ func (t *Tester) CreateFileLines(relativ
// CreateFileDummyPatch creates a patch file with the given name in the
// temporary directory.
-func (t *Tester) CreateFileDummyPatch(relativeFileName string) {
+func (t *Tester) CreateFileDummyPatch(relativeFileName Path) {
t.CreateFileLines(relativeFileName,
CvsID,
"",
@@ -477,9 +476,10 @@ func (t *Tester) CreateFileDummyPatch(re
"+new")
}
-func (t *Tester) CreateFileDummyBuildlink3(relativeFileName string, customLines ...string) {
- dir := path.Dir(relativeFileName)
- lower := path.Base(dir)
+func (t *Tester) CreateFileDummyBuildlink3(relativeFileName Path, customLines ...string) {
+ assert(relativeFileName.Count() == 3)
+ dir := relativeFileName.Dir()
+ lower := dir.Base()
// see pkgtools/createbuildlink/files/createbuildlink, "package specific variables"
upper := strings.Replace(strings.ToUpper(lower), "-", "_", -1)
@@ -519,26 +519,26 @@ func (t *Tester) CreateFileDummyBuildlin
// File returns the absolute path to the given file in the
// temporary directory. It doesn't check whether that file exists.
// Calls to Tester.Chdir change the base directory for the relative filename.
-func (t *Tester) File(relativeFileName string) string {
+func (t *Tester) File(relativeFileName Path) Path {
if t.tmpdir == "" {
- t.tmpdir = filepath.ToSlash(t.c.MkDir())
+ t.tmpdir = NewPathSlash(t.c.MkDir())
}
if t.relCwd != "" {
- return path.Clean(relativeFileName)
+ return relativeFileName.Clean()
}
- return path.Clean(joinPath(t.tmpdir, relativeFileName))
+ return t.tmpdir.JoinClean(relativeFileName)
}
// Copy copies a file inside the temporary directory.
-func (t *Tester) Copy(relativeSrc, relativeDst string) {
+func (t *Tester) Copy(relativeSrc, relativeDst Path) {
src := t.File(relativeSrc)
dst := t.File(relativeDst)
- data, err := ioutil.ReadFile(src)
+ data, err := src.ReadString()
assertNil(err, "Copy.Read")
- err = os.MkdirAll(path.Dir(dst), 0777)
+ err = os.MkdirAll(dst.Dir().String(), 0777)
assertNil(err, "Copy.MkdirAll")
- err = ioutil.WriteFile(dst, data, 0777)
+ err = dst.WriteString(data)
assertNil(err, "Copy.Write")
}
@@ -554,7 +554,7 @@ func (t *Tester) Copy(relativeSrc, relat
//
// As long as this method is not called in a test, the current working
// directory is indeterminate.
-func (t *Tester) Chdir(relativeDirName string) {
+func (t *Tester) Chdir(relativeDirName Path) {
if t.relCwd != "" {
// When multiple calls of Chdir are mixed with calls to CreateFileLines,
// the resulting Lines and MkLines variables will use relative filenames,
@@ -564,17 +564,17 @@ func (t *Tester) Chdir(relativeDirName s
}
absDirName := t.File(relativeDirName)
- assertNil(os.MkdirAll(absDirName, 0700), "MkDirAll")
- assertNil(os.Chdir(absDirName), "Chdir")
+ assertNil(os.MkdirAll(absDirName.String(), 0700), "MkDirAll")
+ assertNil(os.Chdir(absDirName.String()), "Chdir")
t.relCwd = relativeDirName
G.cwd = absDirName
}
// Remove removes the file or directory from the temporary directory.
// The file or directory must exist.
-func (t *Tester) Remove(relativeFileName string) {
+func (t *Tester) Remove(relativeFileName Path) {
filename := t.File(relativeFileName)
- err := os.Remove(filename)
+ err := os.Remove(filename.String())
t.c.Assert(err, check.IsNil)
G.fileCache.Evict(filename)
}
@@ -604,12 +604,12 @@ func (t *Tester) Remove(relativeFileName
// subdir/module.mk includes subdir/version.mk, the include line is just:
// .include "version.mk"
func (t *Tester) SetUpHierarchy() (
- include func(filename string, args ...interface{}) *MkLines,
- get func(string) *MkLines) {
+ include func(filename Path, args ...interface{}) *MkLines,
+ get func(Path) *MkLines) {
- files := map[string]*MkLines{}
+ files := map[Path]*MkLines{}
- include = func(filename string, args ...interface{}) *MkLines {
+ include = func(filename Path, args ...interface{}) *MkLines {
var lines []*Line
lineno := 1
@@ -623,7 +623,7 @@ func (t *Tester) SetUpHierarchy() (
case string:
addLine(arg)
case *MkLines:
- text := sprintf(".include %q", relpath(path.Dir(filename), arg.lines.Filename))
+ text := sprintf(".include %q", relpath(filename.Dir(), arg.lines.Filename))
addLine(text)
lines = append(lines, arg.lines.Lines...)
default:
@@ -637,7 +637,7 @@ func (t *Tester) SetUpHierarchy() (
return mklines
}
- get = func(filename string) *MkLines {
+ get = func(filename Path) *MkLines {
assertf(files[filename] != nil, "MkLines with name %q doesn't exist.", filename)
return files[filename]
}
@@ -715,10 +715,9 @@ func (t *Tester) Main(args ...string) in
argv := []string{"pkglint"}
for _, arg := range args {
- fileArg := t.File(arg)
- _, err := os.Lstat(fileArg)
- if err == nil {
- argv = append(argv, fileArg)
+ fileArg := t.File(NewPath(arg))
+ if fileArg.Exists() {
+ argv = append(argv, fileArg.String())
} else {
argv = append(argv, arg)
}
@@ -845,15 +844,15 @@ func (t *Tester) NewRawLines(args ...int
// NewLine creates an in-memory line with the given text.
// This line does not correspond to any line in a file.
-func (t *Tester) NewLine(filename string, lineno int, text string) *Line {
+func (t *Tester) NewLine(filename Path, lineno int, text string) *Line {
textnl := text + "\n"
rawLine := RawLine{lineno, textnl, textnl}
return NewLine(filename, lineno, text, &rawLine)
}
// NewMkLine creates an in-memory line in the Makefile format with the given text.
-func (t *Tester) NewMkLine(filename string, lineno int, text string) *MkLine {
- basename := path.Base(filename)
+func (t *Tester) NewMkLine(filename Path, lineno int, text string) *MkLine {
+ basename := filename.Base()
assertf(
hasSuffix(basename, ".mk") ||
basename == "Makefile" ||
@@ -872,14 +871,14 @@ func (t *Tester) NewShellLineChecker(tex
// NewLines returns a list of simple lines that belong together.
//
// To work with line continuations like in Makefiles, use SetUpFileMkLines.
-func (t *Tester) NewLines(filename string, lines ...string) *Lines {
+func (t *Tester) NewLines(filename Path, lines ...string) *Lines {
return t.NewLinesAt(filename, 1, lines...)
}
// NewLinesAt returns a list of simple lines that belong together.
//
// To work with line continuations like in Makefiles, use SetUpFileMkLines.
-func (t *Tester) NewLinesAt(filename string, firstLine int, texts ...string) *Lines {
+func (t *Tester) NewLinesAt(filename Path, firstLine int, texts ...string) *Lines {
lines := make([]*Line, len(texts))
for i, text := range texts {
lines[i] = t.NewLine(filename, i+firstLine, text)
@@ -893,8 +892,8 @@ func (t *Tester) NewLinesAt(filename str
//
// No actual file is created for the lines;
// see SetUpFileMkLines for loading Makefile fragments with line continuations.
-func (t *Tester) NewMkLines(filename string, lines ...string) *MkLines {
- basename := path.Base(filename)
+func (t *Tester) NewMkLines(filename Path, lines ...string) *MkLines {
+ basename := filename.Base()
assertf(
hasSuffix(basename, ".mk") || basename == "Makefile" || hasPrefix(basename, "Makefile."),
"filename %q must be realistic, otherwise the variable permissions are wrong", filename)
@@ -924,7 +923,7 @@ func (t *Tester) Output() string {
}
assertf(t.tmpdir != "", "Tester must be initialized before checking the output.")
- return strings.Replace(stdout+stderr, t.tmpdir, "~", -1)
+ return strings.Replace(stdout+stderr, t.tmpdir.String(), "~", -1)
}
// CheckOutputEmpty ensures that the output up to now is empty.
@@ -983,14 +982,14 @@ func (t *Tester) CheckOutputLinesIgnoreS
t.CheckDeepEquals(actual, expected)
}
-func (t *Tester) compareOutputIgnoreSpace(rawOutput string, expectedLines []string, tmpdir string) ([]string, []string) {
+func (t *Tester) compareOutputIgnoreSpace(rawOutput string, expectedLines []string, tmpdir Path) ([]string, []string) {
whitespace := regexp.MustCompile(`\s+`)
// Replace all occurrences of tmpdir in the raw output with a tilde,
// also covering cases where tmpdir is wrapped into multiple lines.
output := func() string {
var tmpdirPattern strings.Builder
- for i, part := range whitespace.Split(tmpdir, -1) {
+ for i, part := range whitespace.Split(tmpdir.String(), -1) {
if i > 0 {
tmpdirPattern.WriteString("\\s+")
}
@@ -1017,7 +1016,7 @@ func (s *Suite) Test_Tester_compareOutpu
t := s.Init(c)
lines := func(lines ...string) []string { return lines }
- test := func(rawOutput string, expectedLines []string, tmpdir string, eq bool) {
+ test := func(rawOutput string, expectedLines []string, tmpdir Path, eq bool) {
actual, expected := t.compareOutputIgnoreSpace(rawOutput, expectedLines, tmpdir)
t.CheckEquals(actual == nil && expected == nil, eq)
}
@@ -1137,10 +1136,10 @@ func (t *Tester) DisableTracing() {
// CheckFileLines loads the lines from the temporary file and checks that
// they equal the given lines.
-func (t *Tester) CheckFileLines(relativeFileName string, lines ...string) {
- content, err := ioutil.ReadFile(t.File(relativeFileName))
+func (t *Tester) CheckFileLines(relativeFileName Path, lines ...string) {
+ content, err := t.File(relativeFileName).ReadString()
t.c.Assert(err, check.IsNil)
- actualLines := strings.Split(string(content), "\n")
+ actualLines := strings.Split(content, "\n")
actualLines = actualLines[:len(actualLines)-1]
t.CheckDeepEquals(emptyToNil(actualLines), emptyToNil(lines))
}
@@ -1149,7 +1148,7 @@ func (t *Tester) CheckFileLines(relative
// that they equal the given lines. The loaded file may use tabs or spaces
// for indentation, while the lines in the code use spaces exclusively,
// in order to make the depth of the indentation clearly visible in the test code.
-func (t *Tester) CheckFileLinesDetab(relativeFileName string, lines ...string) {
+func (t *Tester) CheckFileLinesDetab(relativeFileName Path, lines ...string) {
actualLines := Load(t.File(relativeFileName), MustSucceed)
var detabbedLines []string
@@ -1167,11 +1166,11 @@ func (t *Tester) CheckFileLinesDetab(rel
// development.
func (t *Tester) Use(...interface{}) {}
-func (t *Tester) Shquote(format string, rels ...string) string {
+func (t *Tester) Shquote(format string, rels ...Path) string {
var subs []interface{}
for _, rel := range rels {
- quoted := shquote(path.Join(t.tmpdir, rel))
- subs = append(subs, strings.Replace(quoted, t.tmpdir, "~", -1))
+ quoted := shquote(t.tmpdir.JoinClean(rel).String())
+ subs = append(subs, strings.Replace(quoted, t.tmpdir.String(), "~", -1))
}
return sprintf(format, subs...)
}
Index: pkgsrc/pkgtools/pkglint/files/distinfo.go
diff -u pkgsrc/pkgtools/pkglint/files/distinfo.go:1.36 pkgsrc/pkgtools/pkglint/files/distinfo.go:1.37
--- pkgsrc/pkgtools/pkglint/files/distinfo.go:1.36 Tue Oct 1 21:37:59 2019
+++ pkgsrc/pkgtools/pkglint/files/distinfo.go Sat Nov 23 23:35:56 2019
@@ -8,29 +8,27 @@ import (
"golang.org/x/crypto/ripemd160"
"hash"
"io"
- "io/ioutil"
- "os"
"strings"
)
func CheckLinesDistinfo(pkg *Package, lines *Lines) {
if trace.Tracing {
- defer trace.Call1(lines.Filename)()
+ defer trace.Call(lines.Filename)()
}
filename := lines.Filename
- patchdir := "patches"
- if pkg != nil && dirExists(pkg.File(pkg.Patchdir)) {
+ patchdir := NewPath("patches")
+ if pkg != nil && pkg.File(pkg.Patchdir).IsDir() {
patchdir = pkg.Patchdir
}
if trace.Tracing {
- trace.Step1("patchdir=%q", patchdir)
+ trace.Stepf("patchdir=%q", patchdir)
}
distinfoIsCommitted := isCommitted(filename)
ck := distinfoLinesChecker{
pkg, lines, patchdir, distinfoIsCommitted,
- nil, make(map[string]distinfoFileInfo)}
+ nil, make(map[Path]distinfoFileInfo)}
ck.parse()
ck.check()
CheckLinesTrailingEmptyLines(lines)
@@ -42,11 +40,11 @@ func CheckLinesDistinfo(pkg *Package, li
type distinfoLinesChecker struct {
pkg *Package
lines *Lines
- patchdir string // Relative to pkg
+ patchdir Path // Relative to pkg
distinfoIsCommitted bool
- filenames []string // For keeping the order from top to bottom
- infos map[string]distinfoFileInfo
+ filenames []Path // For keeping the order from top to bottom
+ infos map[Path]distinfoFileInfo
}
func (ck *distinfoLinesChecker) parse() {
@@ -58,16 +56,16 @@ func (ck *distinfoLinesChecker) parse()
}
llex.SkipEmptyOrNote()
- prevFilename := ""
+ prevFilename := NewPath("")
var hashes []distinfoHash
isPatch := func() YesNoUnknown {
switch {
- case !hasPrefix(prevFilename, "patch-"):
+ case !prevFilename.HasPrefixText("patch-"):
return no
case ck.pkg == nil:
return unknown
- case fileExists(ck.pkg.File(joinPath(ck.patchdir, prevFilename))):
+ case ck.pkg.File(ck.patchdir.JoinNoClean(prevFilename)).IsFile():
return yes
default:
return no
@@ -84,7 +82,8 @@ func (ck *distinfoLinesChecker) parse()
line := llex.CurrentLine()
llex.Skip()
- m, alg, filename, hash := match3(line.Text, `^(\w+) \((\w[^)]*)\) = (\S+(?: bytes)?)$`)
+ m, alg, file, hash := match3(line.Text, `^(\w+) \((\w[^)]*)\) = (\S+(?: bytes)?)$`)
+ filename := NewPath(file)
if !m {
line.Errorf("Invalid line: %s", line.Text)
continue
@@ -146,7 +145,7 @@ func (ck *distinfoLinesChecker) checkAlg
// At this point, the file is either a missing patch file or a distfile.
- case hasPrefix(filename, "patch-") && algorithms == "SHA1":
+ case filename.HasPrefixText("patch-") && algorithms == "SHA1":
if ck.pkg.IgnoreMissingPatches {
break
}
@@ -196,7 +195,7 @@ func (ck *distinfoLinesChecker) checkAlg
distdir := G.Pkgsrc.File("distfiles")
distfile := cleanpath(joinPath(distdir, info.filename()))
- if !fileExists(distfile) {
+ if !distfile.IsFile() {
// It's a rare situation that the explanation is generated
// this far from the corresponding diagnostic.
@@ -225,7 +224,7 @@ func (ck *distinfoLinesChecker) checkAlg
}
computeHash := func(hasher hash.Hash) string {
- f, err := os.Open(distfile)
+ f, err := distfile.Open()
assertNil(err, "Opening distfile")
// Don't load the distfile into memory since some of them
@@ -250,7 +249,7 @@ func (ck *distinfoLinesChecker) checkAlg
case "SHA512":
return computeHash(sha512.New())
default:
- fileInfo, err := os.Lstat(distfile)
+ fileInfo, err := distfile.Lstat()
assertNil(err, "Inaccessible distfile info")
return sprintf("%d bytes", fileInfo.Size())
}
@@ -302,7 +301,7 @@ func (ck *distinfoLinesChecker) checkUnr
if ck.pkg == nil {
return
}
- patchFiles, err := ioutil.ReadDir(ck.pkg.File(ck.patchdir))
+ patchFiles, err := ck.pkg.File(ck.patchdir).ReadDir()
if err != nil {
if trace.Tracing {
trace.Stepf("Cannot read patchdir %q: %s", ck.patchdir, err)
@@ -311,11 +310,11 @@ func (ck *distinfoLinesChecker) checkUnr
}
for _, file := range patchFiles {
- patchName := file.Name()
- if file.Mode().IsRegular() && ck.infos[patchName].isPatch != yes && hasPrefix(patchName, "patch-") {
+ patchName := NewPath(file.Name())
+ if file.Mode().IsRegular() && ck.infos[patchName].isPatch != yes && patchName.HasPrefixText("patch-") {
line := NewLineWhole(ck.lines.Filename)
line.Errorf("Patch %q is not recorded. Run %q.",
- line.PathToFile(ck.pkg.File(joinPath(ck.patchdir, patchName))),
+ line.PathToFile(ck.pkg.File(ck.patchdir.JoinNoClean(patchName))),
bmake("makepatchsum"))
}
}
@@ -336,7 +335,7 @@ func (ck *distinfoLinesChecker) checkGlo
// Intentionally checking the filename instead of ck.isPatch.
// Missing the few distfiles that actually start with patch-*
// is more convenient than having lots of false positive mismatches.
- if hasPrefix(filename, "patch-") {
+ if filename.HasPrefixText("patch-") {
return
}
@@ -381,7 +380,7 @@ func (ck *distinfoLinesChecker) checkUnc
}
}
-func (ck *distinfoLinesChecker) checkPatchSha1(line *Line, patchFileName, distinfoSha1Hex string) {
+func (ck *distinfoLinesChecker) checkPatchSha1(line *Line, patchFileName Path, distinfoSha1Hex string) {
lines := Load(ck.pkg.File(patchFileName), 0)
if lines == nil {
line.Errorf("Patch %s does not exist.", patchFileName)
@@ -409,8 +408,8 @@ type distinfoFileInfo struct {
hashes []distinfoHash
}
-func (info *distinfoFileInfo) filename() string { return info.hashes[0].filename }
-func (info *distinfoFileInfo) line() *Line { return info.hashes[0].line }
+func (info *distinfoFileInfo) filename() Path { return info.hashes[0].filename }
+func (info *distinfoFileInfo) line() *Line { return info.hashes[0].line }
func (info *distinfoFileInfo) algorithms() string {
var algs []string
@@ -422,7 +421,7 @@ func (info *distinfoFileInfo) algorithms
type distinfoHash struct {
line *Line
- filename string
+ filename Path
algorithm string
hash string
}
Index: pkgsrc/pkgtools/pkglint/files/files.go
diff -u pkgsrc/pkgtools/pkglint/files/files.go:1.27 pkgsrc/pkgtools/pkglint/files/files.go:1.28
--- pkgsrc/pkgtools/pkglint/files/files.go:1.27 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/files.go Sat Nov 23 23:35:56 2019
@@ -1,9 +1,7 @@
package pkglint
import (
- "io/ioutil"
"netbsd.org/pkglint/textproc"
- "path"
"strings"
)
@@ -16,7 +14,7 @@ const (
LogErrors //
)
-func LoadMk(filename string, options LoadOptions) *MkLines {
+func LoadMk(filename Path, options LoadOptions) *MkLines {
lines := Load(filename, options|Makefile)
if lines == nil {
return nil
@@ -24,12 +22,12 @@ func LoadMk(filename string, options Loa
return NewMkLines(lines)
}
-func Load(filename string, options LoadOptions) *Lines {
+func Load(filename Path, options LoadOptions) *Lines {
if fromCache := G.fileCache.Get(filename, options); fromCache != nil {
return fromCache
}
- rawBytes, err := ioutil.ReadFile(filename)
+ rawText, err := filename.ReadString()
if err != nil {
switch {
case options&MustSucceed != 0:
@@ -40,7 +38,6 @@ func Load(filename string, options LoadO
return nil
}
- rawText := string(rawBytes)
if rawText == "" && options&NotEmpty != 0 {
switch {
case options&MustSucceed != 0:
@@ -52,17 +49,17 @@ func Load(filename string, options LoadO
}
if G.Opts.Profiling {
- G.loaded.Add(path.Clean(filename), 1)
+ G.loaded.Add(filename.Clean().String(), 1)
}
result := convertToLogicalLines(filename, rawText, options&Makefile != 0)
- if hasSuffix(filename, ".mk") {
+ if filename.HasSuffixText(".mk") {
G.fileCache.Put(filename, options, result)
}
return result
}
-func convertToLogicalLines(filename string, rawText string, joinBackslashLines bool) *Lines {
+func convertToLogicalLines(filename Path, rawText string, joinBackslashLines bool) *Lines {
var rawLines []*RawLine
for lineno, rawLine := range strings.SplitAfter(rawText, "\n") {
if rawLine != "" {
@@ -92,7 +89,7 @@ func convertToLogicalLines(filename stri
return NewLines(filename, loglines)
}
-func nextLogicalLine(filename string, rawLines []*RawLine, index int) (*Line, int) {
+func nextLogicalLine(filename Path, rawLines []*RawLine, index int) (*Line, int) {
{ // Handle the common case efficiently
rawLine := rawLines[index]
textnl := rawLine.textnl
Index: pkgsrc/pkgtools/pkglint/files/fuzzer_test.go
diff -u pkgsrc/pkgtools/pkglint/files/fuzzer_test.go:1.4 pkgsrc/pkgtools/pkglint/files/fuzzer_test.go:1.5
--- pkgsrc/pkgtools/pkglint/files/fuzzer_test.go:1.4 Sun Jun 30 20:56:19 2019
+++ pkgsrc/pkgtools/pkglint/files/fuzzer_test.go Sat Nov 23 23:35:56 2019
@@ -3,6 +3,7 @@ package pkglint
import (
"gopkg.in/check.v1"
"math/rand"
+ "time"
)
// Fuzzer generates random strings.
@@ -27,7 +28,7 @@ func NewFuzzer(seed ...int64) *Fuzzer {
if len(seed) > 0 {
actualSeed = seed[0]
} else {
- actualSeed = rand.Int63()
+ actualSeed = time.Now().UnixNano()
}
return &Fuzzer{seed: actualSeed, rnd: rand.New(rand.NewSource(actualSeed))}
}
Index: pkgsrc/pkgtools/pkglint/files/line.go
diff -u pkgsrc/pkgtools/pkglint/files/line.go:1.38 pkgsrc/pkgtools/pkglint/files/line.go:1.39
--- pkgsrc/pkgtools/pkglint/files/line.go:1.38 Sun Jul 14 21:25:47 2019
+++ pkgsrc/pkgtools/pkglint/files/line.go Sat Nov 23 23:35:56 2019
@@ -15,7 +15,6 @@ package pkglint
import (
"netbsd.org/pkglint/regex"
- "path"
"strconv"
)
@@ -38,16 +37,16 @@ type RawLine struct {
func (rline *RawLine) String() string { return sprintf("%d:%s", rline.Lineno, rline.textnl) }
type Location struct {
- Filename string // uses / as directory separator on all platforms
- firstLine int32 // zero means the whole file, -1 means EOF
- lastLine int32 // usually the same as firstLine, may differ in Makefiles
+ Filename Path
+ firstLine int32 // zero means the whole file, -1 means EOF
+ lastLine int32 // usually the same as firstLine, may differ in Makefiles
}
func (loc *Location) String() string {
- return loc.Filename + ":" + loc.Linenos()
+ return loc.Filename.String() + ":" + loc.Linenos()
}
-func NewLocation(filename string, firstLine, lastLine int) Location {
+func NewLocation(filename Path, firstLine, lastLine int) Location {
return Location{filename, int32(firstLine), int32(lastLine)}
}
@@ -83,23 +82,23 @@ type Line struct {
// XXX: Filename and Basename could be replaced with a pointer to a Lines object.
}
-func NewLine(filename string, lineno int, text string, rawLine *RawLine) *Line {
+func NewLine(filename Path, lineno int, text string, rawLine *RawLine) *Line {
assert(rawLine != nil) // Use NewLineMulti for creating a Line with no RawLine attached to it.
return NewLineMulti(filename, lineno, lineno, text, []*RawLine{rawLine})
}
// NewLineMulti is for logical Makefile lines that end with backslash.
-func NewLineMulti(filename string, firstLine, lastLine int, text string, rawLines []*RawLine) *Line {
- return &Line{NewLocation(filename, firstLine, lastLine), path.Base(filename), text, rawLines, nil, Once{}}
+func NewLineMulti(filename Path, firstLine, lastLine int, text string, rawLines []*RawLine) *Line {
+ return &Line{NewLocation(filename, firstLine, lastLine), filename.Base(), text, rawLines, nil, Once{}}
}
// NewLineEOF creates a dummy line for logging, with the "line number" EOF.
-func NewLineEOF(filename string) *Line {
+func NewLineEOF(filename Path) *Line {
return NewLineMulti(filename, -1, 0, "", nil)
}
// NewLineWhole creates a dummy line for logging messages that affect a file as a whole.
-func NewLineWhole(filename string) *Line {
+func NewLineWhole(filename Path) *Line {
return NewLineMulti(filename, 0, 0, "", nil)
}
@@ -111,7 +110,7 @@ func (line *Line) RefTo(other *Line) str
func (line *Line) RefToLocation(other Location) string {
if line.Filename != other.Filename {
- return line.PathToFile(other.Filename) + ":" + other.Linenos()
+ return line.PathToFile(other.Filename).String() + ":" + other.Linenos()
}
return "line " + other.Linenos()
}
@@ -119,8 +118,8 @@ func (line *Line) RefToLocation(other Lo
// PathToFile returns the relative path from this line to the given file path.
// This is typically used for arguments in diagnostics, which should always be
// relative to the line with which the diagnostic is associated.
-func (line *Line) PathToFile(filePath string) string {
- return relpath(path.Dir(line.Filename), filePath)
+func (line *Line) PathToFile(filePath Path) Path {
+ return relpath(line.Filename.Dir(), filePath)
}
func (line *Line) IsMultiline() bool {
Index: pkgsrc/pkgtools/pkglint/files/linelexer.go
diff -u pkgsrc/pkgtools/pkglint/files/linelexer.go:1.6 pkgsrc/pkgtools/pkglint/files/linelexer.go:1.7
--- pkgsrc/pkgtools/pkglint/files/linelexer.go:1.6 Sat Nov 2 16:37:48 2019
+++ pkgsrc/pkgtools/pkglint/files/linelexer.go Sat Nov 23 23:35:56 2019
@@ -4,19 +4,22 @@ import "netbsd.org/pkglint/regex"
// LinesLexer records the state when checking a list of lines from top to bottom.
type LinesLexer struct {
- lines *Lines
+ line *Line
index int
+ lines *Lines
}
func NewLinesLexer(lines *Lines) *LinesLexer {
- return &LinesLexer{lines, 0}
+ llex := LinesLexer{nil, 0, lines}
+ llex.setIndex(0)
+ return &llex
}
// CurrentLine returns the line that the lexer is currently looking at.
-// If it is at the end of file, the line number of the line is EOF.
+// For the EOF, a virtual line with line number "EOF" is returned.
func (llex *LinesLexer) CurrentLine() *Line {
- if llex.index < llex.lines.Len() {
- return llex.lines.Lines[llex.index]
+ if llex.line != nil {
+ return llex.line
}
return NewLineEOF(llex.lines.Filename)
}
@@ -26,20 +29,20 @@ func (llex *LinesLexer) PreviousLine() *
}
func (llex *LinesLexer) EOF() bool {
- return !(llex.index < llex.lines.Len())
+ return llex.line == nil
}
-// Skip skips the current line and returns true.
+// Skip skips the current line.
func (llex *LinesLexer) Skip() bool {
if llex.EOF() {
return false
}
- llex.index++
+ llex.next()
return true
}
func (llex *LinesLexer) Undo() {
- llex.index--
+ llex.setIndex(llex.index - 1)
}
func (llex *LinesLexer) NextRegexp(re regex.Pattern) []string {
@@ -48,8 +51,8 @@ func (llex *LinesLexer) NextRegexp(re re
}
if !llex.EOF() {
- if m := match(llex.lines.Lines[llex.index].Text, re); m != nil {
- llex.index++
+ if m := match(llex.line.Text, re); m != nil {
+ llex.next()
return m
}
}
@@ -65,19 +68,19 @@ func (llex *LinesLexer) SkipPrefix(prefi
defer trace.Call2(llex.CurrentLine().Text, prefix)()
}
- if !llex.EOF() && hasPrefix(llex.lines.Lines[llex.index].Text, prefix) {
- llex.Skip()
+ if !llex.EOF() && hasPrefix(llex.line.Text, prefix) {
+ llex.next()
return true
}
return false
}
-func (llex *LinesLexer) SkipString(text string) bool {
+func (llex *LinesLexer) SkipText(text string) bool {
if trace.Tracing {
defer trace.Call2(llex.CurrentLine().Text, text)()
}
- if !llex.EOF() && llex.lines.Lines[llex.index].Text == text {
+ if !llex.EOF() && llex.line.Text == text {
llex.Skip()
return true
}
@@ -85,7 +88,7 @@ func (llex *LinesLexer) SkipString(text
}
func (llex *LinesLexer) SkipEmptyOrNote() bool {
- if llex.SkipString("") {
+ if llex.SkipText("") {
return true
}
@@ -106,13 +109,24 @@ func (llex *LinesLexer) SkipEmptyOrNote(
}
func (llex *LinesLexer) SkipContainsOrWarn(text string) bool {
- result := llex.SkipString(text)
+ result := llex.SkipText(text)
if !result {
llex.CurrentLine().Warnf("This line should contain the following text: %s", text)
}
return result
}
+func (llex *LinesLexer) setIndex(index int) {
+ llex.index = index
+ if index < llex.lines.Len() {
+ llex.line = llex.lines.Lines[index]
+ } else {
+ llex.line = nil
+ }
+}
+
+func (llex *LinesLexer) next() { llex.setIndex(llex.index + 1) }
+
// MkLinesLexer records the state when checking a list of Makefile lines from top to bottom.
type MkLinesLexer struct {
mklines *MkLines
@@ -133,7 +147,7 @@ func (mlex *MkLinesLexer) CurrentMkLine(
func (mlex *MkLinesLexer) SkipIf(pred func(mkline *MkLine) bool) bool {
if !mlex.EOF() && pred(mlex.CurrentMkLine()) {
- mlex.Skip()
+ mlex.next()
return true
}
return false
Index: pkgsrc/pkgtools/pkglint/files/lines.go
diff -u pkgsrc/pkgtools/pkglint/files/lines.go:1.9 pkgsrc/pkgtools/pkglint/files/lines.go:1.10
--- pkgsrc/pkgtools/pkglint/files/lines.go:1.9 Sat Nov 2 16:37:48 2019
+++ pkgsrc/pkgtools/pkglint/files/lines.go Sat Nov 23 23:35:56 2019
@@ -2,17 +2,16 @@ package pkglint
import (
"netbsd.org/pkglint/regex"
- "path"
)
type Lines struct {
- Filename string
- BaseName string
+ Filename Path
+ BaseName string // TODO: consider converting to Path
Lines []*Line
}
-func NewLines(filename string, lines []*Line) *Lines {
- return &Lines{filename, path.Base(filename), lines}
+func NewLines(filename Path, lines []*Line) *Lines {
+ return &Lines{filename, filename.Base(), lines}
}
func (ls *Lines) Len() int { return len(ls.Lines) }
Index: pkgsrc/pkgtools/pkglint/files/mkline.go
diff -u pkgsrc/pkgtools/pkglint/files/mkline.go:1.63 pkgsrc/pkgtools/pkglint/files/mkline.go:1.64
--- pkgsrc/pkgtools/pkglint/files/mkline.go:1.63 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/mkline.go Sat Nov 23 23:35:56 2019
@@ -4,7 +4,6 @@ import (
"fmt"
"netbsd.org/pkglint/regex"
"netbsd.org/pkglint/textproc"
- "path"
"strings"
)
@@ -60,7 +59,7 @@ type mkLineInclude struct {
mustExist bool // for .sinclude, nonexistent files are ignored
sys bool // whether the include uses <file.mk> (very rare) instead of "file.mk"
indent string // the space between the leading "." and the directive
- includedFile string // the text between the <brackets> or "quotes"
+ includedFile Path // the text between the <brackets> or "quotes"
conditionalVars []string // variables on which this inclusion depends (filled in later, as needed)
}
@@ -277,12 +276,12 @@ func (mkline *MkLine) SetHasElseBranch(e
func (mkline *MkLine) MustExist() bool { return mkline.data.(*mkLineInclude).mustExist }
-func (mkline *MkLine) IncludedFile() string { return mkline.data.(*mkLineInclude).includedFile }
+func (mkline *MkLine) IncludedFile() Path { return mkline.data.(*mkLineInclude).includedFile }
// IncludedFileFull returns the path to the included file, relative to the
// current working directory.
-func (mkline *MkLine) IncludedFileFull() string {
- return cleanpath(path.Join(path.Dir(mkline.Filename), mkline.IncludedFile()))
+func (mkline *MkLine) IncludedFileFull() Path {
+ return cleanpath(mkline.Filename.Dir().JoinClean(mkline.IncludedFile())) // FIXME: JoinNoClean?
}
func (mkline *MkLine) Targets() string { return mkline.data.(mkLineDependency).targets }
@@ -554,31 +553,31 @@ func (*MkLine) WithoutMakeVariables(valu
return valueNovar.String()
}
-func (mkline *MkLine) ResolveVarsInRelativePath(relativePath string) string {
- if !contains(relativePath, "$") {
+func (mkline *MkLine) ResolveVarsInRelativePath(relativePath Path) Path {
+ if !containsVarRef(relativePath.String()) {
return cleanpath(relativePath)
}
- var basedir string
+ var basedir Path
if G.Pkg != nil {
basedir = G.Pkg.File(".")
} else {
- basedir = path.Dir(mkline.Filename)
+ basedir = mkline.Filename.Dir()
}
tmp := relativePath
- if contains(tmp, "PKGSRCDIR") {
+ if tmp.ContainsText("PKGSRCDIR") {
pkgsrcdir := relpath(basedir, G.Pkgsrc.File("."))
if G.Testing {
// Relative pkgsrc paths usually only contain two or three levels.
// A possible reason for reaching this assertion is a pkglint unit test
// that uses t.NewMkLines instead of the correct t.SetUpFileMkLines.
- assertf(!contains(pkgsrcdir, "../../../../.."),
+ assertf(!pkgsrcdir.ContainsPath("../../../../.."),
"Relative path %q for %q is too deep below the pkgsrc root %q.",
pkgsrcdir, basedir, G.Pkgsrc.File("."))
}
- tmp = strings.Replace(tmp, "${PKGSRCDIR}", pkgsrcdir, -1)
+ tmp = tmp.Replace("${PKGSRCDIR}", pkgsrcdir.String())
}
// Strictly speaking, the .CURDIR should be replaced with the basedir.
@@ -586,7 +585,7 @@ func (mkline *MkLine) ResolveVarsInRelat
// path, this would produce diagnostics that "this relative path must not
// be absolute". Since ${.CURDIR} is usually used in package Makefiles and
// followed by "../.." anyway, the exact directory doesn't matter.
- tmp = strings.Replace(tmp, "${.CURDIR}", ".", -1)
+ tmp = tmp.Replace("${.CURDIR}", ".")
// TODO: Add test for exists(${.PARSEDIR}/file).
// TODO: Add test for evaluating ${.PARSEDIR} in an included package.
@@ -595,12 +594,12 @@ func (mkline *MkLine) ResolveVarsInRelat
// This is the only practically relevant use case since the category
// directories don't contain any *.mk files that could be included.
// TODO: Add test that suggests ${.PARSEDIR} in .include to be omitted.
- tmp = strings.Replace(tmp, "${.PARSEDIR}", ".", -1)
+ tmp = tmp.Replace("${.PARSEDIR}", ".")
- replaceLatest := func(varuse, category string, pattern regex.Pattern, replacement string) {
- if contains(tmp, varuse) {
+ replaceLatest := func(varuse string, category Path, pattern regex.Pattern, replacement string) {
+ if tmp.ContainsText(varuse) {
latest := G.Pkgsrc.Latest(category, pattern, replacement)
- tmp = strings.Replace(tmp, varuse, latest, -1)
+ tmp = tmp.Replace(varuse, latest)
}
}
@@ -617,14 +616,14 @@ func (mkline *MkLine) ResolveVarsInRelat
// XXX: Even if these variables are defined indirectly,
// pkglint should be able to resolve them properly.
// There is already G.Pkg.Value, maybe that can be used here.
- tmp = strings.Replace(tmp, "${FILESDIR}", G.Pkg.Filesdir, -1)
- tmp = strings.Replace(tmp, "${PKGDIR}", G.Pkg.Pkgdir, -1)
+ tmp = tmp.Replace("${FILESDIR}", G.Pkg.Filesdir.String())
+ tmp = tmp.Replace("${PKGDIR}", G.Pkg.Pkgdir.String())
}
tmp = cleanpath(tmp)
if trace.Tracing && relativePath != tmp {
- trace.Step2("resolveVarsInRelativePath: %q => %q", relativePath, tmp)
+ trace.Stepf("resolveVarsInRelativePath: %q => %q", relativePath, tmp)
}
return tmp
}
@@ -820,7 +819,7 @@ func (mkline *MkLine) ForEachUsed(action
searchIn(mkline.Sources(), VucLoadTime)
case mkline.IsInclude():
- searchIn(mkline.IncludedFile(), VucLoadTime)
+ searchIn(mkline.IncludedFile().String(), VucLoadTime)
}
}
@@ -1053,7 +1052,10 @@ type indentationLevel struct {
// pkglint will happily accept .include "fname" in both the then and
// the else branch. This is ok since the primary job of this file list
// is to prevent wrong pkglint warnings about missing files.
- checkedFiles []string
+ checkedFiles []Path
+
+ // whether the line is a multiple-inclusion guard
+ guard bool
}
func (ind *Indentation) IsEmpty() bool {
@@ -1085,9 +1087,9 @@ func (ind *Indentation) Pop() {
ind.levels = ind.levels[:len(ind.levels)-1]
}
-func (ind *Indentation) Push(mkline *MkLine, indent int, condition string) {
+func (ind *Indentation) Push(mkline *MkLine, indent int, args string, guard bool) {
assert(mkline.IsDirective())
- ind.levels = append(ind.levels, indentationLevel{mkline, indent, condition, nil, nil})
+ ind.levels = append(ind.levels, indentationLevel{mkline, indent, args, nil, nil, guard})
}
// AddVar remembers that the current indentation depends on the given variable,
@@ -1121,12 +1123,12 @@ func (ind *Indentation) DependsOn(varnam
}
// IsConditional returns whether the current line depends on evaluating
-// any variable in an .if or .elif expression or from a .for loop.
+// any .if or .elif expression, or is inside a .for loop.
//
// Variables named *_MK are excluded since they are usually not interesting.
func (ind *Indentation) IsConditional() bool {
for _, level := range ind.levels {
- if len(level.conditionalVars) > 0 {
+ if !level.guard {
return true
}
}
@@ -1155,14 +1157,14 @@ func (ind *Indentation) Args() string {
return ind.top().args
}
-func (ind *Indentation) AddCheckedFile(filename string) {
+func (ind *Indentation) AddCheckedFile(filename Path) {
top := ind.top()
top.checkedFiles = append(top.checkedFiles, filename)
}
// HasExists returns whether the given filename has been tested in an
// exists(filename) condition and thus may or may not exist.
-func (ind *Indentation) HasExists(filename string) bool {
+func (ind *Indentation) HasExists(filename Path) bool {
for _, level := range ind.levels {
for _, levelFilename := range level.checkedFiles {
if filename == levelFilename {
@@ -1177,13 +1179,16 @@ func (ind *Indentation) TrackBefore(mkli
if !mkline.IsDirective() {
return
}
- if trace.Tracing {
- trace.Stepf("Indentation before line %s: %s", mkline.Linenos(), ind)
- }
- switch mkline.Directive() {
+ directive := mkline.Directive()
+ switch directive {
case "for", "if", "ifdef", "ifndef":
- ind.Push(mkline, ind.Depth(mkline.Directive()), mkline.Args())
+ guard := false
+ if directive == "if" {
+ cond := mkline.Cond()
+ guard = cond != nil && cond.Not != nil && hasSuffix(cond.Not.Defined, "_MK")
+ }
+ ind.Push(mkline, ind.Depth(directive), mkline.Args(), guard)
}
}
@@ -1197,11 +1202,8 @@ func (ind *Indentation) TrackAfter(mklin
switch directive {
case "if":
- cond := mkline.Cond()
-
// For multiple-inclusion guards, the indentation stays at the same level.
- guard := cond != nil && cond.Not != nil && hasSuffix(cond.Not.Defined, "_MK")
- if !guard {
+ if !ind.top().guard {
ind.top().depth += 2
}
@@ -1237,17 +1239,13 @@ func (ind *Indentation) TrackAfter(mklin
cond.Walk(&MkCondCallback{
Call: func(name string, arg string) {
if name == "exists" {
- ind.AddCheckedFile(arg)
+ ind.AddCheckedFile(NewPath(arg))
}
}})
}
-
- if trace.Tracing {
- trace.Stepf("Indentation after line %s: %s", mkline.Linenos(), ind)
- }
}
-func (ind *Indentation) CheckFinish(filename string) {
+func (ind *Indentation) CheckFinish(filename Path) {
if ind.IsEmpty() {
return
}
@@ -1277,7 +1275,7 @@ var (
VarparamBytes = textproc.NewByteSet("A-Za-z_0-9#*+---./[")
)
-func MatchMkInclude(text string) (m bool, indentation, directive, filename string) {
+func MatchMkInclude(text string) (m bool, indentation, directive string, filename Path) {
lexer := textproc.NewLexer(text)
if lexer.SkipByte('.') {
indentation = lexer.NextHspace()
@@ -1291,7 +1289,7 @@ func MatchMkInclude(text string) (m bool
// Note: strictly speaking, the full MkVarUse would have to be parsed
// here. But since these usually don't contain double quotes, it has
// worked fine up to now.
- filename = lexer.NextBytesFunc(func(c byte) bool { return c != '"' })
+ filename = NewPath(lexer.NextBytesFunc(func(c byte) bool { return c != '"' }))
if filename != "" && lexer.SkipByte('"') {
lexer.NextHspace()
if lexer.EOF() {
Index: pkgsrc/pkgtools/pkglint/files/mkline_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mkline_test.go:1.71 pkgsrc/pkgtools/pkglint/files/mkline_test.go:1.72
--- pkgsrc/pkgtools/pkglint/files/mkline_test.go:1.71 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/mkline_test.go Sat Nov 23 23:35:56 2019
@@ -503,7 +503,7 @@ func (s *Suite) Test_MkLine_ResolveVarsI
MkCvsID)
mkline := mklines.mklines[0]
- test := func(before string, after string) {
+ test := func(before Path, after Path) {
t.CheckEquals(mkline.ResolveVarsInRelativePath(before), after)
}
@@ -1129,7 +1129,7 @@ func (s *Suite) Test_MkLine_VariableNeed
"")
// Just for branch coverage.
- trace.Tracing = false
+ t.DisableTracing()
MkLineChecker{mklines, mklines.mklines[2]}.Check()
t.CheckOutputEmpty()
@@ -1265,7 +1265,7 @@ func (s *Suite) Test_Indentation(c *chec
t.CheckEquals(ind.Depth("if"), 0)
t.CheckEquals(ind.DependsOn("VARNAME"), false)
- ind.Push(mkline, 2, "")
+ ind.Push(mkline, 2, "", false)
t.CheckEquals(ind.Depth("if"), 2)
t.CheckEquals(ind.Depth("endfor"), 0)
@@ -1280,7 +1280,7 @@ func (s *Suite) Test_Indentation(c *chec
t.CheckEquals(ind.DependsOn("LEVEL1.VAR1"), true)
t.CheckEquals(ind.DependsOn("OTHER_VAR"), false)
- ind.Push(mkline, 2, "")
+ ind.Push(mkline, 2, "", false)
ind.AddVar("LEVEL2.VAR")
@@ -1308,7 +1308,7 @@ func (s *Suite) Test_Indentation__realis
".if 1",
". if !defined(GUARD_MK)",
". for var in 1 2 3",
- ". if !defined(GUARD_MK)",
+ ". if !defined(GUARD_MK)", // well, not entirely realistic
". if 3",
". endif",
". endif",
@@ -1322,43 +1322,29 @@ func (s *Suite) Test_Indentation__realis
". endfor",
".endif")
- t.EnableTracingToLog()
-
mklines.ForEach(func(mkline *MkLine) {})
- t.CheckOutputLinesMatching(`Indentation`,
- "TRACE: Indentation before line 3: []",
- "TRACE: Indentation after line 3: [2]",
- "TRACE: Indentation before line 4: [2]",
- "TRACE: Indentation after line 4: [2 2]",
- "TRACE: Indentation before line 5: [2 2]",
- "TRACE: Indentation after line 5: [2 2 4]",
- "TRACE: Indentation before line 6: [2 2 4]",
- "TRACE: Indentation after line 6: [2 2 4 4]",
- "TRACE: Indentation before line 7: [2 2 4 4]",
- "TRACE: Indentation after line 7: [2 2 4 4 6]",
- "TRACE: Indentation before line 8: [2 2 4 4 6]",
- "TRACE: Indentation after line 8: [2 2 4 4]",
- "TRACE: Indentation before line 9: [2 2 4 4]",
- "TRACE: Indentation after line 9: [2 2 4]",
- "TRACE: Indentation before line 10: [2 2 4]",
- "TRACE: Indentation after line 10: [2 2]",
- "TRACE: Indentation before line 11: [2 2]",
- "TRACE: Indentation after line 11: [2]",
- "TRACE: Indentation before line 12: [2]",
- "TRACE: Indentation after line 12: [2]",
- "TRACE: Indentation before line 13: [2]",
- "TRACE: Indentation after line 13: [2 4]",
- "TRACE: Indentation before line 14: [2 4]",
- "TRACE: Indentation after line 14: [2]",
- "TRACE: Indentation before line 15: [2]",
- "TRACE: Indentation after line 15: [2]",
- "TRACE: Indentation before line 16: [2]",
- "TRACE: Indentation after line 16: [2 4]",
- "TRACE: Indentation before line 17: [2 4]",
- "TRACE: Indentation after line 17: [2]",
- "TRACE: Indentation before line 18: [2]",
- "TRACE: Indentation after line 18: []")
+ t.CheckOutputEmpty()
+}
+
+func (s *Suite) Test_Indentation_String(c *check.C) {
+ t := s.Init(c)
+
+ mklines := t.NewMkLines("filename.mk",
+ ".if exists(/bin)",
+ "# probably POSIX",
+ ".endif")
+ var str string
+
+ mklines.ForEach(func(mkline *MkLine) {
+ if mkline.IsComment() {
+ t.CheckEquals(mklines.indentation.IsConditional(), true)
+ t.Check(mklines.indentation.Varnames(), check.IsNil)
+ str = mklines.indentation.String()
+ }
+ })
+
+ t.CheckEquals(str, "[2]")
}
func (s *Suite) Test_Indentation_RememberUsedVariables(c *check.C) {
@@ -1440,7 +1426,7 @@ func (s *Suite) Test_Indentation_TrackAf
func (s *Suite) Test_MatchMkInclude(c *check.C) {
t := s.Init(c)
- test := func(input, expectedIndent, expectedDirective, expectedFilename, expectedComment string) {
+ test := func(input, expectedIndent, expectedDirective string, expectedFilename Path, expectedComment string) {
splitResult := NewMkLineParser().split(nil, input, true)
m, indent, directive, args := MatchMkInclude(splitResult.main)
t.CheckDeepEquals(
Index: pkgsrc/pkgtools/pkglint/files/mklinechecker.go
diff -u pkgsrc/pkgtools/pkglint/files/mklinechecker.go:1.53 pkgsrc/pkgtools/pkglint/files/mklinechecker.go:1.54
--- pkgsrc/pkgtools/pkglint/files/mklinechecker.go:1.53 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/mklinechecker.go Sat Nov 23 23:35:56 2019
@@ -3,9 +3,6 @@ package pkglint
import (
"netbsd.org/pkglint/regex"
"netbsd.org/pkglint/textproc"
- "os"
- "path"
- "path/filepath"
"strconv"
"strings"
)
@@ -1089,9 +1086,9 @@ func (ck MkLineChecker) checkVarassignRi
categories := mkline.ValueFields(mkline.Value())
actual := categories[0]
- expected := path.Base(path.Dir(path.Dir(mkline.Filename)))
+ expected := mkline.Filename.Dir().Dir().Base()
if expected == "." {
- expected = path.Base(path.Dir(path.Dir(G.Pkgsrc.ToRel(mkline.Filename))))
+ expected = G.Pkgsrc.ToRel(mkline.Filename).Dir().Dir().Base()
}
if expected == "wip" || actual == expected {
return
@@ -1194,7 +1191,7 @@ func (ck MkLineChecker) checkVarassignMi
}
for _, dir := range mkline.ValueFields(mkline.Value()) {
- if G.Pkg.Plist.Dirs[dir] != nil {
+ if G.Pkg.Plist.Dirs[NewPath(dir)] != nil {
mkline.Notef("The directory %q is redundant in %s.", dir, varname)
mkline.Explain(
"This package defines AUTO_MKDIR, and the directory is contained in the PLIST.",
@@ -1308,12 +1305,12 @@ func (ck MkLineChecker) checkInclude() {
includedFile := mkline.IncludedFile()
mustExist := mkline.MustExist()
if trace.Tracing {
- trace.Step2("includingFile=%s includedFile=%s", mkline.Filename, includedFile)
+ trace.Stepf("includingFile=%s includedFile=%s", mkline.Filename, includedFile)
}
ck.CheckRelativePath(includedFile, mustExist)
switch {
- case hasSuffix(includedFile, "/Makefile"):
+ case includedFile.HasBase("Makefile"):
mkline.Errorf("Other Makefiles must not be included directly.")
mkline.Explain(
"To include portions of another Makefile, extract the common parts",
@@ -1329,25 +1326,25 @@ func (ck MkLineChecker) checkInclude() {
fix.Apply()
}
- case hasSuffix(includedFile, "pkgtools/x11-links/buildlink3.mk"):
+ case includedFile.HasSuffixPath("pkgtools/x11-links/buildlink3.mk"):
fix := mkline.Autofix()
fix.Errorf("%s must not be included directly. Include \"../../mk/x11.buildlink3.mk\" instead.", includedFile)
fix.Replace("pkgtools/x11-links/buildlink3.mk", "mk/x11.buildlink3.mk")
fix.Apply()
- case hasSuffix(includedFile, "graphics/jpeg/buildlink3.mk"):
+ case includedFile.HasSuffixPath("graphics/jpeg/buildlink3.mk"):
fix := mkline.Autofix()
fix.Errorf("%s must not be included directly. Include \"../../mk/jpeg.buildlink3.mk\" instead.", includedFile)
fix.Replace("graphics/jpeg/buildlink3.mk", "mk/jpeg.buildlink3.mk")
fix.Apply()
- case hasSuffix(includedFile, "/intltool/buildlink3.mk"):
+ case includedFile.HasSuffixPath("intltool/buildlink3.mk"):
mkline.Warnf("Please write \"USE_TOOLS+= intltool\" instead of this line.")
- case hasSuffix(includedFile, "/builtin.mk"):
+ case includedFile.HasSuffixText("/builtin.mk"): // TODO: maybe HasSuffixPath
if mkline.Basename != "hacks.mk" && !mkline.HasRationale() {
fix := mkline.Autofix()
- fix.Errorf("%s must not be included directly. Include \"%s/buildlink3.mk\" instead.", includedFile, path.Dir(includedFile))
+ fix.Errorf("%s must not be included directly. Include \"%s/buildlink3.mk\" instead.", includedFile, includedFile.Dir())
fix.Replace("builtin.mk", "buildlink3.mk")
fix.Apply()
}
@@ -1370,28 +1367,28 @@ func (ck MkLineChecker) checkDirectiveIn
// CheckRelativePath checks a relative path that leads to the directory of another package
// or to a subdirectory thereof or a file within there.
-func (ck MkLineChecker) CheckRelativePath(relativePath string, mustExist bool) {
+func (ck MkLineChecker) CheckRelativePath(relativePath Path, mustExist bool) {
if trace.Tracing {
defer trace.Call(relativePath, mustExist)()
}
mkline := ck.MkLine
- if !G.Wip && contains(relativePath, "/wip/") {
+ if !G.Wip && relativePath.ContainsPath("wip") {
mkline.Errorf("A main pkgsrc package must not depend on a pkgsrc-wip package.")
}
resolvedPath := mkline.ResolveVarsInRelativePath(relativePath)
- if containsVarRef(resolvedPath) {
+ if containsVarRef(resolvedPath.String()) {
return
}
- if filepath.IsAbs(resolvedPath) {
+ if resolvedPath.IsAbs() {
mkline.Errorf("The path %q must be relative.", resolvedPath)
return
}
- abs := joinPath(path.Dir(mkline.Filename), resolvedPath)
- if _, err := os.Stat(abs); err != nil {
+ abs := mkline.Filename.Dir().JoinNoClean(resolvedPath)
+ if !abs.Exists() {
if mustExist && !ck.MkLines.indentation.HasExists(resolvedPath) {
mkline.Errorf("Relative path %q does not exist.", resolvedPath)
}
@@ -1399,21 +1396,21 @@ func (ck MkLineChecker) CheckRelativePat
}
switch {
- case !hasPrefix(resolvedPath, "../"):
+ case !resolvedPath.HasPrefixPath(".."):
break
- case hasPrefix(resolvedPath, "../../mk/"):
+ case resolvedPath.HasPrefixPath("../../mk"):
// From a package to the infrastructure.
- case matches(resolvedPath, `^\.\./\.\./[^./][^/]*/[^/]`):
+ case matches(resolvedPath.String(), `^\.\./\.\./[^./][^/]*/[^/]`):
// From a package to another package.
- case hasPrefix(resolvedPath, "../mk/") && relpath(path.Dir(mkline.Filename), G.Pkgsrc.File(".")) == "..":
+ case resolvedPath.HasPrefixPath("../mk") && G.Pkgsrc.ToRel(mkline.Filename).Count() == 2:
// For category Makefiles.
// TODO: Or from a pkgsrc wip package to wip/mk.
- case matches(resolvedPath, `^\.\./[^./][^/]*/[^/]`):
- if G.Wip && contains(resolvedPath, "/mk/") {
+ case matches(resolvedPath.String(), `^\.\./[^./][^/]*/[^/]`):
+ if G.Wip && resolvedPath.ContainsPath("mk") {
mkline.Warnf("References to the pkgsrc-wip infrastructure should look like \"../../wip/mk\", not \"../mk\".")
} else {
mkline.Warnf("References to other packages should look like \"../../category/package\", not \"../package\".")
@@ -1433,16 +1430,16 @@ func (ck MkLineChecker) CheckRelativePat
//
// When used in .include directives, the relative package directories must be written
// with the leading ../.. anyway, so the benefit might not be too big at all.
-func (ck MkLineChecker) CheckRelativePkgdir(pkgdir string) {
+func (ck MkLineChecker) CheckRelativePkgdir(pkgdir Path) {
if trace.Tracing {
- defer trace.Call1(pkgdir)()
+ defer trace.Call(pkgdir)()
}
mkline := ck.MkLine
ck.CheckRelativePath(pkgdir+"/Makefile", true)
pkgdir = mkline.ResolveVarsInRelativePath(pkgdir)
- if !matches(pkgdir, `^\.\./\.\./([^./][^/]*/[^./][^/]*)$`) && !containsVarRef(pkgdir) {
+ if !matches(pkgdir.String(), `^\.\./\.\./([^./][^/]*/[^./][^/]*)$`) && !containsVarRef(pkgdir.String()) {
mkline.Warnf("%q is not a valid relative package directory.", pkgdir)
mkline.Explain(
"A relative pathname always starts with \"../../\", followed",
@@ -1722,11 +1719,30 @@ func (ck MkLineChecker) checkCompareVarS
ck.checkVartype(varname, opUseCompare, value, "")
if varname == "PKGSRC_COMPILER" {
- ck.MkLine.Warnf("Use ${PKGSRC_COMPILER:%s%s} instead of the %s operator.", condStr(op == "==", "M", "N"), value, op)
- ck.MkLine.Explain(
- "The PKGSRC_COMPILER can be a list of chained compilers, e.g. \"ccache distcc clang\".",
- "Therefore, comparing it using == or != leads to wrong results in these cases.")
+ ck.checkCompareVarStrCompiler(op, value)
+ }
+}
+
+func (ck MkLineChecker) checkCompareVarStrCompiler(op string, value string) {
+ if !matches(value, `^\w+$`) {
+ return
}
+
+ // It would be nice if original text of the whole comparison expression
+ // were available at this point, to avoid guessing how much whitespace
+ // the package author really used.
+
+ matchOp := condStr(op == "==", "M", "N")
+
+ fix := ck.MkLine.Autofix()
+ fix.Errorf("Use ${PKGSRC_COMPILER:%s%s} instead of the %s operator.", matchOp, value, op)
+ fix.Explain(
+ "The PKGSRC_COMPILER can be a list of chained compilers, e.g. \"ccache distcc clang\".",
+ "Therefore, comparing it using == or != leads to wrong results in these cases.")
+ fix.Replace("${PKGSRC_COMPILER} "+op+" "+value, "${PKGSRC_COMPILER:"+matchOp+value+"}")
+ fix.Replace("${PKGSRC_COMPILER} "+op+" \""+value+"\"", "${PKGSRC_COMPILER:"+matchOp+value+"}")
+ fix.Anyway()
+ fix.Apply()
}
func (ck MkLineChecker) checkDirectiveFor(forVars map[string]bool, indentation *Indentation) {
Index: pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go:1.48 pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go:1.49
--- pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go:1.48 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/mklinechecker_test.go Sat Nov 23 23:35:56 2019
@@ -102,6 +102,9 @@ func (s *Suite) Test_MkLineChecker_Check
t.CheckOutputLines(
"WARN: x11/xkeyboard-config/Makefile:3: "+
"Invalid part \"/xkbcomp\" after variable name \"${XKBBASE}\".",
+ // TODO: Avoid this duplicate diagnostic.
+ "WARN: x11/xkeyboard-config/Makefile:3: "+
+ "Invalid part \"/xkbcomp\" after variable name \"${XKBBASE}\".",
"WARN: x11/xkeyboard-config/Makefile:3: XKBBASE is used but not defined.")
}
@@ -2413,7 +2416,7 @@ func (s *Suite) Test_MkLineChecker_Check
t.CreateFileLines("other/package/Makefile")
- test := func(relativePkgdir string, diagnostics ...string) {
+ test := func(relativePkgdir Path, diagnostics ...string) {
// Must be in the filesystem because of directory references.
mklines := t.SetUpFileMkLines("category/package/Makefile",
"# dummy")
@@ -2614,7 +2617,7 @@ func (s *Suite) Test_MkLineChecker_check
test(".if ${PKGSRC_COMPILER} == \"msvc\"",
"WARN: filename.mk:1: \"msvc\" is not valid for PKGSRC_COMPILER. "+
"Use one of { ccache ccc clang distcc f2c gcc hp icc ido mipspro mipspro-ucode pcc sunpro xlc } instead.",
- "WARN: filename.mk:1: Use ${PKGSRC_COMPILER:Mmsvc} instead of the == operator.")
+ "ERROR: filename.mk:1: Use ${PKGSRC_COMPILER:Mmsvc} instead of the == operator.")
test(".if ${PKG_LIBTOOL:Mlibtool}",
"NOTE: filename.mk:1: PKG_LIBTOOL should be compared using == instead of matching against \":Mlibtool\".",
@@ -2668,10 +2671,11 @@ func (s *Suite) Test_MkLineChecker_check
"WARN: filename.mk:1: VAR is used but not defined.")
test(".if ${MASTER_SITES:Mftp://*} == \"ftp://netbsd.org/\"",
+ // FIXME: duplicate diagnostic, see MkParser.MkCond.
+ "WARN: filename.mk:1: Invalid variable modifier \"//*\" for \"MASTER_SITES\".",
"WARN: filename.mk:1: Invalid variable modifier \"//*\" for \"MASTER_SITES\".",
"WARN: filename.mk:1: \"ftp\" is not a valid URL.",
- "WARN: filename.mk:1: MASTER_SITES should not be used at load time in any file.",
- "WARN: filename.mk:1: Invalid variable modifier \"//*\" for \"MASTER_SITES\".")
+ "WARN: filename.mk:1: MASTER_SITES should not be used at load time in any file.")
}
func (s *Suite) Test_MkLineChecker_checkDirectiveCond__tracing(c *check.C) {
@@ -2703,7 +2707,7 @@ func (s *Suite) Test_MkLineChecker_check
// Don't warn about unknown shell command "cc".
t.CheckOutputLines(
- "WARN: security/openssl/Makefile:2: Use ${PKGSRC_COMPILER:Mgcc} instead of the == operator.")
+ "ERROR: security/openssl/Makefile:2: Use ${PKGSRC_COMPILER:Mgcc} instead of the == operator.")
}
// The :N modifier filters unwanted values. After this filter, any variable value
@@ -2746,8 +2750,8 @@ func (s *Suite) Test_MkLineChecker_check
mklines.Check()
t.CheckOutputLines(
- "WARN: Makefile:2: Use ${PKGSRC_COMPILER:Mclang} instead of the == operator.",
- "WARN: Makefile:3: Use ${PKGSRC_COMPILER:Ngcc} instead of the != operator.")
+ "ERROR: Makefile:2: Use ${PKGSRC_COMPILER:Mclang} instead of the == operator.",
+ "ERROR: Makefile:3: Use ${PKGSRC_COMPILER:Ngcc} instead of the != operator.")
}
func (s *Suite) Test_MkLineChecker_checkDirectiveCondEmpty(c *check.C) {
@@ -3062,6 +3066,62 @@ func (s *Suite) Test_MkLineChecker_check
t.CheckOutputEmpty()
}
+func (s *Suite) Test_MkLineChecker_checkCompareVarStrCompiler(c *check.C) {
+ t := s.Init(c)
+
+ t.SetUpVartypes()
+ t.Chdir(".")
+
+ test := func(cond string, diagnostics ...string) {
+ mklines := t.SetUpFileMkLines("filename.mk",
+ MkCvsID,
+ "",
+ ".if "+cond,
+ ".endif")
+
+ t.SetUpCommandLine("-Wall")
+ mklines.Check()
+ t.SetUpCommandLine("-Wall", "--autofix")
+ mklines.Check()
+
+ t.CheckOutput(diagnostics)
+ }
+
+ test(
+ "${PKGSRC_COMPILER} == gcc",
+
+ "ERROR: filename.mk:3: "+
+ "Use ${PKGSRC_COMPILER:Mgcc} instead of the == operator.",
+ "AUTOFIX: filename.mk:3: "+
+ "Replacing \"${PKGSRC_COMPILER} == gcc\" "+
+ "with \"${PKGSRC_COMPILER:Mgcc}\".")
+
+ // No autofix because of missing whitespace.
+ // TODO: Provide the autofix regardless of the whitespace.
+ test(
+ "${PKGSRC_COMPILER}==gcc",
+
+ "ERROR: filename.mk:3: "+
+ "Use ${PKGSRC_COMPILER:Mgcc} instead of the == operator.")
+
+ // The comparison value can be with or without quotes.
+ test(
+ "${PKGSRC_COMPILER} == \"gcc\"",
+
+ "ERROR: filename.mk:3: "+
+ "Use ${PKGSRC_COMPILER:Mgcc} instead of the == operator.",
+ "AUTOFIX: filename.mk:3: "+
+ "Replacing \"${PKGSRC_COMPILER} == \\\"gcc\\\"\" "+
+ "with \"${PKGSRC_COMPILER:Mgcc}\".")
+
+ // No warning because it is not obvious what is meant here.
+ // This case probably doesn't occur in practice.
+ test(
+ "${PKGSRC_COMPILER} == \"distcc gcc\"",
+
+ nil...)
+}
+
func (s *Suite) Test_MkLineChecker_checkDirectiveFor(c *check.C) {
t := s.Init(c)
Index: pkgsrc/pkgtools/pkglint/files/shell.go
diff -u pkgsrc/pkgtools/pkglint/files/shell.go:1.48 pkgsrc/pkgtools/pkglint/files/shell.go:1.49
--- pkgsrc/pkgtools/pkglint/files/shell.go:1.48 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/shell.go Sat Nov 23 23:35:56 2019
@@ -250,7 +250,7 @@ func (scc *SimpleCommandChecker) checkAu
if m, dirname := match1(arg, `^(?:\$\{DESTDIR\})?\$\{PREFIX(?:|:Q)\}/(.*)`); m {
autoMkdirs := false
if G.Pkg != nil {
- plistLine := G.Pkg.Plist.Dirs[dirname]
+ plistLine := G.Pkg.Plist.Dirs[NewPath(dirname)]
if plistLine != nil && !containsVarRef(plistLine.Text) {
autoMkdirs = true
}
@@ -760,7 +760,7 @@ func (ck *ShellLineChecker) CheckWord(to
}
func (ck *ShellLineChecker) checkWordQuoting(token string, checkQuoting bool, time ToolTime) {
- tok := NewShTokenizer(ck.mkline.Line, token, false)
+ tok := NewShTokenizer(ck.mkline.Line, token, true)
atoms := tok.ShAtoms()
quoting := shqPlain
Index: pkgsrc/pkgtools/pkglint/files/mklineparser.go
diff -u pkgsrc/pkgtools/pkglint/files/mklineparser.go:1.3 pkgsrc/pkgtools/pkglint/files/mklineparser.go:1.4
--- pkgsrc/pkgtools/pkglint/files/mklineparser.go:1.3 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/mklineparser.go Sat Nov 23 23:35:56 2019
@@ -247,7 +247,7 @@ func (p MkLineParser) parseSysinclude(li
return nil
}
- return &MkLine{line, splitResult, &mkLineInclude{directive == "include", true, indent, includedFile, nil}}
+ return &MkLine{line, splitResult, &mkLineInclude{directive == "include", true, indent, NewPath(includedFile), nil}}
}
func (p MkLineParser) parseDependency(line *Line, splitResult mkLineSplitResult) *MkLine {
Index: pkgsrc/pkgtools/pkglint/files/mklineparser_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mklineparser_test.go:1.3 pkgsrc/pkgtools/pkglint/files/mklineparser_test.go:1.4
--- pkgsrc/pkgtools/pkglint/files/mklineparser_test.go:1.3 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/mklineparser_test.go Sat Nov 23 23:35:56 2019
@@ -543,7 +543,7 @@ func (s *Suite) Test_MkLineParser_parseI
t.CheckEquals(mkline.IsInclude(), true)
t.CheckEquals(mkline.Indent(), " ")
t.CheckEquals(mkline.MustExist(), true)
- t.CheckEquals(mkline.IncludedFile(), "../../mk/bsd.prefs.mk")
+ t.CheckEquals(mkline.IncludedFile(), NewPath("../../mk/bsd.prefs.mk"))
t.CheckEquals(mkline.IsSysinclude(), false)
}
@@ -557,7 +557,7 @@ func (s *Suite) Test_MkLineParser_parseS
t.CheckEquals(mkline.IsSysinclude(), true)
t.CheckEquals(mkline.Indent(), " ")
t.CheckEquals(mkline.MustExist(), true)
- t.CheckEquals(mkline.IncludedFile(), "subdir.mk")
+ t.CheckEquals(mkline.IncludedFile(), NewPath("subdir.mk"))
t.CheckEquals(mkline.IsInclude(), false)
}
Index: pkgsrc/pkgtools/pkglint/files/mklines.go
diff -u pkgsrc/pkgtools/pkglint/files/mklines.go:1.59 pkgsrc/pkgtools/pkglint/files/mklines.go:1.60
--- pkgsrc/pkgtools/pkglint/files/mklines.go:1.59 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/mklines.go Sat Nov 23 23:35:56 2019
@@ -70,7 +70,7 @@ func NewMkLines(lines *Lines) *MkLines {
func (mklines *MkLines) Check() {
if trace.Tracing {
- defer trace.Call1(mklines.lines.Filename)()
+ defer trace.Call(mklines.lines.Filename)()
}
// In the first pass, all additions to BUILD_DEFS and USE_TOOLS
@@ -440,7 +440,7 @@ func (mklines *MkLines) checkVarassignPl
// CheckUsedBy checks that this file (a Makefile.common) has the given
// relativeName in one of the "# used by" comments at the beginning of the file.
-func (mklines *MkLines) CheckUsedBy(relativeName string) {
+func (mklines *MkLines) CheckUsedBy(relativeName Path) {
lines := mklines.lines
if lines.Len() < 3 {
return
@@ -448,7 +448,7 @@ func (mklines *MkLines) CheckUsedBy(rela
paras := mklines.SplitToParagraphs()
- expected := "# used by " + relativeName
+ expected := "# used by " + relativeName.String()
found := false
var usedParas []*Paragraph
Index: pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go
diff -u pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go:1.59 pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go:1.60
--- pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go:1.59 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go Sat Nov 23 23:35:56 2019
@@ -498,7 +498,7 @@ func (s *Suite) Test_VartypeCheck_Enum__
"\tlike ^, *, $. In such a case, using the :M or :N modifiers is useful",
"\tand preferred.",
"",
- "WARN: module.mk:5: Use ${PKGSRC_COMPILER:Mclang} instead of the == operator.",
+ "ERROR: module.mk:5: Use ${PKGSRC_COMPILER:Mclang} instead of the == operator.",
"",
"\tThe PKGSRC_COMPILER can be a list of chained compilers, e.g. \"ccache",
"\tdistcc clang\". Therefore, comparing it using == or != leads to wrong",
@@ -1792,7 +1792,7 @@ func (s *Suite) Test_VartypeCheck_YesNoI
type VartypeCheckTester struct {
tester *Tester
basicType *BasicType
- filename string
+ filename Path
lineno int
varname string
op MkOperator
@@ -1820,7 +1820,7 @@ func (vt *VartypeCheckTester) Varname(va
vt.nextSection()
}
-func (vt *VartypeCheckTester) File(filename string) {
+func (vt *VartypeCheckTester) File(filename Path) {
vt.filename = filename
vt.lineno = 1
}
Index: pkgsrc/pkgtools/pkglint/files/mklines_test.go
diff -u pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.51 pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.52
--- pkgsrc/pkgtools/pkglint/files/mklines_test.go:1.51 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/mklines_test.go Sat Nov 23 23:35:56 2019
@@ -1069,7 +1069,7 @@ func (s *Suite) Test_MkLines_CheckUsedBy
t.SetUpCommandLine("--show-autofix")
- test := func(pkgpath string, lines []string, diagnostics []string) {
+ test := func(pkgpath Path, lines []string, diagnostics []string) {
mklines := t.NewMkLines("Makefile.common", lines...)
mklines.CheckUsedBy(pkgpath)
@@ -1155,7 +1155,7 @@ func (s *Suite) Test_MkLines_CheckUsedBy
func (s *Suite) Test_MkLines_CheckUsedBy(c *check.C) {
t := s.Init(c)
- test := func(pkgpath string, lines []string, diagnostics []string) {
+ test := func(pkgpath Path, lines []string, diagnostics []string) {
mklines := t.NewMkLines("Makefile.common", lines...)
mklines.CheckUsedBy(pkgpath)
Index: pkgsrc/pkgtools/pkglint/files/package.go
diff -u pkgsrc/pkgtools/pkglint/files/package.go:1.68 pkgsrc/pkgtools/pkglint/files/package.go:1.69
--- pkgsrc/pkgtools/pkglint/files/package.go:1.68 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/package.go Sat Nov 23 23:35:56 2019
@@ -3,7 +3,6 @@ package pkglint
import (
"netbsd.org/pkglint/pkgver"
"os"
- "path"
"strconv"
"strings"
)
@@ -17,12 +16,12 @@ const rePkgname = `^([\w\-.+]+)-(\d[.0-9
// This is necessary because variables in Makefiles may be used before they are defined,
// and such dependencies often span multiple files that are included indirectly.
type Package struct {
- dir string // The directory of the package, for resolving files
- 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
+ dir Path // The directory of the package, for resolving files
+ Pkgpath Path // e.g. "category/pkgdir"
+ Pkgdir Path // PKGDIR from the package Makefile
+ Filesdir Path // FILESDIR from the package Makefile
+ Patchdir Path // PATCHDIR from the package Makefile
+ DistinfoFile Path // DISTINFO_FILE from the package Makefile
EffectivePkgname string // PKGNAME or DISTNAME from the package Makefile, including nb13, can be empty
EffectivePkgbase string // EffectivePkgname without the version
EffectivePkgversion string // The version part of the effective PKGNAME, excluding nb13
@@ -32,7 +31,7 @@ type Package struct {
vars Scope
redundant *RedundantScope
- bl3 map[string]*MkLine // buildlink3.mk name => line; contains only buildlink3.mk files that are directly included.
+ bl3 map[Path]*MkLine // buildlink3.mk name => line; contains only buildlink3.mk files that are directly included.
// Remembers the Makefile fragments that have already been included.
// The key to the map is the filename relative to the package directory.
@@ -50,21 +49,24 @@ type Package struct {
// Files from .include lines that are nested inside .if.
// They often depend on OPSYS or on the existence of files in the build environment.
- conditionalIncludes map[string]*MkLine
+ conditionalIncludes map[Path]*MkLine
// Files from .include lines that are not nested.
// These are cross-checked with buildlink3.mk whether they are unconditional there, too.
- unconditionalIncludes map[string]*MkLine
+ unconditionalIncludes map[Path]*MkLine
IgnoreMissingPatches bool // In distinfo, don't warn about patches that cannot be found.
Once Once
}
-func NewPackage(dir string) *Package {
+func NewPackage(dir Path) *Package {
pkgpath := G.Pkgsrc.ToRel(dir)
// Package directory must be two subdirectories below the pkgsrc root.
- assert(strings.Count(pkgpath, "/") == 1)
+ // As of November 2019, it is technically possible to create packages
+ // on different levels, but that is not used at all. Therefore all
+ // relative directories are in the form "../../category/package".
+ assert(pkgpath.Count() == 2)
pkg := Package{
dir: dir,
@@ -75,10 +77,10 @@ func NewPackage(dir string) *Package {
DistinfoFile: "${PKGDIR}/distinfo", // TODO: Redundant, see the vars.Fallback below.
Plist: NewPlistContent(),
vars: NewScope(),
- bl3: make(map[string]*MkLine),
+ bl3: make(map[Path]*MkLine),
included: Once{},
- conditionalIncludes: make(map[string]*MkLine),
- unconditionalIncludes: make(map[string]*MkLine),
+ conditionalIncludes: make(map[Path]*MkLine),
+ unconditionalIncludes: make(map[Path]*MkLine),
}
pkg.vars.DefineAll(G.Pkgsrc.UserDefinedVars)
@@ -97,7 +99,7 @@ func NewPackage(dir string) *Package {
return &pkg
}
-func (pkg *Package) load() ([]string, *MkLines, *MkLines) {
+func (pkg *Package) load() ([]Path, *MkLines, *MkLines) {
// Load the package Makefile and all included files,
// to collect all used and defined variables and similar data.
mklines, allLines := pkg.loadPackageMakefile()
@@ -110,21 +112,30 @@ func (pkg *Package) load() ([]string, *M
files = append(files, dirglob(pkg.File(pkg.Pkgdir))...)
}
files = append(files, dirglob(pkg.File(pkg.Patchdir))...)
- if pkg.DistinfoFile != pkg.vars.fallback["DISTINFO_FILE"] {
+ if pkg.DistinfoFile != NewPath(pkg.vars.fallback["DISTINFO_FILE"]) {
files = append(files, pkg.File(pkg.DistinfoFile))
}
+ isRelevantMk := func(filename Path, basename string) bool {
+ if !hasPrefix(basename, "Makefile.") && !filename.HasSuffixText(".mk") {
+ return false
+ }
+ if filename.Dir().Base() == "patches" {
+ return false
+ }
+ if pkg.Pkgdir == "." {
+ return true
+ }
+ return !filename.ContainsPath(pkg.Pkgdir)
+ }
+
// Determine the used variables and PLIST directories before checking any of the Makefile fragments.
// TODO: Why is this code necessary? What effect does it have?
pkg.collectConditionalIncludes(mklines)
for _, filename := range files {
- basename := path.Base(filename)
- if (hasPrefix(basename, "Makefile.") || hasSuffix(filename, ".mk")) &&
- !matches(filename, `patch-`) &&
- !contains(filename, pkg.Pkgdir+"/") &&
- !contains(filename, pkg.Filesdir+"/") {
+ basename := filename.Base()
+ if isRelevantMk(filename, basename) {
fragmentMklines := LoadMk(filename, MustSucceed)
- fragmentMklines.collectUsedVariables()
pkg.collectConditionalIncludes(fragmentMklines)
}
if hasPrefix(basename, "PLIST") {
@@ -138,7 +149,7 @@ func (pkg *Package) load() ([]string, *M
func (pkg *Package) loadPackageMakefile() (*MkLines, *MkLines) {
filename := pkg.File("Makefile")
if trace.Tracing {
- defer trace.Call1(filename)()
+ defer trace.Call(filename)()
}
mainLines := LoadMk(filename, NotEmpty|LogErrors)
@@ -170,10 +181,10 @@ func (pkg *Package) loadPackageMakefile(
allLines.collectUsedVariables()
- pkg.Pkgdir = pkg.vars.LastValue("PKGDIR")
- pkg.DistinfoFile = pkg.vars.LastValue("DISTINFO_FILE")
- pkg.Filesdir = pkg.vars.LastValue("FILESDIR")
- pkg.Patchdir = pkg.vars.LastValue("PATCHDIR")
+ pkg.Pkgdir = NewPath(pkg.vars.LastValue("PKGDIR"))
+ pkg.DistinfoFile = NewPath(pkg.vars.LastValue("DISTINFO_FILE"))
+ pkg.Filesdir = NewPath(pkg.vars.LastValue("FILESDIR"))
+ pkg.Patchdir = NewPath(pkg.vars.LastValue("PATCHDIR"))
// See lang/php/ext.mk
if pkg.vars.IsDefinedSimilar("PHPEXT_MK") {
@@ -191,19 +202,19 @@ func (pkg *Package) loadPackageMakefile(
}
if trace.Tracing {
- trace.Step1("DISTINFO_FILE=%s", pkg.DistinfoFile)
- trace.Step1("FILESDIR=%s", pkg.Filesdir)
- trace.Step1("PATCHDIR=%s", pkg.Patchdir)
- trace.Step1("PKGDIR=%s", pkg.Pkgdir)
+ trace.Stepf("DISTINFO_FILE=%s", pkg.DistinfoFile)
+ trace.Stepf("FILESDIR=%s", pkg.Filesdir)
+ trace.Stepf("PATCHDIR=%s", pkg.Patchdir)
+ trace.Stepf("PKGDIR=%s", pkg.Pkgdir)
}
return mainLines, allLines
}
// TODO: What is allLines used for, is it still necessary? Would it be better as a field in Package?
-func (pkg *Package) parse(mklines *MkLines, allLines *MkLines, includingFileForUsedCheck string) bool {
+func (pkg *Package) parse(mklines *MkLines, allLines *MkLines, includingFileForUsedCheck Path) bool {
if trace.Tracing {
- defer trace.Call1(mklines.lines.Filename)()
+ defer trace.Call(mklines.lines.Filename)()
}
result := mklines.ForEachEnd(
@@ -217,10 +228,10 @@ func (pkg *Package) parse(mklines *MkLin
// For every included buildlink3.mk, include the corresponding builtin.mk
// automatically since the pkgsrc infrastructure does the same.
filename := mklines.lines.Filename
- if path.Base(filename) == "buildlink3.mk" {
- builtin := cleanpath(path.Dir(filename) + "/builtin.mk")
+ if filename.Base() == "buildlink3.mk" {
+ builtin := cleanpath(filename.Dir().JoinNoClean("builtin.mk"))
builtinRel := relpath(pkg.dir, builtin)
- if pkg.included.FirstTime(builtinRel) && fileExists(builtin) {
+ if pkg.included.FirstTime(builtinRel.String()) && builtin.IsFile() {
builtinMkLines := LoadMk(builtin, MustSucceed|LogErrors)
pkg.parse(builtinMkLines, allLines, "")
}
@@ -246,8 +257,8 @@ func (pkg *Package) parseLine(mklines *M
return false
}
- filenameForUsedCheck := ""
- dir, base := path.Split(includedFile)
+ filenameForUsedCheck := NewPath("")
+ dir, base := includedFile.Split()
if dir != "" && base == "Makefile.common" && dir != "../../"+pkg.Pkgpath+"/" {
filenameForUsedCheck = includingFile
}
@@ -276,14 +287,14 @@ func (pkg *Package) parseLine(mklines *M
// the included file is not processed further for whatever reason. But if
// skip is false, the file could not be read and an appropriate error message
// has already been logged.
-func (pkg *Package) loadIncluded(mkline *MkLine, includingFile string) (includedMklines *MkLines, skip bool) {
+func (pkg *Package) loadIncluded(mkline *MkLine, includingFile Path) (includedMklines *MkLines, skip bool) {
includedFile := pkg.resolveIncludedFile(mkline, includingFile)
if includedFile == "" {
return nil, true
}
- dirname, _ := path.Split(includingFile)
+ dirname, _ := includingFile.Split()
dirname = cleanpath(dirname)
fullIncluded := joinPath(dirname, includedFile)
relIncludedFile := relpath(pkg.dir, fullIncluded)
@@ -292,14 +303,14 @@ func (pkg *Package) loadIncluded(mkline
return nil, true
}
- if !pkg.included.FirstTime(relIncludedFile) {
+ if !pkg.included.FirstTime(relIncludedFile.String()) {
return nil, true
}
pkg.collectSeenInclude(mkline, includedFile)
if trace.Tracing {
- trace.Step1("Including %q.", fullIncluded)
+ trace.Stepf("Including %q.", fullIncluded)
}
includedMklines = LoadMk(fullIncluded, 0)
if includedMklines != nil {
@@ -330,7 +341,7 @@ func (pkg *Package) loadIncluded(mkline
}
mkline.Notef("The path to the included file should be %q.",
- relpath(path.Dir(mkline.Filename), fullIncludedFallback))
+ mkline.PathToFile(fullIncludedFallback))
mkline.Explain(
"The .include directive first searches the file relative to the including file.",
"And if that doesn't exist, falls back to the current directory, which in the",
@@ -344,13 +355,15 @@ func (pkg *Package) loadIncluded(mkline
// resolveIncludedFile resolves Makefile variables such as ${PKGPATH} to
// their actual values.
-func (pkg *Package) resolveIncludedFile(mkline *MkLine, includingFilename string) string {
+func (pkg *Package) resolveIncludedFile(mkline *MkLine, includingFilename Path) Path {
// TODO: resolveVariableRefs uses G.Pkg implicitly. It should be made explicit.
// TODO: Try to combine resolveVariableRefs and ResolveVarsInRelativePath.
- includedFile := resolveVariableRefs(nil /* XXX: or maybe some mklines? */, mkline.ResolveVarsInRelativePath(mkline.IncludedFile()))
- if containsVarRef(includedFile) {
- if trace.Tracing && !contains(includingFilename, "/mk/") {
+ resolved := mkline.ResolveVarsInRelativePath(mkline.IncludedFile())
+ includedText := resolveVariableRefs(nil /* XXX: or maybe some mklines? */, resolved.String())
+ includedFile := NewPath(includedText)
+ if containsVarRef(includedText) {
+ if trace.Tracing && !includingFilename.ContainsPath("mk") {
trace.Stepf("%s:%s: Skipping unresolvable include file %q.",
mkline.Filename, mkline.Linenos(), includedFile)
}
@@ -358,10 +371,10 @@ func (pkg *Package) resolveIncludedFile(
}
if mkline.Basename != "buildlink3.mk" {
- if hasSuffix(includedFile, "/buildlink3.mk") {
+ if includedFile.HasSuffixText("/buildlink3.mk") {
pkg.bl3[includedFile] = mkline
if trace.Tracing {
- trace.Step1("Buildlink3 file in package: %q", includedFile)
+ trace.Step1("Buildlink3 file in package: %q", includedText)
}
}
}
@@ -373,28 +386,31 @@ func (pkg *Package) resolveIncludedFile(
//
// The includingFile is relative to the current working directory,
// the includedFile is taken directly from the .include directive.
-func (*Package) shouldDiveInto(includingFile string, includedFile string) bool {
+func (*Package) shouldDiveInto(includingFile, includedFile Path) bool {
- if hasSuffix(includedFile, "/bsd.pkg.mk") || IsPrefs(includedFile) {
+ if includedFile.HasSuffixPath("bsd.pkg.mk") || IsPrefs(includedFile) {
return false
}
- if contains(includingFile, "/mk/") && !hasPrefix(G.Pkgsrc.ToRel(includingFile), "wip/mk") {
- return hasSuffix(includingFile, "buildlink3.mk") && hasSuffix(includedFile, "builtin.mk")
+ // FIXME: includingFile may be "../../mk/../devel/readline/buildlink.mk" and thus contain "mk"
+ // even though the resolved file is not part of the pkgsrc infrastructure.
+ if includingFile.ContainsPath("mk") && !G.Pkgsrc.ToRel(includingFile).HasPrefixPath("wip/mk") {
+ // TODO: try ".buildlink.mk", ".builtin.mk" instead, see wip/clfswm.
+ return includingFile.HasSuffixText("buildlink3.mk") && includedFile.HasSuffixText("builtin.mk")
}
return true
}
-func (pkg *Package) collectSeenInclude(mkline *MkLine, includedFile string) {
+func (pkg *Package) collectSeenInclude(mkline *MkLine, includedFile Path) {
if mkline.Basename != "Makefile" {
return
}
- incDir, incBase := path.Split(includedFile)
+ incDir, incBase := includedFile.Split()
switch {
case
- hasPrefix(incDir, "../../mk/"),
+ incDir.HasPrefixPath("../../mk"),
incBase == "buildlink3.mk",
incBase == "builtin.mk",
incBase == "options.mk":
@@ -402,7 +418,7 @@ func (pkg *Package) collectSeenInclude(m
}
if trace.Tracing {
- trace.Step1("Including %q sets seenInclude.", includedFile)
+ trace.Stepf("Including %q sets seenInclude.", includedFile)
}
pkg.seenInclude = true
}
@@ -412,22 +428,22 @@ func (pkg *Package) collectConditionalIn
if mkline.IsInclude() {
mkline.SetConditionalVars(mklines.indentation.Varnames())
- key := pkg.Rel(mkline.IncludedFileFull())
+ includedFile := pkg.Rel(mkline.IncludedFileFull())
if mklines.indentation.IsConditional() {
- pkg.conditionalIncludes[key] = mkline
+ pkg.conditionalIncludes[includedFile] = mkline
} else {
- pkg.unconditionalIncludes[key] = mkline
+ pkg.unconditionalIncludes[includedFile] = mkline
}
}
})
}
-func (pkg *Package) loadPlistDirs(plistFilename string) {
+func (pkg *Package) loadPlistDirs(plistFilename Path) {
lines := Load(plistFilename, MustSucceed)
ck := PlistChecker{
pkg,
- make(map[string]*PlistLine),
- make(map[string]*PlistLine),
+ make(map[Path]*PlistLine),
+ make(map[Path]*PlistLine),
"",
Once{},
false}
@@ -441,19 +457,19 @@ func (pkg *Package) loadPlistDirs(plistF
}
}
-func (pkg *Package) check(filenames []string, mklines, allLines *MkLines) {
+func (pkg *Package) check(filenames []Path, mklines, allLines *MkLines) {
haveDistinfo := false
havePatches := false
for _, filename := range filenames {
- if containsVarRef(filename) {
+ if containsVarRef(filename.String()) {
if trace.Tracing {
trace.Stepf("Skipping file %q because the name contains an unresolved variable.", filename)
}
continue
}
- st, err := os.Lstat(filename)
+ st, err := filename.Lstat()
switch {
case err != nil:
// For a missing custom distinfo file, an error message is already generated
@@ -463,7 +479,7 @@ func (pkg *Package) check(filenames []st
// since all those files come from calls to dirglob.
break
- case path.Base(filename) == "Makefile" && strings.Count(G.Pkgsrc.ToRel(filename), "/") == 2:
+ case filename.HasBase("Makefile") && G.Pkgsrc.ToRel(filename).Count() == 3:
G.checkExecutable(filename, st.Mode())
pkg.checkfilePackageMakefile(filename, mklines, allLines)
@@ -471,9 +487,9 @@ func (pkg *Package) check(filenames []st
pkg.checkDirent(filename, st.Mode())
}
- if contains(filename, "/patches/patch-") {
+ if filename.ContainsText("/patches/patch-") {
havePatches = true
- } else if hasSuffix(filename, "/distinfo") {
+ } else if filename.HasSuffixPath("distinfo") {
haveDistinfo = true
}
pkg.checkOwnerMaintainer(filename)
@@ -491,9 +507,9 @@ func (pkg *Package) check(filenames []st
}
}
-func (pkg *Package) checkfilePackageMakefile(filename string, mklines *MkLines, allLines *MkLines) {
+func (pkg *Package) checkfilePackageMakefile(filename Path, mklines *MkLines, allLines *MkLines) {
if trace.Tracing {
- defer trace.Call1(filename)()
+ defer trace.Call(filename)()
}
vars := pkg.vars
@@ -506,12 +522,12 @@ func (pkg *Package) checkfilePackageMake
if !want {
distinfoFile := pkg.File(pkg.DistinfoFile)
- if fileExists(distinfoFile) {
+ if distinfoFile.IsFile() {
NewLineWhole(distinfoFile).Warnf("This file should not exist since NO_CHECKSUM or META_PACKAGE is set.")
}
} else {
distinfoFile := pkg.File(pkg.DistinfoFile)
- if !containsVarRef(distinfoFile) && !fileExists(distinfoFile) {
+ if !containsVarRef(distinfoFile.String()) && !distinfoFile.IsFile() {
line := NewLineWhole(distinfoFile)
line.Warnf("A package that downloads files should have a distinfo file.")
line.Explain(
@@ -554,7 +570,7 @@ func (pkg *Package) checkfilePackageMake
if imake := vars.FirstDefinition("USE_IMAKE"); imake != nil {
if x11 := vars.FirstDefinition("USE_X11"); x11 != nil {
- if !hasSuffix(x11.Filename, "/mk/x11.buildlink3.mk") {
+ if !x11.Filename.HasSuffixPath("mk/x11.buildlink3.mk") {
imake.Notef("USE_IMAKE makes USE_X11 in %s redundant.", imake.RefTo(x11))
}
}
@@ -592,8 +608,8 @@ func (pkg *Package) checkPlist() {
}
needsPlist, line := pkg.needsPlist()
- hasPlist := fileExists(pkg.File(pkg.Pkgdir+"/PLIST")) ||
- fileExists(pkg.File(pkg.Pkgdir+"/PLIST.common"))
+ hasPlist := pkg.File(pkg.Pkgdir.JoinNoClean("PLIST")).IsFile() ||
+ pkg.File(pkg.Pkgdir.JoinNoClean("/PLIST.common")).IsFile()
if needsPlist && !hasPlist {
line.Warnf("This package should have a PLIST file.")
@@ -966,7 +982,7 @@ func (pkg *Package) checkUseLanguagesCom
}
handleInclude := func(mkline *MkLine) {
- _ = seen.FirstTime(pkg.Rel(mkline.IncludedFileFull()))
+ _ = seen.FirstTime(pkg.Rel(mkline.IncludedFileFull()).String())
}
mklines.ForEach(func(mkline *MkLine) {
@@ -1103,7 +1119,7 @@ func (pkg *Package) checkPossibleDowngra
change := G.Pkgsrc.LastChange[pkg.Pkgpath]
if change == nil {
if trace.Tracing {
- trace.Step1("No change log for package %q", pkg.Pkgpath)
+ trace.Stepf("No change log for package %q", pkg.Pkgpath)
}
return
}
@@ -1147,44 +1163,51 @@ func (pkg *Package) checkUpdate() {
}
suggver, comment := sugg.Version, sugg.Comment
- if comment != "" {
- comment = " (" + comment + ")"
+
+ commentSuffix := func() string {
+ if comment != "" {
+ return " (" + comment + ")"
+ }
+ return ""
}
- pkgnameLine := pkg.EffectivePkgnameLine
+ mkline := pkg.EffectivePkgnameLine
cmp := pkgver.Compare(pkg.EffectivePkgversion, suggver)
+ ref := mkline.RefToLocation(sugg.Line)
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.")
+ if comment != "" {
+ mkline.Warnf("This package should be updated to %s (%s; see %s).",
+ sugg.Version, comment, ref)
+ } else {
+ mkline.Warnf("This package should be updated to %s (see %s).",
+ sugg.Version, ref)
+ }
case cmp > 0:
- pkgnameLine.Notef("This package is newer than the update request to %s%s.",
- suggver, comment)
+ mkline.Notef("This package is newer than the update request to %s%s from %s.",
+ suggver, commentSuffix(), ref)
default:
- pkgnameLine.Notef("The update request to %s from doc/TODO%s has been done.",
- suggver, comment)
+ mkline.Notef("The update request to %s%s from %s has been done.",
+ suggver, commentSuffix(), ref)
}
}
}
// checkDirent checks a directory entry based on its filename and its mode
// (regular file, directory, symlink).
-func (pkg *Package) checkDirent(dirent string, mode os.FileMode) {
+func (pkg *Package) checkDirent(dirent Path, mode os.FileMode) {
// TODO: merge duplicate code in Pkglint.checkMode
- basename := path.Base(dirent)
+ basename := dirent.Base()
switch {
case mode.IsRegular():
pkgsrcRel := G.Pkgsrc.ToRel(dirent)
- depth := strings.Count(pkgsrcRel, "/")
+ depth := pkgsrcRel.Count() - 1 // FIXME
G.checkReg(dirent, basename, depth)
case hasPrefix(basename, "work"):
@@ -1197,7 +1220,7 @@ func (pkg *Package) checkDirent(dirent s
switch {
case basename == "files",
basename == "patches",
- matches(dirent, `(?:^|/)files/[^/]*$`),
+ dirent.Dir().Base() == "files",
isEmptyDir(dirent):
break
@@ -1219,7 +1242,7 @@ func (pkg *Package) checkDirent(dirent s
//
// Pkglint assumes that the local username is the same as the NetBSD
// username, which fits most scenarios.
-func (pkg *Package) checkOwnerMaintainer(filename string) {
+func (pkg *Package) checkOwnerMaintainer(filename Path) {
if trace.Tracing {
defer trace.Call(filename)()
}
@@ -1261,7 +1284,7 @@ func (pkg *Package) checkOwnerMaintainer
"keyword \"maintainer\", for more information.")
}
-func (pkg *Package) checkFreeze(filename string) {
+func (pkg *Package) checkFreeze(filename Path) {
freezeStart := G.Pkgsrc.LastFreezeStart
if freezeStart == "" || G.Pkgsrc.LastFreezeEnd != "" {
return
@@ -1278,8 +1301,8 @@ func (pkg *Package) checkFreeze(filename
"See https://www.NetBSD.org/developers/pkgsrc/ for the exact rules.")
}
-func (pkg *Package) checkFileMakefileExt(filename string) {
- base := path.Base(filename)
+func (pkg *Package) checkFileMakefileExt(filename Path) {
+ base := filename.Base()
if !hasPrefix(base, "Makefile.") || base == "Makefile.common" {
return
}
@@ -1313,11 +1336,11 @@ func (pkg *Package) checkLinesBuildlink3
}
// Collect all the included buildlink3.mk files from the file.
- includedFiles := make(map[string]*MkLine)
+ includedFiles := make(map[Path]*MkLine)
for _, mkline := range mklines.mklines {
if mkline.IsInclude() {
includedFile := mkline.IncludedFile()
- if hasSuffix(includedFile, "/buildlink3.mk") {
+ if includedFile.HasSuffixPath("buildlink3.mk") {
includedFiles[includedFile] = mkline
if pkg.bl3[includedFile] == nil {
mkline.Warnf("%s is included by this file but not by the package.", includedFile)
@@ -1329,7 +1352,7 @@ func (pkg *Package) checkLinesBuildlink3
if trace.Tracing {
for packageBl3 := range pkg.bl3 {
if includedFiles[packageBl3] == nil {
- trace.Step1("%s is included by the package but not by the buildlink3.mk file.", packageBl3)
+ trace.Stepf("%s is included by the package but not by the buildlink3.mk file.", packageBl3)
}
}
}
@@ -1405,8 +1428,10 @@ func (pkg *Package) AutofixDistinfo(oldS
// File returns the (possibly absolute) path to relativeFileName,
// as resolved from the package's directory.
// Variables that are known in the package are resolved, e.g. ${PKGDIR}.
-func (pkg *Package) File(relativeFileName string) string {
- return cleanpath(resolveVariableRefs(nil /* XXX: or maybe some mklines? */, joinPath(pkg.dir, relativeFileName)))
+func (pkg *Package) File(relativeFileName Path) Path {
+ joined := pkg.dir.JoinNoClean(relativeFileName)
+ resolved := resolveVariableRefs(nil /* XXX: or maybe some mklines? */, joined.String())
+ return cleanpath(NewPath(resolved))
}
// Rel returns the path by which the given filename (as seen from the
@@ -1415,13 +1440,13 @@ func (pkg *Package) File(relativeFileNam
//
// Example:
// NewPackage("category/package").Rel("other/package") == "../../other/package"
-func (pkg *Package) Rel(filename string) string {
+func (pkg *Package) Rel(filename Path) Path {
return relpath(pkg.dir, filename)
}
// Returns whether the given file (relative to the package directory)
// is included somewhere in the package, either directly or indirectly.
-func (pkg *Package) Includes(filename string) bool {
+func (pkg *Package) Includes(filename Path) bool {
return pkg.unconditionalIncludes[filename] != nil ||
pkg.conditionalIncludes[filename] != nil
}
@@ -1435,12 +1460,12 @@ func (pkg *Package) Includes(filename st
// 2. Ensure that the entries mentioned in the ALTERNATIVES file
// also appear in the PLIST files.
type PlistContent struct {
- Dirs map[string]*PlistLine
- Files map[string]*PlistLine
+ Dirs map[Path]*PlistLine
+ Files map[Path]*PlistLine
}
func NewPlistContent() PlistContent {
return PlistContent{
- make(map[string]*PlistLine),
- make(map[string]*PlistLine)}
+ make(map[Path]*PlistLine),
+ make(map[Path]*PlistLine)}
}
Index: pkgsrc/pkgtools/pkglint/files/package_test.go
diff -u pkgsrc/pkgtools/pkglint/files/package_test.go:1.58 pkgsrc/pkgtools/pkglint/files/package_test.go:1.59
--- pkgsrc/pkgtools/pkglint/files/package_test.go:1.58 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/package_test.go Sat Nov 23 23:35:56 2019
@@ -311,7 +311,7 @@ func (s *Suite) Test_Package__case_insen
t.FinishSetUp()
// this test is only interesting on a case-insensitive filesystem
- if !fileExists(t.File("mk/BSD.PKG.MK")) {
+ if !t.File("mk/BSD.PKG.MK").IsFile() {
return
}
@@ -332,6 +332,64 @@ func (s *Suite) Test_NewPackage(c *check
t.ExpectAssert(func() { NewPackage("category") })
}
+func (s *Suite) Test_Package_load__variable_from_Makefile_used_in_builtin_mk(c *check.C) {
+ t := s.Init(c)
+
+ t.SetUpPackage("devel/binutils",
+ "BINUTILS_PREFIX=\t${PREFIX}/${MACHINE_GNU_PLATFORM}")
+ t.CreateFileLines("devel/binutils/builtin.mk",
+ MkCvsID,
+ ".include \"../../mk/bsd.prefs.mk\"",
+ "BINUTILS_PREFIX?=\t/usr",
+ "",
+ "BUILTIN_FIND_FILES.BINUTILS_FILES:=\t${BINUTILS_PREFIX}/include/bfd.h")
+ t.FinishSetUp()
+
+ G.Check(t.File("devel/binutils"))
+
+ // The BINUTILS_PREFIX from the Makefile is not used since the
+ // builtin.mk file is only parsed inside of buildlink3.mk, and
+ // that doesn't happen for the package itself, but only for those
+ // packages that depend on this package.
+ t.CheckOutputLines(
+ "WARN: ~/devel/binutils/Makefile:20: " +
+ "BINUTILS_PREFIX is defined but not used.")
+}
+
+func (s *Suite) Test_Package_load__buildlink3_mk_includes_other_mk(c *check.C) {
+ t := s.Init(c)
+
+ t.SetUpCommandLine("-Wall", "--explain")
+ t.SetUpPackage("multimedia/libav")
+ t.CreateFileDummyBuildlink3("multimedia/libav/buildlink3.mk",
+ ".include \"available.mk\"")
+ t.CreateFileLines("multimedia/libav/available.mk",
+ MkCvsID,
+ "",
+ "LIBAV_AVAILABLE=\tno")
+ t.FinishSetUp()
+
+ G.Check(t.File("multimedia/libav"))
+
+ // From looking at the file available.mk alone, this variable looks
+ // unused indeed, but its intention is to be used by other packages.
+ // The explanation has a large paragraph covering exactly this case,
+ // therefore the warning is ok.
+ t.CheckOutputLines(
+ "WARN: ~/multimedia/libav/available.mk:3: "+
+ "LIBAV_AVAILABLE is defined but not used.",
+ "",
+ "\tThis might be a simple typo.",
+ "",
+ "\tIf a package provides a file containing several related variables",
+ "\t(such as module.mk, app.mk, extension.mk), that file may define",
+ "\tvariables that look unused since they are only used by other",
+ "\tpackages. These variables should be documented at the head of the",
+ "\tfile; see mk/subst.mk for an example of such a documentation",
+ "\tcomment.",
+ "")
+}
+
// Demonstrates that Makefile fragments are handled differently,
// depending on the directory they are in.
func (s *Suite) Test_Package_load__extra_files(c *check.C) {
@@ -357,7 +415,7 @@ func (s *Suite) Test_Package_load__extra
"@@ -1,1 +1,1 @@",
"- old",
"+ new")
- t.CreateFileLines("patches/readme.mk",
+ t.CreateFileLines("patches/readme.mk", // Is ignored
"This is not a BSD-style Makefile.")
t.Copy("gnu-style.mk", "files/gnu-style.mk")
t.Copy("gnu-style.mk", "../../category/other/gnu-style.mk")
@@ -374,10 +432,6 @@ func (s *Suite) Test_Package_load__extra
"ERROR: gnu-style.mk:3: Unknown Makefile line format: \"else\".",
"ERROR: gnu-style.mk:5: Unknown Makefile line format: \"endif\".",
- // Since the patches directory should contain only patches,
- // each other file is treated as a file belonging to pkgsrc,
- // therefore *.mk is interpreted as a Makefile fragment.
- "ERROR: patches/readme.mk:1: Unknown Makefile line format: \"This is not a BSD-style Makefile.\".",
"ERROR: distinfo: Patch \"patches/patch-Makefile.mk\" is not recorded. Run \""+confMake+" makepatchsum\".",
// The following diagnostics are duplicated because the files from
@@ -1011,7 +1065,7 @@ func (s *Suite) Test_Package_shouldDiveI
t := s.Init(c)
t.Chdir(".")
- test := func(including, included string, expected bool) {
+ test := func(including, included Path, expected bool) {
actual := (*Package)(nil).shouldDiveInto(including, included)
t.CheckEquals(actual, expected)
}
@@ -1105,13 +1159,13 @@ func (s *Suite) Test_Package_loadPlistDi
pkg := NewPackage(t.File("category/package"))
pkg.load()
- var dirs []string
+ var dirs []Path
for dir := range pkg.Plist.Dirs {
dirs = append(dirs, dir)
}
- sort.Strings(dirs)
+ sort.Slice(dirs, func(i, j int) bool { return dirs[i] < dirs[j] })
- t.CheckDeepEquals(dirs, []string{"bin"})
+ t.CheckDeepEquals(dirs, []Path{"bin"})
}
func (s *Suite) Test_Package_loadPlistDirs(c *check.C) {
@@ -1128,13 +1182,13 @@ func (s *Suite) Test_Package_loadPlistDi
pkg := NewPackage(t.File("category/package"))
pkg.load()
- var dirs []string
+ var dirs []Path
for dir := range pkg.Plist.Dirs {
dirs = append(dirs, dir)
}
- sort.Strings(dirs)
+ sort.Slice(dirs, func(i, j int) bool { return dirs[i] < dirs[j] })
- t.CheckDeepEquals(dirs, []string{"bin", "dir", "dir/subdir"})
+ t.CheckDeepEquals(dirs, []Path{"bin", "dir", "dir/subdir"})
}
func (s *Suite) Test_Package_check__files_Makefile(c *check.C) {
@@ -2456,6 +2510,8 @@ func (s *Suite) Test_Package_checkPossib
func (s *Suite) Test_Package_checkUpdate(c *check.C) {
t := s.Init(c)
+ // The package names intentionally differ from the package directories
+ // to ensure that the check uses the package name.
t.SetUpPackage("category/pkg1",
"PKGNAME= package1-1.0")
t.SetUpPackage("category/pkg2",
@@ -2463,27 +2519,29 @@ func (s *Suite) Test_Package_checkUpdate
t.SetUpPackage("category/pkg3",
"PKGNAME= package3-5.0")
t.CreateFileLines("doc/TODO",
+ CvsID,
"Suggested package updates",
+ "=========================",
+ "For possible Perl packages updates, see http://www.NetBSD.org/~wiz/perl.html.",
"",
- "",
- "\t"+"O wrong bullet",
- "\t"+"o package-without-version",
"\t"+"o package1-1.0",
+ "\t"+"o package1-1.0 [with comment]",
+ "\t"+"o package2-2.0",
"\t"+"o package2-2.0 [nice new features]",
+ "\t"+"o package3-3.0",
"\t"+"o package3-3.0 [security update]")
t.Chdir(".")
t.Main("-Wall,no-space", "category/pkg1", "category/pkg2", "category/pkg3")
t.CheckOutputLines(
- "WARN: category/pkg1/../../doc/TODO:3: Invalid line format \"\".",
- "WARN: category/pkg1/../../doc/TODO:4: Invalid line format \"\\tO wrong bullet\".",
- "WARN: category/pkg1/../../doc/TODO:5: Invalid package name \"package-without-version\".",
- "NOTE: category/pkg1/Makefile:4: The update request to 1.0 from doc/TODO has been done.",
- "WARN: category/pkg2/Makefile:4: This package should be updated to 2.0 ([nice new features]).",
- "NOTE: category/pkg3/Makefile:4: This package is newer than the update request to 3.0 ([security update]).",
- "4 warnings and 2 notes found.",
- "(Run \"pkglint -e -Wall,no-space category/pkg1 category/pkg2 category/pkg3\" to show explanations.)")
+ "NOTE: category/pkg1/Makefile:4: The update request to 1.0 from ../../doc/TODO:6 has been done.",
+ "NOTE: category/pkg1/Makefile:4: The update request to 1.0 (with comment) from ../../doc/TODO:7 has been done.",
+ "WARN: category/pkg2/Makefile:4: This package should be updated to 2.0 (see ../../doc/TODO:8).",
+ "WARN: category/pkg2/Makefile:4: This package should be updated to 2.0 (nice new features; see ../../doc/TODO:9).",
+ "NOTE: category/pkg3/Makefile:4: This package is newer than the update request to 3.0 from ../../doc/TODO:10.",
+ "NOTE: category/pkg3/Makefile:4: This package is newer than the update request to 3.0 (security update) from ../../doc/TODO:11.",
+ "2 warnings and 4 notes found.")
}
func (s *Suite) Test_Package_checkDirent__errors(c *check.C) {
@@ -3162,8 +3220,12 @@ func (s *Suite) Test_Package_Includes(c
t.CheckEquals(pkg.Includes("conditionally.mk"), true)
t.CheckEquals(pkg.Includes("other.mk"), false)
- // TODO: Strictly speaking, never.mk should be in conditionalIncludes.
- // This is an edge case though. See collectConditionalIncludes and
- // Indentation.IsConditional for the current implementation.
- t.CheckEquals(pkg.conditionalIncludes["never.mk"], (*MkLine)(nil))
+ // The file never.mk is in conditionalIncludes since pkglint only
+ // analyzes on the syntactical level. It doesn't evaluate the
+ // condition from the .if to see whether it is satisfiable.
+ //
+ // See Package.collectConditionalIncludes and Indentation.IsConditional.
+ t.CheckEquals(
+ pkg.conditionalIncludes["never.mk"].Location,
+ NewLocation(t.File("category/package/Makefile"), 22, 22))
}
Index: pkgsrc/pkgtools/pkglint/files/util.go
diff -u pkgsrc/pkgtools/pkglint/files/util.go:1.58 pkgsrc/pkgtools/pkglint/files/util.go:1.59
--- pkgsrc/pkgtools/pkglint/files/util.go:1.58 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/util.go Sat Nov 23 23:35:56 2019
@@ -3,12 +3,9 @@ package pkglint
import (
"fmt"
"hash/crc64"
- "io/ioutil"
"netbsd.org/pkglint/regex"
"netbsd.org/pkglint/textproc"
- "os"
"path"
- "path/filepath"
"reflect"
"regexp"
"sort"
@@ -30,6 +27,7 @@ func (ynu YesNoUnknown) String() string
}
// Short names for commonly used functions.
+
func contains(s, substr string) bool {
return strings.Contains(s, substr)
}
@@ -240,12 +238,12 @@ func assertf(cond bool, format string, a
}
}
-func isEmptyDir(filename string) bool {
- if hasSuffix(filename, "/CVS") {
+func isEmptyDir(filename Path) bool {
+ if filename.HasSuffixText("/CVS") {
return true
}
- dirents, err := ioutil.ReadDir(filename)
+ dirents, err := filename.ReadDir()
if err != nil {
return true // XXX: Why not false?
}
@@ -255,7 +253,7 @@ func isEmptyDir(filename string) bool {
if isIgnoredFilename(name) {
continue
}
- if dirent.IsDir() && isEmptyDir(joinPath(filename, name)) {
+ if dirent.IsDir() && isEmptyDir(filename.JoinNoClean(NewPath(name))) {
continue
}
return false
@@ -263,17 +261,17 @@ func isEmptyDir(filename string) bool {
return true
}
-func getSubdirs(filename string) []string {
- dirents, err := ioutil.ReadDir(filename)
+func getSubdirs(filename Path) []Path {
+ dirents, err := filename.ReadDir()
if err != nil {
NewLineWhole(filename).Fatalf("Cannot be read: %s", err)
}
- var subdirs []string
+ var subdirs []Path
for _, dirent := range dirents {
name := dirent.Name()
- if dirent.IsDir() && !isIgnoredFilename(name) && !isEmptyDir(joinPath(filename, name)) {
- subdirs = append(subdirs, name)
+ if dirent.IsDir() && !isIgnoredFilename(name) && !isEmptyDir(filename.JoinNoClean(NewPath(name))) {
+ subdirs = append(subdirs, NewPath(name))
}
}
return subdirs
@@ -287,24 +285,24 @@ func isIgnoredFilename(filename string)
return hasPrefix(filename, ".#")
}
-func dirglob(dirname string) []string {
- infos, err := ioutil.ReadDir(dirname)
+func dirglob(dirname Path) []Path {
+ infos, err := dirname.ReadDir()
if err != nil {
return nil
}
- var filenames []string
+ var filenames []Path
for _, info := range infos {
if !(isIgnoredFilename(info.Name())) {
- filenames = append(filenames, cleanpath(joinPath(dirname, info.Name())))
+ filenames = append(filenames, cleanpath(dirname.JoinNoClean(NewPath(info.Name()))))
}
}
return filenames
}
// Checks whether a file is already committed to the CVS repository.
-func isCommitted(filename string) bool {
+func isCommitted(filename Path) bool {
entries := G.loadCvsEntries(filename)
- _, found := entries[path.Base(filename)]
+ _, found := entries[filename.Base()]
return found
}
@@ -313,14 +311,14 @@ func isCommitted(filename string) bool {
//
// There is no corresponding test for Git (as used by pkgsrc-wip) since that
// is more difficult to implement than simply reading a CVS/Entries file.
-func isLocallyModified(filename string) bool {
+func isLocallyModified(filename Path) bool {
entries := G.loadCvsEntries(filename)
- entry, found := entries[path.Base(filename)]
+ entry, found := entries[filename.Base()]
if !found {
return false
}
- st, err := os.Stat(filename)
+ st, err := filename.Stat()
if err != nil {
return true
}
@@ -438,16 +436,6 @@ func varnameParam(varname string) string
return ""
}
-func fileExists(filename string) bool {
- st, err := os.Stat(filename)
- return err == nil && st.Mode().IsRegular()
-}
-
-func dirExists(filename string) bool {
- st, err := os.Stat(filename)
- return err == nil && st.Mode().IsDir()
-}
-
func toInt(s string, def int) int {
if n, err := strconv.Atoi(s); err == nil {
return n
@@ -469,11 +457,15 @@ func mkopSubst(s string, left bool, from
})
}
-func joinPath(a, b string, others ...string) string {
+func joinPath(a, b Path, others ...Path) Path {
if len(others) == 0 {
return a + "/" + b
}
- return a + "/" + b + "/" + strings.Join(others, "/")
+ parts := []string{a.String(), b.String()}
+ for _, part := range others {
+ parts = append(parts, part.String())
+ }
+ return NewPath(strings.Join(parts, "/"))
}
// relpath returns the relative path from the directory "from"
@@ -493,7 +485,7 @@ func joinPath(a, b string, others ...str
//
// TODO: Invent data types for all kinds of relative paths that occur in pkgsrc
// and pkglint. Make sure that these paths cannot be accidentally mixed.
-func relpath(from, to string) (result string) {
+func relpath(from, to Path) (result Path) {
if trace.Tracing {
defer trace.Call(from, to, trace.Result(&result))()
@@ -507,34 +499,31 @@ func relpath(from, to string) (result st
}
// Take a shortcut for the common case from "dir" to "dir/subdir/...".
- if hasPrefix(cto, cfrom) && hasPrefix(cto[len(cfrom):], "/") {
+ if cto.HasPrefixPath(cfrom) {
return cleanpath(cto[len(cfrom)+1:])
}
// Take a shortcut for the common case from "category/package" to ".".
// This is the most common variant in a complete pkgsrc scan.
if cto == "." {
- fromParts := strings.FieldsFunc(cfrom, func(r rune) bool { return r == '/' })
+ fromParts := cfrom.Parts()
if len(fromParts) == 2 && !hasPrefix(fromParts[0], ".") && !hasPrefix(fromParts[1], ".") {
return "../.."
}
}
- if cfrom == "." && !filepath.IsAbs(cto) {
- return path.Clean(cto)
+ if cfrom == "." && !cto.IsAbs() {
+ return cto.Clean()
}
absFrom := abspath(cfrom)
absTopdir := abspath(G.Pkgsrc.topdir)
absTo := abspath(cto)
- toTop, err := filepath.Rel(absFrom, absTopdir)
- assertNil(err, "relpath from %q to topdir %q", absFrom, absTopdir)
-
- fromTop, err := filepath.Rel(absTopdir, absTo)
- assertNil(err, "relpath from topdir %q to %q", absTopdir, absTo)
+ toTop := absFrom.Rel(absTopdir)
+ fromTop := absTopdir.Rel(absTo)
- result = cleanpath(joinPath(filepath.ToSlash(toTop), filepath.ToSlash(fromTop)))
+ result = cleanpath(toTop.JoinNoClean(fromTop))
if trace.Tracing {
trace.Stepf("relpath from %q to %q = %q", cfrom, cto, result)
@@ -542,20 +531,20 @@ func relpath(from, to string) (result st
return
}
-func abspath(filename string) string {
+func abspath(filename Path) Path {
abs := filename
- if !filepath.IsAbs(filename) {
+ if !filename.IsAbs() {
abs = joinPath(G.cwd, abs)
}
- return path.Clean(abs)
+ return abs.Clean()
}
// Differs from path.Clean in that only "../../" is replaced, not "../".
// Also, the initial directory is always kept.
// This is to provide the package path as context in recursive invocations of pkglint.
-func cleanpath(filename string) string {
+func cleanpath(filename Path) Path {
parts := make([]string, 0, 5)
- lex := textproc.NewLexer(filename)
+ lex := textproc.NewLexer(filename.String())
for lex.SkipString("./") {
}
@@ -585,7 +574,7 @@ func cleanpath(filename string) string {
if len(parts) == 0 {
return "."
}
- return strings.Join(parts, "/")
+ return NewPath(strings.Join(parts, "/"))
}
func pathContains(haystack, needle string) bool {
@@ -602,10 +591,10 @@ func pathContains(haystack, needle strin
return false
}
-func pathContainsDir(haystack, needle string) bool {
+func pathContainsDir(haystack, needle Path) bool {
n0 := needle[0]
for i := 0; i < 1+len(haystack)-len(needle); i++ {
- if haystack[i] == n0 && hasPrefix(haystack[i:], needle) {
+ if haystack[i] == n0 && hasPrefix(haystack.String()[i:], needle.String()) {
if i == 0 || haystack[i-1] == '/' {
if i+len(needle) < len(haystack) && haystack[i+len(needle)] == '/' {
return true
@@ -1010,8 +999,8 @@ func naturalLess(str1, str2 string) bool
// IsPrefs returns whether the given file, when included, loads the user
// preferences.
-func IsPrefs(filename string) bool {
- switch path.Base(filename) {
+func IsPrefs(filename Path) bool {
+ switch filename.Base() {
case // See https://github.com/golang/go/issues/28057
"bsd.prefs.mk", // in mk/
"bsd.fast.prefs.mk", // in mk/
@@ -1047,7 +1036,7 @@ func NewFileCache(size int) *FileCache {
0}
}
-func (c *FileCache) Put(filename string, options LoadOptions, lines *Lines) {
+func (c *FileCache) Put(filename Path, options LoadOptions, lines *Lines) {
key := c.key(filename)
entry := c.mapping[key]
@@ -1101,7 +1090,7 @@ func (c *FileCache) removeOldEntries() {
}
}
-func (c *FileCache) Get(filename string, options LoadOptions) *Lines {
+func (c *FileCache) Get(filename Path, options LoadOptions) *Lines {
key := c.key(filename)
entry, found := c.mapping[key]
if found && entry.options == options {
@@ -1118,7 +1107,7 @@ func (c *FileCache) Get(filename string,
return nil
}
-func (c *FileCache) Evict(filename string) {
+func (c *FileCache) Evict(filename Path) {
key := c.key(filename)
entry, found := c.mapping[key]
if !found {
@@ -1136,9 +1125,7 @@ func (c *FileCache) Evict(filename strin
}
}
-func (c *FileCache) key(filename string) string {
- return path.Clean(filename)
-}
+func (c *FileCache) key(filename Path) string { return filename.Clean().String() }
func bmakeHelp(topic string) string { return bmake("help topic=" + topic) }
@@ -1398,27 +1385,27 @@ func pathMatches(pattern, s string) bool
return err == nil && matched
}
-type StringQueue struct {
- entries []string
+type PathQueue struct {
+ entries []Path
}
-func (q *StringQueue) PushFront(entries ...string) {
- q.entries = append(append([]string(nil), entries...), q.entries...)
+func (q *PathQueue) PushFront(entries ...Path) {
+ q.entries = append(append([]Path(nil), entries...), q.entries...)
}
-func (q *StringQueue) Push(entries ...string) {
+func (q *PathQueue) Push(entries ...Path) {
q.entries = append(q.entries, entries...)
}
-func (q *StringQueue) IsEmpty() bool {
+func (q *PathQueue) IsEmpty() bool {
return len(q.entries) == 0
}
-func (q *StringQueue) Front() string {
+func (q *PathQueue) Front() Path {
return q.entries[0]
}
-func (q *StringQueue) Pop() string {
+func (q *PathQueue) Pop() Path {
front := q.entries[0]
q.entries = q.entries[1:]
return front
Index: pkgsrc/pkgtools/pkglint/files/patches.go
diff -u pkgsrc/pkgtools/pkglint/files/patches.go:1.32 pkgsrc/pkgtools/pkglint/files/patches.go:1.33
--- pkgsrc/pkgtools/pkglint/files/patches.go:1.32 Sat Nov 2 16:37:48 2019
+++ pkgsrc/pkgtools/pkglint/files/patches.go Sat Nov 23 23:35:56 2019
@@ -79,7 +79,7 @@ func (ck *PatchChecker) Check() {
}
}
- if patchedFiles > 1 && !matches(ck.lines.Filename, `\bCVE\b`) {
+ if patchedFiles > 1 && !matches(ck.lines.Filename.String(), `\bCVE\b`) {
ck.lines.Whole().Warnf("Contains patches for %d files, should be only one.", patchedFiles)
} else if patchedFiles == 0 {
ck.lines.Whole().Errorf("Contains no patch.")
Index: pkgsrc/pkgtools/pkglint/files/pkglint.go
diff -u pkgsrc/pkgtools/pkglint/files/pkglint.go:1.64 pkgsrc/pkgtools/pkglint/files/pkglint.go:1.65
--- pkgsrc/pkgtools/pkglint/files/pkglint.go:1.64 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/pkglint.go Sat Nov 23 23:35:56 2019
@@ -10,7 +10,6 @@ import (
"os"
"os/user"
"path"
- "path/filepath"
"runtime"
"runtime/debug"
"runtime/pprof"
@@ -26,14 +25,14 @@ type Pkglint struct {
Pkgsrc Pkgsrc // Global data, mostly extracted from mk/*.
Pkg *Package // The package that is currently checked, or nil.
- Todo StringQueue // The files or directories that still need to be checked.
- Wip bool // Is the currently checked file or package from pkgsrc-wip?
- Infrastructure bool // Is the currently checked file from the pkgsrc infrastructure?
- Testing bool // Is pkglint in self-testing mode (only during development)?
- Experimental bool // For experimental features, only enabled individually in tests
- Username string // For checking against OWNER and MAINTAINER
+ Todo PathQueue // The files or directories that still need to be checked.
+ Wip bool // Is the currently checked file or package from pkgsrc-wip?
+ Infrastructure bool // Is the currently checked file from the pkgsrc infrastructure?
+ Testing bool // Is pkglint in self-testing mode (only during development)?
+ Experimental bool // For experimental features, only enabled individually in tests
+ Username string // For checking against OWNER and MAINTAINER
- cvsEntriesDir string // Cached to avoid I/O
+ cvsEntriesDir Path // Cached to avoid I/O
cvsEntries map[string]CvsEntry
Logger Logger
@@ -43,10 +42,10 @@ type Pkglint struct {
fileCache *FileCache
interner StringInterner
- // cwd is the slash-separated absolute path to the current working
+ // cwd is the absolute path to the current working
// directory. It is used for speeding up relpath and abspath.
// There is no other use for it.
- cwd string
+ cwd Path
InterPackage InterPackage
}
@@ -58,7 +57,7 @@ func NewPkglint(stdout io.Writer, stderr
p := Pkglint{
res: regex.NewRegistry(),
fileCache: NewFileCache(200),
- cwd: filepath.ToSlash(cwd),
+ cwd: NewPathSlash(cwd),
interner: NewStringInterner()}
p.Logger.out = NewSeparatorWriter(stdout)
p.Logger.err = NewSeparatorWriter(stderr)
@@ -208,8 +207,8 @@ func (pkglint *Pkglint) setUpProfiling()
func (pkglint *Pkglint) prepareMainLoop() {
firstDir := pkglint.Todo.Front()
- if fileExists(firstDir) {
- firstDir = path.Dir(firstDir)
+ if firstDir.IsFile() {
+ firstDir = firstDir.Dir()
}
relTopdir := findPkgsrcTopdir(firstDir)
@@ -222,7 +221,7 @@ func (pkglint *Pkglint) prepareMainLoop(
}
pkglint.Pkgsrc = NewPkgsrc(joinPath(firstDir, relTopdir))
- pkglint.Wip = matches(pkglint.Pkgsrc.ToRel(firstDir), `^wip(/|$)`) // Same as in Pkglint.Check.
+ pkglint.Wip = pkglint.Pkgsrc.ToRel(firstDir).HasPrefixPath("wip") // Same as in Pkglint.Check.
pkglint.Pkgsrc.LoadInfrastructure()
currentUser, err := user.Current()
@@ -283,7 +282,7 @@ func (pkglint *Pkglint) ParseCommandLine
}
for _, arg := range pkglint.Opts.args {
- pkglint.Todo.Push(filepath.ToSlash(arg))
+ pkglint.Todo.Push(NewPathSlash(arg))
}
if pkglint.Todo.IsEmpty() {
pkglint.Todo.Push(".")
@@ -299,12 +298,12 @@ func (pkglint *Pkglint) ParseCommandLine
//
// It sets up all the global state (infrastructure, wip) for accurately
// classifying the entry.
-func (pkglint *Pkglint) Check(dirent string) {
+func (pkglint *Pkglint) Check(dirent Path) {
if trace.Tracing {
- defer trace.Call1(dirent)()
+ defer trace.Call(dirent)()
}
- st, err := os.Lstat(dirent)
+ st, err := dirent.Lstat()
if err != nil {
NewLineWhole(dirent).Errorf("No such file or directory.")
return
@@ -313,7 +312,7 @@ func (pkglint *Pkglint) Check(dirent str
pkglint.checkMode(dirent, st.Mode())
}
-func (pkglint *Pkglint) checkMode(dirent string, mode os.FileMode) {
+func (pkglint *Pkglint) checkMode(dirent Path, mode os.FileMode) {
// TODO: merge duplicate code in Package.checkDirent
isDir := mode.IsDir()
isReg := mode.IsRegular()
@@ -324,14 +323,14 @@ func (pkglint *Pkglint) checkMode(dirent
dir := dirent
if !isDir {
- dir = path.Dir(dirent)
+ dir = dirent.Dir()
}
- basename := path.Base(dirent)
+ basename := dirent.Base()
pkgsrcRel := pkglint.Pkgsrc.ToRel(dirent)
- pkglint.Wip = matches(pkgsrcRel, `^wip(/|$)`)
- pkglint.Infrastructure = matches(pkgsrcRel, `^mk(/|$)`)
+ pkglint.Wip = pkgsrcRel.HasPrefixPath("wip")
+ pkglint.Infrastructure = pkgsrcRel.HasPrefixPath("mk")
pkgsrcdir := findPkgsrcTopdir(dir)
if pkgsrcdir == "" {
NewLineWhole(dirent).Errorf("Cannot determine the pkgsrc root directory for %q.", cleanpath(dir))
@@ -339,7 +338,7 @@ func (pkglint *Pkglint) checkMode(dirent
}
if isReg {
- depth := strings.Count(pkgsrcRel, "/")
+ depth := pkgsrcRel.Count() - 1 // FIXME
pkglint.checkExecutable(dirent, mode)
pkglint.checkReg(dirent, basename, depth)
return
@@ -363,9 +362,9 @@ func (pkglint *Pkglint) checkMode(dirent
// checkdirPackage checks a complete pkgsrc package, including each
// of the files individually, and also when seen in combination.
-func (pkglint *Pkglint) checkdirPackage(dir string) {
+func (pkglint *Pkglint) checkdirPackage(dir Path) {
if trace.Tracing {
- defer trace.Call1(dir)()
+ defer trace.Call(dir)()
}
pkglint.Pkg = NewPackage(dir)
@@ -377,9 +376,9 @@ func (pkglint *Pkglint) checkdirPackage(
}
// Returns the pkgsrc top-level directory, relative to the given directory.
-func findPkgsrcTopdir(dirname string) string {
- for _, dir := range [...]string{".", "..", "../..", "../../.."} {
- if fileExists(joinPath(dirname, dir, "mk/bsd.pkg.mk")) {
+func findPkgsrcTopdir(dirname Path) Path {
+ for _, dir := range [...]Path{".", "..", "../..", "../../.."} {
+ if joinPath(dirname, dir, "mk/bsd.pkg.mk").IsFile() {
return dir
}
}
@@ -427,9 +426,9 @@ func resolveVariableRefs(mklines *MkLine
}
}
-func CheckFileOther(filename string) {
+func CheckFileOther(filename Path) {
if trace.Tracing {
- defer trace.Call1(filename)()
+ defer trace.Call(filename)()
}
if lines := Load(filename, NotEmpty|LogErrors); lines != nil {
@@ -439,7 +438,7 @@ func CheckFileOther(filename string) {
func CheckLinesDescr(lines *Lines) {
if trace.Tracing {
- defer trace.Call1(lines.Filename)()
+ defer trace.Call(lines.Filename)()
}
for _, line := range lines.Lines {
@@ -473,7 +472,7 @@ func CheckLinesDescr(lines *Lines) {
func CheckLinesMessage(lines *Lines) {
if trace.Tracing {
- defer trace.Call1(lines.Filename)()
+ defer trace.Call(lines.Filename)()
}
// For now, skip all checks when the MESSAGE may be built from multiple
@@ -529,9 +528,9 @@ func CheckLinesMessage(lines *Lines) {
SaveAutofixChanges(lines)
}
-func CheckFileMk(filename string) {
+func CheckFileMk(filename Path) {
if trace.Tracing {
- defer trace.Call1(filename)()
+ defer trace.Call(filename)()
}
mklines := LoadMk(filename, NotEmpty|LogErrors)
@@ -547,7 +546,7 @@ func CheckFileMk(filename string) {
mklines.SaveAutofixChanges()
}
-func (pkglint *Pkglint) checkReg(filename, basename string, depth int) {
+func (pkglint *Pkglint) checkReg(filename Path, basename string, depth int) {
if depth == 2 && !pkglint.Wip {
if contains(basename, "README") || contains(basename, "TODO") {
@@ -606,16 +605,16 @@ func (pkglint *Pkglint) checkReg(filenam
CheckLinesPatch(lines)
}
- case matches(filename, `(?:^|/)patches/manual[^/]*$`):
+ case matches(filename.String(), `(?:^|/)patches/manual[^/]*$`):
if trace.Tracing {
- trace.Step1("Unchecked file %q.", filename)
+ trace.Stepf("Unchecked file %q.", filename)
}
- case matches(filename, `(?:^|/)patches/[^/]*$`):
+ case filename.Dir().Base() == "patches":
NewLineWhole(filename).Warnf("Patch files should be named \"patch-\", followed by letters, '-', '_', '.', and digits only.")
case (hasPrefix(basename, "Makefile") || hasSuffix(basename, ".mk")) &&
- !pathContainsDir(filename, "files"):
+ !pathContainsDir(filename, "files"): // FIXME: G.Pkgsrc.Rel(filename) instead of filename
CheckFileMk(filename)
case hasPrefix(basename, "PLIST"):
@@ -627,11 +626,11 @@ func (pkglint *Pkglint) checkReg(filenam
// This only checks the file but doesn't register the changes globally.
_ = pkglint.Pkgsrc.loadDocChangesFromFile(filename)
- case matches(filename, `(?:^|/)files/[^/]*$`):
+ case filename.Dir().Base() == "files":
// Skip files directly in the files/ directory, but not those further down.
case basename == "spec":
- if !hasPrefix(pkglint.Pkgsrc.ToRel(filename), "regress/") {
+ if !pkglint.Pkgsrc.ToRel(filename).HasPrefixPath("regress") {
NewLineWhole(filename).Warnf("Only packages in regress/ may have spec files.")
}
@@ -652,7 +651,7 @@ func (pkglint *Pkglint) matchesLicenseFi
return basename == path.Base(licenseFile)
}
-func (pkglint *Pkglint) checkExecutable(filename string, mode os.FileMode) {
+func (pkglint *Pkglint) checkExecutable(filename Path, mode os.FileMode) {
if mode.Perm()&0111 == 0 {
// Not executable at all.
return
@@ -677,7 +676,7 @@ func (pkglint *Pkglint) checkExecutable(
fix.Custom(func(showAutofix, autofix bool) {
fix.Describef(0, "Clearing executable bits")
if autofix {
- if err := os.Chmod(filename, mode&^0111); err != nil {
+ if err := filename.Chmod(mode &^ 0111); err != nil {
G.Logger.Errorf(cleanpath(filename), "Cannot clear executable bits: %s", err)
}
}
@@ -732,8 +731,8 @@ func (pkglint *Pkglint) tools(mklines *M
}
}
-func (pkglint *Pkglint) loadCvsEntries(filename string) map[string]CvsEntry {
- dir := path.Dir(filename)
+func (pkglint *Pkglint) loadCvsEntries(filename Path) map[string]CvsEntry {
+ dir := filename.Dir()
if dir == pkglint.cvsEntriesDir {
return pkglint.cvsEntries
}
@@ -798,8 +797,8 @@ func (ip *InterPackage) Enable() {
func (ip *InterPackage) Enabled() bool { return ip.hashes != nil }
-func (ip *InterPackage) Hash(alg, filename string, hashBytes []byte, loc *Location) *Hash {
- key := alg + ":" + filename
+func (ip *InterPackage) Hash(alg string, filename Path, hashBytes []byte, loc *Location) *Hash {
+ key := alg + ":" + filename.String()
if otherHash := ip.hashes[key]; otherHash != nil {
return otherHash
}
Index: pkgsrc/pkgtools/pkglint/files/pkglint_test.go
diff -u pkgsrc/pkgtools/pkglint/files/pkglint_test.go:1.49 pkgsrc/pkgtools/pkglint/files/pkglint_test.go:1.50
--- pkgsrc/pkgtools/pkglint/files/pkglint_test.go:1.49 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/pkglint_test.go Sat Nov 23 23:35:56 2019
@@ -14,9 +14,9 @@ func (pkglint *Pkglint) isUsable() bool
func (s *Suite) Test_Pkglint_Main(c *check.C) {
t := s.Init(c)
- out, err := os.Create(t.CreateFileLines("out"))
+ out, err := os.Create(t.CreateFileLines("out").String())
c.Check(err, check.IsNil)
- outProfiling, err := os.Create(t.CreateFileLines("out.profiling"))
+ outProfiling, err := os.Create(t.CreateFileLines("out.profiling").String())
c.Check(err, check.IsNil)
t.SetUpPackage("category/package")
@@ -238,7 +238,7 @@ func (s *Suite) Test_Pkglint_Main__compl
"Package version \"1.11\" is greater than the latest \"1.10\" "+
"from ../../doc/CHANGES-2018:5.",
"WARN: ~/sysutils/checkperms/Makefile:3: "+
- "This package should be updated to 1.13 ([supports more file formats]).",
+ "This package should be updated to 1.13 (supports more file formats; see ../../doc/TODO:5).",
"ERROR: ~/sysutils/checkperms/Makefile:4: Invalid category \"tools\".",
"ERROR: ~/sysutils/checkperms/README: Packages in main pkgsrc must not have a README file.",
"ERROR: ~/sysutils/checkperms/TODO: Packages in main pkgsrc must not have a TODO file.",
@@ -259,7 +259,7 @@ func (s *Suite) Test_Pkglint_Main__autof
t.CreateFileLines("filename.mk",
"")
- exitcode := t.Main("-Wall", "--autofix", t.File("filename.mk"))
+ exitcode := t.Main("-Wall", "--autofix", "filename.mk")
t.CheckOutputLines(
"AUTOFIX: ~/filename.mk:1: Inserting a line \"" + MkCvsID + "\" before this line.")
@@ -309,7 +309,7 @@ func (s *Suite) Test_Pkglint_Main__profi
// Pkglint always writes the profiling data into the current directory.
// TODO: Make the location of the profiling log a mandatory parameter.
- t.CheckEquals(fileExists("pkglint.pprof"), true)
+ t.CheckEquals(NewPath("pkglint.pprof").IsFile(), true)
err := os.Remove("pkglint.pprof")
c.Check(err, check.IsNil)
@@ -860,7 +860,7 @@ func (s *Suite) Test_Pkglint_checkReg__a
lines := t.SetUpFileLines("category/package/ALTERNATIVES",
"bin/tar bin/gnu-tar")
- t.Main(lines.Filename)
+ t.Main(lines.Filename.String())
t.CheckOutputLines(
"ERROR: ~/category/package/ALTERNATIVES:1: Alternative implementation \"bin/gnu-tar\" must be an absolute path.",
@@ -961,7 +961,7 @@ func (s *Suite) Test_Pkglint_checkReg__r
// Copy category/package/** to wip/package.
err := filepath.Walk(
- t.File("category/package"),
+ t.File("category/package").String(),
func(pathname string, info os.FileInfo, err error) error {
if info.Mode().IsRegular() {
src := filepath.ToSlash(pathname)
@@ -1047,7 +1047,7 @@ func (s *Suite) Test_Pkglint_checkExecut
t := s.Init(c)
filename := t.CreateFileLines("file.mk")
- err := os.Chmod(filename, 0555)
+ err := os.Chmod(filename.String(), 0555)
assertNil(err, "")
G.checkExecutable(filename, 0555)
@@ -1065,7 +1065,7 @@ func (s *Suite) Test_Pkglint_checkExecut
// On Windows, this is effectively a no-op test since there is no
// execute-bit. The only relevant permissions bit is whether a
// file is readonly or not.
- st, err := os.Lstat(filename)
+ st, err := filename.Lstat()
if t.Check(err, check.IsNil) {
t.CheckEquals(st.Mode()&0111, os.FileMode(0))
}
Index: pkgsrc/pkgtools/pkglint/files/pkgsrc.go
diff -u pkgsrc/pkgtools/pkglint/files/pkgsrc.go:1.41 pkgsrc/pkgtools/pkglint/files/pkgsrc.go:1.42
--- pkgsrc/pkgtools/pkglint/files/pkgsrc.go:1.41 Tue Nov 19 06:51:38 2019
+++ pkgsrc/pkgtools/pkglint/files/pkgsrc.go Sat Nov 23 23:35:56 2019
@@ -1,7 +1,6 @@
package pkglint
import (
- "io/ioutil"
"netbsd.org/pkglint/regex"
"netbsd.org/pkglint/textproc"
"os"
@@ -20,7 +19,7 @@ import (
type Pkgsrc struct {
// The top directory (PKGSRCDIR), either absolute or relative to
// the current working directory.
- topdir string
+ topdir Path
// The set of user-defined variables that are added to BUILD_DEFS
// within the bsd.pkg.mk file.
@@ -36,7 +35,7 @@ type Pkgsrc struct {
suggestedUpdates []SuggestedUpdate
suggestedWipUpdates []SuggestedUpdate
- LastChange map[string]*Change
+ LastChange map[Path]*Change
LastFreezeStart string // e.g. "2018-01-01", or ""
LastFreezeEnd string // e.g. "2018-01-01", or ""
@@ -53,7 +52,7 @@ type Pkgsrc struct {
vartypes VarTypeRegistry
}
-func NewPkgsrc(dir string) Pkgsrc {
+func NewPkgsrc(dir Path) Pkgsrc {
return Pkgsrc{
dir,
make(map[string]bool),
@@ -63,7 +62,7 @@ func NewPkgsrc(dir string) Pkgsrc {
make(map[string]string),
nil,
nil,
- make(map[string]*Change),
+ make(map[Path]*Change),
"",
"",
make(map[string][]string),
@@ -149,15 +148,15 @@ func (src *Pkgsrc) loadDocChanges() {
NewLineWhole(docDir).Fatalf("Cannot be read for loading the package changes.")
}
- var filenames []string
+ var filenames []Path
for _, file := range files {
filename := file.Name()
if matches(filename, `^CHANGES-20\d\d$`) && filename >= "CHANGES-2011" { // TODO: Why 2011?
- filenames = append(filenames, filename)
+ filenames = append(filenames, NewPath(filename))
}
}
- src.LastChange = make(map[string]*Change)
+ src.LastChange = make(map[Path]*Change)
for _, filename := range filenames {
changes := src.loadDocChangesFromFile(joinPath(docDir, filename))
for _, change := range changes {
@@ -171,7 +170,7 @@ func (src *Pkgsrc) loadDocChanges() {
src.checkRemovedAfterLastFreeze()
}
-func (src *Pkgsrc) loadDocChangesFromFile(filename string) []*Change {
+func (src *Pkgsrc) loadDocChangesFromFile(filename Path) []*Change {
warn := G.Opts.CheckGlobal && !G.Wip
@@ -179,7 +178,7 @@ func (src *Pkgsrc) loadDocChangesFromFil
// This check has been added in 2018.
// For years earlier than 2018 pkglint doesn't care because it's not a big issue anyway.
year := ""
- if _, yyyy := match1(filename, `-(\d\d\d\d)$`); yyyy >= "2018" {
+ if _, yyyy := match1(filename.Base(), `-(\d\d\d\d)$`); yyyy >= "2018" {
year = yyyy
}
@@ -313,7 +312,7 @@ func (*Pkgsrc) parseDocChange(line *Line
return &Change{
Location: line.Location,
Action: action,
- Pkgpath: intern(pkgpath),
+ Pkgpath: NewPath(intern(pkgpath)),
target: intern(condStr(n == 6, f[3], "")),
Author: intern(author),
Date: intern(date),
@@ -332,7 +331,7 @@ func (src *Pkgsrc) checkRemovedAfterLast
for pkgpath, change := range src.LastChange {
switch change.Action {
case Added, Updated, Downgraded:
- if !dirExists(src.File(pkgpath)) {
+ if !src.File(pkgpath).IsDir() {
wrong = append(wrong, change)
}
}
@@ -360,32 +359,33 @@ func (src *Pkgsrc) parseSuggestedUpdates
}
var updates []SuggestedUpdate
- state := 0
- for _, line := range lines.Lines {
+
+ llex := NewLinesLexer(lines)
+ for !llex.EOF() && !llex.SkipText("Suggested package updates") {
+ llex.Skip()
+ }
+ for !llex.EOF() && !llex.SkipText("") {
+ llex.Skip()
+ }
+ for llex.SkipText("") {
+ }
+
+ for !llex.EOF() && !llex.SkipText("") {
+ line := llex.CurrentLine()
text := line.Text
+ llex.Skip()
- // TODO: Replace this state transition scheme with explicit code,
- // hoping that the code will be easier to understand.
- 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[\t ]([^\t ]+)(?:[\t ]*(.+))?$`); m {
- if m, pkgbase, pkgversion := match2(pkgname, rePkgname); m {
- updates = append(updates, SuggestedUpdate{line.Location, intern(pkgbase), intern(pkgversion), intern(comment)})
- } else {
- line.Warnf("Invalid package name %q.", pkgname)
+ if m, pkgname, comment := match2(text, `^\to[\t ]([^\t ]+)(?:[\t ]*(.+))?$`); m {
+ if m, pkgbase, pkgversion := match2(pkgname, rePkgname); m {
+ if hasPrefix(comment, "[") && hasSuffix(comment, "]") {
+ comment = comment[1 : len(comment)-1]
}
+ updates = append(updates, SuggestedUpdate{line.Location, intern(pkgbase), intern(pkgversion), intern(comment)})
} else {
- line.Warnf("Invalid line format %q.", text)
+ line.Warnf("Invalid package name %q.", pkgname)
}
+ } else {
+ line.Warnf("Invalid line format %q.", text)
}
}
return updates
@@ -405,14 +405,14 @@ func (src *Pkgsrc) loadUserDefinedVars()
func (src *Pkgsrc) loadTools() {
tools := src.Tools
- toolFiles := []string{"defaults.mk"}
+ toolFiles := []Path{"defaults.mk"}
{
toc := src.File("mk/tools/bsd.tools.mk")
mklines := LoadMk(toc, MustSucceed|NotEmpty)
for _, mkline := range mklines.mklines {
if mkline.IsInclude() {
includedFile := mkline.IncludedFile()
- if !contains(includedFile, "/") {
+ if !includedFile.ContainsText("/") {
toolFiles = append(toolFiles, includedFile)
}
}
@@ -436,7 +436,7 @@ func (src *Pkgsrc) loadTools() {
})
}
- for _, relativeName := range [...]string{"mk/bsd.prefs.mk", "mk/bsd.pkg.mk"} {
+ for _, relativeName := range [...]Path{"mk/bsd.prefs.mk", "mk/bsd.pkg.mk"} {
mklines := src.LoadMk(relativeName, MustSucceed|NotEmpty)
mklines.ForEach(func(mkline *MkLine) {
@@ -670,7 +670,7 @@ func (src *Pkgsrc) loadUntypedVars() {
}
}
- handleMkFile := func(path string) {
+ handleMkFile := func(path Path) {
mklines := LoadMk(path, MustSucceed)
mklines.collectVariables()
mklines.collectUsedVariables()
@@ -686,12 +686,12 @@ func (src *Pkgsrc) loadUntypedVars() {
assertNil(err, "handleFile %q", pathName)
baseName := info.Name()
if info.Mode().IsRegular() && (hasSuffix(baseName, ".mk") || baseName == "mk.conf") {
- handleMkFile(filepath.ToSlash(pathName))
+ handleMkFile(NewPath(filepath.ToSlash(pathName))) // FIXME: This is too deep to handle os-specific paths
}
return nil
}
- err := filepath.Walk(src.File("mk"), handleFile)
+ err := filepath.Walk(src.File("mk").String(), handleFile)
assertNil(err, "Walk error in pkgsrc infrastructure")
}
@@ -775,7 +775,7 @@ func (src *Pkgsrc) loadDefaultBuildDefs(
// Example:
// Latest("lang", `^php[0-9]+$`, "../../lang/$0")
// => "../../lang/php72"
-func (src *Pkgsrc) Latest(category string, re regex.Pattern, repl string) string {
+func (src *Pkgsrc) Latest(category Path, re regex.Pattern, repl string) string {
versions := src.ListVersions(category, re, repl, true)
if len(versions) > 0 {
@@ -791,7 +791,7 @@ func (src *Pkgsrc) Latest(category strin
// Example:
// ListVersions("lang", `^php[0-9]+$`, "php-$0")
// => {"php-53", "php-56", "php-73"}
-func (src *Pkgsrc) ListVersions(category string, re regex.Pattern, repl string, errorIfEmpty bool) []string {
+func (src *Pkgsrc) ListVersions(category Path, re regex.Pattern, repl string, errorIfEmpty bool) []string {
if G.Testing {
// Regular expression must be anchored at both ends, to avoid typos.
assert(hasPrefix(string(re), "^"))
@@ -799,13 +799,11 @@ func (src *Pkgsrc) ListVersions(category
}
// TODO: Maybe convert cache key to a struct, to save allocations.
- cacheKey := category + "/" + string(re) + " => " + repl
+ cacheKey := category.String() + "/" + string(re) + " => " + repl
if latest, found := src.listVersions[cacheKey]; found {
return latest
}
- categoryDir := src.File(category)
-
var names []string
for _, fileInfo := range src.ReadDir(category) {
name := fileInfo.Name()
@@ -815,7 +813,7 @@ func (src *Pkgsrc) ListVersions(category
}
if len(names) == 0 {
if errorIfEmpty {
- dummyLine.Errorf("Cannot find package versions of %q in %q.", re, categoryDir)
+ dummyLine.Errorf("Cannot find package versions of %q in %q.", re, src.File(category))
}
src.listVersions[cacheKey] = nil
return nil
@@ -973,7 +971,7 @@ func (src *Pkgsrc) checkToplevelUnusedLi
for _, licenseFile := range src.ReadDir("licenses") {
licenseName := licenseFile.Name()
if !G.InterPackage.IsLicenseUsed(licenseName) {
- licensePath := joinPath(licensesDir, licenseName)
+ licensePath := joinPath(licensesDir, NewPath(licenseName))
NewLineWhole(licensePath).Warnf("This license seems to be unused.")
}
}
@@ -997,9 +995,9 @@ func (src *Pkgsrc) IsBuildDef(varname st
// ReadDir lists the files and subdirectories from the given directory
// (relative to the pkgsrc root), filtering out any ignored files (CVS/*)
// and empty directories.
-func (src *Pkgsrc) ReadDir(dirName string) []os.FileInfo {
+func (src *Pkgsrc) ReadDir(dirName Path) []os.FileInfo {
dir := src.File(dirName)
- files, err := ioutil.ReadDir(dir)
+ files, err := dir.ReadDir()
if err != nil {
return nil
}
@@ -1007,7 +1005,7 @@ func (src *Pkgsrc) ReadDir(dirName strin
var relevantFiles []os.FileInfo
for _, dirent := range files {
name := dirent.Name()
- if !dirent.IsDir() || !isIgnoredFilename(name) && !isEmptyDir(joinPath(dir, name)) {
+ if !dirent.IsDir() || !isIgnoredFilename(name) && !isEmptyDir(dir.JoinNoClean(NewPath(name))) {
relevantFiles = append(relevantFiles, dirent)
}
}
@@ -1015,22 +1013,25 @@ func (src *Pkgsrc) ReadDir(dirName strin
return relevantFiles
}
-func (src *Pkgsrc) LoadMkInfra(filename string, options LoadOptions) *MkLines {
- if G.Testing {
- // During testing, the infrastructure files don't have to exist.
- // They are often emulated by setting their data structures manually.
- options &^= MustSucceed
+// LoadMkExisting loads a file that must exist.
+//
+// During pkglint testing, these files often don't exist, as they are
+// emulated by setting their data structures manually.
+func (src *Pkgsrc) LoadMkExisting(filename Path) *MkLines {
+ options := NotEmpty
+ if !G.Testing {
+ options |= MustSucceed
}
return src.LoadMk(filename, options)
}
// LoadMk loads the Makefile relative to the pkgsrc top directory.
-func (src *Pkgsrc) LoadMk(filename string, options LoadOptions) *MkLines {
+func (src *Pkgsrc) LoadMk(filename Path, options LoadOptions) *MkLines {
return LoadMk(src.File(filename), options)
}
// Load loads the file relative to the pkgsrc top directory.
-func (src *Pkgsrc) Load(filename string, options LoadOptions) *Lines {
+func (src *Pkgsrc) Load(filename Path, options LoadOptions) *Lines {
return Load(src.File(filename), options)
}
@@ -1038,7 +1039,7 @@ func (src *Pkgsrc) Load(filename string,
//
// Example:
// NewPkgsrc("/usr/pkgsrc").File("distfiles") => "/usr/pkgsrc/distfiles"
-func (src *Pkgsrc) File(relativeName string) string {
+func (src *Pkgsrc) File(relativeName Path) Path {
// TODO: Package.File resolves variables, Pkgsrc.File doesn't. They should behave the same.
return cleanpath(joinPath(src.topdir, relativeName))
}
@@ -1047,23 +1048,23 @@ func (src *Pkgsrc) File(relativeName str
//
// Example:
// NewPkgsrc("/usr/pkgsrc").ToRel("/usr/pkgsrc/distfiles") => "distfiles"
-func (src *Pkgsrc) ToRel(filename string) string {
+func (src *Pkgsrc) ToRel(filename Path) Path {
return relpath(src.topdir, filename)
}
// IsInfra returns whether the given filename (relative to the pkglint
// working directory) is part of the pkgsrc infrastructure.
-func (src *Pkgsrc) IsInfra(filename string) bool {
+func (src *Pkgsrc) IsInfra(filename Path) bool {
rel := src.ToRel(filename)
- return hasPrefix(rel, "mk/") || hasPrefix(rel, "wip/mk/")
+ return rel.HasPrefixPath("mk") || rel.HasPrefixPath("wip/mk")
}
// Change describes a modification to a single package, from the doc/CHANGES-* files.
type Change struct {
Location Location
Action ChangeAction // Added, Updated, Downgraded, Renamed, Moved, Removed
- Pkgpath string // For renamed or moved packages, the previous PKGPATH
- target string
+ Pkgpath Path // For renamed or moved packages, the previous PKGPATH
+ target string // The path or version number, depending on the action
Author string
Date string
}
@@ -1075,9 +1076,9 @@ func (ch *Change) Version() string {
}
// Target returns the target PKGPATH for a Renamed or Moved package.
-func (ch *Change) Target() string {
+func (ch *Change) Target() Path {
assert(ch.Action == Renamed || ch.Action == Moved)
- return ch.target
+ return NewPath(ch.target)
}
// Successor returns the successor for a Removed package.
Index: pkgsrc/pkgtools/pkglint/files/plist.go
diff -u pkgsrc/pkgtools/pkglint/files/plist.go:1.44 pkgsrc/pkgtools/pkglint/files/plist.go:1.45
--- pkgsrc/pkgtools/pkglint/files/plist.go:1.44 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/plist.go Sat Nov 23 23:35:56 2019
@@ -9,7 +9,7 @@ import (
func CheckLinesPlist(pkg *Package, lines *Lines) {
if trace.Tracing {
- defer trace.Call1(lines.Filename)()
+ defer trace.Call(lines.Filename)()
}
idOk := lines.CheckCvsID(0, `@comment `, "@comment ")
@@ -31,8 +31,8 @@ func CheckLinesPlist(pkg *Package, lines
ck := PlistChecker{
pkg,
- make(map[string]*PlistLine),
- make(map[string]*PlistLine),
+ make(map[Path]*PlistLine),
+ make(map[Path]*PlistLine),
"",
Once{},
false}
@@ -41,8 +41,8 @@ func CheckLinesPlist(pkg *Package, lines
type PlistChecker struct {
pkg *Package
- allFiles map[string]*PlistLine
- allDirs map[string]*PlistLine
+ allFiles map[Path]*PlistLine
+ allDirs map[Path]*PlistLine
lastFname string
once Once
nonAsciiAllowed bool
@@ -53,7 +53,7 @@ func (ck *PlistChecker) Load(lines *Line
ck.collectFilesAndDirs(plines)
if lines.BaseName == "PLIST.common_end" {
- commonLines := Load(strings.TrimSuffix(lines.Filename, "_end"), NotEmpty)
+ commonLines := Load(lines.Filename.TrimSuffix("_end"), NotEmpty)
if commonLines != nil {
ck.collectFilesAndDirs(ck.NewLines(commonLines))
}
@@ -107,15 +107,16 @@ func (ck *PlistChecker) collectFilesAndD
first := text[0]
switch {
case plistLineStart.Contains(first):
- if prev := ck.allFiles[text]; prev == nil || stringSliceLess(pline.conditions, prev.conditions) {
- ck.allFiles[text] = pline
+ path := NewPath(text)
+ if prev := ck.allFiles[path]; prev == nil || stringSliceLess(pline.conditions, prev.conditions) {
+ ck.allFiles[path] = pline
}
- for dir := path.Dir(text); dir != "."; dir = path.Dir(dir) {
+ for dir := path.Dir(); dir != "."; dir = dir.Dir() {
ck.allDirs[dir] = pline
}
case first == '@':
if m, dirname := match1(text, `^@exec \$\{MKDIR\} %D/(.*)$`); m {
- for dir := dirname; dir != "."; dir = path.Dir(dir) {
+ for dir := NewPath(dirname); dir != "."; dir = dir.Dir() {
ck.allDirs[dir] = pline
}
}
@@ -259,7 +260,7 @@ func (ck *PlistChecker) checkDuplicate(p
return
}
- prev := ck.allFiles[text]
+ prev := ck.allFiles[NewPath(text)]
if prev == pline || len(prev.conditions) > 0 {
return
}
@@ -317,7 +318,7 @@ func (ck *PlistChecker) checkPathLib(pli
if contains(basename, ".a") || contains(basename, ".so") {
if m, noext := match1(pline.text, `^(.*)(?:\.a|\.so[0-9.]*)$`); m {
- if laLine := ck.allFiles[noext+".la"]; laLine != nil {
+ if laLine := ck.allFiles[NewPath(noext+".la")]; laLine != nil {
pline.Warnf("Redundant library found. The libtool library is in %s.", pline.RefTo(laLine.Line))
}
}
@@ -350,7 +351,7 @@ func (ck *PlistChecker) checkPathMan(pli
pline.Warnf("Unknown section %q for manual page.", section)
}
- if catOrMan == "cat" && ck.allFiles["man/man"+section+"/"+manpage+"."+section] == nil {
+ if catOrMan == "cat" && ck.allFiles[NewPath("man/man"+section+"/"+manpage+"."+section)] == nil {
pline.Warnf("Preformatted manual page without unformatted one.")
}
Index: pkgsrc/pkgtools/pkglint/files/redundantscope.go
diff -u pkgsrc/pkgtools/pkglint/files/redundantscope.go:1.7 pkgsrc/pkgtools/pkglint/files/redundantscope.go:1.8
--- pkgsrc/pkgtools/pkglint/files/redundantscope.go:1.7 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/redundantscope.go Sat Nov 23 23:35:56 2019
@@ -223,14 +223,14 @@ func (s *RedundantScope) onOverwrite(ove
// one of two variable assignments is redundant. Two assignments can
// only be redundant if one location includes the other.
type includePath struct {
- files []string
+ files []Path
}
-func (p *includePath) push(filename string) {
+func (p *includePath) push(filename Path) {
p.files = append(p.files, filename)
}
-func (p *includePath) popUntil(filename string) {
+func (p *includePath) popUntil(filename Path) {
for p.files[len(p.files)-1] != filename {
p.files = p.files[:len(p.files)-1]
}
@@ -276,5 +276,5 @@ func (p *includePath) equals(other inclu
}
func (p *includePath) copy() includePath {
- return includePath{append([]string(nil), p.files...)}
+ return includePath{append([]Path(nil), p.files...)}
}
Index: pkgsrc/pkgtools/pkglint/files/redundantscope_test.go
diff -u pkgsrc/pkgtools/pkglint/files/redundantscope_test.go:1.7 pkgsrc/pkgtools/pkglint/files/redundantscope_test.go:1.8
--- pkgsrc/pkgtools/pkglint/files/redundantscope_test.go:1.7 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/redundantscope_test.go Sat Nov 23 23:35:56 2019
@@ -1525,7 +1525,7 @@ func (s *Suite) Test_RedundantScope_hand
func (s *Suite) Test_includePath_includes(c *check.C) {
t := s.Init(c)
- path := func(locations ...string) includePath {
+ path := func(locations ...Path) includePath {
return includePath{locations}
}
@@ -1550,7 +1550,7 @@ func (s *Suite) Test_includePath_include
func (s *Suite) Test_includePath_equals(c *check.C) {
t := s.Init(c)
- path := func(locations ...string) includePath {
+ path := func(locations ...Path) includePath {
return includePath{locations}
}
Index: pkgsrc/pkgtools/pkglint/files/shell_test.go
diff -u pkgsrc/pkgtools/pkglint/files/shell_test.go:1.56 pkgsrc/pkgtools/pkglint/files/shell_test.go:1.57
--- pkgsrc/pkgtools/pkglint/files/shell_test.go:1.56 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/shell_test.go Sat Nov 23 23:35:56 2019
@@ -912,7 +912,10 @@ func (s *Suite) Test_ShellLineChecker_Ch
"WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Make variable or $$f if you mean a shell variable.",
"WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Make variable or $$f if you mean a shell variable.",
"NOTE: Makefile:3: Please use the SUBST framework instead of ${SED} and ${MV}.",
- "WARN: Makefile:3: f is used but not defined.")
+ "WARN: Makefile:3: f is used but not defined.",
+ // TODO: Avoid these duplicate diagnostics.
+ "WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Make variable or $$f if you mean a shell variable.",
+ "WARN: Makefile:3: $f is ambiguous. Use ${f} if you mean a Make variable or $$f if you mean a shell variable.")
ck.CheckShellCommandLine("install -c manpage.1 ${PREFIX}/man/man1/manpage.1")
Index: pkgsrc/pkgtools/pkglint/files/shtokenizer.go
diff -u pkgsrc/pkgtools/pkglint/files/shtokenizer.go:1.19 pkgsrc/pkgtools/pkglint/files/shtokenizer.go:1.20
--- pkgsrc/pkgtools/pkglint/files/shtokenizer.go:1.19 Mon Jul 1 22:25:52 2019
+++ pkgsrc/pkgtools/pkglint/files/shtokenizer.go Sat Nov 23 23:35:56 2019
@@ -8,6 +8,7 @@ type ShTokenizer struct {
func NewShTokenizer(line *Line, text string, emitWarnings bool) *ShTokenizer {
// TODO: Switching to NewMkParser is nontrivial since emitWarnings must equal (line != nil).
+ // assert((line != nil) == emitWarnings)
p := MkParser{line, textproc.NewLexer(text), emitWarnings}
return &ShTokenizer{&p}
}
Index: pkgsrc/pkgtools/pkglint/files/tools.go
diff -u pkgsrc/pkgtools/pkglint/files/tools.go:1.19 pkgsrc/pkgtools/pkglint/files/tools.go:1.20
--- pkgsrc/pkgtools/pkglint/files/tools.go:1.19 Sun Sep 8 22:47:47 2019
+++ pkgsrc/pkgtools/pkglint/files/tools.go Sat Nov 23 23:35:56 2019
@@ -345,7 +345,7 @@ func (tr *Tools) implicitTools(toolName
func (tr *Tools) validity(basename string, useTools bool) Validity {
switch {
- case IsPrefs(basename): // IsPrefs is not 100% accurate here but good enough
+ case IsPrefs(NewPath(basename)): // IsPrefs is not 100% accurate here but good enough
return AfterPrefsMk
case basename == "Makefile" && !tr.SeenPrefs:
return AfterPrefsMk
Index: pkgsrc/pkgtools/pkglint/files/testnames_test.go
diff -u pkgsrc/pkgtools/pkglint/files/testnames_test.go:1.8 pkgsrc/pkgtools/pkglint/files/testnames_test.go:1.9
--- pkgsrc/pkgtools/pkglint/files/testnames_test.go:1.8 Tue Nov 19 06:51:38 2019
+++ pkgsrc/pkgtools/pkglint/files/testnames_test.go Sat Nov 23 23:35:56 2019
@@ -11,6 +11,7 @@ import (
func (s *Suite) Test__test_names(c *check.C) {
ck := intqa.NewTestNameChecker(c.Errorf)
ck.Configure("*", "*", "*", -intqa.EMissingTest)
+ ck.Configure("path.go", "*", "*", +intqa.EMissingTest)
ck.Configure("*yacc.go", "*", "*", intqa.ENone)
ck.Check()
}
Index: pkgsrc/pkgtools/pkglint/files/tools_test.go
diff -u pkgsrc/pkgtools/pkglint/files/tools_test.go:1.21 pkgsrc/pkgtools/pkglint/files/tools_test.go:1.22
--- pkgsrc/pkgtools/pkglint/files/tools_test.go:1.21 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/tools_test.go Sat Nov 23 23:35:56 2019
@@ -46,7 +46,7 @@ func (s *Suite) Test_Tools__USE_TOOLS_pr
"\t${SED} < input > output",
"\t${AWK} < input > output")
- t.Main("-Wall", t.File("module.mk"))
+ t.Main("-Wall", "module.mk")
// Since this test doesn't load the usual tool definitions via
// G.Pkgsrc.loadTools, AWK is not known at all.
Index: pkgsrc/pkgtools/pkglint/files/toplevel.go
diff -u pkgsrc/pkgtools/pkglint/files/toplevel.go:1.23 pkgsrc/pkgtools/pkglint/files/toplevel.go:1.24
--- pkgsrc/pkgtools/pkglint/files/toplevel.go:1.23 Fri Nov 1 19:56:53 2019
+++ pkgsrc/pkgtools/pkglint/files/toplevel.go Sat Nov 23 23:35:56 2019
@@ -1,14 +1,14 @@
package pkglint
type Toplevel struct {
- dir string
- previousSubdir string
- subdirs []string
+ dir Path
+ previousSubdir Path
+ subdirs []Path
}
-func CheckdirToplevel(dir string) {
+func CheckdirToplevel(dir Path) {
if trace.Tracing {
- defer trace.Call1(dir)()
+ defer trace.Call(dir)()
}
ctx := Toplevel{dir, "", nil}
@@ -36,7 +36,7 @@ func CheckdirToplevel(dir string) {
}
func (ctx *Toplevel) checkSubdir(mkline *MkLine) {
- subdir := mkline.Value()
+ subdir := NewPath(mkline.Value())
if mkline.IsCommentedVarassign() {
if !mkline.HasComment() || mkline.Comment() == "" {
@@ -44,7 +44,7 @@ func (ctx *Toplevel) checkSubdir(mkline
}
}
- if containsVarRef(subdir) || !fileExists(joinPath(ctx.dir, subdir, "Makefile")) {
+ if containsVarRef(subdir.String()) || !ctx.dir.JoinNoClean(subdir).JoinNoClean("Makefile").IsFile() {
return
}
Index: pkgsrc/pkgtools/pkglint/files/vardefs_test.go
diff -u pkgsrc/pkgtools/pkglint/files/vardefs_test.go:1.23 pkgsrc/pkgtools/pkglint/files/vardefs_test.go:1.24
--- pkgsrc/pkgtools/pkglint/files/vardefs_test.go:1.23 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/vardefs_test.go Sat Nov 23 23:35:56 2019
@@ -178,7 +178,7 @@ func (s *Suite) Test_VarTypeRegistry_Ini
G.Testing = false
t.ExpectFatal(
t.FinishSetUp,
- "FATAL: ~/mk/fetch/sites.mk: Cannot be read.")
+ "FATAL: ~/editors/emacs/modules.mk: Cannot be read.")
}
func (s *Suite) Test_VarTypeRegistry_Init__MASTER_SITES(c *check.C) {
Index: pkgsrc/pkgtools/pkglint/files/vardefs.go
diff -u pkgsrc/pkgtools/pkglint/files/vardefs.go:1.77 pkgsrc/pkgtools/pkglint/files/vardefs.go:1.78
--- pkgsrc/pkgtools/pkglint/files/vardefs.go:1.77 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/vardefs.go Sat Nov 23 23:35:56 2019
@@ -2,7 +2,6 @@ package pkglint
import (
"netbsd.org/pkglint/regex"
- "path"
"strings"
)
@@ -331,7 +330,7 @@ func (reg *VarTypeRegistry) infralist(va
// compilerLanguages reads the available languages that are typically
// bundled in a single compiler framework, such as GCC or Clang.
func (reg *VarTypeRegistry) compilerLanguages(src *Pkgsrc) *BasicType {
- mklines := src.LoadMkInfra("mk/compiler.mk", NotEmpty|MustSucceed)
+ mklines := src.LoadMkExisting("mk/compiler.mk")
languages := make(map[string]bool)
if mklines != nil {
@@ -371,8 +370,8 @@ func (reg *VarTypeRegistry) compilerLang
//
// If the file cannot be found, the allowed values are taken from
// defval. This is mostly useful when testing pkglint.
-func (reg *VarTypeRegistry) enumFrom(pkgsrc *Pkgsrc, filename string, defval string, varcanons ...string) *BasicType {
- mklines := LoadMk(pkgsrc.File(filename), NotEmpty)
+func (reg *VarTypeRegistry) enumFrom(pkgsrc *Pkgsrc, filename Path, defval string, varcanons ...string) *BasicType {
+ mklines := pkgsrc.LoadMkExisting(filename)
if mklines == nil {
return enum(defval)
}
@@ -419,7 +418,7 @@ func (reg *VarTypeRegistry) enumFrom(pkg
//
// If the directories cannot be found, the allowed values are taken
// from defval. This is mostly useful when testing pkglint.
-func (reg *VarTypeRegistry) enumFromDirs(pkgsrc *Pkgsrc, category string, re regex.Pattern, repl string, defval string) *BasicType {
+func (reg *VarTypeRegistry) enumFromDirs(pkgsrc *Pkgsrc, category Path, re regex.Pattern, repl string, defval string) *BasicType {
versions := pkgsrc.ListVersions(category, re, repl, false)
if len(versions) == 0 {
return enum(defval)
@@ -432,10 +431,10 @@ func (reg *VarTypeRegistry) enumFromDirs
//
// If no files are found, the allowed values are taken
// from defval. This should only happen in the pkglint tests.
-func (reg *VarTypeRegistry) enumFromFiles(basedir string, re regex.Pattern, repl string, defval string) *BasicType {
+func (reg *VarTypeRegistry) enumFromFiles(basedir Path, re regex.Pattern, repl string, defval string) *BasicType {
var relevant []string
for _, filename := range dirglob(G.Pkgsrc.File(basedir)) {
- basename := path.Base(filename)
+ basename := filename.Base()
if matches(basename, re) {
relevant = append(relevant, replaceAll(basename, re, repl))
}
@@ -1249,8 +1248,8 @@ func (reg *VarTypeRegistry) Init(src *Pk
reg.sys("MANOWN", BtUserGroupName)
reg.pkglist("MASTER_SITES", BtFetchURL)
- for _, filename := range []string{"mk/fetch/sites.mk", "mk/fetch/fetch.mk"} {
- sitesMk := src.LoadMkInfra(filename, NotEmpty|MustSucceed)
+ for _, filename := range []Path{"mk/fetch/sites.mk", "mk/fetch/fetch.mk"} {
+ sitesMk := src.LoadMkExisting(filename)
if sitesMk != nil {
sitesMk.ForEach(func(mkline *MkLine) {
if mkline.IsVarassign() && hasPrefix(mkline.Varname(), "MASTER_SITE_") {
Index: pkgsrc/pkgtools/pkglint/files/vartypecheck.go
diff -u pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.66 pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.67
--- pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.66 Sun Nov 17 01:26:25 2019
+++ pkgsrc/pkgtools/pkglint/files/vartypecheck.go Sat Nov 23 23:35:56 2019
@@ -225,7 +225,7 @@ func (cv *VartypeCheck) BuildlinkDepmeth
}
func (cv *VartypeCheck) Category() {
- if cv.Value != "wip" && fileExists(G.Pkgsrc.File(cv.Value+"/Makefile")) {
+ if cv.Value != "wip" && G.Pkgsrc.File(NewPath(cv.Value).JoinNoClean("Makefile")).IsFile() {
return
}
@@ -452,7 +452,7 @@ func (cv *VartypeCheck) DependencyWithPa
}
if !containsVarRef(relpath) {
- MkLineChecker{cv.MkLines, cv.MkLine}.CheckRelativePkgdir(relpath)
+ MkLineChecker{cv.MkLines, cv.MkLine}.CheckRelativePkgdir(NewPath(relpath))
}
switch pkg {
@@ -1073,22 +1073,23 @@ func (cv *VartypeCheck) PkgOptionsVar()
func (cv *VartypeCheck) Pkgpath() {
cv.Pathname()
- pkgpath := cv.Value
- if pkgpath != cv.ValueNoVar || cv.Op == opUseMatch {
+ value := cv.Value
+ if value != cv.ValueNoVar || cv.Op == opUseMatch {
return
}
- if !G.Wip && hasPrefix(pkgpath, "wip/") {
+ pkgpath := NewPath(value)
+ if !G.Wip && pkgpath.HasPrefixPath("wip") {
cv.MkLine.Errorf("A main pkgsrc package must not depend on a pkgsrc-wip package.")
}
- if !fileExists(G.Pkgsrc.File(joinPath(pkgpath, "Makefile"))) {
+ if !G.Pkgsrc.File(pkgpath.JoinNoClean("Makefile")).IsFile() {
cv.MkLine.Errorf("There is no package in %q.",
- relpath(path.Dir(cv.MkLine.Filename), G.Pkgsrc.File(pkgpath)))
+ cv.MkLine.PathToFile(G.Pkgsrc.File(pkgpath)))
return
}
- if !matches(pkgpath, `^([^./][^/]*/[^./][^/]*)$`) {
+ if !matches(value, `^([^./][^/]*/[^./][^/]*)$`) {
cv.MkLine.Errorf("%q is not a valid path to a package.", pkgpath)
cv.MkLine.Explain(
"A path to a package has the form \"category/pkgbase\".",
@@ -1164,7 +1165,7 @@ func (cv *VartypeCheck) RPkgVer() {
// RelativePkgDir refers to a package directory, e.g. ../../category/pkgbase.
func (cv *VartypeCheck) RelativePkgDir() {
- MkLineChecker{cv.MkLines, cv.MkLine}.CheckRelativePkgdir(cv.Value)
+ MkLineChecker{cv.MkLines, cv.MkLine}.CheckRelativePkgdir(NewPath(cv.Value))
}
// RelativePkgPath refers to a file or directory, e.g. ../../category/pkgbase,
@@ -1172,7 +1173,7 @@ func (cv *VartypeCheck) RelativePkgDir()
//
// See RelativePkgDir, which requires a directory, not a file.
func (cv *VartypeCheck) RelativePkgPath() {
- MkLineChecker{cv.MkLines, cv.MkLine}.CheckRelativePath(cv.Value, true)
+ MkLineChecker{cv.MkLines, cv.MkLine}.CheckRelativePath(NewPath(cv.Value), true)
}
func (cv *VartypeCheck) Restricted() {
Index: pkgsrc/pkgtools/pkglint/files/textproc/lexer.go
diff -u pkgsrc/pkgtools/pkglint/files/textproc/lexer.go:1.6 pkgsrc/pkgtools/pkglint/files/textproc/lexer.go:1.7
--- pkgsrc/pkgtools/pkglint/files/textproc/lexer.go:1.6 Tue Oct 1 21:38:00 2019
+++ pkgsrc/pkgtools/pkglint/files/textproc/lexer.go Sat Nov 23 23:35:56 2019
@@ -75,7 +75,7 @@ func (l *Lexer) NextString(prefix string
return ""
}
-// SkipString skips over the given string, if the remaining string starts
+// SkipText skips over the given string, if the remaining string starts
// with it. It returns whether it actually skipped.
func (l *Lexer) SkipString(prefix string) bool {
skipped := strings.HasPrefix(l.rest, prefix)
Index: pkgsrc/pkgtools/pkglint/files/trace/tracing.go
diff -u pkgsrc/pkgtools/pkglint/files/trace/tracing.go:1.10 pkgsrc/pkgtools/pkglint/files/trace/tracing.go:1.11
--- pkgsrc/pkgtools/pkglint/files/trace/tracing.go:1.10 Sun Jun 30 20:56:19 2019
+++ pkgsrc/pkgtools/pkglint/files/trace/tracing.go Sat Nov 23 23:35:56 2019
@@ -92,7 +92,9 @@ func argsStr(args []interface{}) string
if rv.Len() > 0 {
rv.WriteString(", ")
}
- if str, ok := arg.(fmt.Stringer); ok && !isNil(str) {
+ if str, ok := arg.(fmt.GoStringer); ok && !isNil(str) {
+ rv.WriteString(str.GoString())
+ } else if str, ok := arg.(fmt.Stringer); ok && !isNil(str) {
rv.WriteString(str.String())
} else {
_, _ = fmt.Fprintf(&rv, "%#v", arg)
Home |
Main Index |
Thread Index |
Old Index