From eb1b7d7d9149114eb6b4287b7cb40c49dccfb26e Mon Sep 17 00:00:00 2001 From: Gabriel Arakaki Giovanini Date: Sun, 16 Oct 2022 19:13:41 +0200 Subject: feat: Add storage interface With this is easier to interact with storage layers. --- storage/storage.go | 6 +++ storage/storage_fs.go | 86 ++++++++++++++++++++++++++++++++-- storage/storage_fs_test.go | 3 +- storage/storage_wd.go | 114 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 storage/storage_wd.go (limited to 'storage') diff --git a/storage/storage.go b/storage/storage.go index b788efb..880396a 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -17,6 +17,12 @@ const ( type Storage interface { Walk(path string, walkMode WalkMode) <-chan string Get(path string) (io.Reader, error) + Put(path string, f io.Reader) error + List(path string) ([]string, error) + Move(src string, dest string) error + Copy(src string, dest string) error + Mkdir(path string) error + Exists(path string) (bool, error) } func CalculateSHA256(r io.Reader) (string, error) { diff --git a/storage/storage_fs.go b/storage/storage_fs.go index 35ce58b..16bf8e8 100644 --- a/storage/storage_fs.go +++ b/storage/storage_fs.go @@ -1,22 +1,38 @@ package storage import ( + "errors" + "fmt" + "io" + "io/ioutil" "os" "path/filepath" + "porg/pipe" ) type FileSystem struct { - root string } -func WalkFolder(folder string, walkMode WalkMode) <-chan string { +func NewFileSystem() *FileSystem { + return &FileSystem{} +} + +func (fs *FileSystem) Get(path string) (io.Reader, error) { + return os.Open(path) +} + +func (fs *FileSystem) Walk(folder string, walkMode WalkMode) <-chan string { c := make(chan string) go func(folder string, c chan string) { filepath.Walk(folder, func(path string, info os.FileInfo, err error) error { file, _ := os.Open(path) defer file.Close() - fileInfo, _ := file.Stat() + fileInfo, err := file.Stat() + if err != nil { + fmt.Println("@@@@ ", err.Error()) + return nil + } switch walkMode { case Folder: @@ -38,3 +54,67 @@ func WalkFolder(folder string, walkMode WalkMode) <-chan string { return c } + +func (fs *FileSystem) Put(path string, f io.Reader) error { + fo, err := os.Create(path) + if err != nil { + return err + } + + if _, err := io.Copy(fo, f); err != nil { + return err + } + + return nil +} + +func (fs *FileSystem) List(path string) ([]string, error) { + files, err := ioutil.ReadDir(path) + if err != err { + return nil, err + } + + findPath := func(f os.FileInfo) string { + return path + "/" + f.Name() + } + return pipe.Map(findPath, files), nil +} + +func (fs *FileSystem) Move(src string, dst string) error { + return os.Rename(src, dst) +} + +func (fs *FileSystem) Copy(src string, dst string) error { + in, err := os.Open(src) + if err != nil { + return err + } + defer in.Close() + + out, err := os.Create(dst) + if err != nil { + return err + } + defer out.Close() + + _, err = io.Copy(out, in) + if err != nil { + return err + } + return out.Close() +} + +func (fs *FileSystem) Exists(path string) (bool, error) { + _, err := os.Stat(path) + if err == nil { + return true, nil + } + if errors.Is(err, os.ErrNotExist) { + return false, nil + } + return false, err +} + +func (fs *FileSystem) Mkdir(path string) error { + return os.MkdirAll(path, 0777) +} diff --git a/storage/storage_fs_test.go b/storage/storage_fs_test.go index b746c7e..429de58 100644 --- a/storage/storage_fs_test.go +++ b/storage/storage_fs_test.go @@ -10,12 +10,13 @@ func TestWalk(t *testing.T) { folder := testutil.CreateFolder() files := map[string]struct{}{} walkedFiles := map[string]struct{}{} + fs := NewFileSystem() for i := 0; i < fileCount; i++ { files[testutil.AppendEmptyFile(folder)] = struct{}{} } - c := WalkFolder(folder, File) + c := fs.Walk(folder, File) for file := range c { walkedFiles[file] = struct{}{} } diff --git a/storage/storage_wd.go b/storage/storage_wd.go new file mode 100644 index 0000000..b166992 --- /dev/null +++ b/storage/storage_wd.go @@ -0,0 +1,114 @@ +package storage + +import ( + "errors" + "io" + "os" + + "github.com/studio-b12/gowebdav" +) + +type WebDav struct { + client *gowebdav.Client +} + +func NewWebDavStorage(root string, username string, password string) *WebDav { + c := gowebdav.NewClient(root, username, password) + return &WebDav{client: c} +} + +func (wd *WebDav) Mkdir(path string) error { + if err := wd.client.MkdirAll(path, 0644); err != nil { + return err + } + return nil +} + +func (wd *WebDav) Put(path string, f io.Reader) error { + return wd.client.WriteStream(path, f, 0644) +} + +func (wd *WebDav) Move(src string, dest string) error { + if src != dest { + if err := wd.client.Rename(src, dest, true); err != nil { + return nil + } + } + return nil +} + +func (wd *WebDav) Exists(path string) (bool, error) { + _, err := wd.client.Stat(path) + if err == nil { + return true, nil + } + if errors.Is(err, os.ErrNotExist) { + return false, nil + } + return false, err +} + +func (wd *WebDav) Copy(src string, dest string) error { + if src != dest { + if err := wd.client.Copy(src, dest, true); err != nil { + return nil + } + } + return nil +} + +func (wd *WebDav) Get(path string) (io.Reader, error) { + return wd.client.ReadStream(path) +} + +func (wd *WebDav) List(path string) ([]string, error) { + files, err := wd.client.ReadDir(path) + if err != nil { + return nil, err + } + + r := make([]string, len(files)) + + for i, v := range files { + r[i] = v.Name() + } + + return r, nil +} + +func (wd *WebDav) Walk(folder string, walkMode WalkMode) <-chan string { + c := make(chan string) + + go func(string, chan string) { + var queue []string + queue = append(queue, folder) + + for len(queue) > 0 { + f := queue[0] + queue = queue[1:] + + files, _ := wd.client.ReadDir(f) + for _, fileInfo := range files { + if fileInfo.IsDir() { + queue = append(queue, f+"/"+fileInfo.Name()) + } + + switch walkMode { + case Folder: + if fileInfo.IsDir() { + c <- f + "/" + fileInfo.Name() + } + case File: + if !fileInfo.IsDir() { + c <- f + "/" + fileInfo.Name() + } + case FileFolder: + c <- f + "/" + fileInfo.Name() + } + } + } + close(c) + }(folder, c) + + return c +} -- cgit v1.2.3