git: fix issue with checking out annotated tags by full ref

If tag was already pulled by --tags or without refs/tags
that creates ambigous reference in the shared repository.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
Tonis Tiigi
2025-09-24 17:51:15 -07:00
parent fbc3b11385
commit ef8e5f97db
2 changed files with 74 additions and 2 deletions

View File

@@ -531,7 +531,11 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out
// local refs are needed so they would be advertised on next fetches. Force is used
// in case the ref is a branch and it now points to a different commit sha
// TODO: is there a better way to do this?
args = append(args, "--force", ref+":tags/"+ref)
targetRef := ref
if !strings.HasPrefix(ref, "refs/tags/") {
targetRef = "tags/" + ref
}
args = append(args, "--force", ref+":"+targetRef)
}
if _, err := git.Run(ctx, args...); err != nil {
return nil, errors.Wrapf(err, "failed to fetch remote %s", urlutil.RedactCredentials(gs.src.Remote))
@@ -615,7 +619,11 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out
pullref := ref
if isAnnotatedTag {
pullref += ":refs/tags/" + pullref
targetRef := pullref
if !strings.HasPrefix(pullref, "refs/tags/") {
targetRef = "refs/tags/" + pullref
}
pullref += ":" + targetRef
} else if gitutil.IsCommitSHA(ref) {
pullref = "refs/buildkit/" + identity.NewID()
_, err = git.Run(ctx, "update-ref", pullref, ref)

View File

@@ -639,6 +639,70 @@ func testFetchByTag(t *testing.T, tag, expectedCommitSubject string, isAnnotated
require.Contains(t, strings.TrimSpace(string(gitLogOutput)), expectedCommitSubject)
}
}
func TestFetchAnnotatedTagAfterCloneSHA1(t *testing.T) {
testFetchAnnotatedTagAfterClone(t, "sha1")
}
func TestFetchAnnotatedTagAfterCloneSHA256(t *testing.T) {
testFetchAnnotatedTagAfterClone(t, "sha256")
}
func testFetchAnnotatedTagAfterClone(t *testing.T, format string) {
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)
repo := setupGitRepo(t, format)
cmd := exec.Command("git", "rev-parse", "HEAD")
cmd.Dir = repo.mainPath
out, err := cmd.Output()
require.NoError(t, err)
expLen := 40
if format == "sha256" {
expLen = 64
}
sha := strings.TrimSpace(string(out))
require.Equal(t, expLen, len(sha))
gs := setupGitSource(t, t.TempDir())
id := &GitIdentifier{Remote: repo.mainURL, Ref: sha, KeepGitDir: true}
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)
require.GreaterOrEqual(t, len(key1), expLen+4)
require.Equal(t, expLen, len(pin1))
ref, err := g.Snapshot(ctx, nil)
require.NoError(t, err)
ref.Release(context.TODO())
id = &GitIdentifier{Remote: repo.mainURL, Ref: "refs/tags/v1.2.3", KeepGitDir: true}
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)
require.GreaterOrEqual(t, len(key1), expLen+4)
require.Equal(t, expLen, len(pin1))
ref, err = g.Snapshot(ctx, nil)
require.NoError(t, err)
ref.Release(context.TODO())
}
func TestMultipleTagAccessKeepGitDirSHA1(t *testing.T) {
testMultipleTagAccess(t, true, "sha1")