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

Function ParseDiffText

internal/diff/parser.go:30–113  ·  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

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

Calls 2

finalizeDiffFunction · 0.85
StringMethod · 0.45