MCPcopy Create free account
hub / github.com/alibaba/open-code-review / ParseDiffText

Function ParseDiffText

internal/diff/parser.go:33–116  ·  view source on GitHub ↗

ParseDiffText splits the unified diff text into per-file Diff structs. ref, if non-empty, is a git ref used to read new-file content via git show instead of reading from the working tree. runner, if non-nil, is used to execute git subprocesses through a shared concurrency limiter.

(ctx context.Context, diffText string, repoDir string, ref string, runner *gitcmd.Runner)

Source from the content-addressed store, hash-verified

31// runner, if non-nil, is used to execute git subprocesses through a
32// shared concurrency limiter.
33func ParseDiffText(ctx context.Context, diffText string, repoDir string, ref string, runner *gitcmd.Runner) ([]model.Diff, error) {
34 lines := strings.Split(diffText, "\n")
35 var diffs []model.Diff
36 var current *model.Diff
37 var buf strings.Builder
38 // inHunk tracks whether the current line sits inside a "@@" hunk of the
39 // current file's section. Only hunk content lines carry a leading
40 // "+"/"-"/" " marker, so insertion/deletion counting and the binary
41 // marker must look at hunk state: outside a hunk, "+++ b/file" and
42 // "--- a/file" are headers, not content; inside a hunk, an added line
43 // like "++i" renders as "+++i" and still counts as an insertion.
44 inHunk := false
45
46 ctx, cancel := context.WithTimeout(ctx, 2*time.Minute)
47 defer cancel()
48
49 for _, line := range lines {
50 if m := diffHeaderRe.FindStringSubmatch(line); m != nil {
51 // Flush previous diff
52 if current != nil {
53 current.Diff = strings.TrimSuffix(buf.String(), "\n")
54 finalizeDiff(ctx, current, repoDir, ref, runner)
55 diffs = append(diffs, *current)
56 buf.Reset()
57 }
58 current = &model.Diff{
59 OldPath: m[1],
60 NewPath: m[2],
61 }
62 inHunk = false
63 }
64 if current == nil {
65 continue
66 }
67
68 switch {
69 case strings.HasPrefix(line, "@@"):
70 inHunk = true
71 // The object IDs and mode in Git's extended "index" header are not
72 // useful review context. Keep index text in hunks, where it is file
73 // content and therefore carries a diff prefix.
74 case !inHunk && strings.HasPrefix(line, "index "):
75 continue
76 case !inHunk && binaryRe.MatchString(line):
77 current.IsBinary = true
78 // Extended header lines (unambiguous: content lines always carry a
79 // leading "+", "-" or " " prefix, so a bare prefix match is safe).
80 case strings.HasPrefix(line, "new file mode "):
81 current.IsNew = true
82 case strings.HasPrefix(line, "deleted file mode "):
83 current.IsDeleted = true
84 case strings.HasPrefix(line, "rename from "):
85 // Authoritative old path for renames; more reliable than the
86 // "diff --git" header when paths contain spaces.
87 current.OldPath = strings.TrimPrefix(line, "rename from ")
88 current.IsRenamed = true
89 case strings.HasPrefix(line, "rename to "):
90 current.NewPath = strings.TrimPrefix(line, "rename to ")

Calls 2

finalizeDiffFunction · 0.85
StringMethod · 0.45