Files
simplegit/common/config.go
T
2026-07-16 09:14:16 -04:00

100 lines
2.5 KiB
Go

package common
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"sync/atomic"
)
// Config carries the daemon's startup params. The server needs the git root to
// open repos and the rest to answer the Status RPC (which also hands gitctl the
// db_uri so it can connect directly for inspection reads).
type Config struct {
Root string
RPCAddr string
SSHAddr string
ManageAddr string
AuthURL string
DBUri string
SkipAuth bool
preparedDbUri string
prepared atomic.Bool
driver string
dsn string
}
func (c *Config) RepoRoot() string {
return filepath.Join(c.Root, "repos")
}
// Prepare checks that the config is valid and creates the repo root if needed.
func (c *Config) Prepare() error {
if c.prepared.Load() {
return nil
}
var err error
if c.DBUri == "" {
return errors.New("simplegit: -db is required (e.g. sqlite://state.db)")
}
if err := os.MkdirAll(c.RepoRoot(), 0o755); err != nil {
return fmt.Errorf("simplegit: Failed to create data root: %s (%v)", c.RepoRoot(), err)
}
c.driver, c.dsn, c.preparedDbUri, err = ParseDBURI(c.Root, c.DBUri)
if err != nil {
return errors.New("simplegit: ParseDBURI failed")
}
if c.RPCAddr == "" {
return errors.New("simplegit: -rpc is required (the HTTP server is this binary's only listener)")
}
if c.ManageAddr == "" {
return fmt.Errorf("*manageAddr == nil")
}
c.prepared.Store(true)
return nil
}
func (c *Config) Driver() string {
if !c.prepared.Load() {
panic("Config.Driver called before Prepare")
}
return c.driver
}
func (c *Config) DSN() string {
if !c.prepared.Load() {
panic("Config.DSN called before Prepare")
}
return c.dsn
}
func (c *Config) DBURI() string {
if !c.prepared.Load() {
panic("Config.PreparedDBUri called before Prepare")
}
return c.preparedDbUri
}
// normalizeName strips one trailing ".git" so both "myrepo" and "myrepo.git"
// refer to the same repo.
func normalizeName(name string) string {
return strings.TrimSuffix(name, ".git")
}
// relPath returns the repo path relative to root: "owner/name.git".
func relPath(owner, name string) string {
return owner + "/" + normalizeName(name) + ".git"
}
// RepoPath returns the absolute on-disk path for owner/name, but only if the
// repo is registered in the DB -- the DB is the authority, not the filesystem.
// In skip-auth mode the DB check is skipped (any path under root resolves).
func (s *Config) RepoPath(owner, name string) (string, error) {
name = normalizeName(name)
rel := relPath(owner, name)
return Resolve(s.RepoRoot(), rel)
}