forked from tangled.org/core
this repo has no description

appview/pages: support split diffs for interdiff

Signed-off-by: oppiliappan <me@oppi.li>

authored by oppi.li and committed by Tangled 23a0ae17 8ff57897

Changed files
+289 -136
appview
patchutil
types
+1
appview/pages/pages.go
··· 876 876 Round int 877 877 Interdiff *patchutil.InterdiffResult 878 878 OrderedReactionKinds []db.ReactionKind 879 + DiffOpts types.DiffOpts 879 880 } 880 881 881 882 // this name is a mouthful
-123
appview/pages/templates/repo/fragments/diff.html
··· 104 104 {{ end }} 105 105 {{ end }} 106 106 {{ end }} 107 - 108 - {{ define "unifiedDiffLines" }} 109 - {{ $name := .Name.New }} 110 - <pre class="overflow-x-auto"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}<div class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">&middot;&middot;&middot;</div> 111 - {{- $oldStart := .OldPosition -}} 112 - {{- $newStart := .NewPosition -}} 113 - {{- $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" -}} 114 - {{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}} 115 - {{- $lineNrSepStyle1 := "" -}} 116 - {{- $lineNrSepStyle2 := "pr-2 border-r border-gray-200 dark:border-gray-700" -}} 117 - {{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}} 118 - {{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400 " -}} 119 - {{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}} 120 - {{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}} 121 - {{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}} 122 - {{- range .Lines -}} 123 - {{- if eq .Op.String "+" -}} 124 - <div class="{{ $addStyle }} {{ $containerStyle }}" id="{{$name}}-N{{$newStart}}"> 125 - <div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><span aria-hidden="true" class="invisible">{{$newStart}}</span></div> 126 - <div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{$newStart}}">{{ $newStart }}</a></div> 127 - <div class="{{ $opStyle }}">{{ .Op.String }}</div> 128 - <div class="px-2">{{ .Line }}</div> 129 - </div> 130 - {{- $newStart = add64 $newStart 1 -}} 131 - {{- end -}} 132 - {{- if eq .Op.String "-" -}} 133 - <div class="{{ $delStyle }} {{ $containerStyle }}" id="{{$name}}-O{{$oldStart}}"> 134 - <div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}">{{ $oldStart }}</a></div> 135 - <div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><span aria-hidden="true" class="invisible">{{$oldStart}}</span></div> 136 - <div class="{{ $opStyle }}">{{ .Op.String }}</div> 137 - <div class="px-2">{{ .Line }}</div> 138 - </div> 139 - {{- $oldStart = add64 $oldStart 1 -}} 140 - {{- end -}} 141 - {{- if eq .Op.String " " -}} 142 - <div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-O{{$oldStart}}-N{{$newStart}}"> 143 - <div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}-N{{$newStart}}">{{ $oldStart }}</a></div> 144 - <div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}-N{{$newStart}}">{{ $newStart }}</a></div> 145 - <div class="{{ $opStyle }}">{{ .Op.String }}</div> 146 - <div class="px-2">{{ .Line }}</div> 147 - </div> 148 - {{- $newStart = add64 $newStart 1 -}} 149 - {{- $oldStart = add64 $oldStart 1 -}} 150 - {{- end -}} 151 - {{- end -}} 152 - {{- end -}}</div></div></pre> 153 - {{ end }} 154 - 155 - {{ define "splitDiffLines" }} 156 - {{ $name := .Name.New }} 157 - {{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800" -}} 158 - {{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}} 159 - {{- $lineNrSepStyle := "pr-2 border-r border-gray-200 dark:border-gray-700" -}} 160 - {{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}} 161 - {{- $emptyStyle := "bg-gray-200/30 dark:bg-gray-700/30" -}} 162 - {{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400" -}} 163 - {{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}} 164 - {{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}} 165 - {{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}} 166 - <div class="grid grid-cols-2 divide-x divide-gray-200 dark:divide-gray-700"> 167 - <pre class="overflow-x-auto col-span-1"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}<div class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">&middot;&middot;&middot;</div> 168 - {{- range .LeftLines -}} 169 - {{- if .IsEmpty -}} 170 - <div class="{{ $emptyStyle }} {{ $containerStyle }}"> 171 - <div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><span aria-hidden="true" class="invisible">{{.LineNumber}}</span></div> 172 - <div class="{{ $opStyle }}"><span aria-hidden="true" class="invisible">{{ .Op.String }}</span></div> 173 - <div class="px-2 invisible" aria-hidden="true">{{ .Content }}</div> 174 - </div> 175 - {{- else if eq .Op.String "-" -}} 176 - <div class="{{ $delStyle }} {{ $containerStyle }}" id="{{$name}}-O{{.LineNumber}}"> 177 - <div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{.LineNumber}}">{{ .LineNumber }}</a></div> 178 - <div class="{{ $opStyle }}">{{ .Op.String }}</div> 179 - <div class="px-2">{{ .Content }}</div> 180 - </div> 181 - {{- else if eq .Op.String " " -}} 182 - <div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-O{{.LineNumber}}"> 183 - <div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{.LineNumber}}">{{ .LineNumber }}</a></div> 184 - <div class="{{ $opStyle }}">{{ .Op.String }}</div> 185 - <div class="px-2">{{ .Content }}</div> 186 - </div> 187 - {{- end -}} 188 - {{- end -}} 189 - {{- end -}}</div></div></pre> 190 - 191 - <pre class="overflow-x-auto col-span-1"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}<div class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">&middot;&middot;&middot;</div> 192 - {{- range .RightLines -}} 193 - {{- if .IsEmpty -}} 194 - <div class="{{ $emptyStyle }} {{ $containerStyle }}"> 195 - <div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><span aria-hidden="true" class="invisible">{{.LineNumber}}</span></div> 196 - <div class="{{ $opStyle }}"><span aria-hidden="true" class="invisible">{{ .Op.String }}</span></div> 197 - <div class="px-2 invisible" aria-hidden="true">{{ .Content }}</div> 198 - </div> 199 - {{- else if eq .Op.String "+" -}} 200 - <div class="{{ $addStyle }} {{ $containerStyle }}" id="{{$name}}-N{{.LineNumber}}"> 201 - <div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{.LineNumber}}">{{ .LineNumber }}</a></div> 202 - <div class="{{ $opStyle }}">{{ .Op.String }}</div> 203 - <div class="px-2" >{{ .Content }}</div> 204 - </div> 205 - {{- else if eq .Op.String " " -}} 206 - <div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-N{{.LineNumber}}"> 207 - <div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{.LineNumber}}">{{ .LineNumber }}</a></div> 208 - <div class="{{ $opStyle }}">{{ .Op.String }}</div> 209 - <div class="px-2">{{ .Content }}</div> 210 - </div> 211 - {{- end -}} 212 - {{- end -}} 213 - {{- end -}}</div></div></pre> 214 - </div> 215 - {{ end }} 216 - 217 - {{ define "statPill" }} 218 - <div class="flex items-center font-mono text-sm"> 219 - {{ if and .Insertions .Deletions }} 220 - <span class="rounded-l p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">+{{ .Insertions }}</span> 221 - <span class="rounded-r p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">-{{ .Deletions }}</span> 222 - {{ else if .Insertions }} 223 - <span class="rounded p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">+{{ .Insertions }}</span> 224 - {{ else if .Deletions }} 225 - <span class="rounded p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">-{{ .Deletions }}</span> 226 - {{ end }} 227 - </div> 228 - {{ end }} 229 -
+13
appview/pages/templates/repo/fragments/diffStatPill.html
··· 1 + {{ define "repo/fragments/diffStatPill" }} 2 + <div class="flex items-center font-mono text-sm"> 3 + {{ if and .Insertions .Deletions }} 4 + <span class="rounded-l p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">+{{ .Insertions }}</span> 5 + <span class="rounded-r p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">-{{ .Deletions }}</span> 6 + {{ else if .Insertions }} 7 + <span class="rounded p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">+{{ .Insertions }}</span> 8 + {{ else if .Deletions }} 9 + <span class="rounded p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">-{{ .Deletions }}</span> 10 + {{ end }} 11 + </div> 12 + {{ end }} 13 +
+1 -12
appview/pages/templates/repo/fragments/interdiff.html
··· 1 1 {{ define "repo/fragments/interdiff" }} 2 2 {{ $repo := index . 0 }} 3 3 {{ $x := index . 1 }} 4 + {{ $opts := index . 2 }} 4 5 {{ $fileTree := fileTree $x.AffectedFiles }} 5 6 {{ $diff := $x.Files }} 6 7 {{ $last := sub (len $diff) 1 }} ··· 87 88 {{ end }} 88 89 {{ end }} 89 90 90 - {{ define "statPill" }} 91 - <div class="flex items-center font-mono text-sm"> 92 - {{ if and .Insertions .Deletions }} 93 - <span class="rounded-l p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">+{{ .Insertions }}</span> 94 - <span class="rounded-r p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">-{{ .Deletions }}</span> 95 - {{ else if .Insertions }} 96 - <span class="rounded p-1 select-none bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400">+{{ .Insertions }}</span> 97 - {{ else if .Deletions }} 98 - <span class="rounded p-1 select-none bg-red-100 text-red-700 dark:bg-red-800/50 dark:text-red-400">-{{ .Deletions }}</span> 99 - {{ end }} 100 - </div> 101 - {{ end }}
+61
appview/pages/templates/repo/fragments/splitDiff.html
··· 1 + {{ define "repo/fragments/splitDiff" }} 2 + {{ $name := .Id }} 3 + {{- $lineNrStyle := "min-w-[3.5rem] flex-shrink-0 select-none text-right bg-white dark:bg-gray-800" -}} 4 + {{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}} 5 + {{- $lineNrSepStyle := "pr-2 border-r border-gray-200 dark:border-gray-700" -}} 6 + {{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}} 7 + {{- $emptyStyle := "bg-gray-200/30 dark:bg-gray-700/30" -}} 8 + {{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400" -}} 9 + {{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}} 10 + {{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}} 11 + {{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}} 12 + <div class="grid grid-cols-2 divide-x divide-gray-200 dark:divide-gray-700"> 13 + <pre class="overflow-x-auto col-span-1"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}<div class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">&middot;&middot;&middot;</div> 14 + {{- range .LeftLines -}} 15 + {{- if .IsEmpty -}} 16 + <div class="{{ $emptyStyle }} {{ $containerStyle }}"> 17 + <div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><span aria-hidden="true" class="invisible">{{.LineNumber}}</span></div> 18 + <div class="{{ $opStyle }}"><span aria-hidden="true" class="invisible">{{ .Op.String }}</span></div> 19 + <div class="px-2 invisible" aria-hidden="true">{{ .Content }}</div> 20 + </div> 21 + {{- else if eq .Op.String "-" -}} 22 + <div class="{{ $delStyle }} {{ $containerStyle }}" id="{{$name}}-O{{.LineNumber}}"> 23 + <div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{.LineNumber}}">{{ .LineNumber }}</a></div> 24 + <div class="{{ $opStyle }}">{{ .Op.String }}</div> 25 + <div class="px-2">{{ .Content }}</div> 26 + </div> 27 + {{- else if eq .Op.String " " -}} 28 + <div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-O{{.LineNumber}}"> 29 + <div class="{{ $lineNrStyle }} {{ $lineNrSepStyle }}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{.LineNumber}}">{{ .LineNumber }}</a></div> 30 + <div class="{{ $opStyle }}">{{ .Op.String }}</div> 31 + <div class="px-2">{{ .Content }}</div> 32 + </div> 33 + {{- end -}} 34 + {{- end -}} 35 + {{- end -}}</div></div></pre> 36 + 37 + <pre class="overflow-x-auto col-span-1"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}<div class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">&middot;&middot;&middot;</div> 38 + {{- range .RightLines -}} 39 + {{- if .IsEmpty -}} 40 + <div class="{{ $emptyStyle }} {{ $containerStyle }}"> 41 + <div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><span aria-hidden="true" class="invisible">{{.LineNumber}}</span></div> 42 + <div class="{{ $opStyle }}"><span aria-hidden="true" class="invisible">{{ .Op.String }}</span></div> 43 + <div class="px-2 invisible" aria-hidden="true">{{ .Content }}</div> 44 + </div> 45 + {{- else if eq .Op.String "+" -}} 46 + <div class="{{ $addStyle }} {{ $containerStyle }}" id="{{$name}}-N{{.LineNumber}}"> 47 + <div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{.LineNumber}}">{{ .LineNumber }}</a></div> 48 + <div class="{{ $opStyle }}">{{ .Op.String }}</div> 49 + <div class="px-2" >{{ .Content }}</div> 50 + </div> 51 + {{- else if eq .Op.String " " -}} 52 + <div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-N{{.LineNumber}}"> 53 + <div class="{{$lineNrStyle}} {{$lineNrSepStyle}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{.LineNumber}}">{{ .LineNumber }}</a></div> 54 + <div class="{{ $opStyle }}">{{ .Op.String }}</div> 55 + <div class="px-2">{{ .Content }}</div> 56 + </div> 57 + {{- end -}} 58 + {{- end -}} 59 + {{- end -}}</div></div></pre> 60 + </div> 61 + {{ end }}
+47
appview/pages/templates/repo/fragments/unifiedDiff.html
··· 1 + {{ define "repo/fragments/unifiedDiff" }} 2 + {{ $name := .Id }} 3 + <pre class="overflow-x-auto"><div class="overflow-x-auto"><div class="min-w-full inline-block">{{- range .TextFragments -}}<div class="bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 select-none text-center">&middot;&middot;&middot;</div> 4 + {{- $oldStart := .OldPosition -}} 5 + {{- $newStart := .NewPosition -}} 6 + {{- $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" -}} 7 + {{- $linkStyle := "text-gray-400 dark:text-gray-500 hover:underline" -}} 8 + {{- $lineNrSepStyle1 := "" -}} 9 + {{- $lineNrSepStyle2 := "pr-2 border-r border-gray-200 dark:border-gray-700" -}} 10 + {{- $containerStyle := "flex min-w-full items-center target:border target:rounded-sm target:border-yellow-200 target:dark:border-yellow-700 scroll-mt-20" -}} 11 + {{- $addStyle := "bg-green-100 dark:bg-green-800/30 text-green-700 dark:text-green-400 " -}} 12 + {{- $delStyle := "bg-red-100 dark:bg-red-800/30 text-red-700 dark:text-red-400 " -}} 13 + {{- $ctxStyle := "bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400" -}} 14 + {{- $opStyle := "w-5 flex-shrink-0 select-none text-center" -}} 15 + {{- range .Lines -}} 16 + {{- if eq .Op.String "+" -}} 17 + <div class="{{ $addStyle }} {{ $containerStyle }}" id="{{$name}}-N{{$newStart}}"> 18 + <div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><span aria-hidden="true" class="invisible">{{$newStart}}</span></div> 19 + <div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><a class="{{$linkStyle}}" href="#{{$name}}-N{{$newStart}}">{{ $newStart }}</a></div> 20 + <div class="{{ $opStyle }}">{{ .Op.String }}</div> 21 + <div class="px-2">{{ .Line }}</div> 22 + </div> 23 + {{- $newStart = add64 $newStart 1 -}} 24 + {{- end -}} 25 + {{- if eq .Op.String "-" -}} 26 + <div class="{{ $delStyle }} {{ $containerStyle }}" id="{{$name}}-O{{$oldStart}}"> 27 + <div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}">{{ $oldStart }}</a></div> 28 + <div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><span aria-hidden="true" class="invisible">{{$oldStart}}</span></div> 29 + <div class="{{ $opStyle }}">{{ .Op.String }}</div> 30 + <div class="px-2">{{ .Line }}</div> 31 + </div> 32 + {{- $oldStart = add64 $oldStart 1 -}} 33 + {{- end -}} 34 + {{- if eq .Op.String " " -}} 35 + <div class="{{ $ctxStyle }} {{ $containerStyle }}" id="{{$name}}-O{{$oldStart}}-N{{$newStart}}"> 36 + <div class="{{$lineNrStyle}} {{$lineNrSepStyle1}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}-N{{$newStart}}">{{ $oldStart }}</a></div> 37 + <div class="{{$lineNrStyle}} {{$lineNrSepStyle2}}"><a class="{{$linkStyle}}" href="#{{$name}}-O{{$oldStart}}-N{{$newStart}}">{{ $newStart }}</a></div> 38 + <div class="{{ $opStyle }}">{{ .Op.String }}</div> 39 + <div class="px-2">{{ .Line }}</div> 40 + </div> 41 + {{- $newStart = add64 $newStart 1 -}} 42 + {{- $oldStart = add64 $oldStart 1 -}} 43 + {{- end -}} 44 + {{- end -}} 45 + {{- end -}}</div></div></pre> 46 + {{ end }} 47 +
+10 -1
appview/pulls/pulls.go
··· 414 414 return 415 415 } 416 416 417 + var diffOpts types.DiffOpts 418 + if d := r.URL.Query().Get("diff"); d == "split" { 419 + diffOpts.Split = true 420 + } 421 + 417 422 pull, ok := r.Context().Value("pull").(*db.Pull) 418 423 if !ok { 419 424 log.Println("failed to get pull") ··· 462 467 463 468 interdiff := patchutil.Interdiff(previousPatch, currentPatch) 464 469 470 + for _, f := range interdiff.Files { 471 + log.Println("", "", f.Split()) 472 + } 473 + 465 474 s.pages.RepoPullInterdiffPage(w, pages.RepoPullInterdiffParams{ 466 475 LoggedInUser: s.oauth.GetUser(r), 467 476 RepoInfo: f.RepoInfo(user), ··· 469 478 Round: roundIdInt, 470 479 DidHandleMap: didHandleMap, 471 480 Interdiff: interdiff, 481 + DiffOpts: diffOpts, 472 482 }) 473 - return 474 483 } 475 484 476 485 func (s *Pulls) RepoPullPatchRaw(w http.ResponseWriter, r *http.Request) {
+25
patchutil/interdiff.go
··· 5 5 "strings" 6 6 7 7 "github.com/bluekeyes/go-gitdiff/gitdiff" 8 + "tangled.sh/tangled.sh/core/types" 8 9 ) 9 10 10 11 type InterdiffResult struct { ··· 33 34 *gitdiff.File 34 35 Name string 35 36 Status InterdiffFileStatus 37 + } 38 + 39 + func (s *InterdiffFile) Split() *types.SplitDiff { 40 + fragments := make([]types.SplitFragment, len(s.TextFragments)) 41 + 42 + for i, fragment := range s.TextFragments { 43 + leftLines, rightLines := types.SeparateLines(fragment) 44 + 45 + fragments[i] = types.SplitFragment{ 46 + Header: fragment.Header(), 47 + LeftLines: leftLines, 48 + RightLines: rightLines, 49 + } 50 + } 51 + 52 + return &types.SplitDiff{ 53 + Name: s.Id(), 54 + TextFragments: fragments, 55 + } 56 + } 57 + 58 + // used by html elements as a unique ID for hrefs 59 + func (s *InterdiffFile) Id() string { 60 + return s.Name 36 61 } 37 62 38 63 func (s *InterdiffFile) String() string {
+131
types/split.go
··· 1 + package types 2 + 3 + import ( 4 + "github.com/bluekeyes/go-gitdiff/gitdiff" 5 + ) 6 + 7 + type SplitLine struct { 8 + LineNumber int `json:"line_number,omitempty"` 9 + Content string `json:"content"` 10 + Op gitdiff.LineOp `json:"op"` 11 + IsEmpty bool `json:"is_empty"` 12 + } 13 + 14 + type SplitFragment struct { 15 + Header string `json:"header"` 16 + LeftLines []SplitLine `json:"left_lines"` 17 + RightLines []SplitLine `json:"right_lines"` 18 + } 19 + 20 + type SplitDiff struct { 21 + Name string `json:"name"` 22 + TextFragments []SplitFragment `json:"fragments"` 23 + } 24 + 25 + // used by html elements as a unique ID for hrefs 26 + func (d *SplitDiff) Id() string { 27 + return d.Name 28 + } 29 + 30 + // separate lines into left and right, this includes additional logic to 31 + // group consecutive runs of additions and deletions in order to align them 32 + // properly in the final output 33 + // 34 + // TODO: move all diff stuff to a single package, we are spread across patchutil and types right now 35 + func SeparateLines(fragment *gitdiff.TextFragment) ([]SplitLine, []SplitLine) { 36 + lines := fragment.Lines 37 + var leftLines, rightLines []SplitLine 38 + oldLineNum := fragment.OldPosition 39 + newLineNum := fragment.OldPosition 40 + 41 + // process deletions and additions in groups for better alignment 42 + i := 0 43 + for i < len(lines) { 44 + line := lines[i] 45 + 46 + switch line.Op { 47 + case gitdiff.OpContext: 48 + leftLines = append(leftLines, SplitLine{ 49 + LineNumber: int(oldLineNum), 50 + Content: line.Line, 51 + Op: gitdiff.OpContext, 52 + IsEmpty: false, 53 + }) 54 + rightLines = append(rightLines, SplitLine{ 55 + LineNumber: int(newLineNum), 56 + Content: line.Line, 57 + Op: gitdiff.OpContext, 58 + IsEmpty: false, 59 + }) 60 + oldLineNum++ 61 + newLineNum++ 62 + i++ 63 + 64 + case gitdiff.OpDelete: 65 + deletionCount := 0 66 + for j := i; j < len(lines) && lines[j].Op == gitdiff.OpDelete; j++ { 67 + leftLines = append(leftLines, SplitLine{ 68 + LineNumber: int(oldLineNum), 69 + Content: lines[j].Line, 70 + Op: gitdiff.OpDelete, 71 + IsEmpty: false, 72 + }) 73 + oldLineNum++ 74 + deletionCount++ 75 + } 76 + i += deletionCount 77 + 78 + additionCount := 0 79 + for j := i; j < len(lines) && lines[j].Op == gitdiff.OpAdd; j++ { 80 + rightLines = append(rightLines, SplitLine{ 81 + LineNumber: int(newLineNum), 82 + Content: lines[j].Line, 83 + Op: gitdiff.OpAdd, 84 + IsEmpty: false, 85 + }) 86 + newLineNum++ 87 + additionCount++ 88 + } 89 + i += additionCount 90 + 91 + // add empty lines to balance the sides 92 + if deletionCount > additionCount { 93 + // more deletions than additions - pad right side 94 + for k := 0; k < deletionCount-additionCount; k++ { 95 + rightLines = append(rightLines, SplitLine{ 96 + Content: "", 97 + Op: gitdiff.OpContext, 98 + IsEmpty: true, 99 + }) 100 + } 101 + } else if additionCount > deletionCount { 102 + // more additions than deletions - pad left side 103 + for k := 0; k < additionCount-deletionCount; k++ { 104 + leftLines = append(leftLines, SplitLine{ 105 + Content: "", 106 + Op: gitdiff.OpContext, 107 + IsEmpty: true, 108 + }) 109 + } 110 + } 111 + 112 + case gitdiff.OpAdd: 113 + // standalone addition (not preceded by deletion) 114 + leftLines = append(leftLines, SplitLine{ 115 + Content: "", 116 + Op: gitdiff.OpContext, 117 + IsEmpty: true, 118 + }) 119 + rightLines = append(rightLines, SplitLine{ 120 + LineNumber: int(newLineNum), 121 + Content: line.Line, 122 + Op: gitdiff.OpAdd, 123 + IsEmpty: false, 124 + }) 125 + newLineNum++ 126 + i++ 127 + } 128 + } 129 + 130 + return leftLines, rightLines 131 + }