FIXED:
* `envs/funcs.go:78:3: unknown field IgnoreWhiteSpace in struct literal of type EnvErrNoVal, but does have IgnoreWhitespace`
* `envs/funcs_enverrnoval.go:15:8: sb.WasFound undefined (type *strings.Builder has no field or method WasFound)`
This commit is contained in:
brent saner
2025-08-13 14:54:49 -04:00
parent 8260e4fa93
commit e797a14911
16 changed files with 790 additions and 28 deletions

View File

@@ -129,7 +129,7 @@ func GetFirstWithRef(p []string) (content []byte, isDir, ok bool, idx int) {
var locPaths []string
var exists bool
var stat os.FileInfo
var stat fs.FileInfo
var err error
idx = -1
@@ -194,7 +194,7 @@ This is a bit more sane option than os.MkdirAll as it will normalize paths a lit
*/
func MakeDirIfNotExist(p string) (err error) {
var stat os.FileInfo
var stat fs.FileInfo
var exists bool
var locPath string = p
@@ -235,6 +235,8 @@ 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).
Note that RealPath does *not* resolve symlinks. Only RealPathExistsStatTarget does that.
*/
func RealPath(p *string) (err error) {
@@ -346,18 +348,22 @@ func RealPathExists(p *string) (exists bool, err error) {
}
/*
RealPathExistsStat is like RealPathExists except it will also return the os.FileInfo
RealPathExistsStat is like RealPathExists except it will also return the 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.
*/
func RealPathExistsStat(p *string) (exists bool, stat os.FileInfo, err error) {
func RealPathExistsStat(p *string) (exists bool, stat fs.FileInfo, err error) {
if exists, err = RealPathExists(p); err != nil {
return
}
if !exists {
return
}
if stat, err = os.Stat(*p); err != nil {
return
}
@@ -365,6 +371,48 @@ func RealPathExistsStat(p *string) (exists bool, stat os.FileInfo, err error) {
return
}
/*
RealPathExistsStatTarget is the only "RealPather" that will resolve p to the (final) *target* of p if p is a symlink.
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).
*/
func RealPathExistsStatTarget(p *string, relRoot string) (pExists, tgtExists, wasLink bool, pStat fs.FileInfo, tgtStat fs.FileInfo, err error) {
var tgts []string
if pExists, err = RealPathExists(p); err != nil {
return
}
tgtExists = pExists
if !pExists {
return
}
// Can't use RealPathExistsStat because it calls os.Stat, not os.Lstat... thus defeating the purpose.
if pStat, err = os.Lstat(*p); err != nil {
return
}
tgtStat = pStat
wasLink = pStat.Mode().Type()&fs.ModeSymlink == fs.ModeSymlink
if wasLink {
if tgts, err = WalkLink(*p, relRoot); err != nil || tgts == nil || len(tgts) == 0 {
tgtExists = false
tgtStat = nil
return
}
if tgtExists, tgtStat, err = RealPathExistsStat(&tgts[len(tgts)-1]); err != nil {
return
}
*p = tgts[len(tgts)-1]
}
return
}
// SearchFsPaths gets a file/directory/etc. path list based on the provided criteria.
func SearchFsPaths(matcher FsSearchCriteria) (found, miss []*FsSearchResult, err error) {
@@ -643,6 +691,80 @@ func StripSys(p string, abs, strict bool, n int) (slicedPath string) {
return
}
/*
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.
If lnk itself does not exist, tgts will be nil and err will be that of 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))`).
*/
func WalkLink(lnk, relRoot string) (tgts []string, err error) {
var exists bool
var curDepth uint
var stat fs.FileInfo
var curTgt string
var prevTgt string
if exists, err = RealPathExists(&lnk); err != nil {
return
} else if !exists {
err = fs.ErrNotExist
return
}
if relRoot != "" {
if err = RealPath(&relRoot); err != nil {
return
}
}
tgts = []string{}
curTgt = lnk
for curDepth = 0; curDepth < MaxSymlinkLevel; curDepth++ {
if exists, err = RealPathExists(&curTgt); err != nil {
return
}
prevTgt = curTgt
tgts = append(tgts, curTgt)
if !exists {
err = fs.ErrNotExist
return
}
if stat, err = os.Lstat(curTgt); err != nil {
return
}
if stat.Mode().Type()&os.ModeSymlink != os.ModeSymlink {
break
}
if curTgt, err = os.Readlink(curTgt); err != nil {
return
}
if !filepath.IsAbs(curTgt) {
if relRoot != "" {
curTgt = filepath.Join(relRoot, curTgt)
} else {
curTgt = filepath.Join(filepath.Dir(prevTgt), curTgt)
}
}
}
if curDepth >= MaxSymlinkLevel {
err = ErrMaxSymlinkLevel
return
}
return
}
/*
filterTimes checks a times.Timespec of a file using:
- an age specified by the caller