v1.12.0
FIXED: * paths: Async searching works correctly now, and is consolidated to a single struct for searching options for async and synchronous searches.
This commit is contained in:
125
paths/funcs_fssearchcriteria.go
Normal file
125
paths/funcs_fssearchcriteria.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package paths
|
||||
|
||||
import (
|
||||
`io/fs`
|
||||
`os`
|
||||
`path/filepath`
|
||||
`time`
|
||||
|
||||
`github.com/djherbis/times`
|
||||
`r00t2.io/goutils/bitmask`
|
||||
)
|
||||
|
||||
/*
|
||||
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.
|
||||
|
||||
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.
|
||||
*/
|
||||
func (f *FsSearchCriteria) Match(path string, d fs.DirEntry, fi fs.FileInfo) (match, miss *FsSearchResult, err error) {
|
||||
|
||||
var typeMode fs.FileMode
|
||||
var m FsSearchResult
|
||||
var typeFilter *bitmask.MaskBit = bitmask.NewMaskBitExplicit(uint(f.TargetType))
|
||||
|
||||
m = FsSearchResult{
|
||||
Path: path,
|
||||
DirEntry: d,
|
||||
FileInfo: fi,
|
||||
Criteria: f,
|
||||
}
|
||||
|
||||
if f == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// A DirEntry can be created from a FileInfo but not vice versa.
|
||||
if m.FileInfo == nil {
|
||||
if m.DirEntry != nil {
|
||||
if m.FileInfo, err = m.DirEntry.Info(); err != nil {
|
||||
err = filterNoFileDir(err)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if f.FollowSymlinks {
|
||||
if m.FileInfo, err = os.Stat(path); err != nil {
|
||||
err = filterNoFileDir(err)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if m.FileInfo, err = os.Lstat(path); err != nil {
|
||||
err = filterNoFileDir(err)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
m.DirEntry = fs.FileInfoToDirEntry(m.FileInfo)
|
||||
}
|
||||
}
|
||||
if m.DirEntry == nil {
|
||||
m.DirEntry = fs.FileInfoToDirEntry(m.FileInfo)
|
||||
}
|
||||
if m.DirEntry == nil || m.FileInfo == nil {
|
||||
m.MissReason = MissNoMeta
|
||||
miss = &m
|
||||
return
|
||||
}
|
||||
|
||||
if m.Times, err = times.Stat(path); err != nil {
|
||||
err = filterNoFileDir(err)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if f.PathPtrn != nil && !f.PathPtrn.MatchString(path) {
|
||||
m.MissReason = MissBadPath
|
||||
miss = &m
|
||||
return
|
||||
}
|
||||
if f.BasePtrn != nil && !f.BasePtrn.MatchString(filepath.Base(path)) {
|
||||
m.MissReason = MissBadBase
|
||||
miss = &m
|
||||
return
|
||||
}
|
||||
|
||||
// age
|
||||
if f.Age != nil {
|
||||
if f.Now == nil {
|
||||
f.Now = new(time.Time)
|
||||
*f.Now = time.Now()
|
||||
}
|
||||
if !filterTimes(m.Times, f.Age, &f.AgeType, f.OlderThan, f.Now) {
|
||||
m.MissReason = MissBadTime
|
||||
miss = &m
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// fs object type (file, dir, etc.)
|
||||
typeMode = m.FileInfo.Mode().Type()
|
||||
if typeMode == 0 && f.NoFiles {
|
||||
m.MissReason = MissFile
|
||||
miss = &m
|
||||
return
|
||||
} else if typeMode != 0 {
|
||||
if !typeFilter.HasFlag(bitmask.MaskBit(typeMode)) {
|
||||
m.MissReason = MissType
|
||||
miss = &m
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// If it gets to here, it matches.
|
||||
match = &m
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user