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

Function ParseDiffText

internal/diff/parser.go:30–108  ·  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 case !inHunk && binaryRe.MatchString(line):
69 current.IsBinary = true
70 // Extended header lines (unambiguous: content lines always carry a
71 // leading "+", "-" or " " prefix, so a bare prefix match is safe).
72 case strings.HasPrefix(line, "new file mode "):
73 current.IsNew = true
74 case strings.HasPrefix(line, "deleted file mode "):
75 current.IsDeleted = true
76 case strings.HasPrefix(line, "rename from "):
77 // Authoritative old path for renames; more reliable than the
78 // "diff --git" header when paths contain spaces.
79 current.OldPath = strings.TrimPrefix(line, "rename from ")
80 current.IsRenamed = true
81 case strings.HasPrefix(line, "rename to "):
82 current.NewPath = strings.TrimPrefix(line, "rename to ")
83 current.IsRenamed = true
84 // git emits "--- /dev/null" / "+++ /dev/null" without a/ b/ prefixes.
85 // Guarded by inHunk: inside a hunk the same strings can be content
86 // (e.g. an added line "++ /dev/null").
87 case !inHunk && line == "--- /dev/null":

Calls 2

finalizeDiffFunction · 0.85
StringMethod · 0.80