go-judge/filestore/file_local.go
2021-03-19 00:28:11 -07:00

94 lines
1.7 KiB
Go

package filestore
import (
"errors"
"os"
"path"
"sync"
"github.com/criyle/go-judge/envexec"
)
type fileLocalStore struct {
dir string // directory to store file
name map[string]string // id to name mapping if exists
mu sync.RWMutex
}
// NewFileLocalStore create new local file store
func NewFileLocalStore(dir string) FileStore {
return &fileLocalStore{
dir: dir,
name: make(map[string]string),
}
}
func (s *fileLocalStore) Add(name string, content []byte) (string, error) {
s.mu.Lock()
defer s.mu.Unlock()
id, err := generateUniqueID(func(id string) (bool, error) {
_, err := os.Stat(path.Join(s.dir, id))
switch {
case errors.Is(err, os.ErrNotExist):
return false, nil
case err == nil:
return true, nil
default:
return false, err
}
})
if err != nil {
return "", err
}
err = os.WriteFile(path.Join(s.dir, id), content, 0644)
if err != nil {
return "", err
}
s.name[id] = name
return id, err
}
func (s *fileLocalStore) Get(id string) (string, envexec.File) {
s.mu.RLock()
defer s.mu.RUnlock()
p := path.Join(s.dir, id)
if _, err := os.Stat(p); os.IsNotExist(err) {
return "", nil
}
name, ok := s.name[id]
if !ok {
name = id
}
return name, envexec.NewFileInput(p)
}
func (s *fileLocalStore) Remove(id string) bool {
s.mu.Lock()
defer s.mu.Unlock()
delete(s.name, id)
p := path.Join(s.dir, id)
if _, err := os.Stat(p); os.IsNotExist(err) {
return false
}
os.Remove(p)
return true
}
func (s *fileLocalStore) List() []string {
s.mu.RLock()
defer s.mu.RUnlock()
var names []string
fi, err := os.ReadDir(s.dir)
if err != nil {
return nil
}
for _, f := range fi {
names = append(names, f.Name())
}
return names
}