1
0
Fork 0
mirror of https://github.com/Luzifer/cloudbox.git synced 2024-12-23 03:01:18 +00:00
cloudbox/providers/local/provider.go

120 lines
2.7 KiB
Go

package local
import (
"crypto/sha256"
"hash"
"io"
"os"
"path"
"path/filepath"
"strings"
"time"
"github.com/pkg/errors"
"github.com/Luzifer/cloudbox/providers"
)
func New(uri string) (providers.CloudProvider, error) {
if !strings.HasPrefix(uri, "file://") {
return nil, providers.ErrInvalidURI
}
return &Provider{directory: strings.TrimPrefix(uri, "file://")}, nil
}
type Provider struct {
directory string
}
func (p Provider) Capabilities() providers.Capability { return providers.CapBasic }
func (p Provider) Name() string { return "local" }
func (p Provider) GetChecksumMethod() hash.Hash { return sha256.New() }
func (p Provider) ListFiles() ([]providers.File, error) {
var (
absPath string
err error
files []providers.File
)
if absPath, err = filepath.Abs(p.directory); err != nil {
return nil, errors.Wrap(err, "Unable to calculate absolute path")
}
err = filepath.Walk(absPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
// We behave like git: We don't care about dirs themselves
return nil
}
files = append(files, File{
info: info,
relativeName: strings.TrimLeft(strings.TrimPrefix(path, absPath), "/"),
fullPath: path,
})
return nil
})
return files, errors.Wrap(err, "File listing failed")
}
func (p Provider) DeleteFile(relativeName string) error {
return os.Remove(path.Join(p.directory, relativeName))
}
func (p Provider) GetFile(relativeName string) (providers.File, error) {
fullPath := path.Join(p.directory, relativeName)
stat, err := os.Stat(fullPath)
if err != nil {
if os.IsNotExist(err) {
return nil, providers.ErrFileNotFound
}
return nil, errors.Wrap(err, "Unable to get file stat")
}
return File{
info: stat,
relativeName: relativeName,
fullPath: fullPath,
}, nil
}
func (p Provider) PutFile(f providers.File) (providers.File, error) {
fullPath := path.Join(p.directory, f.Info().RelativeName)
fp, err := os.Create(fullPath)
if err != nil {
return nil, errors.Wrap(err, "Unable to create file")
}
rfp, err := f.Content()
if err != nil {
return nil, errors.Wrap(err, "Unable to get remote file content")
}
defer rfp.Close()
if _, err := io.Copy(fp, rfp); err != nil {
return nil, errors.Wrap(err, "Unable to copy file contents")
}
if err := fp.Close(); err != nil {
return nil, errors.Wrap(err, "Unable to close local file")
}
if err := os.Chtimes(fullPath, time.Now(), f.Info().LastModified); err != nil {
return nil, errors.Wrap(err, "Unable to set last file mod time")
}
return p.GetFile(f.Info().RelativeName)
}
func (p Provider) Share(relativeName string) (string, error) {
return "", providers.ErrFeatureNotSupported
}