Documentation ¶
Overview ¶
Package pfs provides a symlink-following file-systemtraverser and other file-system functions.
Index ¶
- Constants
- func Abs(dir string) (out string)
- func AbsEval(path string, retainSymlinks ...bool) (absPath string, err error)
- func AddDirEntry(abs string) (dirEntry fs.DirEntry, err error)
- func AddStatDirEntry(abs string) (dirEntry fs.DirEntry, err error)
- func Exists(path string) (fileInfo fs.FileInfo)
- func Exists2(path string) (fileInfo fs.FileInfo, isNotExist bool, err error)
- func GetModeBitValues() (s string)
- func IsDirectory(path string, flags IsDirectoryArg) (isDirectory bool, err error)
- func NewDirEntryIterator(path string) (iterator iters.Iterator[DirEntry])
- func NewDirIterator(path string) (iterator iters.Iterator[ResultEntry])
- func NewIterator(path string) (iterator iters.Iterator[ResultEntry])
- func ReadDir(abs string, sort ...bool) (entries []fs.DirEntry, err error)
- func Stat(path string) (fileInfo fs.FileInfo, err error)
- type DeferringDirEntry
- type DirEntry
- type DirEntryIterator
- type DirIterator
- type FileMode
- type IsDirectoryArg
- type Iterator
- type Registry
- type ResultEntry
- type ResultReason
- type Root2
- type Traverser
Constants ¶
const ( // AllModeBits is all known github.com/fsnotify/fsevents.EventFlags AllModeBits fs.FileMode = fs.ModeDir | fs.ModeAppend | fs.ModeExclusive | fs.ModeTemporary | fs.ModeSymlink | fs.ModeDevice | fs.ModeNamedPipe | fs.ModeSocket | fs.ModeSetuid | fs.ModeSetgid | fs.ModeCharDevice | fs.ModeSticky | fs.ModeIrregular )
const ( // [DirectoryOrder] NoSorting = false )
const ( // do not evaluate symlinks argument to [AbsEval] RetainSymlinks = true )
Variables ¶
This section is empty.
Functions ¶
func Abs ¶ added in v0.4.23
Abs ensures a file system path is fully qualified. Abs is single-return-value and panics on troubles
func AbsEval ¶
AbsEval returns an absolute path with resolved symlinks
- if symlinks are evaluated, the path must exist
- non-existing path is checked using punix.IsENOENT(err)
- if path is relative, the process’ current directory is used to make path absolute. path empty returns the process’ current directory as absolute evaled path
- absPath is absolute and only empty on error
- absPath is clean:
- — no multiple Separators in sequence
- — no “.” path name elements
- — no infix or postfix “..” path name element or to path above root
- when evaluating symlinks, the path is verified to exist
- if retainSymlinks is RetainSymlinks, symlinks are returned
- errors originate from:
- — os.Lstat os.Readlink os.Getwd or
- — infix path-segment not directory or
- — encountering more than 255 symlinks
func AddDirEntry ¶ added in v0.4.138
AddDirEntry returns an fs.DirEntry with fs.FileInfo available
- error if os.Lstat fails
func AddStatDirEntry ¶ added in v0.4.138
AddDirEntry returns an fs.DirEntry for the target of a symbolic link
func Exists ¶
Exists determines if a path exists If the path exists, fileInfo is non-nil if the path does not exist, fileInfo is nil panic on troubles
func Exists2 ¶ added in v0.4.127
Exists2 determines if a path exists
- fileInfo non-nil: does exist
- isNotExists true, fileInfo nil, err non-nil: does not exist
- isNotExist false, fileInfo nil, err non-nil: some error
func GetModeBitValues ¶
func GetModeBitValues() (s string)
func IsDirectory ¶
func IsDirectory(path string, flags IsDirectoryArg) (isDirectory bool, err error)
IsDirectory determines if path exists, is directory or another type of file-system entry
- path may be relative, contain symlinks or be unclean
- isDirectory is true if path exists and is directory. Non-existing path is not an error.
- if IsDirectoryNonExistentIsError is present, non-existing path returns error
- if IsDirectoryNotDirIsError is present, a file-system entry that is not directory returns error
- flags is bitfield: IsDirectoryNonExistentIsError | IsDirectoryNotDirIsError
- symlinks are followed os.Stat
func NewDirEntryIterator ¶ added in v0.4.148
func NewDirIterator ¶ added in v0.4.141
func NewDirIterator(path string) (iterator iters.Iterator[ResultEntry])
NewIterator returns an iterator for a file-system entry and any child entries if directory
- path is the initial path for the file-system walk. it may be relative or absolute, contain symlinks and point to a file, directory or special file
- only directories are returned. if directories are not skipped, they descended into.
- symlinks are followed. Broken symlinks are ignored.
- any errored file-system entry cancels the iterator with error.
func NewIterator ¶ added in v0.4.138
func NewIterator(path string) (iterator iters.Iterator[ResultEntry])
NewIterator returns an iterator for a file-system entry and any child entries if directory
- path is the initial path for the file-system walk. it may be relative or absolute, contain symlinks and point to a file, directory or special file
- if symlinks and directories are not skipped, they are followed
- all errors during traversal are provided as is
func ReadDir ¶ added in v0.4.148
directoryOrder returns unsorted entries, most with deferred fs.FileInfo
Types ¶
type DeferringDirEntry ¶ added in v0.4.138
type DeferringDirEntry struct {
// contains filtered or unexported fields
}
func NewDeferringDirEntry ¶ added in v0.4.138
func NewDeferringDirEntry(abs string) (entry *DeferringDirEntry)
NewDeferringDirEntry returns fs.DirEntry with fs.FileInfo deferred
- abs is absolute path that maybe does not exist
func (*DeferringDirEntry) Info ¶ added in v0.4.138
func (e *DeferringDirEntry) Info() (fileInfo fs.FileInfo, err error)
Info returns the FileInfo for the file or subdirectory described by the entry
- thread-safe, does os.Lstat every time
func (*DeferringDirEntry) IsDir ¶ added in v0.4.138
func (e *DeferringDirEntry) IsDir() (isDir bool)
IsDir reports whether the entry is a directory, ie. ModeDir bit being set
- may panic unless Info has successfully completed
func (*DeferringDirEntry) Name ¶ added in v0.4.138
func (e *DeferringDirEntry) Name() (base string)
base name of the file
func (*DeferringDirEntry) Type ¶ added in v0.4.138
func (e *DeferringDirEntry) Type() (modeType fs.FileMode)
Type returns ModeType bits, 0 for regular file
- ModeDir ModeSymlink ModeNamedPipe ModeSocket ModeDevice ModeCharDevice ModeIrregular
type DirEntryIterator ¶ added in v0.4.148
type DirEntryIterator struct { iters.BaseIterator[DirEntry] // contains filtered or unexported fields }
func (*DirEntryIterator) Init ¶ added in v0.4.148
func (i *DirEntryIterator) Init() (result DirEntry, iterator iters.Iterator[DirEntry])
Init implements the right-hand side of a short variable declaration in the init statement of a Go “for” clause
for i, iterator := iters.NewSlicePointerIterator(someSlice).Init(); iterator.Cond(&i); { // i is pointer to slice element
type DirIterator ¶ added in v0.4.141
type DirIterator struct { // BaseIterator provides iterator methods: // [iters.Iterator.Cancel] [iters.Iterator.Cond] [iters.Iterator.Next] iters.BaseIterator[ResultEntry] // contains filtered or unexported fields }
DirIterator traverses file-system directories
func (*DirIterator) Init ¶ added in v0.4.141
func (i *DirIterator) Init() (result ResultEntry, iterator iters.Iterator[ResultEntry])
Init implements the right-hand side of a short variable declaration in the init statement of a Go “for” clause
for i, iterator := iters.NewSlicePointerIterator(someSlice).Init(); iterator.Cond(&i); { // i is pointer to slice element
type FileMode ¶
type IsDirectoryArg ¶
type IsDirectoryArg uint8
bitfield argument to IsDirectory
- IsDirectoryNonExistentIsError IsDirectoryNotDirIsError
const ( // if path does not exist, return the error [IsDirectory] IsDirectoryNonExistentIsError IsDirectoryArg = 1 << iota // if existing path is not directory, return an error [IsDirectory] // - symlinks are followed, so a symlink pointing ot directory is ok IsDirectoryNotDirIsError )
type Iterator ¶ added in v0.4.138
type Iterator struct { // BaseIterator provides iterator methods: // [iters.Iterator.Cancel] [iters.Iterator.Cond] [iters.Iterator.Next] iters.BaseIterator[ResultEntry] // contains filtered or unexported fields }
Iterator traverses file-system entries and errors
func (*Iterator) Init ¶ added in v0.4.138
func (i *Iterator) Init() (result ResultEntry, iterator iters.Iterator[ResultEntry])
Init implements the right-hand side of a short variable declaration in the init statement of a Go “for” clause
for i, iterator := iters.NewSlicePointerIterator(someSlice).Init(); iterator.Cond(&i); { // i is pointer to slice element
type Registry ¶ added in v0.4.138
type Registry[V any] struct { // contains filtered or unexported fields }
Registry stores values that are accessible by index or by absolute path
func NewRegistry ¶ added in v0.4.138
NewRegistry returns a registry of values by absolute path
func (*Registry[V]) GetValue ¶ added in v0.4.138
GetValue retrieves value by index
- if index is less than 0 or too large or for a removed value, nil is returned
func (*Registry[V]) HasAbs ¶ added in v0.4.138
HasAbs check whether an absolute path is stored in the registry as a key to a value
func (*Registry[V]) ListLength ¶ added in v0.4.138
ListLength returns the length of the value slice
- a value can still be nil for a discarded root
func (*Registry[V]) ObsoleteIndex ¶ added in v0.4.138
type ResultEntry ¶ added in v0.4.138
type ResultEntry struct { // - always non-nil // - may be deferred-info executing [os.Lstat] every time, ie. only invoke Info once // - if Err is non-nil, Info may return error fs.DirEntry // path as provided that may be easier to read // - may be implicitly relative to current directory: “subdir/file.txt” // - may have no directory or extension part: “README.css” “z” // - may be relative: “../file.txt” // - may contain symlinks, unnecessary “.” and “..” or // multiple separators in sequence // - may be empty string for current working directory ProvidedPath string // - equivalent of Path: absolute, symlink-free, clean // - if Err non-nil, may be empty // - if the entry is symbolic link: // - — ProvidedPath is the symbolic link location // - — Abs is what the symbolic link points to Abs string // function to skip descending into directory or following symlink SkipEntry func(no uint64) // skippable serial number No uint64 // any error associated with this entry Err error // why this entry was provided // - REnd REntry RSkippable RDirBad RSymlinkBad RError Reason ResultReason }
ResultEntry is an existing file-system entry, traversal-end marker or an error-entry during file-system traversal
- non-error non-end file-system entries have been proven to exist
- ResultEntry.IsEnd or Reason == REnd indicates end
- Reson indicates why the ResultEntry was returned:
- REnd REntry RSkippable RDirBad RSymlinkBad RError
- —
- ResultEntry is a value-container that as a local variable, function argument or result is a tuple not causing allocation by using temporary stack storage
- taking the address of a &ResultEntry causes allocation
func (ResultEntry) IsEnd ¶ added in v0.4.138
func (e ResultEntry) IsEnd() (isEnd bool)
IsEnd indicates that this ResultEntry is an end of entries marker
func (ResultEntry) Skip ¶ added in v0.4.138
func (e ResultEntry) Skip()
Skip marks the returned entry to be skipped
- the entry is directory or symbolic link
- can only be invoked when [ResultEntry.Reason] is RSkippable
func (ResultEntry) String ¶ added in v0.4.145
func (e ResultEntry) String() (s string)
resultEntry path: "…" abs"/…" err ‘OK’ reason ‘non-symlink non-directory non-error entry’
type ResultReason ¶ added in v0.4.138
type ResultReason uint8
Why a directory entry was provided by Traverser
- REnd REntry RSkippable RDirBad RSymlinkBad RError
const ( // the filesystem traversal completed all entries REnd ResultReason = iota // a non-symlink non-directory non-error entry REntry // a directory or symlink about to be traversed RSkippable // a directory whose listing failed [os.Open] [os.File.ReadDir] RDirBad // a broken symlink [os.Stat] RSymlinkBad // failure in [os.Lstat] [os.Readlink] [os.Getwd] RError )
func (ResultReason) String ¶ added in v0.4.138
func (r ResultReason) String() (s string)
type Root2 ¶ added in v0.4.138
type Root2 struct { // path as provided that may be easier to read // - may be implicitly relative to current directory: “subdir/file.txt” // - may have no directory or extension part: “README.css” “z” // - may be relative: “../file.txt” // - may contain symlinks, unnecessary “.” and “..” or // multiple separators in sequence // - may be empty string for current working directory ProvidedPath string // Abs is required for relating roots // - equivalent of Path: absolute, symlink-free, clean // - may not exist Abs string }
Root2 is a file system hierarchy
func NewAbsRoot2 ¶ added in v0.4.138
type Traverser ¶ added in v0.4.138
type Traverser struct {
// contains filtered or unexported fields
}
Traverser represents a file system that is scanned following symlinks
- each file system entry is returned exactly once except:
- — error reading a directory returns the directory a second time
- directories and symlinks are returned before they are read so that they can be more efficiently skipped by invoking ResultEntry.Skip
- directory entries are returned in 8-bit character order
- returned entries may not exist, such entries have [ResultEntry.Err] non-nil
- result.ProvidedPath is based on the initial path and may be relative, unclean and contain symlinks
- if [ResultEntry.Err] is nil, Abs is absolute, symlink-free clean path
- —
- ResultEntry.DirEntry.Info typically invokes os.Lstat every time, so this value should be cached
- because symlinks may point to parents or separate trees, the file system scan may involve multiple roots which may affect the order of return entries
- symlinks are followed and not returned. Therefore, a symlink pointing to a scanned location is effectively ignored
- the returned struct is by value. If its address is not taken, no allocation will occur
func NewTraverser ¶ added in v0.4.138
NewTraverser returns a file-system traverser
- typically used via pfs.Iterator or pfs.DirIterator
- path is the initial path. Path may be relative or absolute, contain symlinks and be unclean. Path may be of any modeType: file, directory or special file. Empty string means process’ current directory
- the Next method is used to obtain file-system entries and errors
- consider using pfs iterators:
- — Iterator for all entries and errors
- — DirIterator for error-free directories
Usage:
var traverser = pfs.NewTraverser(path) for { var result = traverser.Next() if result.IsEnd() || result.Err != nil { break } println(result.Abs) }
func (*Traverser) Next ¶ added in v0.4.138
func (t *Traverser) Next() (result ResultEntry)
Next returns the next file-system entry
- Next ends with [ResultEntry.DirEntry] nil, ie. ResultEntry.IsEnd returns true or ResultEntry.Reason == REnd
- symlinks and directories can be skipped by invoking ResultEntry.Skip. Those have ResultEntry.Reason == RSkippable
- symlinks have information based on the symlink source but [ResultEntry.Abs] is the fully resolved symlink target
- [ResultEntry.ProvidedPath] is a path to the entry based upon the initially provided path. May be empty string
- [ResultEntry.Abs] is an absolute symlink-free clean path but only available when [ResultEntry.Err] is nil
- [ResultEntry.Err] holds any error associated with the returned entry
- —
- result.Err is from:
- — process working directory cannot be read
- — directory read error or os.Readlink or os.Lstat failed