You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bog/infrastructure/fs/swampfile/repository.go

155 lines
3.0 KiB
Go

package swampfile
import (
"caj-larsson/bog/dataswamp/swampfile"
"os"
"path"
"path/filepath"
"io/fs"
"time"
"errors"
)
var ErrDirtyRepo = errors.New("Dirty repository without flag")
type FileSystemSwampFileData struct {
path string
size int64
mod_time time.Time
file *os.File
}
func (f FileSystemSwampFileData) Read(p []byte) (int, error) {
return f.file.Read(p)
}
func (f FileSystemSwampFileData) Write(p []byte) (int, error) {
return f.file.Write(p)
}
func (f FileSystemSwampFileData) Close() error {
return f.file.Close()
}
func (f FileSystemSwampFileData) Seek(offset int64, whence int) (int64, error) {
return f.file.Seek(offset, whence)
}
func (f FileSystemSwampFileData) Path() string {
return f.path
}
func (f FileSystemSwampFileData) Size() int64 {
return f.size
}
func (f FileSystemSwampFileData) Modified() time.Time {
return time.Now()
}
type Repository struct {
Root string
}
func NewRepository(root string) (*Repository, error) {
fi, err := os.ReadDir(root)
if err != nil {
return nil, err
}
flagpath := path.Join(root, ".bogrepo")
if len(fi) == 0 {
// New Repository, write flagfile
f, err := os.OpenFile(flagpath, os.O_CREATE, 0644)
if err != nil {
return nil, err
}
f.Close()
}
flagfile, err := os.OpenFile(flagpath, os.O_RDONLY, 0)
if err != nil {
return nil, ErrDirtyRepo
}
flagfile.Close()
return &Repository { root }, nil
}
func (f Repository) absPath(filename string, namespace_ns string) string {
return path.Join(f.Root, namespace_ns, filename)
}
func (f Repository) Create(filename string, namespace_ns string) (swampfile.SwampInFile, error) {
abs_path := f.absPath(filename, namespace_ns)
dir := path.Dir(abs_path)
os.MkdirAll(dir, 0750)
file, err := os.OpenFile(abs_path, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
panic(err)
}
stat_info, err := file.Stat()
if err != nil {
panic(err)
}
bfd := FileSystemSwampFileData{filename, stat_info.Size(), stat_info.ModTime(), file}
return bfd, nil
}
func (f Repository) Open(filename string, namespace_ns string) (swampfile.SwampOutFile, error) {
abs_path := f.absPath(filename, namespace_ns)
dir := path.Dir(abs_path)
os.MkdirAll(dir, 0750)
file, err := os.OpenFile(abs_path, os.O_RDONLY, 0644)
if err != nil {
return nil, swampfile.ErrNotExists
}
bfd := FileSystemSwampFileData{filename, 0, time.Now(), file}
return bfd, nil
}
func (f Repository) Delete(filename string, namespace_ns string) {
abs_path := f.absPath(filename, namespace_ns)
os.Remove(abs_path)
}
func (r Repository) DeleteOlderThan(namespace_stub string, ts time.Time) error {
dr := path.Join(r.Root, namespace_stub)
err := filepath.Walk(dr, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}
mode := info.Mode()
if mode.IsRegular() {
if ts.Before(info.ModTime()) {
err = os.Remove(path)
if err != nil {
panic(err)
}
}
return nil
}
if !mode.IsDir() {
return swampfile.ErrCorrupted
}
return nil
})
return err
}