From 4c477c06a45198ba03f0f628b5f436b9e32d0aa6 Mon Sep 17 00:00:00 2001 From: oppiliappan Date: Fri, 18 Jul 2025 21:32:56 +0100 Subject: [PATCH] appview/pages: initial support for split diffs Change-Id: oltoyqxypnwrqvkqsqpkspuzrxqlyqok Signed-off-by: oppiliappan --- appview/pages/pages.go | 3 + appview/pages/templates/repo/commit.html | 2 +- .../pages/templates/repo/compare/compare.html | 2 +- .../pages/templates/repo/fragments/diff.html | 157 +++++++++++++----- .../repo/fragments/diffChangedFiles.html | 2 +- .../repo/fragments/interdiffFiles.html | 2 +- appview/pages/templates/repo/pulls/patch.html | 2 +- appview/pages/templates/repo/pulls/pull.html | 1 - appview/pulls/pulls.go | 6 + appview/repo/repo.go | 13 +- types/diff.go | 26 +++ 11 files changed, 170 insertions(+), 46 deletions(-) diff --git a/appview/pages/pages.go b/appview/pages/pages.go index 255a669..51e339f 100644 --- a/appview/pages/pages.go +++ b/appview/pages/pages.go @@ -527,6 +527,7 @@ type RepoCommitParams struct { Active string EmailToDidOrHandle map[string]string Pipeline *db.Pipeline + DiffOpts types.DiffOpts // singular because it's always going to be just one VerifiedCommit commitverify.VerifiedCommits @@ -859,6 +860,7 @@ type RepoPullPatchParams struct { Round int Submission *db.PullSubmission OrderedReactionKinds []db.ReactionKind + DiffOpts types.DiffOpts } // this name is a mouthful @@ -964,6 +966,7 @@ type RepoCompareParams struct { Base string Head string Diff *types.NiceDiff + DiffOpts types.DiffOpts Active string } diff --git a/appview/pages/templates/repo/commit.html b/appview/pages/templates/repo/commit.html index 266b1bb..e71bd1d 100644 --- a/appview/pages/templates/repo/commit.html +++ b/appview/pages/templates/repo/commit.html @@ -119,7 +119,7 @@ {{ end }} {{ define "contentAfter" }} - {{ template "repo/fragments/diff" (list .RepoInfo.FullName .Diff) }} + {{ template "repo/fragments/diff" (list .RepoInfo.FullName .Diff .DiffOpts) }} {{end}} {{ define "contentAfterLeft" }} diff --git a/appview/pages/templates/repo/compare/compare.html b/appview/pages/templates/repo/compare/compare.html index 389912f..08c2319 100644 --- a/appview/pages/templates/repo/compare/compare.html +++ b/appview/pages/templates/repo/compare/compare.html @@ -50,7 +50,7 @@ {{ end }} {{ define "contentAfter" }} - {{ template "repo/fragments/diff" (list .RepoInfo.FullName .Diff) }} + {{ template "repo/fragments/diff" (list .RepoInfo.FullName .Diff .DiffOpts) }} {{end}} {{ define "contentAfterLeft" }} diff --git a/appview/pages/templates/repo/fragments/diff.html b/appview/pages/templates/repo/fragments/diff.html index 6519346..2e79bb9 100644 --- a/appview/pages/templates/repo/fragments/diff.html +++ b/appview/pages/templates/repo/fragments/diff.html @@ -1,8 +1,11 @@ {{ define "repo/fragments/diff" }} {{ $repo := index . 0 }} {{ $diff := index . 1 }} +{{ $opts := index . 2 }} + {{ $commit := $diff.Commit }} {{ $diff := $diff.Diff }} +{{ $isSplit := $opts.Split }} {{ $this := $commit.This }} {{ $parent := $commit.Parent }} @@ -85,45 +88,11 @@ This is a binary file and will not be displayed.

{{ else }} - {{ $name := .Name.New }} -
{{- range .TextFragments -}}
···
- {{- $oldStart := .OldPosition -}} - {{- $newStart := .NewPosition -}} - {{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800 scroll-mt-10 target:border target:border-amber-500 target:rounded " -}} - {{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}} - {{- $lineNrSepStyle1 := "" -}} - {{- $lineNrSepStyle2 := "pr-2" -}} - {{- range .Lines -}} - {{- if eq .Op.String "+" -}} -
-
- -
{{ .Op.String }}
-
{{ .Line }}
-
- {{- $newStart = add64 $newStart 1 -}} - {{- end -}} - {{- if eq .Op.String "-" -}} -
- -
-
{{ .Op.String }}
-
{{ .Line }}
-
- {{- $oldStart = add64 $oldStart 1 -}} - {{- end -}} - {{- if eq .Op.String " " -}} -
- - -
{{ .Op.String }}
-
{{ .Line }}
-
- {{- $newStart = add64 $newStart 1 -}} - {{- $oldStart = add64 $oldStart 1 -}} - {{- end -}} - {{- end -}} - {{- end -}}
+ {{ if $isSplit }} + {{- template "repo/fragments/splitDiff" .Split -}} + {{ else }} + {{- template "repo/fragments/unifiedDiff" . -}} + {{ end }} {{- end -}} @@ -136,6 +105,115 @@ {{ end }} {{ end }} +{{ define "unifiedDiffLines" }} +{{ $name := .Name.New }} +
{{- range .TextFragments -}}
···
+ {{- $oldStart := .OldPosition -}} + {{- $newStart := .NewPosition -}} + {{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800 target:bg-yellow-200 target:dark:bg-yellow-600" -}} + {{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}} + {{- $lineNrSepStyle1 := "" -}} + {{- $lineNrSepStyle2 := "pr-2 border-r border-gray-200 dark:border-gray-700" -}} + {{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}} + {{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400 " -}} + {{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}} + {{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}} + {{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}} + {{- range .Lines -}} + {{- if eq .Op.String "+" -}} +
+
+ +
{{ .Op.String }}
+
{{ .Line }}
+
+ {{- $newStart = add64 $newStart 1 -}} + {{- end -}} + {{- if eq .Op.String "-" -}} +
+ +
+
{{ .Op.String }}
+
{{ .Line }}
+
+ {{- $oldStart = add64 $oldStart 1 -}} + {{- end -}} + {{- if eq .Op.String " " -}} +
+ + +
{{ .Op.String }}
+
{{ .Line }}
+
+ {{- $newStart = add64 $newStart 1 -}} + {{- $oldStart = add64 $oldStart 1 -}} + {{- end -}} + {{- end -}} + {{- end -}}
+{{ end }} + +{{ define "splitDiffLines" }} +{{ $name := .Name.New }} +{{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800" -}} +{{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}} +{{- $lineNrSepStyle := "pr-2 border-r border-gray-200 dark:border-gray-700" -}} +{{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}} +{{- $emptyStyle := "bg-gray-200/30 dark:bg-gray-700/30" -}} +{{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400" -}} +{{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}} +{{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}} +{{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}} +
+
{{- range .TextFragments -}}
···
+ {{- range .LeftLines -}} + {{- if .IsEmpty -}} +
+
+
+ +
+ {{- else if eq .Op.String "-" -}} +
+ +
{{ .Op.String }}
+
{{ .Content }}
+
+ {{- else if eq .Op.String " " -}} +
+ +
{{ .Op.String }}
+
{{ .Content }}
+
+ {{- end -}} + {{- end -}} + {{- end -}}
+ +
{{- range .TextFragments -}}
···
+ {{- range .RightLines -}} + {{- if .IsEmpty -}} +
+
+
+ +
+ {{- else if eq .Op.String "+" -}} +
+ +
{{ .Op.String }}
+
{{ .Content }}
+
+ {{- else if eq .Op.String " " -}} +
+ +
{{ .Op.String }}
+
{{ .Content }}
+
+ {{- end -}} + {{- end -}} + {{- end -}}
+
+{{ end }} + {{ define "statPill" }}
{{ if and .Insertions .Deletions }} @@ -148,3 +226,4 @@ {{ end }}
{{ end }} + diff --git a/appview/pages/templates/repo/fragments/diffChangedFiles.html b/appview/pages/templates/repo/fragments/diffChangedFiles.html index d8024a1..081bb62 100644 --- a/appview/pages/templates/repo/fragments/diffChangedFiles.html +++ b/appview/pages/templates/repo/fragments/diffChangedFiles.html @@ -2,7 +2,7 @@ {{ $stat := .Stat }} {{ $fileTree := fileTree .ChangedFiles }}
-
+
Changed files diff --git a/appview/pages/templates/repo/fragments/interdiffFiles.html b/appview/pages/templates/repo/fragments/interdiffFiles.html index 4cb26f1..0825d23 100644 --- a/appview/pages/templates/repo/fragments/interdiffFiles.html +++ b/appview/pages/templates/repo/fragments/interdiffFiles.html @@ -1,6 +1,6 @@ {{ define "repo/fragments/interdiffFiles" }} {{ $fileTree := fileTree .AffectedFiles }} -
+
files diff --git a/appview/pages/templates/repo/pulls/patch.html b/appview/pages/templates/repo/pulls/patch.html index 886fab6..ce28da4 100644 --- a/appview/pages/templates/repo/pulls/patch.html +++ b/appview/pages/templates/repo/pulls/patch.html @@ -74,7 +74,7 @@ {{ end }} {{ define "contentAfter" }} - {{ template "repo/fragments/diff" (list .RepoInfo.FullName .Diff) }} + {{ template "repo/fragments/diff" (list .RepoInfo.FullName .Diff .DiffOpts) }} {{end}} {{ define "contentAfterLeft" }} diff --git a/appview/pages/templates/repo/pulls/pull.html b/appview/pages/templates/repo/pulls/pull.html index 51906ce..bf6a09b 100644 --- a/appview/pages/templates/repo/pulls/pull.html +++ b/appview/pages/templates/repo/pulls/pull.html @@ -179,7 +179,6 @@ {{ end }}
-
{{ end }} {{ end }} {{ end }} diff --git a/appview/pulls/pulls.go b/appview/pulls/pulls.go index 5b30412..11f926d 100644 --- a/appview/pulls/pulls.go +++ b/appview/pulls/pulls.go @@ -355,6 +355,11 @@ func (s *Pulls) RepoPullPatch(w http.ResponseWriter, r *http.Request) { return } + var diffOpts types.DiffOpts + if d := r.URL.Query().Get("diff"); d == "split" { + diffOpts.Split = true + } + pull, ok := r.Context().Value("pull").(*db.Pull) if !ok { log.Println("failed to get pull") @@ -395,6 +400,7 @@ func (s *Pulls) RepoPullPatch(w http.ResponseWriter, r *http.Request) { Round: roundIdInt, Submission: pull.Submissions[roundIdInt], Diff: &diff, + DiffOpts: diffOpts, }) } diff --git a/appview/repo/repo.go b/appview/repo/repo.go index c2587b5..86067e5 100644 --- a/appview/repo/repo.go +++ b/appview/repo/repo.go @@ -268,6 +268,11 @@ func (rp *Repo) RepoCommit(w http.ResponseWriter, r *http.Request) { protocol = "https" } + var diffOpts types.DiffOpts + if d := r.URL.Query().Get("diff"); d == "split" { + diffOpts.Split = true + } + if !plumbing.IsHash(ref) { rp.pages.Error404(w) return @@ -321,8 +326,8 @@ func (rp *Repo) RepoCommit(w http.ResponseWriter, r *http.Request) { EmailToDidOrHandle: emailToDidOrHandle(rp, emailToDidMap), VerifiedCommit: vc, Pipeline: pipeline, + DiffOpts: diffOpts, }) - return } func (rp *Repo) RepoTree(w http.ResponseWriter, r *http.Request) { @@ -1269,6 +1274,11 @@ func (rp *Repo) RepoCompare(w http.ResponseWriter, r *http.Request) { return } + var diffOpts types.DiffOpts + if d := r.URL.Query().Get("diff"); d == "split" { + diffOpts.Split = true + } + // if user is navigating to one of // /compare/{base}/{head} // /compare/{base}...{head} @@ -1331,6 +1341,7 @@ func (rp *Repo) RepoCompare(w http.ResponseWriter, r *http.Request) { Base: base, Head: head, Diff: &diff, + DiffOpts: diffOpts, }) } diff --git a/types/diff.go b/types/diff.go index 5978dc6..12ecd9e 100644 --- a/types/diff.go +++ b/types/diff.go @@ -5,6 +5,10 @@ import ( "github.com/go-git/go-git/v5/plumbing/object" ) +type DiffOpts struct { + Split bool `json:"split"` +} + type TextFragment struct { Header string `json:"comment"` Lines []gitdiff.Line `json:"lines"` @@ -77,3 +81,25 @@ func (d *NiceDiff) ChangedFiles() []string { return files } + +// used by html elements as a unique ID for hrefs +func (d *Diff) Id() string { + return d.Name.New +} + +func (d *Diff) Split() *SplitDiff { + fragments := make([]SplitFragment, len(d.TextFragments)) + for i, fragment := range d.TextFragments { + leftLines, rightLines := SeparateLines(&fragment) + fragments[i] = SplitFragment{ + Header: fragment.Header(), + LeftLines: leftLines, + RightLines: rightLines, + } + } + + return &SplitDiff{ + Name: d.Id(), + TextFragments: fragments, + } +} -- 2.43.0