- commit
- 78d8ea1
- parent
- 09798a4
- author
- Eric Bower
- date
- 2025-02-02 12:14:20 -0500 EST
fix(range-diff): properly handle removed files from a patchset
5 files changed,
+107,
-25
+49,
-1
1@@ -159,9 +159,16 @@ type RangeDiffFile struct {
2
3 func outputDiff(patchA, patchB *PatchRange) []*RangeDiffFile {
4 diffs := []*RangeDiffFile{}
5+
6 for _, fileA := range patchA.Files {
7+ found := false
8 for _, fileB := range patchB.Files {
9 if fileA.NewName == fileB.NewName {
10+ found = true
11+ // this means both files have been deleted so we should skip
12+ if fileA.NewName == "" {
13+ continue
14+ }
15 strA := ""
16 for _, frag := range fileA.TextFragments {
17 for _, line := range frag.Lines {
18@@ -185,7 +192,6 @@ func outputDiff(patchA, patchB *PatchRange) []*RangeDiffFile {
19 if !hasDiff {
20 continue
21 }
22- // curDiff := DoDiff(fileA.String(), fileB.String())
23 fp := &RangeDiffFile{
24 OldFile: fileA,
25 NewFile: fileB,
26@@ -194,6 +200,48 @@ func outputDiff(patchA, patchB *PatchRange) []*RangeDiffFile {
27 diffs = append(diffs, fp)
28 }
29 }
30+
31+ // find files in patchA but not in patchB
32+ if !found {
33+ strA := ""
34+ for _, frag := range fileA.TextFragments {
35+ for _, line := range frag.Lines {
36+ strA += line.String()
37+ }
38+ }
39+ fp := &RangeDiffFile{
40+ OldFile: fileA,
41+ NewFile: nil,
42+ Diff: DoDiff(strA, ""),
43+ }
44+ diffs = append(diffs, fp)
45+ }
46+ }
47+
48+ // find files in patchB not in patchA
49+ for _, fileB := range patchB.Files {
50+ found := false
51+ for _, fileA := range patchA.Files {
52+ if fileA.NewName == fileB.NewName {
53+ found = true
54+ break
55+ }
56+ }
57+
58+ if !found {
59+ strB := ""
60+ for _, frag := range fileB.TextFragments {
61+ for _, line := range frag.Lines {
62+ strB += line.String()
63+ }
64+ }
65+ fp := &RangeDiffFile{
66+ OldFile: nil,
67+ NewFile: fileB,
68+ Diff: DoDiff("", strB),
69+ }
70+ diffs = append(diffs, fp)
71+ }
72 }
73
74 return diffs
+18,
-0
1@@ -24,7 +24,11 @@
2
3 {{range $patch.PatchFiles}}
4 <div class="flex justify-between items-center">
5+ {{if .NewName}}
6 <a class="flex-1 word-break-word mono" href="#patch-{{$patch.ID}}-{{.NewName}}">{{.NewName}}</a>
7+ {{else}}
8+ <a class="flex-1 word-break-word mono" href="#patch-{{$patch.ID}}-{{.OldName}}">{{.OldName}}</a>
9+ {{end}}
10 <div class="flex gap">
11 <code class="pill-success">+{{.Adds}}</code>
12 <code class="pill-admin">-{{.Dels}}</code>
13@@ -49,6 +53,7 @@
14 {{if $patch.Body}}<pre class="w-full">{{$patch.Body}}</pre>{{end}}
15
16 {{range $patch.PatchFiles}}
17+ {{if .NewName}}
18 <details class="details-min" open="true" id="patch-{{$patch.ID}}-{{.NewName}}">
19 <summary class="group-h patch-file">
20 <span class="mono">{{.NewName}}</span>
21@@ -60,6 +65,19 @@
22 </summary>
23 <div>{{.DiffText}}</div>
24 </details>
25+ {{else}}
26+ <details class="details-min" open="true" id="patch-{{$patch.ID}}-{{.OldName}}">
27+ <summary class="group-h patch-file">
28+ <span class="mono">{{.OldName}}</span>
29+ <a href="#patch-{{$patch.ID}}-{{.OldName}}" class="word-break-word">link</a>
30+ <div class="flex gap">
31+ <code class="pill-success">+{{.Adds}}</code>
32+ <code class="pill-admin">-{{.Dels}}</code>
33+ </div>
34+ </summary>
35+ <div>{{.DiffText}}</div>
36+ </details>
37+ {{end}}
38 {{end}}
39 </div>
40 <hr class="my" />
+2,
-0
1@@ -6,6 +6,7 @@
2 <th class="text-left">Status</th>
3 <th class="text-left">User</th>
4 <th class="text-left">Title</th>
5+ <th class="text-left">Patchsets</th>
6 <th class="text-left">Created At</th>
7 </tr>
8 </thead>
9@@ -22,6 +23,7 @@
10 <code>#{{.ID}}</code>
11 <a href="{{.PrLink.Url}}">{{.PrLink.Text}}</a>
12 </td>
13+ <td><code>{{.NumPatchsets}}</code></td>
14 <td><date>{{.Date}}</date></td>
15 </tr>
16 {{else}}
+19,
-13
1@@ -47,7 +47,7 @@
2 <div class="group">
3 {{range .PatchsetData.RangeDiff}}
4 <div id="{{.Header.OldIdx}}-{{.Header.NewIdx}}">
5- <div>
6+ <div class="mb">
7 <code class='{{if eq .Type "rm"}}pill-admin{{else if eq .Type "add"}}pill-success{{else if eq .Type "diff"}}pill-review{{end}}'>
8 {{.Header}}
9 </code>
10@@ -58,15 +58,18 @@
11 {{range .Files}}
12 <div class="flex gap">
13 <div class="flex-1" style="width: 48%;">
14- <div>{{.OldFile.NewName}}</div>
15- <pre>{{- range .Diff -}}
16- {{- if eq .InnerType "insert" -}}
17+ <div>
18+ {{if .OldFile.OldName}}<code>{{.OldFile.OldName}}</code>{{end}}
19+ {{if .OldFile.NewName}}<code>{{.OldFile.NewName}}</code>{{end}}
20+ </div>
21+ <pre class="m-0">{{- range .Diff -}}
22+ {{- if eq .OuterType "delete" -}}
23+ <span style="background-color: tomato;">{{.Text}}</span>
24+ {{- else if eq .OuterType "insert" -}}
25+ {{- else if eq .InnerType "insert" -}}
26 <span style="color: limegreen;">{{.Text}}</span>
27 {{- else if eq .InnerType "delete" -}}
28 <span style="color: tomato;">{{.Text}}</span>
29- {{- else if eq .OuterType "delete" -}}
30- <span style="background-color: tomato;">{{.Text}}</span>
31- {{- else if eq .OuterType "insert" -}}
32 {{- else -}}
33 <span>{{.Text}}</span>
34 {{- end -}}
35@@ -74,15 +77,18 @@
36 </div>
37
38 <div class="flex-1" style="width: 48%;">
39- <div>{{.NewFile.NewName}}</div>
40- <pre>{{- range .Diff -}}
41- {{- if eq .InnerType "insert" -}}
42+ <div>
43+ {{if .NewFile.OldName}}<code>{{.NewFile.OldName}}</code>{{end}}
44+ {{if .NewFile.NewName}}<code>{{.NewFile.NewName}}</code>{{end}}
45+ </div>
46+ <pre class="m-0">{{- range .Diff -}}
47+ {{- if eq .OuterType "insert" -}}
48+ <span style="background-color: limegreen;">{{.Text}}</span>
49+ {{- else if eq .OuterType "delete" -}}
50+ {{- else if eq .InnerType "insert" -}}
51 <span style="color: limegreen;">{{.Text}}</span>
52 {{- else if eq .InnerType "delete" -}}
53 <span style="color: tomato;">{{.Text}}</span>
54- {{- else if eq .OuterType "insert" -}}
55- <span style="background-color: limegreen;">{{.Text}}</span>
56- {{- else if eq .OuterType "delete" -}}
57 {{- else -}}
58 <span>{{.Text}}</span>
59 {{- end -}}
M
web.go
+19,
-11
1@@ -203,6 +203,12 @@ func getPrTableData(web *WebCtx, prs []*PatchRequest, query url.Values) ([]*PrLi
2 continue
3 }
4
5+ ps, err := web.Pr.GetPatchsetsByPrID(curpr.ID)
6+ if err != nil {
7+ web.Logger.Error("cannot get patchsets for pr", "err", err)
8+ continue
9+ }
10+
11 if hasFilter {
12 if status != "" {
13 if status != curpr.Status {
14@@ -241,9 +247,10 @@ func getPrTableData(web *WebCtx, prs []*PatchRequest, query url.Values) ([]*PrLi
15 Url: template.URL(fmt.Sprintf("/prs/%d", curpr.ID)),
16 Text: curpr.Name,
17 },
18- DateOrig: curpr.CreatedAt,
19- Date: curpr.CreatedAt.Format(web.Backend.Cfg.TimeFormat),
20- Status: curpr.Status,
21+ NumPatchsets: len(ps),
22+ DateOrig: curpr.CreatedAt,
23+ Date: curpr.CreatedAt.Format(web.Backend.Cfg.TimeFormat),
24+ Status: curpr.Status,
25 }
26 prdata = append(prdata, prls)
27 }
28@@ -306,14 +313,15 @@ type MetaData struct {
29
30 type PrListData struct {
31 UserData
32- RepoNs string
33- RepoLink LinkData
34- PrLink LinkData
35- Title string
36- ID int64
37- DateOrig time.Time
38- Date string
39- Status string
40+ RepoNs string
41+ RepoLink LinkData
42+ PrLink LinkData
43+ Title string
44+ NumPatchsets int
45+ ID int64
46+ DateOrig time.Time
47+ Date string
48+ Status string
49 }
50
51 func userDetailHandler(w http.ResponseWriter, r *http.Request) {