UPDATED:
* docs for sysutils/paths now link to references.
This commit is contained in:
brent saner 2025-10-08 12:36:19 -04:00
parent 35c56d3f98
commit acb4352113
Signed by: bts
GPG Key ID: 8C004C2F93481F6B
6 changed files with 50 additions and 46 deletions

View File

@ -10,7 +10,6 @@ const (
// Mostly just for reference.
const (
// ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice | ModeCharDevice | ModeIrregular
modeDir pathMode = pathMode(fs.ModeDir)
modeSymlink pathMode = pathMode(fs.ModeSymlink)
modePipe pathMode = pathMode(fs.ModeNamedPipe)

View File

@ -7,7 +7,7 @@ const (
MaxSymLinkLevel on Windows is weird; Microsoft calls them "reparse points".
And it changes on the Windows version you're on, but it's been 63 past Windows Server 2003/Windows XP.
They're *very* EOL, so I'm completely ignoring them.
They're *very* EOL, so I'm completely ignoring earlier cases.
https://learn.microsoft.com/en-us/windows/win32/fileio/symbolic-link-programming-consideration
*/

View File

@ -93,7 +93,7 @@ func ExpandHome(p *string) (err error) {
}
/*
GetFirst is the file equivalent of envs.GetFirst.
GetFirst is the file equivalent of [r00t2.io/sysutils/envs.GetFirst].
It iterates through paths, normalizing them along the way
(so abstracted paths such as ~/foo/bar.txt and relative paths
@ -107,7 +107,7 @@ If no path exists, ok will be false.
As always, results are not guaranteed due to permissions, etc.
potentially returning an inaccurate result.
This is a thin wrapper around GetFirstWithRef.
This is a thin wrapper around [GetFirstWithRef].
*/
func GetFirst(p []string) (content []byte, isDir, ok bool) {
@ -117,9 +117,9 @@ func GetFirst(p []string) (content []byte, isDir, ok bool) {
}
/*
GetFirstWithRef is the file equivalent of envs.GetFirstWithRef.
GetFirstWithRef is the file equivalent of [r00t2.io/sysutils/envs.GetFirstWithRef].
It behaves exactly like GetFirst, but with an additional returned value, idx,
It behaves exactly like [GetFirst], but with an additional returned value, idx,
which specifies the index in p in which a path was found.
As always, results are not guaranteed due to permissions, etc.
@ -162,9 +162,9 @@ func GetFirstWithRef(p []string) (content []byte, isDir, ok bool, idx int) {
}
/*
Len returns the number of path segments in p, as split with the same param signature to Segment.
Len returns the number of path segments in p, as split with the same param signature to [Segment].
See Segment for details on abs and strict.
See [Segment] for details on abs and strict.
*/
func Len(p string, abs, strict bool) (segments int) {
@ -174,9 +174,9 @@ func Len(p string, abs, strict bool) (segments int) {
}
/*
LenSys returns the number of path segments in p, as split with the same param signature to SegmentSys.
LenSys returns the number of path segments in p, as split with the same param signature to [SegmentSys].
See Segment for details on abs and strict.
See [Segment] for details on abs and strict.
*/
func LenSys(p string, abs, strict bool) (segments int) {
@ -188,9 +188,9 @@ func LenSys(p string, abs, strict bool) (segments int) {
/*
MakeDirIfNotExist will create a directory at a given path if it doesn't exist.
See also the documentation for RealPath.
See also the documentation for [RealPath].
This is a bit more sane option than os.MkdirAll as it will normalize paths a little better.
This is a bit more sane option than [os.MkdirAll] as it will normalize paths a little better.
*/
func MakeDirIfNotExist(p string) (err error) {
@ -234,9 +234,9 @@ path syntax/string itself is not supported on the runtime OS. This can be done v
if errors.Is(err, fs.ErrInvalid) {...}
RealPath is simply a wrapper around ExpandHome(path) and filepath.Abs(*path).
RealPath is simply a wrapper around [ExpandHome] and [filepath.Abs].
Note that RealPath does *not* resolve symlinks. Only RealPathExistsStatTarget does that.
Note that RealPath does *not* resolve symlinks. Only [RealPathExistsStatTarget] does that.
*/
func RealPath(p *string) (err error) {
@ -252,7 +252,7 @@ func RealPath(p *string) (err error) {
}
/*
RealPathJoin combines RealPath with (path).Join.
RealPathJoin combines [RealPath] with [path.Join].
If dst is nil, then p will be updated with the new value.
You probably don't want that.
@ -283,7 +283,7 @@ func RealPathJoin(p, dst *string, subPaths ...string) (err error) {
}
/*
RealPathJoinSys combines RealPath with (path/filepath).Join.
RealPathJoinSys combines [RealPath] with [path/filepath.Join].
If dst is nil, then path will be updated with the new value.
You probably don't want that.
@ -314,10 +314,10 @@ func RealPathJoinSys(p, dst *string, subPaths ...string) (err error) {
}
/*
RealPathExists is like RealPath, but will also return a boolean as to whether the path
RealPathExists is like [RealPath], but will also return a boolean as to whether the path
actually exists or not.
Note that err *may* be os.ErrPermission/fs.ErrPermission, in which case the exists value
Note that err *may* be [os.ErrPermission] / [fs.ErrPermission], in which case the exists value
cannot be trusted as a permission error occurred when trying to stat the path - if the
calling user/process does not have read permission on e.g. a parent directory, then
exists may be false but the path may actually exist. This condition can be checked via
@ -325,9 +325,9 @@ via:
if errors.Is(err, fs.ErrPermission) {...}
See also the documentation for RealPath.
See also the documentation for [RealPath].
In those cases, it may be preferable to use RealPathExistsStat and checking stat for nil.
In those cases, it may be preferable to use [RealPathExistsStat] and checking stat for nil.
*/
func RealPathExists(p *string) (exists bool, err error) {
@ -348,11 +348,11 @@ func RealPathExists(p *string) (exists bool, err error) {
}
/*
RealPathExistsStat is like RealPathExists except it will also return the fs.FileInfo
RealPathExistsStat is like [RealPathExists] except it will also return the [io/fs.FileInfo]
for the path (assuming it exists).
If stat is nil, it is highly recommended to check err via the methods suggested
in the documentation for RealPath and RealPathExists.
in the documentation for [RealPath] and [RealPathExists].
*/
func RealPathExistsStat(p *string) (exists bool, stat fs.FileInfo, err error) {
@ -376,7 +376,7 @@ RealPathExistsStatTarget is the only "RealPather" that will resolve p to the (fi
If p is not a symlink but does exist, the tgt* will reflect the same as p*.
See WalkLink for details on relRoot and other assorted rules/logic (RealPathExistsStatTarget wraps WalkLink).
See [WalkLink] for details on relRoot and other assorted rules/logic (RealPathExistsStatTarget wraps [WalkLink]).
*/
func RealPathExistsStatTarget(p *string, relRoot string) (pExists, tgtExists, wasLink bool, pStat fs.FileInfo, tgtStat fs.FileInfo, err error) {
@ -413,7 +413,7 @@ func RealPathExistsStatTarget(p *string, relRoot string) (pExists, tgtExists, wa
return
}
// SearchFsPaths gets a file/directory/etc. path list based on the provided criteria.
// SearchFsPaths gets a file/directory/etc. path list based on the provided [FsSearchCriteria].
func SearchFsPaths(matcher FsSearchCriteria) (found, miss []*FsSearchResult, err error) {
var matched *FsSearchResult
@ -465,11 +465,11 @@ func SearchFsPaths(matcher FsSearchCriteria) (found, miss []*FsSearchResult, err
}
/*
SearchFsPathsAsync is exactly like SearchFsPaths, but dispatches off concurrent
SearchFsPathsAsync is exactly like [SearchFsPaths], but dispatches off concurrent
workers for the filtering logic instead of performing iteratively/recursively.
It may, in some cases, be *slightly more* performant and *slightly less* in others.
Note that unlike SearchFsPaths, the results written to the
FsSearchCriteriaAsync.ResChan are not guaranteed to be in any predictable order.
Note that unlike [SearchFsPaths], the results written to the
[FsSearchCriteriaAsync].ResChan are not guaranteed to be in any predictable order.
All channels are expected to have already been initialized by the caller.
They will not be closed by this function.
@ -574,7 +574,7 @@ func SearchFsPathsAsync(matcher FsSearchCriteriaAsync) {
}
/*
Segment returns path p's segments as a slice of strings, using GenericSeparator as a separator.
Segment returns path p's segments as a slice of strings, using [GenericSeparator] as a separator.
If abs is true, the placeholder leading prefix(es) (if any) of GenericSeparator will be kept in-place;
otherwise it/they will be trimmed out.
@ -583,14 +583,14 @@ e.g.:
abs == true: //foo/bar/baz => []string{"", "", "foo", "bar", "baz"}
abs == false: /foo/bar/baz => []string{"foo", "bar", "baz"}
If strict is true, any trailing GenericSeparator will be kept in-place;
If strict is true, any trailing [GenericSeparator] will be kept in-place;
otherwise they will be trimmed out.
e.g. (assuming abs == false):
strict == true: /foo/bar/baz// => []string{"foo", "bar", "baz", "", ""}
strict == false: /foo/bar/baz/ => []string{"foo", "bar", "baz"}
It is recommended to call RealPath for path's ptr first for normalization.
It is recommended to call [RealPath] for path's ptr first for normalization.
*/
func Segment(p string, abs, strict bool) (segments []string) {
@ -606,7 +606,7 @@ func Segment(p string, abs, strict bool) (segments []string) {
return
}
// SegmentSys is exactly like Segment, except using os.PathSeparator instead of GenericSeparator.
// SegmentSys is exactly like [Segment], except using [os.PathSeparator] instead of [GenericSeparator].
func SegmentSys(p string, abs, strict bool) (segments []string) {
if !abs {
@ -622,14 +622,17 @@ func SegmentSys(p string, abs, strict bool) (segments []string) {
}
/*
Strip is like Segment but trims out the leading n number of segments and reassembles the path using path.Join.
Strip is like [Segment] but trims out the leading n number of segments and reassembles the path using [path.Join].
n may be negative, in which case the *trailing* n number of segments will be trimmed out.
(i.e. n == -1, p == `foo/bar/baz/quux` would be `foo/bar/baz`, not `bar/baz/quux`)
If you require more traditional slicing (e.g. with interval),
you may want to use path.Join with a sliced result of Segment instead.
e.g.: *only* the *last* n segments: path.Join(Segment(p, ...)[Len(p, ...)-n:]...)
you may want to use [path.Join] with a sliced result of [Segment] instead.
e.g.: *only* the *last* n segments:
path.Join(Segment(p, ...)[Len(p, ...)-n:]...)
If n == 0 or int(math.Abs(float64(n))) >= len(Segment(p, ...)), no transformation will be done.
@ -664,7 +667,7 @@ func Strip(p string, abs, strict bool, n int) (slicedPath string) {
return
}
// StripSys is exactly like Strip but using (path/filepath).Join and SegmentSys.
// StripSys is exactly like [Strip] but using [path/filepath.Join] and [SegmentSys].
func StripSys(p string, abs, strict bool, n int) (slicedPath string) {
var pLen int
@ -692,19 +695,19 @@ func StripSys(p string, abs, strict bool, n int) (slicedPath string) {
}
/*
WalkLink walks the recursive target(s) of lnk (unless/until MaxSymlinkLevel is hit, which will trigger ErrMaxSymlinkLevel)
WalkLink walks the recursive target(s) of lnk (unless/until [MaxSymlinkLevel] is hit, which will trigger [ErrMaxSymlinkLevel])
until it reaches a real (non-symlink) target.
lnk will have RealPath called on it first.
If lnk is not a symlink, then tgts == []string{lnk} and err = nil.
A broken link will return fs.ErrNotExist, with tgts containing the targets up to and including the path that triggered the error.
A broken link will return [io/fs.ErrNotExist], with tgts containing the targets up to and including the path that triggered the error.
If lnk itself does not exist, tgts will be nil and err will be that of fs.ErrNotExist.
If lnk itself does not exist, tgts will be nil and err will be that of [io/fs.ErrNotExist].
relRoot is a root directory to resolve relative links to. If empty, relative link target `t` from link `l` will be treated
as relative to `(path/filepath).Dir(l)` (that is to say, `t = filepath.Join(filepath.Dir(l), os.Readlink(l))`).
as relative to [path/filepath.Dir] on l (that is to say, `t = filepath.Join(filepath.Dir(l), os.Readlink(l))`).
*/
func WalkLink(lnk, relRoot string) (tgts []string, err error) {
@ -766,7 +769,7 @@ func WalkLink(lnk, relRoot string) (tgts []string, err error) {
}
/*
filterTimes checks a times.Timespec of a file using:
filterTimes checks a [times.Timespec] of a file using:
- an age specified by the caller
- an ageType bitmask for types of times to compare
- an olderThan bool (if false, the file must be younger than)

View File

@ -11,13 +11,15 @@ import (
)
/*
Match returns match (a ptr to a FsSearchResult if the specified path matches, otherwise nil),
miss (ptr the specified path does not match, otherwise nil), and an fs.DirEntry and fs.FileInfo
for path. d and/or fi may be nil.
Match returns match (a ptr to a [FsSearchResult] if the specified path matches, otherwise nil),
miss (ptr the specified path does not match, otherwise nil), and an [io/fs.DirEntry] and [io/fs.FileInfo]
for path.
d and/or fi may be nil.
If err is not nil, it represents an unexpected error and as such, both match and miss should be nil.
Match, miss, and err will all be nil if the filesystem object/path does not exist.
match, miss, and err will all be nil if the filesystem object/path does not exist.
*/
func (f *FsSearchCriteria) Match(path string, d fs.DirEntry, fi fs.FileInfo) (match, miss *FsSearchResult, err error) {

View File

@ -4,7 +4,7 @@ import (
`r00t2.io/goutils/bitmask`
)
// Mask returns a bitmask.MaskBit from a pathTimeType.
// Mask returns a [r00t2.io/goutils/bitmask.MaskBit] from a pathTimeType.
func (p *pathTimeType) Mask() (mask *bitmask.MaskBit) {
mask = bitmask.NewMaskBitExplicit(uint(*p))

View File

@ -109,7 +109,7 @@ type FsSearchCriteriaAsync struct {
SemaphoreCtx context.Context
}
// FsSearchResult contains a match/miss result for FsSearchCriteria and FsSearchCriteriaAsync.
// FsSearchResult contains a match/miss result for [FsSearchCriteria] and [FsSearchCriteriaAsync].
type FsSearchResult struct {
/*
Path is the path to the object on the filesystem.