feat(platform): add GitClient helper with idempotent EnsureRepo
This commit is contained in:
23
internal/platform/git.go
Normal file
23
internal/platform/git.go
Normal 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)
|
||||||
|
}
|
||||||
55
internal/platform/git_test.go
Normal file
55
internal/platform/git_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user