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 }