From 49fe20da31efed5409b61bc1a982ade70257d924 Mon Sep 17 00:00:00 2001 From: Justin Tobler Date: Tue, 23 Jan 2024 17:25:39 -0600 Subject: diff: Introduce `DiffBlob` RPC --- internal/gitaly/service/diff/diff_blob.go | 68 +++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 internal/gitaly/service/diff/diff_blob.go diff --git a/internal/gitaly/service/diff/diff_blob.go b/internal/gitaly/service/diff/diff_blob.go new file mode 100644 index 000000000..6a13f1b70 --- /dev/null +++ b/internal/gitaly/service/diff/diff_blob.go @@ -0,0 +1,68 @@ +package diff + +import ( + "fmt" + + "gitlab.com/gitlab-org/gitaly/v16/internal/git" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/diff" + "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" + "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" +) + +func (s *server) DiffBlob(in *gitalypb.DiffBlobRequest, stream gitalypb.DiffService_DiffBlobServer) error { + ctx := stream.Context() + + repo := s.localrepo(in.GetRepository()) + + objectHash, err := repo.ObjectHash(ctx) + if err != nil { + return fmt.Errorf("detecting object format: %w", err) + } + + gitCmd := git.Command{ + Name: "diff", + Flags: []git.Option{ + // The diff parser requires raw output even if only a single diff is generated. + git.Flag{Name: "--raw"}, + git.Flag{Name: "--patch"}, + git.Flag{Name: fmt.Sprintf("--abbrev=%d", objectHash.EncodedLen())}, + git.Flag{Name: "--full-index"}, + git.Flag{Name: "--no-prefix"}, + }, + Args: []string{in.LeftCommitId, in.RightCommitId}, + } + + cmd, err := repo.Exec(ctx, gitCmd, git.WithSetupStdout()) + if err != nil { + return structerr.NewInternal("cmd: %w", err) + } + + diffParser := diff.NewDiffParser(objectHash, cmd, diff.Limits{}) + + if !diffParser.Parse() { + return structerr.NewInternal("something went wrong") + } + + blobDiff := diffParser.Diff() + + if diffParser.Err() != nil { + return err + } + + for len(blobDiff.Patch) > 0 { + resp := &gitalypb.DiffBlobResponse{ + Patch: blobDiff.Patch, + } + + if len(resp.Patch) > s.MsgSizeThreshold { + resp.Patch = blobDiff.Patch[:s.MsgSizeThreshold] + blobDiff.Patch = blobDiff.Patch[s.MsgSizeThreshold:] + } + + if err := stream.Send(resp); err != nil { + return structerr.NewAborted("send: %w", err) + } + } + + return nil +} -- cgit v1.2.3