package repo
import (
"fmt"
"os"
"path/filepath"
"regexp"
)
var validName = regexp.MustCompile(`^[A-Za-z0-9_][A-Za-z0-9_.-]*$`)
type Store struct {
Root string
}
func NewStore(root string) (*Store, error) {
abs, err := filepath.Abs(root)
if err != nil {
return nil, err
}
if err := os.MkdirAll(abs, 0o755); err != nil {
return nil, fmt.Errorf("create repo root: %w", err)
}
return &Store{Root: abs}, nil
}
func ValidateName(name string) error {
if !validName.MatchString(name) {
return fmt.Errorf("invalid repo name %q", name)
}
return nil
}
func (s *Store) Path(name string) (string, error) {
if err := ValidateName(name); err != nil {
return "", err
}
return filepath.Join(s.Root, name+".git"), nil
}
func (s *Store) Exists(name string) bool {
path, err := s.Path(name)
if err != nil {
return false
}
info, err := os.Stat(path)
return err == nil && info.IsDir()
}
func (s *Store) List() ([]string, error) {
entries, err := os.ReadDir(s.Root)
if err != nil {
return nil, err
}
var names []string
for _, e := range entries {
if e.IsDir() && filepath.Ext(e.Name()) == ".git" {
names = append(names, e.Name()[:len(e.Name())-len(".git")])
}
}
return names, nil
}