Skip to content

Commit

Permalink
libgit2: return func to help callers free git2go objects
Browse files Browse the repository at this point in the history
Signed-off-by: Paulo Gomes <paulo.gomes@weave.works>
  • Loading branch information
Paulo Gomes committed May 11, 2022
1 parent 393db80 commit 187a9f0
Showing 1 changed file with 16 additions and 20 deletions.
36 changes: 16 additions & 20 deletions pkg/git/libgit2/checkout.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,11 @@ type CheckoutBranch struct {
func (c *CheckoutBranch) Checkout(ctx context.Context, path, url string, opts *git.AuthOptions) (_ *git.Commit, err error) {
defer recoverPanic(&err)

repo, remote, err := getBlankRepoAndRemote(ctx, path, url, opts)

repo, remote, free, err := getBlankRepoAndRemote(ctx, path, url, opts)
if err != nil {
return nil, err
}
defer repo.Free()
defer remote.Free()
defer remote.Disconnect()
defer free()

// When the last observed revision is set, check whether it is still
// the same at the remote branch. If so, short-circuit the clone operation here.
Expand Down Expand Up @@ -154,15 +151,11 @@ type CheckoutTag struct {
func (c *CheckoutTag) Checkout(ctx context.Context, path, url string, opts *git.AuthOptions) (_ *git.Commit, err error) {
defer recoverPanic(&err)

repo, remote, err := getBlankRepoAndRemote(ctx, path, url, opts)

repo, remote, free, err := getBlankRepoAndRemote(ctx, path, url, opts)
if err != nil {
return nil, err
}

defer repo.Free()
defer remote.Free()
defer remote.Disconnect()
defer free()

if c.LastRevision != "" {
heads, err := remote.Ls(c.Tag)
Expand Down Expand Up @@ -416,30 +409,33 @@ func buildSignature(s *git2go.Signature) git.Signature {
}

// getBlankRepoAndRemote returns a newly initialized repository, and a remote connected to the provided url.
// Callers must make sure to call the below defer statements:
// defer repo.Free()
// defer remote.Free()
// defer remote.Disconnect()
func getBlankRepoAndRemote(ctx context.Context, path, url string, opts *git.AuthOptions) (*git2go.Repository, *git2go.Remote, error) {
// Callers must call the returning function to free all git2go objects.
func getBlankRepoAndRemote(ctx context.Context, path, url string, opts *git.AuthOptions) (*git2go.Repository, *git2go.Remote, func(), error) {
repo, err := git2go.InitRepository(path, false)
if err != nil {
return nil, nil, fmt.Errorf("unable to init repository for '%s': %w", managed.EffectiveURL(url), gitutil.LibGit2Error(err))
return nil, nil, nil, fmt.Errorf("unable to init repository for '%s': %w", managed.EffectiveURL(url), gitutil.LibGit2Error(err))
}

remote, err := repo.Remotes.Create("origin", url)
if err != nil {
repo.Free()
return nil, nil, fmt.Errorf("unable to create remote for '%s': %w", managed.EffectiveURL(url), gitutil.LibGit2Error(err))
return nil, nil, nil, fmt.Errorf("unable to create remote for '%s': %w", managed.EffectiveURL(url), gitutil.LibGit2Error(err))
}

callBacks := RemoteCallbacks(ctx, opts)
err = remote.ConnectFetch(&callBacks, &git2go.ProxyOptions{Type: git2go.ProxyTypeAuto}, nil)
if err != nil {
remote.Free()
repo.Free()
return nil, nil, fmt.Errorf("unable to fetch-connect to remote '%s': %w", managed.EffectiveURL(url), gitutil.LibGit2Error(err))
return nil, nil, nil, fmt.Errorf("unable to fetch-connect to remote '%s': %w", managed.EffectiveURL(url), gitutil.LibGit2Error(err))
}

free := func() {
remote.Disconnect()
remote.Free()
repo.Free()
}
return repo, remote, nil
return repo, remote, free, nil
}

func recoverPanic(err *error) {
Expand Down

0 comments on commit 187a9f0

Please sign in to comment.