From a289f1b911352817bb9b3ac8928189c782ddd5b0 Mon Sep 17 00:00:00 2001 From: Jabberwocky238 <7176656@qq.com> Date: Thu, 16 Jul 2026 09:14:16 -0400 Subject: [PATCH] s --- common/config.go | 40 ++++++++++++++++++++++++++++++++++++---- gitrpc/server.go | 23 ++++++++++++----------- state/db.go | 23 ++--------------------- state/mut.go | 10 +++++----- 4 files changed, 55 insertions(+), 41 deletions(-) diff --git a/common/config.go b/common/config.go index 3f5cdb3..25541a1 100644 --- a/common/config.go +++ b/common/config.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path/filepath" + "strings" "sync/atomic" ) @@ -20,9 +21,10 @@ type Config struct { DBUri string SkipAuth bool - prepared atomic.Bool - driver string - dsn string + preparedDbUri string + prepared atomic.Bool + driver string + dsn string } func (c *Config) RepoRoot() string { @@ -31,6 +33,9 @@ func (c *Config) RepoRoot() string { // 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)") @@ -38,7 +43,7 @@ func (c *Config) Prepare() error { 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.DBUri, err = ParseDBURI(c.Root, c.DBUri) + c.driver, c.dsn, c.preparedDbUri, err = ParseDBURI(c.Root, c.DBUri) if err != nil { return errors.New("simplegit: ParseDBURI failed") } @@ -65,3 +70,30 @@ func (c *Config) DSN() string { } 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) +} diff --git a/gitrpc/server.go b/gitrpc/server.go index b46163b..c8b046b 100644 --- a/gitrpc/server.go +++ b/gitrpc/server.go @@ -21,20 +21,21 @@ import ( ) type Server struct { - gitRepoRoot string - cfg *common.Config - startedAt time.Time - middleware *MiddlewareClient - mut state.IStateMut + cfg *common.Config + startedAt time.Time + middleware *MiddlewareClient + mut state.IStateMut } func NewServer(cfg *common.Config, middleware *MiddlewareClient, mut state.IStateMut) *Server { + if err := cfg.Prepare(); err != nil { + return nil + } return &Server{ - gitRepoRoot: cfg.Root, - cfg: cfg, - startedAt: time.Now(), - middleware: middleware, - mut: mut, + cfg: cfg, + startedAt: time.Now(), + middleware: middleware, + mut: mut, } } @@ -168,7 +169,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { } func (s *Server) open(ctx context.Context, repo string) (*gitcmd.Repository, error) { - p, err := common.Resolve(s.gitRepoRoot, repo) + p, err := common.Resolve(s.cfg.RepoRoot(), repo) if err != nil { return nil, newError(codeInvalidParams, "invalid repo name: "+err.Error()) } diff --git a/state/db.go b/state/db.go index e50c0aa..c2c8b31 100644 --- a/state/db.go +++ b/state/db.go @@ -185,22 +185,11 @@ func fingerprint(key ssh.PublicKey) string { return "SHA256:" + hex.EncodeToString(sum[:]) } -// 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" -} - // findRepo looks up a repo by (owner, name). name may include ".git". A missing // row yields ErrRepoNotFound. func (s *LocalState) findRepo(owner, name string) (*Repo, error) { var r Repo - has, err := s.engine.Where("namespace = ? AND name = ?", owner, normalizeName(name)).Get(&r) + has, err := s.engine.Where("namespace = ? AND name = ?", owner, strings.TrimSuffix(name, ".git")).Get(&r) if err != nil { return nil, fmt.Errorf("lookup repo: %w", err) } @@ -210,16 +199,8 @@ func (s *LocalState) findRepo(owner, name string) (*Repo, error) { return &r, nil } -// 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 *LocalState) RepoPath(owner, name string) (string, error) { - name = normalizeName(name) - rel := relPath(owner, name) - if _, err := s.findRepo(owner, name); err != nil { - return "", err - } - return common.Resolve(s.cfg.RepoRoot(), rel) + return s.cfg.RepoPath(owner, name) } // Open returns a gitcmd.Repository for owner/name. The repo must be registered diff --git a/state/mut.go b/state/mut.go index a87bce7..5707ef9 100644 --- a/state/mut.go +++ b/state/mut.go @@ -106,7 +106,7 @@ func (s *LocalState) nextNamespaceID() (int64, error) { // namespace must already exist (have at least one repo) so NamespaceID can be // resolved; NameID is freshly assigned. skip-auth: disk-only (git init, no DB). func (s *LocalState) CreateRepo(ns, name string) error { - path, err := s.RepoPath(ns, name) + path, err := s.cfg.RepoPath(ns, name) if err != nil { return err } @@ -157,7 +157,7 @@ func (s *LocalState) ExistRepo(ns, name string) error { // DeleteRepo removes the repo row, its repo-targeted ACL grants, and the // on-disk bare directory. Hard-deletes. skip-auth: disk-only. func (s *LocalState) DeleteRepo(ns, name string) error { - path, _ := s.RepoPath(ns, name) + path, _ := s.cfg.RepoPath(ns, name) r, err := s.findRepo(ns, name) if err != nil { return err @@ -186,11 +186,11 @@ func (s *LocalState) MoveRepo(old, new string) error { if err != nil { return err } - oldPath, err := s.RepoPath(oldNs, oldName) + oldPath, err := s.cfg.RepoPath(oldNs, oldName) if err != nil { return err } - newPath, err := s.RepoPath(newNs, newName) + newPath, err := s.cfg.RepoPath(newNs, newName) if err != nil { return err } @@ -207,7 +207,7 @@ func (s *LocalState) MoveRepo(old, new string) error { if err != nil { return err } - upd := Repo{Namespace: newNs, Name: normalizeName(newName)} + upd := Repo{Namespace: newNs, Name: strings.TrimSuffix(newName, ".git")} cols := []string{"namespace", "name"} if newNs != oldNs { nsID, err := s.resolveNamespaceID(newNs)