From dff03a24fa420c3c74ac05c31d83232d6b0babf9 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Fri, 21 Jun 2024 15:47:41 -0700 Subject: [PATCH] git: fix pulling commit SHA only referenced from a tag On commit SHA input we currently do a full fetch of remote so we can pick up the commit by SHA later. This only pulls in tags that are also part of branches. Extra flag is needed to also get the tags that are not part of branches. Signed-off-by: Tonis Tiigi --- source/git/source.go | 1 + source/git/source_test.go | 80 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/source/git/source.go b/source/git/source.go index 998ede24ea4e..1b757500d7a3 100644 --- a/source/git/source.go +++ b/source/git/source.go @@ -470,6 +470,7 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out if !isCommitSHA(ref) { // TODO: find a branch from ls-remote? args = append(args, "--depth=1", "--no-tags") } else { + args = append(args, "--tags") if _, err := os.Lstat(filepath.Join(gitDir, "shallow")); err == nil { args = append(args, "--unshallow") } diff --git a/source/git/source_test.go b/source/git/source_test.go index 0b52ae9e6b3b..49fe6a7ada7b 100644 --- a/source/git/source_test.go +++ b/source/git/source_test.go @@ -217,6 +217,72 @@ func testFetchBySHA(t *testing.T, keepGitDir bool) { require.Equal(t, "subcontents\n", string(dt)) } +func TestFetchUnreferencedTagSha(t *testing.T) { + testFetchUnreferencedTagSha(t, false) +} + +func TestFetchUnreferencedTagShaKeepGitDir(t *testing.T) { + testFetchUnreferencedTagSha(t, true) +} + +// testFetchUnreferencedTagSha tests fetching a SHA that points to a tag that is not reachable from any branch. +func testFetchUnreferencedTagSha(t *testing.T, keepGitDir bool) { + if runtime.GOOS == "windows" { + t.Skip("Depends on unimplemented containerd bind-mount support on Windows") + } + + t.Parallel() + ctx := namespaces.WithNamespace(context.Background(), "buildkit-test") + ctx = logProgressStreams(ctx, t) + + gs := setupGitSource(t, t.TempDir()) + + repo := setupGitRepo(t) + + cmd := exec.Command("git", "rev-parse", "v1.2.3-special") + cmd.Dir = repo.mainPath + + out, err := cmd.Output() + require.NoError(t, err) + + sha := strings.TrimSpace(string(out)) + require.Equal(t, 40, len(sha)) + + id := &GitIdentifier{Remote: repo.mainURL, Ref: sha, KeepGitDir: keepGitDir} + + g, err := gs.Resolve(ctx, id, nil, nil) + require.NoError(t, err) + + key1, pin1, _, done, err := g.CacheKey(ctx, nil, 0) + require.NoError(t, err) + require.True(t, done) + + expLen := 40 + if keepGitDir { + expLen += 4 + } + + require.Equal(t, expLen, len(key1)) + require.Equal(t, 40, len(pin1)) + + ref1, err := g.Snapshot(ctx, nil) + require.NoError(t, err) + defer ref1.Release(context.TODO()) + + mount, err := ref1.Mount(ctx, true, nil) + require.NoError(t, err) + + lm := snapshot.LocalMounter(mount) + dir, err := lm.Mount() + require.NoError(t, err) + defer lm.Unmount() + + dt, err := os.ReadFile(filepath.Join(dir, "bar")) + require.NoError(t, err) + + require.Equal(t, "foo\n", string(dt)) +} + func TestFetchByTag(t *testing.T) { testFetchByTag(t, "lightweight-tag", "third", false, true, false) } @@ -610,6 +676,13 @@ func setupGitRepo(t *testing.T) gitRepoFixture { "git add subfile", "git commit -m initial", ) + // * (refs/heads/feature) withsub + // * feature + // * (HEAD -> refs/heads/master, tag: refs/tags/lightweight-tag) third + // | * (tag: refs/tags/v1.2.3-special) tagonly-leaf + // |/ + // * (tag: refs/tags/v1.2.3) second + // * (tag: refs/tags/a/v1.2.3) initial runShell(t, fixture.mainPath, "git -c init.defaultBranch=master init", "git config --local user.email test", @@ -622,6 +695,12 @@ func setupGitRepo(t *testing.T) gitRepoFixture { "git add def", "git commit -m second", "git tag -a -m \"this is an annotated tag\" v1.2.3", + "echo foo > bar", + "git add bar", + "git commit -m tagonly-leaf", + "git tag --no-sign v1.2.3-special", + // switch master back to v1.2.3 + "git checkout -B master v1.2.3", "echo sbb > foo13", "git add foo13", "git commit -m third", @@ -635,6 +714,7 @@ func setupGitRepo(t *testing.T) gitRepoFixture { "git add -A", "git commit -m withsub", "git checkout master", + // "git log --oneline --graph --decorate=full --all", ) return fixture }