diff --git a/fs/fs.go b/fs/fs.go new file mode 100644 index 0000000..4005d1d --- /dev/null +++ b/fs/fs.go @@ -0,0 +1,69 @@ +package fs + +import ( + "fmt" + "io" + "os" + "path/filepath" +) + +type FS interface { + isFS() +} + +type DirEntry struct { + Name string + FS FS +} + +type Entries interface { + Get() []DirEntry +} + +type Dir struct { + Entries +} + +func (d Dir) isFS() {} + +type Contents interface { + Get() io.Reader +} + +type File struct { + Contents +} + +func (f File) isFS() {} + +func Realize(path string, f FS) error { + if f == nil { + return fmt.Errorf("cannot realize nil FS at %s", path) + } + switch t := f.(type) { + case File: + osf, err := os.Create(path) + if err != nil { + return fmt.Errorf("cannot create file %s: %w", path, err) + } + defer osf.Close() + _, err = io.Copy(osf, t.Get()) + if err != nil { + return fmt.Errorf("cannot write file %s: %w", path, err) + } + case Dir: + err := os.Mkdir(path, 0666) + if err != nil { + return fmt.Errorf("cannot create dir %s: %w", path, err) + } + for _, child := range t.Get() { + err := Realize(filepath.Join(path, child.Name), child.FS) + if err != nil { + return err + } + } + default: + panic("unknown File type") + } + return nil +} diff --git a/fsstuff/main.go b/fsstuff/main.go new file mode 100644 index 0000000..0cdae04 --- /dev/null +++ b/fsstuff/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "io" + "log" + "strings" + + "git.codemonkeysoftware.net/b/sbsqlitessgcms/fs" +) + +type File string + +func (f File) Get() io.Reader { + return strings.NewReader(string(f)) +} + +type Dir map[string]interface{} + +func (d Dir) Get() []fs.DirEntry { + var entries []fs.DirEntry + for name, child := range d { + entry := fs.DirEntry{ + Name: name, + } + switch t := child.(type) { + case File: + entry.FS = fs.File{Contents: t} + case Dir: + entry.FS = fs.Dir{Entries: t} + default: + panic("aw hell naw") + } + entries = append(entries, entry) + } + return entries +} + +func main() { + dir := fs.Dir{ + Entries: Dir{ + "a": File("apple"), + "b": File("bootilicious"), + "c": File("curveball"), + "d": Dir{ + "e": File("ectoplasm"), + "f": File("^&*("), + "g": File("grrrl power"), + "h": File("hellabyte"), + }, + }, + } + err := fs.Realize("./stuff", dir) + if err != nil { + log.Fatal(err) + } +}