c9f3e7a639
ADDED: * stringsx: ** RunesInString ** RuneMapFromString ** SquashConsec ** SquashConsecRunes ** SquashConsecRunesAll ** SquashMap ** SquashWhitespace
95 lines
2.0 KiB
Go
95 lines
2.0 KiB
Go
package main
|
|
|
|
import (
|
|
"embed"
|
|
"os"
|
|
"slices"
|
|
|
|
"github.com/deckarep/golang-set/v2"
|
|
"r00t2.io/sysutils/paths"
|
|
)
|
|
|
|
// NewEmbedFsMember returns an embedFsMember from embedFs.
|
|
func NewEmbedFsMember(embedFs *embed.FS) (m *embedFsMember) {
|
|
|
|
m = &embedFsMember{
|
|
FS: embedFs,
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
/*
|
|
NewMergedFS returns a MergedFS.
|
|
|
|
The last filesystem in a MergedFS is always embedTplFS.
|
|
If fsPaths is empty, mfs will only contain embedTplFS.
|
|
|
|
Nonexisting paths in fsPaths will be skipped (and added to the noExist slice).
|
|
|
|
Order will be retained but duplicates will be skipped and added to the dupes slice.
|
|
|
|
noExist and dupes will be nil if no non-existing or duplicate paths are encountereed.
|
|
*/
|
|
func NewMergedFS(fsPaths ...string) (mfs *MergedFS, noExist, dupes []string, err error) {
|
|
|
|
var m MergedFS
|
|
var exists bool
|
|
var fsPath string
|
|
var fsMem mergedFsMember
|
|
|
|
m = MergedFS{
|
|
fses: make([]mergedFsMember, 0, len(fsPaths)+1),
|
|
overridePaths: make([]string, 0, len(fsPaths)+1),
|
|
uniq: mapset.NewSet[string](),
|
|
}
|
|
|
|
for _, fsPath = range fsPaths {
|
|
if exists, err = paths.RealPathExists(&fsPath); err != nil {
|
|
return
|
|
}
|
|
if !exists {
|
|
noExist = append(noExist, fsPath)
|
|
continue
|
|
}
|
|
if !m.uniq.Add(fsPath) {
|
|
dupes = append(dupes, fsPath)
|
|
continue
|
|
}
|
|
if fsMem, err = NewRealFsMember(fsPath); err != nil {
|
|
return
|
|
}
|
|
m.fses = append(m.fses, fsMem)
|
|
m.overridePaths = append(m.overridePaths, fsPath)
|
|
}
|
|
// embedded fs last
|
|
m.fses = append(m.fses, NewEmbedFsMember(&embedTplFS))
|
|
m.overridePaths = append(m.overridePaths, "")
|
|
|
|
m.fses = slices.Clip(m.fses)
|
|
m.overridePaths = slices.Clip(m.overridePaths)
|
|
|
|
mfs = &m
|
|
|
|
return
|
|
}
|
|
|
|
// NewRealFsMember returns a realFsMember (which properly conforms to mergedFsMember) from a real filesystem path.
|
|
func NewRealFsMember(fsPath string) (fsm *realFsMember, err error) {
|
|
|
|
var fsp string
|
|
var m realFsMember
|
|
|
|
if err = paths.RealPath(&fsp); err != nil {
|
|
return
|
|
}
|
|
|
|
if m.Root, err = os.OpenRoot(fsPath); err != nil {
|
|
return
|
|
}
|
|
|
|
fsm = &m
|
|
|
|
return
|
|
}
|