From 4645296cb74cbdfd95675c5d555794792d731dff Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Fri, 5 Sep 2025 16:33:30 -0700 Subject: [PATCH] git: add sha256 commits support Signed-off-by: Tonis Tiigi --- source/git/source.go | 40 ++-- source/git/source_test.go | 324 +++++++++++++++++++++++--------- util/gitutil/git_commit.go | 2 +- util/gitutil/git_commit_test.go | 5 +- 4 files changed, 262 insertions(+), 109 deletions(-) diff --git a/source/git/source.go b/source/git/source.go index 697cce238..497990c43 100644 --- a/source/git/source.go +++ b/source/git/source.go @@ -105,7 +105,7 @@ func (gs *gitSource) Identifier(scheme, ref string, attrs map[string]string, pla } // needs to be called with repo lock -func (gs *gitSource) mountRemote(ctx context.Context, remote string, authArgs []string, g session.Group) (target string, release func() error, retErr error) { +func (gs *gitSource) mountRemote(ctx context.Context, remote string, authArgs []string, sha256 bool, g session.Group) (target string, release func() error, retErr error) { sis, err := searchGitRemote(ctx, gs.cache, remote) if err != nil { return "", nil, errors.Wrapf(err, "failed to search metadata for %s", urlutil.RedactCredentials(remote)) @@ -171,7 +171,11 @@ func (gs *gitSource) mountRemote(ctx context.Context, remote string, authArgs [] // implied default to suppress "hint:" output about not having a // default initial branch name set which otherwise spams unit // test logs. - if _, err := git.Run(ctx, "-c", "init.defaultBranch=master", "init", "--bare"); err != nil { + args := []string{"-c", "init.defaultBranch=master", "init", "--bare"} + if sha256 { + args = append(args, "--object-format=sha256") + } + if _, err := git.Run(ctx, args...); err != nil { return "", nil, errors.Wrapf(err, "failed to init repo at %s", dir) } @@ -198,6 +202,7 @@ type gitSourceHandler struct { *gitSource src GitIdentifier cacheKey string + sha256 bool sm *session.Manager authArgs []string } @@ -376,13 +381,14 @@ func (gs *gitSourceHandler) CacheKey(ctx context.Context, g session.Group, index if refCommitFullHash != "" { cacheKey := gs.shaToCacheKey(refCommitFullHash, ref2) gs.cacheKey = cacheKey + gs.sha256 = len(refCommitFullHash) == 64 // gs.src.Checksum is verified when checking out the commit return cacheKey, refCommitFullHash, nil, true, nil } gs.getAuthToken(ctx, g) - git, cleanup, err := gs.gitCli(ctx, g) + tmpGit, cleanup, err := gs.emptyGitCli(ctx, g) if err != nil { return "", "", nil, false, err } @@ -390,7 +396,7 @@ func (gs *gitSourceHandler) CacheKey(ctx context.Context, g session.Group, index ref := gs.src.Ref if ref == "" { - ref, err = getDefaultBranch(ctx, git, gs.src.Remote) + ref, err = getDefaultBranch(ctx, tmpGit, gs.src.Remote) if err != nil { return "", "", nil, false, err } @@ -398,7 +404,7 @@ func (gs *gitSourceHandler) CacheKey(ctx context.Context, g session.Group, index // TODO: should we assume that remote tag is immutable? add a timer? - buf, err := git.Run(ctx, "ls-remote", "origin", ref, ref+"^{}") + buf, err := tmpGit.Run(ctx, "ls-remote", gs.src.Remote, ref, ref+"^{}") if err != nil { return "", "", nil, false, errors.Wrapf(err, "failed to fetch remote %s", urlutil.RedactCredentials(remote)) } @@ -445,6 +451,7 @@ func (gs *gitSourceHandler) CacheKey(ctx context.Context, g session.Group, index } cacheKey := gs.shaToCacheKey(sha, usedRef) gs.cacheKey = cacheKey + gs.sha256 = len(sha) == 64 return cacheKey, sha, nil, true, nil } @@ -475,15 +482,18 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out gs.locker.Lock(gs.src.Remote) defer gs.locker.Unlock(gs.src.Remote) - git, cleanup, err := gs.gitCli(ctx, g) + git, cleanup, err := gs.emptyGitCli(ctx, g) if err != nil { return nil, err } defer cleanup() - gitDir, err := git.GitDir(ctx) + + gitDir, unmountGitDir, err := gs.mountRemote(ctx, gs.src.Remote, gs.authArgs, gs.sha256, g) if err != nil { return nil, err } + defer unmountGitDir() + git = git.New(gitutil.WithGitDir(gitDir)) ref := gs.src.Ref if ref == "" { @@ -581,7 +591,11 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out return nil, err } checkoutGit := git.New(gitutil.WithWorkTree(checkoutDir), gitutil.WithGitDir(checkoutDirGit)) - _, err = checkoutGit.Run(ctx, "-c", "init.defaultBranch=master", "init") + args := []string{"-c", "init.defaultBranch=master", "init"} + if gs.sha256 { + args = append(args, "--object-format=sha256") + } + _, err = checkoutGit.Run(ctx, args...) if err != nil { return nil, err } @@ -713,7 +727,7 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out return snap, nil } -func (gs *gitSourceHandler) gitCli(ctx context.Context, g session.Group, opts ...gitutil.Option) (*gitutil.GitCLI, func() error, error) { +func (gs *gitSourceHandler) emptyGitCli(ctx context.Context, g session.Group, opts ...gitutil.Option) (*gitutil.GitCLI, func() error, error) { var cleanups []func() error cleanup := func() error { var err error @@ -727,13 +741,6 @@ func (gs *gitSourceHandler) gitCli(ctx context.Context, g session.Group, opts .. } var err error - gitDir, unmountGitDir, err := gs.mountRemote(ctx, gs.src.Remote, gs.authArgs, g) - if err != nil { - cleanup() - return nil, nil, err - } - cleanups = append(cleanups, unmountGitDir) - var sock string if gs.src.MountSSHSock != "" { var unmountSock func() error @@ -757,7 +764,6 @@ func (gs *gitSourceHandler) gitCli(ctx context.Context, g session.Group, opts .. } opts = append([]gitutil.Option{ - gitutil.WithGitDir(gitDir), gitutil.WithArgs(gs.authArgs...), gitutil.WithSSHAuthSock(sock), gitutil.WithSSHKnownHosts(knownHosts), diff --git a/source/git/source_test.go b/source/git/source_test.go index db810a79d..3d8c55427 100644 --- a/source/git/source_test.go +++ b/source/git/source_test.go @@ -39,14 +39,21 @@ import ( bolt "go.etcd.io/bbolt" ) -func TestRepeatedFetch(t *testing.T) { - testRepeatedFetch(t, false) +func TestRepeatedFetchSHA1(t *testing.T) { + testRepeatedFetch(t, false, "sha1") } -func TestRepeatedFetchKeepGitDir(t *testing.T) { - testRepeatedFetch(t, true) +func TestRepeatedFetchKeepGitDirSHA1(t *testing.T) { + testRepeatedFetch(t, true, "sha1") } -func testRepeatedFetch(t *testing.T, keepGitDir bool) { +func TestRepeatedFetchSHA256(t *testing.T) { + testRepeatedFetch(t, false, "sha256") +} +func TestRepeatedFetchKeepGitDirSHA256(t *testing.T) { + testRepeatedFetch(t, true, "sha256") +} + +func testRepeatedFetch(t *testing.T, keepGitDir bool, format string) { if runtime.GOOS == "windows" { t.Skip("Depends on unimplemented containerd bind-mount support on Windows") } @@ -56,7 +63,7 @@ func testRepeatedFetch(t *testing.T, keepGitDir bool) { gs := setupGitSource(t, t.TempDir()) - repo := setupGitRepo(t) + repo := setupGitRepo(t, format) id := &GitIdentifier{Remote: repo.mainURL, KeepGitDir: keepGitDir} @@ -68,13 +75,17 @@ func testRepeatedFetch(t *testing.T, keepGitDir bool) { require.True(t, done) expLen := 40 + if format == "sha256" { + expLen = 64 + } + expPinLen := expLen if keepGitDir { expLen += 4 require.GreaterOrEqual(t, len(key1), expLen) } else { require.Equal(t, expLen, len(key1)) } - require.Equal(t, 40, len(pin1)) + require.Equal(t, expPinLen, len(pin1)) ref1, err := g.Snapshot(ctx, nil) require.NoError(t, err) @@ -184,7 +195,7 @@ func testFetchBySHA(t *testing.T, format string, keepGitDir bool) { gs := setupGitSource(t, t.TempDir()) - repo := setupGitRepoFormat(t, format) + repo := setupGitRepo(t, format) cmd := exec.Command("git", "rev-parse", "feature") cmd.Dir = repo.mainPath @@ -246,32 +257,56 @@ func testFetchBySHA(t *testing.T, format string, keepGitDir bool) { require.Equal(t, "subcontents\n", string(dt)) } -func TestFetchUnreferencedTagSha(t *testing.T) { - testFetchUnreferencedRefSha(t, "v1.2.3-special", false) +func TestFetchUnreferencedTagShaSHA1(t *testing.T) { + testFetchUnreferencedRefSha(t, "v1.2.3-special", false, "sha1") } -func TestFetchUnreferencedTagShaKeepGitDir(t *testing.T) { - testFetchUnreferencedRefSha(t, "v1.2.3-special", true) +func TestFetchUnreferencedTagShaKeepGitDirSHA1(t *testing.T) { + testFetchUnreferencedRefSha(t, "v1.2.3-special", true, "sha1") } -func TestFetchUnreferencedRefSha(t *testing.T) { - testFetchUnreferencedRefSha(t, "refs/special", false) +func TestFetchUnreferencedRefShaSHA1(t *testing.T) { + testFetchUnreferencedRefSha(t, "refs/special", false, "sha1") } -func TestFetchUnreferencedRefShaKeepGitDir(t *testing.T) { - testFetchUnreferencedRefSha(t, "refs/special", true) +func TestFetchUnreferencedRefShaKeepGitDirSHA1(t *testing.T) { + testFetchUnreferencedRefSha(t, "refs/special", true, "sha1") } -func TestFetchUnadvertisedRefSha(t *testing.T) { - testFetchUnreferencedRefSha(t, "refs/special~", false) +func TestFetchUnadvertisedRefShaSHA1(t *testing.T) { + testFetchUnreferencedRefSha(t, "refs/special~", false, "sha1") } -func TestFetchUnadvertisedRefShaKeepGitDir(t *testing.T) { - testFetchUnreferencedRefSha(t, "refs/special~", true) +func TestFetchUnadvertisedRefShaKeepGitDirSHA1(t *testing.T) { + testFetchUnreferencedRefSha(t, "refs/special~", true, "sha1") +} + +func TestFetchUnreferencedTagShaSHA256(t *testing.T) { + testFetchUnreferencedRefSha(t, "v1.2.3-special", false, "sha256") +} + +func TestFetchUnreferencedTagShaKeepGitDirSHA256(t *testing.T) { + testFetchUnreferencedRefSha(t, "v1.2.3-special", true, "sha256") +} + +func TestFetchUnreferencedRefShaSHA256(t *testing.T) { + testFetchUnreferencedRefSha(t, "refs/special", false, "sha256") +} + +func TestFetchUnreferencedRefShaKeepGitDirSHA256(t *testing.T) { + testFetchUnreferencedRefSha(t, "refs/special", true, "sha256") +} + +func TestFetchUnadvertisedRefShaSHA256(t *testing.T) { + testFetchUnreferencedRefSha(t, "refs/special~", false, "sha256") +} + +func TestFetchUnadvertisedRefShaKeepGitDirSHA256(t *testing.T) { + testFetchUnreferencedRefSha(t, "refs/special~", true, "sha256") } // testFetchUnreferencedRefSha tests fetching a SHA that points to a ref that is not reachable from any branch. -func testFetchUnreferencedRefSha(t *testing.T, ref string, keepGitDir bool) { +func testFetchUnreferencedRefSha(t *testing.T, ref string, keepGitDir bool, format string) { if runtime.GOOS == "windows" { t.Skip("Depends on unimplemented containerd bind-mount support on Windows") } @@ -282,7 +317,7 @@ func testFetchUnreferencedRefSha(t *testing.T, ref string, keepGitDir bool) { gs := setupGitSource(t, t.TempDir()) - repo := setupGitRepo(t) + repo := setupGitRepo(t, format) cmd := exec.Command("git", "rev-parse", ref) cmd.Dir = repo.mainPath @@ -290,8 +325,13 @@ func testFetchUnreferencedRefSha(t *testing.T, ref string, keepGitDir bool) { out, err := cmd.Output() require.NoError(t, err) + expSHALen := 40 + if format == "sha256" { + expSHALen = 64 + } + sha := strings.TrimSpace(string(out)) - require.Equal(t, 40, len(sha)) + require.Equal(t, expSHALen, len(sha)) id := &GitIdentifier{Remote: repo.mainURL, Ref: sha, KeepGitDir: keepGitDir} @@ -303,13 +343,17 @@ func testFetchUnreferencedRefSha(t *testing.T, ref string, keepGitDir bool) { require.True(t, done) expLen := 40 + if format == "sha256" { + expLen = 64 + } + expPinLen := expLen if keepGitDir { expLen += 4 require.GreaterOrEqual(t, len(key1), expLen) } else { require.Equal(t, expLen, len(key1)) } - require.Equal(t, 40, len(pin1)) + require.Equal(t, expPinLen, len(pin1)) ref1, err := g.Snapshot(ctx, nil) require.NoError(t, err) @@ -329,64 +373,124 @@ func testFetchUnreferencedRefSha(t *testing.T, ref string, keepGitDir bool) { require.Equal(t, "foo\n", string(dt)) } -func TestFetchByTag(t *testing.T) { - testFetchByTag(t, "lightweight-tag", "third", false, true, false, testChecksumModeNone) +func TestFetchByTagSHA1(t *testing.T) { + testFetchByTag(t, "lightweight-tag", "third", false, true, false, testChecksumModeNone, "sha1") } -func TestFetchByTagKeepGitDir(t *testing.T) { - testFetchByTag(t, "lightweight-tag", "third", false, true, true, testChecksumModeNone) +func TestFetchByTagKeepGitDirSHA1(t *testing.T) { + testFetchByTag(t, "lightweight-tag", "third", false, true, true, testChecksumModeNone, "sha1") } -func TestFetchByTagFull(t *testing.T) { - testFetchByTag(t, "refs/tags/lightweight-tag", "third", false, true, true, testChecksumModeNone) +func TestFetchByTagFullSHA1(t *testing.T) { + testFetchByTag(t, "refs/tags/lightweight-tag", "third", false, true, true, testChecksumModeNone, "sha1") } -func TestFetchByAnnotatedTag(t *testing.T) { - testFetchByTag(t, "v1.2.3", "second", true, false, false, testChecksumModeNone) +func TestFetchByAnnotatedTagSHA1(t *testing.T) { + testFetchByTag(t, "v1.2.3", "second", true, false, false, testChecksumModeNone, "sha1") } -func TestFetchByAnnotatedTagKeepGitDir(t *testing.T) { - testFetchByTag(t, "v1.2.3", "second", true, false, true, testChecksumModeNone) +func TestFetchByAnnotatedTagKeepGitDirSHA1(t *testing.T) { + testFetchByTag(t, "v1.2.3", "second", true, false, true, testChecksumModeNone, "sha1") } -func TestFetchByAnnotatedTagFull(t *testing.T) { - testFetchByTag(t, "refs/tags/v1.2.3", "second", true, false, true, testChecksumModeNone) +func TestFetchByAnnotatedTagFullSHA1(t *testing.T) { + testFetchByTag(t, "refs/tags/v1.2.3", "second", true, false, true, testChecksumModeNone, "sha1") } -func TestFetchByBranch(t *testing.T) { - testFetchByTag(t, "feature", "withsub", false, true, false, testChecksumModeNone) +func TestFetchByBranchSHA1(t *testing.T) { + testFetchByTag(t, "feature", "withsub", false, true, false, testChecksumModeNone, "sha1") } -func TestFetchByBranchKeepGitDir(t *testing.T) { - testFetchByTag(t, "feature", "withsub", false, true, true, testChecksumModeNone) +func TestFetchByBranchKeepGitDirSHA1(t *testing.T) { + testFetchByTag(t, "feature", "withsub", false, true, true, testChecksumModeNone, "sha1") } -func TestFetchByBranchFull(t *testing.T) { - testFetchByTag(t, "refs/heads/feature", "withsub", false, true, true, testChecksumModeNone) +func TestFetchByBranchFullSHA1(t *testing.T) { + testFetchByTag(t, "refs/heads/feature", "withsub", false, true, true, testChecksumModeNone, "sha1") } -func TestFetchByRef(t *testing.T) { - testFetchByTag(t, "test", "feature", false, true, false, testChecksumModeNone) +func TestFetchByRefSHA1(t *testing.T) { + testFetchByTag(t, "test", "feature", false, true, false, testChecksumModeNone, "sha1") } -func TestFetchByRefKeepGitDir(t *testing.T) { - testFetchByTag(t, "test", "feature", false, true, true, testChecksumModeNone) +func TestFetchByRefKeepGitDirSHA1(t *testing.T) { + testFetchByTag(t, "test", "feature", false, true, true, testChecksumModeNone, "sha1") } -func TestFetchByRefFull(t *testing.T) { - testFetchByTag(t, "refs/test", "feature", false, true, true, testChecksumModeNone) +func TestFetchByRefFullSHA1(t *testing.T) { + testFetchByTag(t, "refs/test", "feature", false, true, true, testChecksumModeNone, "sha1") } -func TestFetchByTagWithChecksum(t *testing.T) { - testFetchByTag(t, "lightweight-tag", "third", false, true, false, testChecksumModeValid) +func TestFetchByTagWithChecksumSHA1(t *testing.T) { + testFetchByTag(t, "lightweight-tag", "third", false, true, false, testChecksumModeValid, "sha1") } -func TestFetchByTagWithChecksumPartial(t *testing.T) { - testFetchByTag(t, "lightweight-tag", "third", false, true, false, testChecksumModeValidPartial) +func TestFetchByTagWithChecksumPartialSHA1(t *testing.T) { + testFetchByTag(t, "lightweight-tag", "third", false, true, false, testChecksumModeValidPartial, "sha1") } -func TestFetchByTagWithChecksumInvalid(t *testing.T) { - testFetchByTag(t, "lightweight-tag", "third", false, true, false, testChecksumModeInvalid) +func TestFetchByTagWithChecksumInvalidSHA1(t *testing.T) { + testFetchByTag(t, "lightweight-tag", "third", false, true, false, testChecksumModeInvalid, "sha1") +} + +func TestFetchByTagSHA256(t *testing.T) { + testFetchByTag(t, "lightweight-tag", "third", false, true, false, testChecksumModeNone, "sha256") +} + +func TestFetchByTagKeepGitDirSHA256(t *testing.T) { + testFetchByTag(t, "lightweight-tag", "third", false, true, true, testChecksumModeNone, "sha256") +} + +func TestFetchByTagFullSHA256(t *testing.T) { + testFetchByTag(t, "refs/tags/lightweight-tag", "third", false, true, true, testChecksumModeNone, "sha256") +} + +func TestFetchByAnnotatedTagSHA256(t *testing.T) { + testFetchByTag(t, "v1.2.3", "second", true, false, false, testChecksumModeNone, "sha256") +} + +func TestFetchByAnnotatedTagKeepGitDirSHA256(t *testing.T) { + testFetchByTag(t, "v1.2.3", "second", true, false, true, testChecksumModeNone, "sha256") +} + +func TestFetchByAnnotatedTagFullSHA256(t *testing.T) { + testFetchByTag(t, "refs/tags/v1.2.3", "second", true, false, true, testChecksumModeNone, "sha256") +} + +func TestFetchByBranchSHA256(t *testing.T) { + testFetchByTag(t, "feature", "withsub", false, true, false, testChecksumModeNone, "sha256") +} + +func TestFetchByBranchKeepGitDirSHA256(t *testing.T) { + testFetchByTag(t, "feature", "withsub", false, true, true, testChecksumModeNone, "sha256") +} + +func TestFetchByBranchFullSHA256(t *testing.T) { + testFetchByTag(t, "refs/heads/feature", "withsub", false, true, true, testChecksumModeNone, "sha256") +} + +func TestFetchByRefSHA256(t *testing.T) { + testFetchByTag(t, "test", "feature", false, true, false, testChecksumModeNone, "sha256") +} + +func TestFetchByRefKeepGitDirSHA256(t *testing.T) { + testFetchByTag(t, "test", "feature", false, true, true, testChecksumModeNone, "sha256") +} + +func TestFetchByRefFullSHA256(t *testing.T) { + testFetchByTag(t, "refs/test", "feature", false, true, true, testChecksumModeNone, "sha256") +} + +func TestFetchByTagWithChecksumSHA256(t *testing.T) { + testFetchByTag(t, "lightweight-tag", "third", false, true, false, testChecksumModeValid, "sha256") +} + +func TestFetchByTagWithChecksumPartialSHA256(t *testing.T) { + testFetchByTag(t, "lightweight-tag", "third", false, true, false, testChecksumModeValidPartial, "sha256") +} + +func TestFetchByTagWithChecksumInvalidSHA256(t *testing.T) { + testFetchByTag(t, "lightweight-tag", "third", false, true, false, testChecksumModeInvalid, "sha256") } type testChecksumMode int @@ -398,7 +502,7 @@ const ( testChecksumModeInvalid ) -func testFetchByTag(t *testing.T, tag, expectedCommitSubject string, isAnnotatedTag, hasFoo13File, keepGitDir bool, checksumMode testChecksumMode) { +func testFetchByTag(t *testing.T, tag, expectedCommitSubject string, isAnnotatedTag, hasFoo13File, keepGitDir bool, checksumMode testChecksumMode, format string) { if runtime.GOOS == "windows" { t.Skip("Depends on unimplemented containerd bind-mount support on Windows") } @@ -409,7 +513,7 @@ func testFetchByTag(t *testing.T, tag, expectedCommitSubject string, isAnnotated gs := setupGitSource(t, t.TempDir()) - repo := setupGitRepo(t) + repo := setupGitRepo(t, format) id := &GitIdentifier{Remote: repo.mainURL, Ref: tag, KeepGitDir: keepGitDir} @@ -420,8 +524,12 @@ func testFetchByTag(t *testing.T, tag, expectedCommitSubject string, isAnnotated out, err := cmd.Output() require.NoError(t, err) + expLen := 40 + if format == "sha256" { + expLen = 64 + } sha := strings.TrimSpace(string(out)) - require.Equal(t, 40, len(sha)) + require.Equal(t, expLen, len(sha)) switch checksumMode { case testChecksumModeValid: @@ -430,6 +538,9 @@ func testFetchByTag(t *testing.T, tag, expectedCommitSubject string, isAnnotated id.Checksum = sha[:8] case testChecksumModeInvalid: id.Checksum = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" + if format == "sha256" { + id.Checksum = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" + } default: // NOTREACHED } @@ -443,13 +554,17 @@ func testFetchByTag(t *testing.T, tag, expectedCommitSubject string, isAnnotated require.True(t, done) expLen := 40 + if format == "sha256" { + expLen = 64 + } + expPinLen := expLen if keepGitDir { expLen += 4 require.GreaterOrEqual(t, len(key1), expLen) } else { require.Equal(t, expLen, len(key1)) } - require.Equal(t, 40, len(pin1)) + require.Equal(t, expPinLen, len(pin1)) ref1, err := g.Snapshot(ctx, nil) if checksumMode == testChecksumModeInvalid { @@ -525,15 +640,23 @@ func testFetchByTag(t *testing.T, tag, expectedCommitSubject string, isAnnotated } } -func TestMultipleTagAccessKeepGitDir(t *testing.T) { - testMultipleTagAccess(t, true) +func TestMultipleTagAccessKeepGitDirSHA1(t *testing.T) { + testMultipleTagAccess(t, true, "sha1") } -func TestMultipleTagAccess(t *testing.T) { - testMultipleTagAccess(t, false) +func TestMultipleTagAccessSHA1(t *testing.T) { + testMultipleTagAccess(t, false, "sha1") } -func testMultipleTagAccess(t *testing.T, keepGitDir bool) { +func TestMultipleTagAccessKeepGitDirSHA256(t *testing.T) { + testMultipleTagAccess(t, true, "sha256") +} + +func TestMultipleTagAccessSHA256(t *testing.T) { + testMultipleTagAccess(t, false, "sha256") +} + +func testMultipleTagAccess(t *testing.T, keepGitDir bool, format string) { if runtime.GOOS == "windows" { t.Skip("Depends on unimplemented containerd bind-mount support on Windows") } @@ -544,7 +667,7 @@ func testMultipleTagAccess(t *testing.T, keepGitDir bool) { gs := setupGitSource(t, t.TempDir()) - repo := setupGitRepo(t) + repo := setupGitRepo(t, format) id := &GitIdentifier{Remote: repo.mainURL, KeepGitDir: keepGitDir, Ref: "a/v1.2.3"} @@ -552,6 +675,10 @@ func testMultipleTagAccess(t *testing.T, keepGitDir bool) { require.NoError(t, err) expLen := 40 + if format == "sha256" { + expLen = 64 + } + expPinLen := expLen if keepGitDir { expLen += 4 } @@ -563,7 +690,7 @@ func testMultipleTagAccess(t *testing.T, keepGitDir bool) { } else { require.Equal(t, expLen, len(key1)) } - require.Equal(t, 40, len(pin1)) + require.Equal(t, expPinLen, len(pin1)) ref1, err := g.Snapshot(ctx, nil) require.NoError(t, err) @@ -580,7 +707,7 @@ func testMultipleTagAccess(t *testing.T, keepGitDir bool) { } else { require.Equal(t, expLen, len(key1)) } - require.Equal(t, 40, len(pin2)) + require.Equal(t, expPinLen, len(pin2)) require.Equal(t, pin1, pin2) if !keepGitDir { @@ -624,15 +751,23 @@ func testMultipleTagAccess(t *testing.T, keepGitDir bool) { require.Equal(t, string(dt1), string(dt2)) } -func TestMultipleRepos(t *testing.T) { - testMultipleRepos(t, false) +func TestMultipleReposSHA1(t *testing.T) { + testMultipleRepos(t, false, "sha1") } func TestMultipleReposKeepGitDir(t *testing.T) { - testMultipleRepos(t, true) + testMultipleRepos(t, true, "sha1") } -func testMultipleRepos(t *testing.T, keepGitDir bool) { +func TestMultipleReposSHA256(t *testing.T) { + testMultipleRepos(t, false, "sha256") +} + +func TestMultipleReposKeepGitDirSHA256(t *testing.T) { + testMultipleRepos(t, true, "sha256") +} + +func testMultipleRepos(t *testing.T, keepGitDir bool, format string) { if runtime.GOOS == "windows" { t.Skip("Depends on unimplemented containerd bind-mount support on Windows") } @@ -643,7 +778,7 @@ func testMultipleRepos(t *testing.T, keepGitDir bool) { gs := setupGitSource(t, t.TempDir()) - repo := setupGitRepo(t) + repo := setupGitRepo(t, format) repodir2 := t.TempDir() @@ -667,8 +802,14 @@ func testMultipleRepos(t *testing.T, keepGitDir bool) { require.NoError(t, err) expLen := 40 + expLen2 := expLen + if format == "sha256" { + expLen = 64 + } + expPinLen := expLen if keepGitDir { expLen += 4 + expLen2 += 4 } key1, pin1, _, _, err := g.CacheKey(ctx, nil, 0) @@ -678,14 +819,14 @@ func testMultipleRepos(t *testing.T, keepGitDir bool) { } else { require.Equal(t, expLen, len(key1)) } - require.Equal(t, 40, len(pin1)) + require.Equal(t, expPinLen, len(pin1)) key2, pin2, _, _, err := g2.CacheKey(ctx, nil, 0) require.NoError(t, err) if keepGitDir { - require.GreaterOrEqual(t, len(key2), expLen) + require.GreaterOrEqual(t, len(key2), expLen2) } else { - require.Equal(t, expLen, len(key2)) + require.Equal(t, expLen2, len(key2)) } require.Equal(t, 40, len(pin2)) @@ -749,15 +890,23 @@ func TestCredentialRedaction(t *testing.T) { require.NotContains(t, err.Error(), "keepthissecret") } -func TestSubmoduleSubdir(t *testing.T) { - testSubmoduleSubdir(t, false) +func TestSubmoduleSubdirSHA1(t *testing.T) { + testSubmoduleSubdir(t, false, "sha1") } -func TestSubmoduleSubdirKeepGitDir(t *testing.T) { - testSubmoduleSubdir(t, true) +func TestSubmoduleSubdirKeepGitDirSHA1(t *testing.T) { + testSubmoduleSubdir(t, true, "sha1") } -func testSubmoduleSubdir(t *testing.T, keepGitDir bool) { +func TestSubmoduleSubdirSHA256(t *testing.T) { + testSubmoduleSubdir(t, false, "sha256") +} + +func TestSubmoduleSubdirKeepGitDirSHA256(t *testing.T) { + testSubmoduleSubdir(t, true, "sha256") +} + +func testSubmoduleSubdir(t *testing.T, keepGitDir bool, format string) { if runtime.GOOS == "windows" { t.Skip("Depends on unimplemented containerd bind-mount support on Windows") } @@ -767,7 +916,7 @@ func testSubmoduleSubdir(t *testing.T, keepGitDir bool) { gs := setupGitSource(t, t.TempDir()) - repo := setupGitRepo(t) + repo := setupGitRepo(t, format) id := &GitIdentifier{Remote: repo.mainURL, KeepGitDir: keepGitDir, Ref: "feature", Subdir: "sub"} @@ -779,8 +928,13 @@ func testSubmoduleSubdir(t *testing.T, keepGitDir bool) { require.True(t, done) expLen := 44 + expPinLen := 40 + if format == "sha256" { + expLen = 68 + expPinLen = 64 + } require.GreaterOrEqual(t, len(key1), expLen) - require.Equal(t, 40, len(pin1)) + require.Equal(t, expPinLen, len(pin1)) ref1, err := g.Snapshot(ctx, nil) require.NoError(t, err) @@ -920,13 +1074,7 @@ type gitRepoFixture struct { mainURL, subURL string // HTTP URLs for the respective repos } -// small helper for the common case -func setupGitRepo(t *testing.T) gitRepoFixture { - t.Helper() - return setupGitRepoFormat(t, "sha1") -} - -func setupGitRepoFormat(t *testing.T, format string) gitRepoFixture { +func setupGitRepo(t *testing.T, format string) gitRepoFixture { t.Helper() dir := t.TempDir() srv := serveGitRepo(t, dir) diff --git a/util/gitutil/git_commit.go b/util/gitutil/git_commit.go index 8049e7e2d..448dcb921 100644 --- a/util/gitutil/git_commit.go +++ b/util/gitutil/git_commit.go @@ -1,7 +1,7 @@ package gitutil func IsCommitSHA(str string) bool { - if len(str) != 40 { + if l := len(str); l != 40 && l != 64 { return false } diff --git a/util/gitutil/git_commit_test.go b/util/gitutil/git_commit_test.go index 0320ecedf..a16e6aeec 100644 --- a/util/gitutil/git_commit_test.go +++ b/util/gitutil/git_commit_test.go @@ -10,7 +10,8 @@ import ( func TestIsCommitSHA(t *testing.T) { for truthy, commits := range map[bool][]string{ true: { - "01234567890abcdef01234567890abcdef012345", // 40 valid characters (SHA-1) + "01234567890abcdef01234567890abcdef012345", // 40 valid characters (SHA-1) + "01234567890abcdef01234567890abcdef01234567890abcdef01234567890ab", // 64 valid characters (SHA-256) }, false: { "", // empty string @@ -24,8 +25,6 @@ func TestIsCommitSHA(t *testing.T) { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", // 64 invalid characters "01234567890abcdef01234567890abcdef01234567890abcdef01234567890abc", // 65 valid characters - // TODO: add SHA-256 support and move this up to the "true" section - "01234567890abcdef01234567890abcdef01234567890abcdef01234567890ab", // 64 valid characters (SHA-256) }, } { for _, commit := range commits {