+44
appview/db/pulls.go
+44
appview/db/pulls.go
···
3
3
import (
4
4
"database/sql"
5
5
"fmt"
6
+
"log"
6
7
"strings"
7
8
"time"
8
9
10
+
"github.com/bluekeyes/go-gitdiff/gitdiff"
9
11
"github.com/bluesky-social/indigo/atproto/syntax"
12
+
"github.com/sotangled/tangled/types"
10
13
)
11
14
12
15
type PullState int
···
100
103
func (p *Pull) LatestPatch() string {
101
104
latestSubmission := p.Submissions[len(p.Submissions)-1]
102
105
return latestSubmission.Patch
106
+
}
107
+
108
+
func (s PullSubmission) AsNiceDiff(targetBranch string) types.NiceDiff {
109
+
patch := s.Patch
110
+
111
+
diffs, _, err := gitdiff.Parse(strings.NewReader(patch))
112
+
if err != nil {
113
+
log.Println(err)
114
+
}
115
+
116
+
nd := types.NiceDiff{}
117
+
nd.Commit.Parent = targetBranch
118
+
119
+
for _, d := range diffs {
120
+
ndiff := types.Diff{}
121
+
ndiff.Name.New = d.NewName
122
+
ndiff.Name.Old = d.OldName
123
+
ndiff.IsBinary = d.IsBinary
124
+
ndiff.IsNew = d.IsNew
125
+
ndiff.IsDelete = d.IsDelete
126
+
ndiff.IsCopy = d.IsCopy
127
+
ndiff.IsRename = d.IsRename
128
+
129
+
for _, tf := range d.TextFragments {
130
+
ndiff.TextFragments = append(ndiff.TextFragments, *tf)
131
+
for _, l := range tf.Lines {
132
+
switch l.Op {
133
+
case gitdiff.OpAdd:
134
+
nd.Stat.Insertions += 1
135
+
case gitdiff.OpDelete:
136
+
nd.Stat.Deletions += 1
137
+
}
138
+
}
139
+
}
140
+
141
+
nd.Diff = append(nd.Diff, ndiff)
142
+
}
143
+
144
+
nd.Stat.FilesChanged = len(diffs)
145
+
146
+
return nd
103
147
}
104
148
105
149
func NewPull(tx *sql.Tx, pull *Pull) error {
+112
appview/pages/templates/fragments/diff.html
+112
appview/pages/templates/fragments/diff.html
···
1
+
{{ define "fragments/diff" }}
2
+
{{ $repo := index . 0 }}
3
+
{{ $diff := index . 1 }}
4
+
{{ $commit := $diff.Commit }}
5
+
{{ $stat := $diff.Stat }}
6
+
{{ $diff := $diff.Diff }}
7
+
8
+
{{ $this := $commit.This }}
9
+
{{ $parent := $commit.Parent }}
10
+
11
+
{{ $last := sub (len $diff) 1 }}
12
+
{{ range $idx, $hunk := $diff }}
13
+
{{ with $hunk }}
14
+
<section class="mt-6 border border-gray-200 w-full mx-auto rounded bg-white drop-shadow-sm">
15
+
<div id="file-{{ .Name.New }}">
16
+
<div id="diff-file">
17
+
<details open>
18
+
<summary class="list-none cursor-pointer sticky top-0">
19
+
<div id="diff-file-header" class="rounded cursor-pointer bg-white flex justify-between">
20
+
<div id="left-side-items" class="p-2 flex gap-2 items-center">
21
+
{{ $markerstyle := "diff-type p-1 mr-1 font-mono text-sm rounded select-none" }}
22
+
23
+
{{ if .IsNew }}
24
+
<span class="bg-green-100 text-green-700 {{ $markerstyle }}">ADDED</span>
25
+
{{ else if .IsDelete }}
26
+
<span class="bg-red-100 text-red-700 {{ $markerstyle }}">DELETED</span>
27
+
{{ else if .IsCopy }}
28
+
<span class="bg-gray-100 text-gray-700 {{ $markerstyle }}">COPIED</span>
29
+
{{ else if .IsRename }}
30
+
<span class="bg-gray-100 text-gray-700 {{ $markerstyle }}">RENAMED</span>
31
+
{{ else }}
32
+
<span class="bg-gray-100 text-gray-700 {{ $markerstyle }}">MODIFIED</span>
33
+
{{ end }}
34
+
35
+
{{ if .IsDelete }}
36
+
<a {{if $this }}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.Old }}"{{end}}>
37
+
{{ .Name.Old }}
38
+
</a>
39
+
{{ else if (or .IsCopy .IsRename) }}
40
+
<a {{if $parent}}href="/{{ $repo }}/blob/{{ $parent }}/{{ .Name.Old }}"{{end}}>
41
+
{{ .Name.Old }}
42
+
</a>
43
+
<i class="w-4 h-4" data-lucide="arrow-right"></i>
44
+
<a {{if $this}}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}"{{end}}>
45
+
{{ .Name.New }}
46
+
</a>
47
+
{{ else }}
48
+
<a {{if $this}}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}"{{end}}>
49
+
{{ .Name.New }}
50
+
</a>
51
+
{{ end }}
52
+
</div>
53
+
54
+
{{ $iconstyle := "p-1 mx-1 hover:bg-gray-100 rounded" }}
55
+
<div id="right-side-items" class="p-2 flex items-center">
56
+
<a title="top of file" href="#file-{{ .Name.New }}" class="{{ $iconstyle }}"><i class="w-4 h-4" data-lucide="arrow-up-to-line"></i></a>
57
+
{{ if gt $idx 0 }}
58
+
{{ $prev := index $diff (sub $idx 1) }}
59
+
<a title="previous file" href="#file-{{ $prev.Name.New }}" class="{{ $iconstyle }}"><i class="w-4 h-4" data-lucide="arrow-up"></i></a>
60
+
{{ end }}
61
+
62
+
{{ if lt $idx $last }}
63
+
{{ $next := index $diff (add $idx 1) }}
64
+
<a title="next file" href="#file-{{ $next.Name.New }}" class="{{ $iconstyle }}"><i class="w-4 h-4" data-lucide="arrow-down"></i></a>
65
+
{{ end }}
66
+
</div>
67
+
68
+
</div>
69
+
</summary>
70
+
71
+
<div class="transition-all duration-700 ease-in-out">
72
+
{{ if .IsDelete }}
73
+
<p class="text-center text-gray-400 p-4">
74
+
This file has been deleted in this commit.
75
+
</p>
76
+
{{ else }}
77
+
{{ if .IsBinary }}
78
+
<p class="text-center text-gray-400 p-4">
79
+
This is a binary file and will not be displayed.
80
+
</p>
81
+
{{ else }}
82
+
<pre class="overflow-auto">
83
+
{{- range .TextFragments -}}
84
+
<div class="bg-gray-100 text-gray-500 select-none">{{ .Header }}</div>
85
+
{{- range .Lines -}}
86
+
{{- if eq .Op.String "+" -}}
87
+
<div class="bg-green-100 text-green-700 p-1"><span class="select-none mx-2">{{ .Op.String }}</span><span>{{ .Line }}</span></div>
88
+
{{- end -}}
89
+
90
+
{{- if eq .Op.String "-" -}}
91
+
<div class="bg-red-100 text-red-700 p-1"><span class="select-none mx-2">{{ .Op.String }}</span><span>{{ .Line }}</span></div>
92
+
{{- end -}}
93
+
94
+
{{- if eq .Op.String " " -}}
95
+
<div class="bg-white text-gray-500 px"><span class="select-none mx-2">{{ .Op.String }}</span><span>{{ .Line }}</span></div>
96
+
{{- end -}}
97
+
98
+
{{- end -}}
99
+
{{- end -}}
100
+
</pre>
101
+
{{- end -}}
102
+
{{ end }}
103
+
</div>
104
+
105
+
</details>
106
+
107
+
</div>
108
+
</div>
109
+
</section>
110
+
{{ end }}
111
+
{{ end }}
112
+
{{ end }}
+1
-103
appview/pages/templates/repo/commit.html
+1
-103
appview/pages/templates/repo/commit.html
···
55
55
{{end}}
56
56
57
57
{{ define "repoAfter" }}
58
-
59
-
{{ $repo := .RepoInfo.FullName }}
60
-
{{ $commit := .Diff.Commit }}
61
-
{{ $stat := .Diff.Stat }}
62
-
{{ $diff := .Diff.Diff }}
63
-
64
-
{{ $this := $commit.This }}
65
-
{{ $parent := $commit.Parent }}
66
-
67
-
{{ $last := sub (len $diff) 1 }}
68
-
{{ range $idx, $hunk := $diff }}
69
-
{{ with $hunk }}
70
-
<section class="mt-6 border border-gray-200 w-full mx-auto rounded bg-white drop-shadow-sm">
71
-
<div id="file-{{ .Name.New }}">
72
-
<div id="diff-file">
73
-
<details open>
74
-
<summary class="list-none cursor-pointer sticky top-0">
75
-
<div id="diff-file-header" class="rounded cursor-pointer bg-white flex justify-between">
76
-
<div id="left-side-items" class="p-2 flex gap-2 items-center">
77
-
{{ $markerstyle := "diff-type p-1 mr-1 font-mono text-sm rounded select-none" }}
78
-
79
-
{{ if .IsNew }}
80
-
<span class="bg-green-100 text-green-700 {{ $markerstyle }}">ADDED</span>
81
-
{{ else if .IsDelete }}
82
-
<span class="bg-red-100 text-red-700 {{ $markerstyle }}">DELETED</span>
83
-
{{ else if .IsCopy }}
84
-
<span class="bg-gray-100 text-gray-700 {{ $markerstyle }}">COPIED</span>
85
-
{{ else if .IsRename }}
86
-
<span class="bg-gray-100 text-gray-700 {{ $markerstyle }}">RENAMED</span>
87
-
{{ else }}
88
-
<span class="bg-gray-100 text-gray-700 {{ $markerstyle }}">MODIFIED</span>
89
-
{{ end }}
90
-
91
-
{{ if .IsDelete }}
92
-
<a href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.Old }}">{{ .Name.Old }}</a>
93
-
{{ else if (or .IsCopy .IsRename) }}
94
-
<a href="/{{ $repo }}/blob/{{ $parent }}/{{ .Name.Old }}">{{ .Name.Old }}</a>
95
-
<i class="w-4 h-4" data-lucide="arrow-right"></i>
96
-
<a href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}">{{ .Name.New }}</a>
97
-
{{ else }}
98
-
<a href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.New }}">{{ .Name.New }}</a>
99
-
{{ end }}
100
-
</div>
101
-
102
-
{{ $iconstyle := "p-1 mx-1 hover:bg-gray-100 rounded" }}
103
-
<div id="right-side-items" class="p-2 flex items-center">
104
-
<a title="top of file" href="#file-{{ .Name.New }}" class="{{ $iconstyle }}"><i class="w-4 h-4" data-lucide="arrow-up-to-line"></i></a>
105
-
{{ if gt $idx 0 }}
106
-
{{ $prev := index $diff (sub $idx 1) }}
107
-
<a title="previous file" href="#file-{{ $prev.Name.New }}" class="{{ $iconstyle }}"><i class="w-4 h-4" data-lucide="arrow-up"></i></a>
108
-
{{ end }}
109
-
110
-
{{ if lt $idx $last }}
111
-
{{ $next := index $diff (add $idx 1) }}
112
-
<a title="next file" href="#file-{{ $next.Name.New }}" class="{{ $iconstyle }}"><i class="w-4 h-4" data-lucide="arrow-down"></i></a>
113
-
{{ end }}
114
-
</div>
115
-
116
-
</div>
117
-
</summary>
118
-
119
-
<div class="transition-all duration-700 ease-in-out">
120
-
{{ if .IsDelete }}
121
-
<p class="text-center text-gray-400 p-4">
122
-
This file has been deleted in this commit.
123
-
</p>
124
-
{{ else }}
125
-
{{ if .IsBinary }}
126
-
<p class="text-center text-gray-400 p-4">
127
-
This is a binary file and will not be displayed.
128
-
</p>
129
-
{{ else }}
130
-
<pre class="overflow-auto">
131
-
{{- range .TextFragments -}}
132
-
<div class="bg-gray-100 text-gray-500 select-none">{{ .Header }}</div>
133
-
{{- range .Lines -}}
134
-
{{- if eq .Op.String "+" -}}
135
-
<div class="bg-green-100 text-green-700 p-1"><span class="select-none mx-2">{{ .Op.String }}</span><span>{{ .Line }}</span></div>
136
-
{{- end -}}
137
-
138
-
{{- if eq .Op.String "-" -}}
139
-
<div class="bg-red-100 text-red-700 p-1"><span class="select-none mx-2">{{ .Op.String }}</span><span>{{ .Line }}</span></div>
140
-
{{- end -}}
141
-
142
-
{{- if eq .Op.String " " -}}
143
-
<div class="bg-white text-gray-500 px"><span class="select-none mx-2">{{ .Op.String }}</span><span>{{ .Line }}</span></div>
144
-
{{- end -}}
145
-
146
-
{{- end -}}
147
-
{{- end -}}
148
-
</pre>
149
-
{{- end -}}
150
-
{{ end }}
151
-
</div>
152
-
153
-
</details>
154
-
155
-
</div>
156
-
</div>
157
-
</section>
158
-
{{ end }}
159
-
{{ end }}
160
-
58
+
{{ template "fragments/diff" (list .RepoInfo.FullName .Diff) }}
161
59
{{end}}
+1
-1
appview/pages/templates/repo/index.html
+1
-1
appview/pages/templates/repo/index.html
···
13
13
{{ define "branchSelector" }}
14
14
<div class="flex justify-between pb-5">
15
15
<select
16
-
onchange="window.location.href = '/{{ .RepoInfo.FullName }}/tree/' + this.value"
16
+
onchange="window.location.href = '/{{ .RepoInfo.FullName }}/tree/' + encodeURIComponent(this.value)"
17
17
class="p-1 border border-gray-200 bg-white"
18
18
>
19
19
<optgroup label="branches" class="bold text-sm">
+6
-5
appview/pages/templates/repo/pulls/pull.html
+6
-5
appview/pages/templates/repo/pulls/pull.html
···
93
93
94
94
{{ define "submissions" }}
95
95
{{ $lastIdx := sub (len .Pull.Submissions) 1 }}
96
+
{{ $targetBranch := .Pull.TargetBranch }}
97
+
{{ $repoName := .RepoInfo.FullName }}
96
98
{{ range $idx, $item := .Pull.Submissions }}
99
+
{{ $diff := $item.AsNiceDiff $targetBranch }}
97
100
{{ with $item }}
98
101
{{ $oneIndexedRound := add .RoundNumber 1 }}
99
102
<details {{ if eq $idx $lastIdx }}open{{ end }}>
···
106
109
<span>
107
110
{{ $owner := index $.DidHandleMap $.Pull.OwnerDid }}
108
111
submitted by <a href="/{{ $owner }}">{{ $owner }}</a>
109
-
<span class="before:content-['·']"></span>
110
-
<a href="/{{ $.RepoInfo.FullName }}/pulls/{{ $.Pull.PullId }}/patch">view patch</a>
111
112
<span class="select-none before:content-['\00B7']"></span>
112
113
<time>{{ .Created | timeFmt }}</time>
113
114
<span class="select-none before:content-['·']"></span>
···
121
122
</div>
122
123
</summary>
123
124
<div class="pl-12 flex flex-col gap-2 mt-2 relative">
124
-
<!--div class="bg-white rounded drop-shadow-sm p-4">
125
-
<pre class="overflow-auto"><code>{{- .Patch -}}</code></pre>
126
-
</div-->
125
+
<div>
126
+
{{ template "fragments/diff" (list $repoName $diff) }}
127
+
</div>
127
128
128
129
{{ range .Comments }}
129
130
<div id="comment-{{.ID}}" class="bg-white rounded drop-shadow-sm py-2 px-4 relative w-fit">
+11
-1
flake.nix
+11
-1
flake.nix
···
313
313
314
314
environment.systemPackages = with pkgs; [git];
315
315
316
+
system.activationScripts.gitConfig = ''
317
+
mkdir -p /home/git/.config/git
318
+
cat > /home/git/.config/git/config << EOF
319
+
[user]
320
+
name = Git User
321
+
email = git@example.com
322
+
EOF
323
+
chown -R git:git /home/git/.config
324
+
'';
325
+
316
326
users.users.git = {
317
327
isNormalUser = true;
318
328
home = "/home/git";
···
380
390
services.tangled-knotserver = {
381
391
enable = true;
382
392
server = {
383
-
secret = "ad7b32ded52fbe96e09f469a288084ee01cd12c971da87a1cbb87ef67081bd87";
393
+
secret = "6995e040e80e2d593b5e5e9ca611a70140b9ef8044add0a28b48b1ee34aa3e85";
384
394
hostname = "localhost:6000";
385
395
listenAddr = "0.0.0.0:6000";
386
396
};