summaryrefslogtreecommitdiff
path: root/pkgtools/pkglint/files/path.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkgtools/pkglint/files/path.go')
-rw-r--r--pkgtools/pkglint/files/path.go162
1 files changed, 162 insertions, 0 deletions
diff --git a/pkgtools/pkglint/files/path.go b/pkgtools/pkglint/files/path.go
new file mode 100644
index 00000000000..746c5572fc7
--- /dev/null
+++ b/pkgtools/pkglint/files/path.go
@@ -0,0 +1,162 @@
+package pkglint
+
+import (
+ "io/ioutil"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+)
+
+// Path is a slash-separated path in the filesystem.
+// It may be absolute or relative.
+// Some paths may contain placeholders like @VAR@ or ${VAR}.
+// The base directory of relative paths depends on the context
+// in which the path is used.
+type Path string
+
+func NewPath(name string) Path { return Path(name) }
+
+func NewPathSlash(name string) Path { return Path(filepath.ToSlash(name)) }
+
+func (p Path) String() string { return string(p) }
+
+func (p Path) GoString() string { return sprintf("%q", string(p)) }
+
+func (p Path) Dir() Path { return Path(path.Dir(string(p))) }
+
+func (p Path) Base() string { return path.Base(string(p)) }
+
+func (p Path) Split() (dir Path, base string) {
+ strDir, strBase := path.Split(string(p))
+ return Path(strDir), strBase
+}
+
+func (p Path) Parts() []string {
+ return strings.FieldsFunc(string(p), func(r rune) bool { return r == '/' })
+}
+
+func (p Path) Count() int { return len(p.Parts()) }
+
+func (p Path) HasPrefixText(prefix string) bool {
+ return hasPrefix(string(p), prefix)
+}
+
+// HasPrefixPath returns whether the path starts with the given prefix.
+// The basic unit of comparison is a path component, not a character.
+func (p Path) HasPrefixPath(prefix Path) bool {
+ return hasPrefix(string(p), string(prefix)) &&
+ (len(p) == len(prefix) || p[len(prefix)] == '/')
+}
+
+// TODO: Check each call whether ContainsPath is more appropriate; add tests
+func (p Path) ContainsText(contained string) bool {
+ return contains(string(p), contained)
+}
+
+// ContainsPath returns whether the sub path is part of the path.
+// The basic unit of comparison is a path component, not a character.
+//
+// Note that the paths used in pkglint may contains seemingly unnecessary
+// components, like "../../wip/mk/../../devel/gettext-lib". To ignore these
+// components, use ContainsPathCanonical instead.
+func (p Path) ContainsPath(sub Path) bool {
+ limit := len(p) - len(sub)
+ for i := 0; i <= limit; i++ {
+ if (i == 0 || p[i-1] == '/') && p[i:].HasPrefixPath(sub) {
+ return true
+ }
+ }
+ return sub == "."
+}
+
+func (p Path) ContainsPathCanonical(sub Path) bool {
+ cleaned := cleanpath(p)
+ return cleaned.ContainsPath(sub)
+}
+
+// TODO: Check each call whether HasSuffixPath is more appropriate; add tests
+func (p Path) HasSuffixText(suffix string) bool {
+ return hasSuffix(string(p), suffix)
+}
+
+// HasSuffixPath returns whether the path ends with the given prefix.
+// The basic unit of comparison is a path component, not a character.
+func (p Path) HasSuffixPath(suffix Path) bool {
+ return hasSuffix(string(p), string(suffix)) &&
+ (len(p) == len(suffix) || p[len(p)-len(suffix)-1] == '/')
+}
+
+func (p Path) HasBase(base string) bool { return p.Base() == base }
+
+func (p Path) TrimSuffix(suffix string) Path {
+ return Path(strings.TrimSuffix(string(p), suffix))
+}
+
+func (p Path) Replace(from, to string) Path {
+ return Path(strings.Replace(string(p), from, to, -1))
+}
+
+func (p Path) JoinClean(s Path) Path {
+ return Path(path.Join(string(p), string(s)))
+}
+
+func (p Path) JoinNoClean(s Path) Path {
+ return Path(string(p) + "/" + string(s))
+}
+
+func (p Path) Clean() Path { return NewPath(path.Clean(string(p))) }
+
+func (p Path) IsAbs() bool {
+ return p.HasPrefixText("/") || filepath.IsAbs(filepath.FromSlash(string(p)))
+}
+
+func (p Path) Rel(other Path) Path {
+ fp := filepath.FromSlash(p.String())
+ fpOther := filepath.FromSlash(other.String())
+ rel, err := filepath.Rel(fp, fpOther)
+ assertNil(err, "relpath from %q to %q", p, other)
+ return NewPath(filepath.ToSlash(rel))
+}
+
+func (p Path) Rename(newName Path) error {
+ return os.Rename(string(p), string(newName))
+}
+
+func (p Path) Lstat() (os.FileInfo, error) { return os.Lstat(string(p)) }
+
+func (p Path) Stat() (os.FileInfo, error) { return os.Stat(string(p)) }
+
+func (p Path) Exists() bool {
+ _, err := p.Lstat()
+ return err == nil
+}
+
+func (p Path) IsFile() bool {
+ info, err := p.Lstat()
+ return err == nil && info.Mode().IsRegular()
+}
+
+func (p Path) IsDir() bool {
+ info, err := p.Lstat()
+ return err == nil && info.IsDir()
+}
+
+func (p Path) Chmod(mode os.FileMode) error {
+ return os.Chmod(string(p), mode)
+}
+
+func (p Path) ReadDir() ([]os.FileInfo, error) {
+ return ioutil.ReadDir(string(p))
+}
+
+func (p Path) Open() (*os.File, error) { return os.Open(string(p)) }
+
+func (p Path) ReadString() (string, error) {
+ bytes, err := ioutil.ReadFile(string(p))
+ return string(bytes), err
+}
+
+func (p Path) WriteString(s string) error {
+ return ioutil.WriteFile(string(p), []byte(s), 0666)
+}