diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2020-10-13 14:16:37 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2020-10-15 14:50:07 +0300 |
commit | 2f2e703cf4a535ed8b007b3d6123751a9a2baf78 (patch) | |
tree | 5c1e95e9f3f0ccb117dec6e63f0dd579fece5687 /cmd/gitaly-git2go | |
parent | 8d01fd4b39a645e75a9006860827d8f03c928e2f (diff) |
git2go: Refactor conflict error handling
Due to the process-gap between the conflicts service and its Git2Go
executable, it's not as straight-forward to pass around information as
it usually is. One of those areas which are currently lacking in
conflict handling is how we treat error codes. In case there's a
potentially expected error happening inside the command, it's currently
impossible to tell because all the different errors are lumped together
into a single error return code.
Address this issue by instead serializing error codes into the result
structure. Like this, we can become more informative around the specific
error code and discern different cases.
Diffstat (limited to 'cmd/gitaly-git2go')
-rw-r--r-- | cmd/gitaly-git2go/conflicts.go | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/cmd/gitaly-git2go/conflicts.go b/cmd/gitaly-git2go/conflicts.go index df4bda432..f2ba28abd 100644 --- a/cmd/gitaly-git2go/conflicts.go +++ b/cmd/gitaly-git2go/conflicts.go @@ -10,6 +10,9 @@ import ( git "github.com/libgit2/git2go/v30" "gitlab.com/gitlab-org/gitaly/internal/git2go" + "gitlab.com/gitlab-org/gitaly/internal/helper" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) type conflictsSubcommand struct { @@ -46,7 +49,7 @@ func conflictContent(repo *git.Repository, conflict git.IndexConflict) ([]byte, blob, err := repo.LookupBlob(entry.Id) if err != nil { - return nil, fmt.Errorf("could not get conflicting blob: %w", err) + return nil, helper.ErrPreconditionFailedf("could not get conflicting blob: %w", err) } input.Path = entry.Path @@ -62,6 +65,21 @@ func conflictContent(repo *git.Repository, conflict git.IndexConflict) ([]byte, return merge.Contents, nil } +func conflictError(code codes.Code, message string) error { + result := git2go.ConflictsResult{ + Error: git2go.ConflictError{ + Code: code, + Message: message, + }, + } + + if err := result.SerializeTo(os.Stdout); err != nil { + return err + } + + return nil +} + // Run performs a merge and prints resulting conflicts to stdout. func (cmd *conflictsSubcommand) Run() error { request, err := git2go.ConflictsCommandFromSerialized(cmd.request) @@ -96,7 +114,7 @@ func (cmd *conflictsSubcommand) Run() error { index, err := repo.MergeCommits(ours, theirs, nil) if err != nil { - return fmt.Errorf("could not merge commits: %w", err) + return conflictError(codes.FailedPrecondition, fmt.Sprintf("could not merge commits: %v", err)) } conflicts, err := index.ConflictIterator() @@ -117,6 +135,9 @@ func (cmd *conflictsSubcommand) Run() error { content, err := conflictContent(repo, conflict) if err != nil { + if status, ok := status.FromError(err); ok { + return conflictError(status.Code(), status.Message()) + } return err } |