From 0df2b0e0f07089828308bab5852ebac1a30f0c68 Mon Sep 17 00:00:00 2001 From: Blake Burkhart Date: Mon, 28 Jun 2021 19:50:10 -0500 Subject: [PATCH] Fix tag checkout with libgit2 SetHeadDetached (git_repository_set_head_detached) only changes HEAD, and does not actually checkout the files on disk. Use CheckoutHead with the CheckoutForce Strategy to actually check the files out on disk. Additionally add a test that validates the hash of a checked out file's contents. Previously, the hash of the desired tag was being reported as the checked out revision by the GitRepository. However the wrong files were checked out and an incorrect revision would be deployed by Flux. Signed-off-by: Blake Burkhart --- pkg/git/libgit2/checkout.go | 17 +++++++++++++++-- pkg/git/libgit2/checkout_test.go | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/pkg/git/libgit2/checkout.go b/pkg/git/libgit2/checkout.go index a5007b70..5aee26a1 100644 --- a/pkg/git/libgit2/checkout.go +++ b/pkg/git/libgit2/checkout.go @@ -112,7 +112,14 @@ func (c *CheckoutTag) Checkout(ctx context.Context, path, url string, auth *git. if err != nil { return nil, "", fmt.Errorf("git commit '%s' not found: %w", head.Target(), err) } - return &Commit{commit}, fmt.Sprintf("%s/%s", c.tag, head.Target().String()), nil + err = repo.CheckoutHead(&git2go.CheckoutOpts{ + Strategy: git2go.CheckoutForce, + }) + if err != nil { + return nil, "", fmt.Errorf("git checkout error: %w", err) + } + + return &Commit{commit}, fmt.Sprintf("%s/%s", c.tag, commit.Id().String()), nil } type CheckoutCommit struct { @@ -218,6 +225,12 @@ func (c *CheckoutSemVer) Checkout(ctx context.Context, path, url string, auth *g if err != nil { return nil, "", fmt.Errorf("git commit '%s' not found: %w", head.Target().String(), err) } + err = repo.CheckoutHead(&git2go.CheckoutOpts{ + Strategy: git2go.CheckoutForce, + }) + if err != nil { + return nil, "", fmt.Errorf("git checkout error: %w", err) + } - return &Commit{commit}, fmt.Sprintf("%s/%s", t, head.Target().String()), nil + return &Commit{commit}, fmt.Sprintf("%s/%s", t, commit.Id().String()), nil } diff --git a/pkg/git/libgit2/checkout_test.go b/pkg/git/libgit2/checkout_test.go index 5ef6e81d..8c9d9483 100644 --- a/pkg/git/libgit2/checkout_test.go +++ b/pkg/git/libgit2/checkout_test.go @@ -18,8 +18,12 @@ package libgit2 import ( "context" + "crypto/sha256" + "encoding/hex" + "io" "io/ioutil" "os" + "path" "testing" git2go "github.com/libgit2/git2go/v31" @@ -44,6 +48,21 @@ func TestCheckoutTagSemVer_Checkout(t *testing.T) { t.Error(err) } + // Ensure the correct files are checked out on disk + f, err := os.Open(path.Join(tmpDir, "README.md")) + if err != nil { + t.Error(err) + } + defer f.Close() + h := sha256.New() + if _, err := io.Copy(h, f); err != nil { + t.Error(err) + } + fileHash := hex.EncodeToString(h.Sum(nil)) + if fileHash != "2bd1707542a11f987ee24698dcc095a9f57639f401133ef6a29da97bf8f3f302" { + t.Errorf("expected files not checked out. Expected hash %s, got %s", "2bd1707542a11f987ee24698dcc095a9f57639f401133ef6a29da97bf8f3f302", fileHash) + } + semVer := CheckoutSemVer{ semVer: ">=1.0.0 <=1.7.0", }