aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/chigopher/pathlib/path.go
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2025-01-22 16:07:17 +0100
committerTaras Madan <tarasmadan@google.com>2025-01-23 10:42:36 +0000
commit7b4377ad9d8a7205416df8d6217ef2b010f89481 (patch)
treee6fec4fd12ff807a16d847923f501075bf71d16c /vendor/github.com/chigopher/pathlib/path.go
parent475a4c203afb8b7d3af51c4fd32bb170ff32a45e (diff)
vendor: delete
Diffstat (limited to 'vendor/github.com/chigopher/pathlib/path.go')
-rw-r--r--vendor/github.com/chigopher/pathlib/path.go657
1 files changed, 0 insertions, 657 deletions
diff --git a/vendor/github.com/chigopher/pathlib/path.go b/vendor/github.com/chigopher/pathlib/path.go
deleted file mode 100644
index 2f802e159..000000000
--- a/vendor/github.com/chigopher/pathlib/path.go
+++ /dev/null
@@ -1,657 +0,0 @@
-package pathlib
-
-import (
- "fmt"
- "io"
- "os"
- "path/filepath"
- "strings"
- "time"
-
- "github.com/spf13/afero"
-)
-
-// Path is an object that represents a path
-type Path struct {
- path string
- fs afero.Fs
-
- // DefaultFileMode is the mode that is used when creating new files in functions
- // that do not accept os.FileMode as a parameter.
- DefaultFileMode os.FileMode
- // DefaultDirMode is the mode that will be used when creating new directories
- DefaultDirMode os.FileMode
- // Sep is the seperator used in path calculations. By default this is set to
- // os.PathSeparator.
- Sep string
-}
-
-type PathOpts func(p *Path)
-
-func PathWithAfero(fs afero.Fs) PathOpts {
- return func(p *Path) {
- p.fs = fs
- }
-}
-
-func PathWithSeperator(sep string) PathOpts {
- return func(p *Path) {
- p.Sep = sep
- }
-}
-
-// NewPath returns a new OS path
-func NewPath(path string, opts ...PathOpts) *Path {
- p := &Path{
- path: path,
- fs: afero.NewOsFs(),
- DefaultFileMode: DefaultFileMode,
- DefaultDirMode: DefaultDirMode,
- Sep: string(os.PathSeparator),
- }
- for _, opt := range opts {
- opt(p)
- }
- return p
-}
-
-// NewPathAfero returns a Path object with the given Afero object
-//
-// Deprecated: Use the PathWithAfero option in Newpath instead.
-func NewPathAfero(path string, fs afero.Fs) *Path {
- return NewPath(path, PathWithAfero(fs))
-}
-
-// Glob returns all of the path objects matched by the given pattern
-// inside of the afero filesystem.
-func Glob(fs afero.Fs, pattern string) ([]*Path, error) {
- matches, err := afero.Glob(fs, pattern)
- if err != nil {
- return nil, fmt.Errorf("failed to glob: %w", err)
- }
-
- pathMatches := []*Path{}
- for _, match := range matches {
- pathMatches = append(pathMatches, NewPathAfero(match, fs))
- }
- return pathMatches, nil
-}
-
-type namer interface {
- Name() string
-}
-
-func getFsName(fs afero.Fs) string {
- if name, ok := fs.(namer); ok {
- return name.Name()
- }
- return ""
-}
-
-// Fs returns the internal afero.Fs object.
-func (p *Path) Fs() afero.Fs {
- return p.fs
-}
-
-func (p *Path) doesNotImplementErr(interfaceName string) error {
- return doesNotImplementErr(interfaceName, p.Fs())
-}
-
-func doesNotImplementErr(interfaceName string, fs afero.Fs) error {
- return fmt.Errorf("%w: Path's afero filesystem %s does not implement %s", ErrDoesNotImplement, getFsName(fs), interfaceName)
-}
-
-func (p *Path) lstatNotPossible() error {
- return lstatNotPossible(p.Fs())
-}
-
-func lstatNotPossible(fs afero.Fs) error {
- return fmt.Errorf("%w: Path's afero filesystem %s does not support lstat", ErrLstatNotPossible, getFsName(fs))
-}
-
-// *******************************
-// * afero.Fs wrappers *
-// *******************************
-
-// Create creates a file if possible, returning the file and an error, if any happens.
-func (p *Path) Create() (File, error) {
- file, err := p.Fs().Create(p.String())
- return File{file}, err
-}
-
-// Mkdir makes the current dir. If the parents don't exist, an error
-// is returned.
-func (p *Path) Mkdir() error {
- return p.Fs().Mkdir(p.String(), p.DefaultDirMode)
-}
-
-// MkdirMode makes the current dir. If the parents don't exist, an error
-// is returned.
-func (p *Path) MkdirMode(perm os.FileMode) error {
- return p.Fs().Mkdir(p.String(), perm)
-}
-
-// MkdirAll makes all of the directories up to, and including, the given path.
-func (p *Path) MkdirAll() error {
- return p.Fs().MkdirAll(p.String(), p.DefaultDirMode)
-}
-
-// MkdirAllMode makes all of the directories up to, and including, the given path.
-func (p *Path) MkdirAllMode(perm os.FileMode) error {
- return p.Fs().MkdirAll(p.String(), perm)
-}
-
-// Open opens a file for read-only, returning it or an error, if any happens.
-func (p *Path) Open() (*File, error) {
- handle, err := p.Fs().Open(p.String())
- return &File{
- File: handle,
- }, err
-}
-
-// OpenFile opens a file using the given flags.
-// See the list of flags at: https://golang.org/pkg/os/#pkg-constants
-func (p *Path) OpenFile(flag int) (*File, error) {
- handle, err := p.Fs().OpenFile(p.String(), flag, p.DefaultFileMode)
- return &File{
- File: handle,
- }, err
-}
-
-// OpenFileMode opens a file using the given flags and the given mode.
-// See the list of flags at: https://golang.org/pkg/os/#pkg-constants
-func (p *Path) OpenFileMode(flag int, perm os.FileMode) (*File, error) {
- handle, err := p.Fs().OpenFile(p.String(), flag, perm)
- return &File{
- File: handle,
- }, err
-}
-
-// Remove removes a file, returning an error, if any
-// happens.
-func (p *Path) Remove() error {
- return p.Fs().Remove(p.String())
-}
-
-// RemoveAll removes the given path and all of its children.
-func (p *Path) RemoveAll() error {
- return p.Fs().RemoveAll(p.String())
-}
-
-// RenameStr renames a file
-func (p *Path) RenameStr(newname string) error {
- if err := p.Fs().Rename(p.String(), newname); err != nil {
- return err
- }
-
- // Rename succeeded. Set our path to the newname.
- p.path = newname
- return nil
-}
-
-// Rename renames a file
-func (p *Path) Rename(target *Path) error {
- return p.RenameStr(target.String())
-}
-
-// Stat returns the os.FileInfo of the given path
-func (p *Path) Stat() (os.FileInfo, error) {
- return p.Fs().Stat(p.String())
-}
-
-// Chmod changes the file mode of the given path
-func (p *Path) Chmod(mode os.FileMode) error {
- return p.Fs().Chmod(p.String(), mode)
-}
-
-// Chtimes changes the modification and access time of the given path.
-func (p *Path) Chtimes(atime time.Time, mtime time.Time) error {
- return p.Fs().Chtimes(p.String(), atime, mtime)
-}
-
-// ************************
-// * afero.Afero wrappers *
-// ************************
-
-// DirExists returns whether or not the path represents a directory that exists
-func (p *Path) DirExists() (bool, error) {
- return afero.DirExists(p.Fs(), p.String())
-}
-
-// Exists returns whether the path exists
-func (p *Path) Exists() (bool, error) {
- return afero.Exists(p.Fs(), p.String())
-}
-
-// FileContainsAnyBytes returns whether or not the path contains
-// any of the listed bytes.
-func (p *Path) FileContainsAnyBytes(subslices [][]byte) (bool, error) {
- return afero.FileContainsAnyBytes(p.Fs(), p.String(), subslices)
-}
-
-// FileContainsBytes returns whether or not the given file contains the bytes
-func (p *Path) FileContainsBytes(subslice []byte) (bool, error) {
- return afero.FileContainsBytes(p.Fs(), p.String(), subslice)
-}
-
-// IsDir checks if a given path is a directory.
-func (p *Path) IsDir() (bool, error) {
- return afero.IsDir(p.Fs(), p.String())
-}
-
-// IsDir returns whether or not the os.FileMode object represents a
-// directory.
-func IsDir(mode os.FileMode) bool {
- return mode.IsDir()
-}
-
-// IsEmpty checks if a given file or directory is empty.
-func (p *Path) IsEmpty() (bool, error) {
- return afero.IsEmpty(p.Fs(), p.String())
-}
-
-// ReadDir reads the current path and returns a list of the corresponding
-// Path objects. This function differs from os.Readdir in that it does
-// not call Stat() on the files. Instead, it calls Readdirnames which
-// is less expensive and does not force the caller to make expensive
-// Stat calls.
-func (p *Path) ReadDir() ([]*Path, error) {
- paths := []*Path{}
- handle, err := p.Open()
- if err != nil {
- return paths, err
- }
- children, err := handle.Readdirnames(-1)
- if err != nil {
- return paths, err
- }
- for _, child := range children {
- paths = append(paths, p.Join(child))
- }
- return paths, err
-}
-
-// ReadFile reads the given path and returns the data. If the file doesn't exist
-// or is a directory, an error is returned.
-func (p *Path) ReadFile() ([]byte, error) {
- return afero.ReadFile(p.Fs(), p.String())
-}
-
-// SafeWriteReader is the same as WriteReader but checks to see if file/directory already exists.
-func (p *Path) SafeWriteReader(r io.Reader) error {
- return afero.SafeWriteReader(p.Fs(), p.String(), r)
-}
-
-// WriteFileMode writes the given data to the path (if possible). If the file exists,
-// the file is truncated. If the file is a directory, or the path doesn't exist,
-// an error is returned.
-func (p *Path) WriteFileMode(data []byte, perm os.FileMode) error {
- return afero.WriteFile(p.Fs(), p.String(), data, perm)
-}
-
-// WriteFile writes the given data to the path (if possible). If the file exists,
-// the file is truncated. If the file is a directory, or the path doesn't exist,
-// an error is returned.
-func (p *Path) WriteFile(data []byte) error {
- return afero.WriteFile(p.Fs(), p.String(), data, p.DefaultFileMode)
-}
-
-// WriteReader takes a reader and writes the content
-func (p *Path) WriteReader(r io.Reader) error {
- return afero.WriteReader(p.Fs(), p.String(), r)
-}
-
-// *************************************
-// * pathlib.Path-like implementations *
-// *************************************
-
-// Name returns the string representing the final path component
-func (p *Path) Name() string {
- return filepath.Base(p.path)
-}
-
-// Parent returns the Path object of the parent directory
-func (p *Path) Parent() *Path {
- return NewPathAfero(filepath.Dir(p.String()), p.Fs())
-}
-
-// Readlink returns the target path of a symlink.
-//
-// This will fail if the underlying afero filesystem does not implement
-// afero.LinkReader.
-func (p *Path) Readlink() (*Path, error) {
- linkReader, ok := p.Fs().(afero.LinkReader)
- if !ok {
- return nil, p.doesNotImplementErr("afero.LinkReader")
- }
-
- resolvedPathStr, err := linkReader.ReadlinkIfPossible(p.path)
- if err != nil {
- return nil, err
- }
- return NewPathAfero(resolvedPathStr, p.fs), nil
-}
-
-func resolveIfSymlink(path *Path) (*Path, bool, error) {
- isSymlink, err := path.IsSymlink()
- if err != nil {
- return path, isSymlink, err
- }
- if isSymlink {
- resolvedPath, err := path.Readlink()
- if err != nil {
- // Return the path unchanged on errors
- return path, isSymlink, err
- }
- return resolvedPath, isSymlink, nil
- }
- return path, isSymlink, nil
-}
-
-func resolveAllHelper(path *Path) (*Path, error) {
- parts := path.Parts()
-
- for i := 0; i < len(parts); i++ {
- rightOfComponent := parts[i+1:]
- upToComponent := parts[:i+1]
-
- componentPath := NewPathAfero(strings.Join(upToComponent, path.Sep), path.Fs())
- resolved, isSymlink, err := resolveIfSymlink(componentPath)
- if err != nil {
- return path, err
- }
-
- if isSymlink {
- if resolved.IsAbsolute() {
- return resolveAllHelper(resolved.Join(strings.Join(rightOfComponent, path.Sep)))
- }
- return resolveAllHelper(componentPath.Parent().JoinPath(resolved).Join(rightOfComponent...))
- }
- }
-
- // If we get through the entire iteration above, that means no component was a symlink.
- // Return the argument.
- return path, nil
-}
-
-// ResolveAll canonicalizes the path by following every symlink in
-// every component of the given path recursively. The behavior
-// should be identical to the `readlink -f` command from POSIX OSs.
-// This will fail if the underlying afero filesystem does not implement
-// afero.LinkReader. The path will be returned unchanged on errors.
-func (p *Path) ResolveAll() (*Path, error) {
- return resolveAllHelper(p)
-}
-
-// Parts returns the individual components of a path
-func (p *Path) Parts() []string {
- parts := []string{}
- if p.IsAbsolute() {
- parts = append(parts, p.Sep)
- }
- normalizedPathStr := normalizePathString(p.String())
- normalizedParts := normalizePathParts(strings.Split(normalizedPathStr, p.Sep))
- return append(parts, normalizedParts...)
-}
-
-// IsAbsolute returns whether or not the path is an absolute path. This is
-// determined by checking if the path starts with a slash.
-func (p *Path) IsAbsolute() bool {
- return strings.HasPrefix(p.path, "/")
-}
-
-// Join joins the current object's path with the given elements and returns
-// the resulting Path object.
-func (p *Path) Join(elems ...string) *Path {
- paths := []string{p.path}
- paths = append(paths, elems...)
- return NewPathAfero(strings.Join(paths, p.Sep), p.Fs())
-}
-
-// JoinPath is the same as Join() except it accepts a path object
-func (p *Path) JoinPath(path *Path) *Path {
- return p.Join(path.Parts()...)
-}
-
-func normalizePathString(path string) string {
- path = strings.TrimSpace(path)
- path = strings.TrimPrefix(path, "./")
- path = strings.TrimRight(path, " ")
- if len(path) > 1 {
- path = strings.TrimSuffix(path, "/")
- }
- return path
-}
-
-func normalizePathParts(path []string) []string {
- // We might encounter cases where path represents a split of the path
- // "///" etc. We will get a bunch of erroneous empty strings in such a split,
- // so remove all of the trailing empty strings except for the first one (if any)
- normalized := []string{}
- for i := 0; i < len(path); i++ {
- if path[i] != "" {
- normalized = append(normalized, path[i])
- }
- }
- return normalized
-}
-
-// RelativeTo computes a relative version of path to the other path. For instance,
-// if the object is /path/to/foo.txt and you provide /path/ as the argment, the
-// returned Path object will represent to/foo.txt.
-func (p *Path) RelativeTo(other *Path) (*Path, error) {
- thisPathNormalized := normalizePathString(p.String())
- otherPathNormalized := normalizePathString(other.String())
-
- thisParts := p.Parts()
- otherParts := other.Parts()
-
- var relativeBase int
- for idx, part := range otherParts {
- if idx >= len(thisParts) || thisParts[idx] != part {
- return p, fmt.Errorf("%s does not start with %s: %w", thisPathNormalized, otherPathNormalized, ErrRelativeTo)
- }
- relativeBase = idx
- }
-
- relativePath := thisParts[relativeBase+1:]
-
- if len(relativePath) == 0 || (len(relativePath) == 1 && relativePath[0] == "") {
- relativePath = []string{"."}
- }
-
- return NewPathAfero(strings.Join(relativePath, "/"), p.Fs()), nil
-}
-
-// RelativeToStr computes a relative version of path to the other path. For instance,
-// if the object is /path/to/foo.txt and you provide /path/ as the argment, the
-// returned Path object will represent to/foo.txt.
-func (p *Path) RelativeToStr(other string) (*Path, error) {
- return p.RelativeTo(NewPathAfero(other, p.Fs()))
-}
-
-// Lstat lstat's the path if the underlying afero filesystem supports it. If
-// the filesystem does not support afero.Lstater, or if the filesystem implements
-// afero.Lstater but returns false for the "lstat called" return value.
-//
-// A nil os.FileInfo is returned on errors.
-func (p *Path) Lstat() (os.FileInfo, error) {
- lStater, ok := p.Fs().(afero.Lstater)
- if !ok {
- return nil, p.doesNotImplementErr("afero.Lstater")
- }
- stat, lstatCalled, err := lStater.LstatIfPossible(p.String())
- if !lstatCalled && err == nil {
- return nil, p.lstatNotPossible()
- }
- return stat, err
-}
-
-// SymlinkStr symlinks to the target location. This will fail if the underlying
-// afero filesystem does not implement afero.Linker.
-func (p *Path) SymlinkStr(target string) error {
- return p.Symlink(NewPathAfero(target, p.Fs()))
-}
-
-// Symlink symlinks to the target location. This will fail if the underlying
-// afero filesystem does not implement afero.Linker.
-func (p *Path) Symlink(target *Path) error {
- symlinker, ok := p.fs.(afero.Linker)
- if !ok {
- return p.doesNotImplementErr("afero.Linker")
- }
-
- return symlinker.SymlinkIfPossible(target.path, p.path)
-}
-
-// String returns the string representation of the path
-func (p *Path) String() string {
- return p.path
-}
-
-// IsFile returns true if the given path is a file.
-func (p *Path) IsFile() (bool, error) {
- fileInfo, err := p.Stat()
- if err != nil {
- return false, err
- }
- return IsFile(fileInfo.Mode()), nil
-}
-
-// IsFile returns whether or not the file described by the given
-// os.FileMode is a regular file.
-func IsFile(mode os.FileMode) bool {
- return mode.IsRegular()
-}
-
-// IsSymlink returns true if the given path is a symlink.
-// Fails if the filesystem doesn't implement afero.Lstater.
-func (p *Path) IsSymlink() (bool, error) {
- fileInfo, err := p.Lstat()
- if err != nil {
- return false, err
- }
- return IsSymlink(fileInfo.Mode()), nil
-}
-
-// IsSymlink returns true if the file described by the given
-// os.FileMode describes a symlink.
-func IsSymlink(mode os.FileMode) bool {
- return mode&os.ModeSymlink != 0
-}
-
-// DeepEquals returns whether or not the path pointed to by other
-// has the same resolved filepath as self.
-func (p *Path) DeepEquals(other *Path) (bool, error) {
- selfResolved, err := p.ResolveAll()
- if err != nil {
- return false, err
- }
- otherResolved, err := other.ResolveAll()
- if err != nil {
- return false, err
- }
-
- return selfResolved.Clean().Equals(otherResolved.Clean()), nil
-}
-
-// Equals returns whether or not the object's path is identical
-// to other's, in a shallow sense. It simply checks for equivalence
-// in the unresolved Paths() of each object.
-func (p *Path) Equals(other *Path) bool {
- return p.String() == other.String()
-}
-
-// GetLatest returns the file or directory that has the most recent mtime. Only
-// works if this path is a directory and it exists. If the directory is empty,
-// the returned Path object will be nil.
-func (p *Path) GetLatest() (*Path, error) {
- files, err := p.ReadDir()
- if err != nil {
- return nil, err
- }
-
- var greatestFileSeen *Path
- for _, file := range files {
- if greatestFileSeen == nil {
- greatestFileSeen = p.Join(file.Name())
- }
-
- greatestMtime, err := greatestFileSeen.Mtime()
- if err != nil {
- return nil, err
- }
-
- thisMtime, err := file.Mtime()
- // There is a possible race condition where the file is deleted after
- // our call to ReadDir. We throw away the error if it isn't
- // os.ErrNotExist
- if err != nil && !os.IsNotExist(err) {
- return nil, err
- }
- if thisMtime.After(greatestMtime) {
- greatestFileSeen = p.Join(file.Name())
- }
- }
-
- return greatestFileSeen, nil
-}
-
-// Glob returns all matches of pattern relative to this object's path.
-func (p *Path) Glob(pattern string) ([]*Path, error) {
- return Glob(p.Fs(), p.Join(pattern).String())
-}
-
-// Clean returns a new object that is a lexically-cleaned
-// version of Path.
-func (p *Path) Clean() *Path {
- return NewPathAfero(filepath.Clean(p.String()), p.Fs())
-}
-
-// Mtime returns the modification time of the given path.
-func (p *Path) Mtime() (time.Time, error) {
- stat, err := p.Stat()
- if err != nil {
- return time.Time{}, err
- }
- return Mtime(stat)
-}
-
-// Copy copies the path to another path using io.Copy.
-// Returned is the number of bytes copied and any error values.
-// The destination file is truncated if it exists, and is created
-// if it does not exist.
-func (p *Path) Copy(other *Path) (int64, error) {
- srcFile, err := p.Open()
- if err != nil {
- return 0, fmt.Errorf("opening source file: %w", err)
- }
- defer srcFile.Close()
- dstFile, err := other.OpenFile(os.O_TRUNC | os.O_CREATE | os.O_WRONLY)
- if err != nil {
- return 0, fmt.Errorf("opening destination file: %w", err)
- }
- defer dstFile.Close()
- return io.Copy(dstFile, srcFile)
-}
-
-// Mtime returns the mtime described in the given os.FileInfo object
-func Mtime(fileInfo os.FileInfo) (time.Time, error) {
- return fileInfo.ModTime(), nil
-}
-
-// Size returns the size of the object. Fails if the object doesn't exist.
-func (p *Path) Size() (int64, error) {
- stat, err := p.Stat()
- if err != nil {
- return 0, err
- }
- return Size(stat), nil
-}
-
-// Size returns the size described by the os.FileInfo. Before you say anything,
-// yes... you could just do fileInfo.Size(). This is purely a convenience function
-// to create API consistency.
-func Size(fileInfo os.FileInfo) int64 {
- return fileInfo.Size()
-}