feat(platform): add GitClient helper with idempotent EnsureRepo

This commit is contained in:
MDietermann
2026-04-14 08:32:04 +02:00
parent 3f4223879b
commit 1903217b5f
2 changed files with 78 additions and 0 deletions

23
internal/platform/git.go Normal file
View File

@@ -0,0 +1,23 @@
package platform
import (
"context"
"os"
"path/filepath"
)
// GitClient wraps `git` via a Runner.
type GitClient struct{ Runner Runner }
// Clone always runs `git clone --depth=1 url dest`.
func (g GitClient) Clone(ctx context.Context, url, dest string) error {
return g.Runner.Run(ctx, "git", "clone", "--depth=1", url, dest)
}
// EnsureRepo clones url into dest if dest/.git is missing; otherwise noop.
func (g GitClient) EnsureRepo(ctx context.Context, url, dest string) error {
if _, err := os.Stat(filepath.Join(dest, ".git")); err == nil {
return nil
}
return g.Clone(ctx, url, dest)
}

View File

@@ -0,0 +1,55 @@
package platform
import (
"context"
"os"
"path/filepath"
"testing"
)
type gitFakeRunner struct {
calls [][]string
err error
}
func (f *gitFakeRunner) Run(_ context.Context, name string, args ...string) error {
f.calls = append(f.calls, append([]string{name}, args...))
return f.err
}
func (f *gitFakeRunner) Output(_ context.Context, name string, args ...string) ([]byte, error) {
return nil, nil
}
func TestGitEnsureRepoClonesWhenMissing(t *testing.T) {
r := &gitFakeRunner{}
g := GitClient{Runner: r}
dest := filepath.Join(t.TempDir(), "repo")
if err := g.EnsureRepo(context.Background(), "https://x/y.git", dest); err != nil {
t.Fatal(err)
}
if len(r.calls) != 1 {
t.Fatalf("want 1 call, got %d: %v", len(r.calls), r.calls)
}
got := r.calls[0]
want := []string{"git", "clone", "--depth=1", "https://x/y.git", dest}
for i := range want {
if i >= len(got) || got[i] != want[i] {
t.Fatalf("call = %v, want %v", got, want)
}
}
}
func TestGitEnsureRepoSkipsWhenPresent(t *testing.T) {
dest := t.TempDir()
if err := os.MkdirAll(filepath.Join(dest, ".git"), 0o755); err != nil {
t.Fatal(err)
}
r := &gitFakeRunner{}
g := GitClient{Runner: r}
if err := g.EnsureRepo(context.Background(), "https://x/y.git", dest); err != nil {
t.Fatal(err)
}
if len(r.calls) != 0 {
t.Fatalf("expected no calls, got %v", r.calls)
}
}