package store
import (
"fmt"
"time"
bolt "go.etcd.io/bbolt"
)
// Repo is a bare git repository hosted on this instance.
type Repo struct {
Name string `json:"name"` // e.g. "alice/mon-projet"
Owner string `json:"owner"` // principal, e.g. "alice@instancea.example"
Path string `json:"path"` // absolute path to the bare repo on disk
CreatedAt time.Time `json:"created_at"`
// Public repos are readable (never writable) by any principal that can
// authenticate to this instance, without needing an explicit ACL entry.
// This does not grant anonymous/unauthenticated access — the reader
// still needs a valid local account or a certificate from a domain
// this instance already trusts (§5.2); it only skips the per-repo
// collaborator check for reads.
Public bool `json:"public"`
Topics []string `json:"topics,omitempty"`
Description string `json:"description,omitempty"`
}
func (s *Store) CreateRepo(r Repo) error {
if r.Name == "" || r.Owner == "" || r.Path == "" {
return fmt.Errorf("store: repo name, owner and path are required")
}
r.CreatedAt = time.Now().UTC()
return s.db.Update(func(tx *bolt.Tx) error {
if tx.Bucket(bucketRepos).Get([]byte(r.Name)) != nil {
return fmt.Errorf("store: repo %q already exists", r.Name)
}
return putJSON(tx, bucketRepos, r.Name, r)
})
}
func (s *Store) GetRepo(name string) (Repo, error) {
var r Repo
err := s.db.View(func(tx *bolt.Tx) error {
return getJSON(tx, bucketRepos, name, &r)
})
return r, err
}
func (s *Store) ListRepos() ([]Repo, error) {
var repos []Repo
err := s.db.View(func(tx *bolt.Tx) error {
var err error
repos, err = listJSON[Repo](tx, bucketRepos)
return err
})
return repos, err
}
func (s *Store) DeleteRepo(name string) error {
return s.db.Update(func(tx *bolt.Tx) error {
return deleteKey(tx, bucketRepos, name)
})
}
func (s *Store) SetRepoPublic(name string, public bool) error {
return s.db.Update(func(tx *bolt.Tx) error {
var r Repo
if err := getJSON(tx, bucketRepos, name, &r); err != nil {
return err
}
r.Public = public
return putJSON(tx, bucketRepos, name, r)
})
}
func (s *Store) SetRepoTopics(name string, topics []string) error {
return s.db.Update(func(tx *bolt.Tx) error {
var r Repo
if err := getJSON(tx, bucketRepos, name, &r); err != nil {
return err
}
r.Topics = topics
return putJSON(tx, bucketRepos, name, r)
})
}
func (s *Store) SetRepoDescription(name, description string) error {
return s.db.Update(func(tx *bolt.Tx) error {
var r Repo
if err := getJSON(tx, bucketRepos, name, &r); err != nil {
return err
}
r.Description = description
return putJSON(tx, bucketRepos, name, r)
})
}