diff --git a/internal/controller/git/git.go b/internal/controller/git/git.go index 8c1542004..16601d088 100644 --- a/internal/controller/git/git.go +++ b/internal/controller/git/git.go @@ -95,6 +95,19 @@ type repo struct { currentBranch string } +// CloneOptions represents options for cloning a git repository. +type CloneOptions struct { + // Branch is the name of the branch to clone. If not specified, the default + // branch will be cloned. + Branch string + // SingleBranch indicates whether the clone should be a single-branch clone. + SingleBranch bool + // Shallow indicates whether the clone should be with a depth of 1. This is + // useful for speeding up the cloning process when all we care about is the + // latest commit from a single branch. + Shallow bool +} + // Clone produces a local clone of the remote git repository at the specified // URL and returns an implementation of the Repo interface that is stateful and // NOT suitable for use across multiple goroutines. This function will also @@ -103,6 +116,7 @@ type repo struct { func Clone( repoURL string, repoCreds RepoCredentials, + opts *CloneOptions, ) (Repo, error) { homeDir, err := os.MkdirTemp("", "") if err != nil { @@ -120,7 +134,7 @@ func Clone( if err = r.setupAuth(repoCreds); err != nil { return nil, err } - return r, r.clone() + return r, r.clone(opts) } func (r *repo) AddAll() error { @@ -140,9 +154,25 @@ func (r *repo) Clean() error { return errors.Wrapf(err, "error cleaning branch %q", r.currentBranch) } -func (r *repo) clone() error { - r.currentBranch = "HEAD" - cmd := r.buildCommand("clone", "--no-tags", r.url, r.dir) +func (r *repo) clone(opts *CloneOptions) error { + if opts == nil { + opts = &CloneOptions{} + } + args := []string{"clone", "--no-tags"} + if opts.Branch != "" { + args = append(args, "--branch", opts.Branch) + r.currentBranch = opts.Branch + } else { + r.currentBranch = "HEAD" + } + if opts.SingleBranch { + args = append(args, "--single-branch") + } + if opts.Shallow { + args = append(args, "--depth=1") + } + args = append(args, r.url, r.dir) + cmd := r.buildCommand(args...) cmd.Dir = r.homeDir // Override the cmd.Dir that's set by r.buildCommand() _, err := libExec.Exec(cmd) return errors.Wrapf( diff --git a/internal/controller/promotion/git.go b/internal/controller/promotion/git.go index 12c2db451..56f0164ef 100644 --- a/internal/controller/promotion/git.go +++ b/internal/controller/promotion/git.go @@ -243,7 +243,7 @@ func (g *gitMechanism) gitCommit( if creds == nil { creds = &git.RepoCredentials{} } - repo, err := git.Clone(update.RepoURL, *creds) + repo, err := git.Clone(update.RepoURL, *creds, nil) if err != nil { return "", errors.Wrapf(err, "error cloning git repo %q", update.RepoURL) } diff --git a/internal/controller/warehouses/git.go b/internal/controller/warehouses/git.go index b5d48125f..26d9b48de 100644 --- a/internal/controller/warehouses/git.go +++ b/internal/controller/warehouses/git.go @@ -84,19 +84,17 @@ func getLatestCommitMeta( if creds == nil { creds = &git.RepoCredentials{} } - repo, err := git.Clone(repoURL, *creds) + repo, err := git.Clone( + repoURL, + *creds, + &git.CloneOptions{ + Branch: branch, + SingleBranch: true, + Shallow: true, + }, + ) if err != nil { return nil, errors.Wrapf(err, "error cloning git repo %q", repoURL) - - } - if branch != "" { - if err = repo.Checkout(branch); err != nil { - return nil, errors.Wrapf( - err, - "error checking out branch %q from git repo", - repoURL, - ) - } } var gm gitMeta gm.Commit, err = repo.LastCommitID() diff --git a/internal/controller/warehouses/git_test.go b/internal/controller/warehouses/git_test.go index 975f11e35..0cc94e131 100644 --- a/internal/controller/warehouses/git_test.go +++ b/internal/controller/warehouses/git_test.go @@ -155,17 +155,6 @@ func TestGetLatestCommitID(t *testing.T) { require.Contains(t, err.Error(), "error cloning git repo") }, }, - - { - name: "error checking out branch", - repoURL: "https://github.com/akuity/kargo.git", - branch: "bogus", // This should force a failure - assertions: func(_ *gitMeta, err error) { - require.Error(t, err) - require.Contains(t, err.Error(), "error checking out branch") - }, - }, - { name: "success", repoURL: "https://github.com/akuity/kargo.git",