package storage import ( "bytes" "io" "io/ioutil" "os" "path" "path/filepath" "strings" ) type Files struct { root string } func NewFiles(root string) (*Files, error) { _, err := os.Stat(path.Dir(root)) if err != nil { return nil, err } root, err = filepath.Abs(root) if err != nil { return nil, err } return &Files{ root: root, }, os.MkdirAll(root, os.ModePerm) } func (b *Files) List(ns []string, limits ...string) ([]string, error) { namespace := resolveNamespace(ns) files := make([]string, 0) err := filepath.Walk(b.root, func(p string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { return nil } if !strings.HasPrefix(strings.TrimPrefix(p, b.root+"/"), namespace+"/") { return nil } files = append(files, strings.TrimPrefix(p, path.Join(b.root, namespace)+"/")) return nil }) return files, err /* limits = resolveLimits(limits) */ } func (b *Files) Get(key string, ns ...string) ([]byte, error) { r, err := b.GetStream(key, ns...) if err != nil { return nil, err } return ioutil.ReadAll(r) } func (b *Files) GetStream(key string, ns ...string) (io.Reader, error) { namespace := resolveNamespace(ns) path := path.Join(b.root, namespace, key) return os.Open(path) } func (b *Files) Set(key string, value []byte, ns ...string) error { r := bytes.NewReader(value) if value == nil { r = nil } return b.SetStream(key, r, ns...) } func (b *Files) SetStream(key string, r io.Reader, ns ...string) error { namespace := resolveNamespace(ns) dir := path.Join(b.root, namespace) if r == nil { err := os.Remove(path.Join(dir, key)) if os.IsNotExist(err) { err = nil } return err } if err := os.MkdirAll(dir, os.ModePerm); err != nil { return err } path := path.Join(dir, key) f, err := os.Create(path) if err != nil { return err } defer f.Close() _, err = io.Copy(f, r) return err } func (b *Files) Close() error { return nil }