From 01b2f455d99bafd9e27d1d3a520a7031d82831de Mon Sep 17 00:00:00 2001 From: oppiliappan Date: Thu, 4 Dec 2025 17:56:46 +0000 Subject: [PATCH] knotserver: use local clones if repo is hosted on the same knot Change-Id: mozkrnmzvkruwlvwxsmwwqvxkswsyuww detect the host to clone from and use a local clone if possible. Signed-off-by: oppiliappan --- knotserver/git/fork.go | 40 ++++++++++++++++++++++++++++++++-- knotserver/xrpc/create_repo.go | 2 +- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/knotserver/git/fork.go b/knotserver/git/fork.go index 1ed9b5e8..5093de8f 100644 --- a/knotserver/git/fork.go +++ b/knotserver/git/fork.go @@ -3,14 +3,27 @@ package git import ( "errors" "fmt" + "log/slog" + "net/url" "os/exec" + "path/filepath" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" + knotconfig "tangled.org/core/knotserver/config" ) -func Fork(repoPath, source string) error { - cloneCmd := exec.Command("git", "clone", "--bare", source, repoPath) +func Fork(repoPath, source string, cfg *knotconfig.Config) error { + u, err := url.Parse(source) + if err != nil { + return fmt.Errorf("failed to parse source URL: %w", err) + } + + if o := optimizeClone(u, cfg); o != nil { + u = o + } + + cloneCmd := exec.Command("git", "clone", "--bare", u.String(), repoPath) if err := cloneCmd.Run(); err != nil { return fmt.Errorf("failed to bare clone repository: %w", err) } @@ -23,6 +36,29 @@ func Fork(repoPath, source string) error { return nil } +func optimizeClone(u *url.URL, cfg *knotconfig.Config) *url.URL { + // only optimize if it's the same host + if u.Host != cfg.Server.Hostname { + return nil + } + + local := filepath.Join(cfg.Repo.ScanPath, u.Path) + + // sanity check: is there a git repo there? + if _, err := PlainOpen(local); err != nil { + return nil + } + + // create optimized file:// URL + optimized := &url.URL{ + Scheme: "file", + Path: local, + } + + slog.Debug("performing local clone", "url", optimized.String()) + return optimized +} + func (g *GitRepo) Sync() error { branch := g.h.String() diff --git a/knotserver/xrpc/create_repo.go b/knotserver/xrpc/create_repo.go index b35c72bd..d0654336 100644 --- a/knotserver/xrpc/create_repo.go +++ b/knotserver/xrpc/create_repo.go @@ -84,7 +84,7 @@ func (h *Xrpc) CreateRepo(w http.ResponseWriter, r *http.Request) { repoPath, _ := securejoin.SecureJoin(h.Config.Repo.ScanPath, relativeRepoPath) if data.Source != nil && *data.Source != "" { - err = git.Fork(repoPath, *data.Source) + err = git.Fork(repoPath, *data.Source, h.Config) if err != nil { l.Error("forking repo", "error", err.Error()) writeError(w, xrpcerr.GenericError(err), http.StatusInternalServerError) -- 2.43.0