diff options
author | Toon Claes <toon@gitlab.com> | 2022-10-19 17:37:09 +0300 |
---|---|---|
committer | Toon Claes <toon@gitlab.com> | 2022-10-21 12:01:18 +0300 |
commit | c488ac952f293d090020a4722edd5a864b219bc6 (patch) | |
tree | 6159f40748dd7ec22334ea735e2a2f5c5b930bfc | |
parent | 1e7c1a320633351a75bc4d56e977d6739ec4e349 (diff) |
gitpipe: Handle error in DiffTree skip function
Change the prototype of the gitpipe.DiffTree skipResult function so it
also can return an error and the gitpipe can be aborted.
-rw-r--r-- | internal/git/gitpipe/diff_tree.go | 17 | ||||
-rw-r--r-- | internal/git/gitpipe/diff_tree_test.go | 27 | ||||
-rw-r--r-- | internal/gitaly/linguist/linguist.go | 6 |
3 files changed, 41 insertions, 9 deletions
diff --git a/internal/git/gitpipe/diff_tree.go b/internal/git/gitpipe/diff_tree.go index cf81a1ba3..4133c5085 100644 --- a/internal/git/gitpipe/diff_tree.go +++ b/internal/git/gitpipe/diff_tree.go @@ -15,7 +15,7 @@ import ( type diffTreeConfig struct { recursive bool ignoreSubmodules bool - skipResult func(*RevisionResult) bool + skipResult func(*RevisionResult) (bool, error) } // DiffTreeOption is an option for the DiffTree pipeline step. @@ -38,7 +38,7 @@ func DiffTreeWithIgnoreSubmodules() DiffTreeOption { // DiffTreeWithSkip will execute the given function for each RevisionResult processed by the // pipeline. If the callback returns `true`, then the object will be skipped and not passed down // the pipeline. -func DiffTreeWithSkip(skipResult func(*RevisionResult) bool) DiffTreeOption { +func DiffTreeWithSkip(skipResult func(*RevisionResult) (bool, error)) DiffTreeOption { return func(cfg *diffTreeConfig) { cfg.skipResult = skipResult } @@ -116,8 +116,17 @@ func DiffTree( ObjectName: attrsAndFile[1], } - if cfg.skipResult != nil && cfg.skipResult(&result) { - continue + if cfg.skipResult != nil { + skip, err := cfg.skipResult(&result) + if err != nil { + sendRevisionResult(ctx, resultChan, RevisionResult{ + err: fmt.Errorf("diff-tree skip: %q", err), + }) + return + } + if skip { + continue + } } if isDone := sendRevisionResult(ctx, resultChan, result); isDone { diff --git a/internal/git/gitpipe/diff_tree_test.go b/internal/git/gitpipe/diff_tree_test.go index 616fb8291..fb90b01ac 100644 --- a/internal/git/gitpipe/diff_tree_test.go +++ b/internal/git/gitpipe/diff_tree_test.go @@ -188,12 +188,35 @@ func TestDiffTree(t *testing.T) { } }, options: []DiffTreeOption{ - DiffTreeWithSkip(func(r *RevisionResult) bool { - return bytes.Equal(r.ObjectName, []byte("b")) + DiffTreeWithSkip(func(r *RevisionResult) (bool, error) { + return bytes.Equal(r.ObjectName, []byte("b")), nil }), }, }, { + desc: "with skip failure", + setup: func(t *testing.T, repoPath string) (git.Revision, git.Revision, []RevisionResult) { + treeA := gittest.WriteTree(t, cfg, repoPath, []gittest.TreeEntry{ + {Path: "a", Mode: "100644", Content: "1"}, + {Path: "b", Mode: "100644", Content: "2"}, + }) + + changedBlobA := gittest.WriteBlob(t, cfg, repoPath, []byte("x")) + treeB := gittest.WriteTree(t, cfg, repoPath, []gittest.TreeEntry{ + {Path: "a", Mode: "100644", OID: changedBlobA}, + {Path: "b", Mode: "100644", Content: "y"}, + }) + + return treeA.Revision(), treeB.Revision(), nil + }, + options: []DiffTreeOption{ + DiffTreeWithSkip(func(r *RevisionResult) (bool, error) { + return true, errors.New("broken") + }), + }, + expectedErr: errors.New(`diff-tree skip: "broken"`), + }, + { desc: "invalid revision", setup: func(t *testing.T, repoPath string) (git.Revision, git.Revision, []RevisionResult) { gittest.WriteCommit(t, cfg, repoPath, gittest.WithBranch("main")) diff --git a/internal/gitaly/linguist/linguist.go b/internal/gitaly/linguist/linguist.go index f5f11b067..8083bfea6 100644 --- a/internal/gitaly/linguist/linguist.go +++ b/internal/gitaly/linguist/linguist.go @@ -153,7 +153,7 @@ func (inst *Instance) enryStats(ctx context.Context, commitID string) (ByteCount // Stats are cached for one commit, so get the git-diff-tree(1) // between that commit and the one we're calculating stats for. - skipFunc := func(result *gitpipe.RevisionResult) bool { + skipFunc := func(result *gitpipe.RevisionResult) (bool, error) { // Skip files that are deleted, or // an excluded filetype based on filename. if git.ObjectHashSHA1.IsZeroOID(result.OID) || @@ -162,9 +162,9 @@ func (inst *Instance) enryStats(ctx context.Context, commitID string) (ByteCount // function, but for every file that's deleted, // remove the stats. stats.drop(string(result.ObjectName)) - return true + return true, nil } - return false + return false, nil } revlistIt = gitpipe.DiffTree(ctx, inst.repo, |