summaryrefslogtreecommitdiff
path: root/pkgtools/pkglint/files/util.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkgtools/pkglint/files/util.go')
-rw-r--r--pkgtools/pkglint/files/util.go123
1 files changed, 55 insertions, 68 deletions
diff --git a/pkgtools/pkglint/files/util.go b/pkgtools/pkglint/files/util.go
index 0c832a21679..b9648c6580d 100644
--- a/pkgtools/pkglint/files/util.go
+++ b/pkgtools/pkglint/files/util.go
@@ -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, args ...interface{}) {
}
}
-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) bool {
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 string, right bool, to string, flags st
})
}
-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 ...string) string {
//
// 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 string) {
}
// 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 string) {
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 string) bool {
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, options LoadOptions) *Lines {
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 string) {
}
}
-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