+62
appview/filetree/filetree.go
+62
appview/filetree/filetree.go
···
···
1
+
package filetree
2
+
3
+
import (
4
+
"path/filepath"
5
+
"sort"
6
+
"strings"
7
+
)
8
+
9
+
type FileTreeNode struct {
10
+
Name string
11
+
Path string
12
+
IsDirectory bool
13
+
Children map[string]*FileTreeNode
14
+
}
15
+
16
+
// NewNode creates a new node
17
+
func newNode(name, path string, isDir bool) *FileTreeNode {
18
+
return &FileTreeNode{
19
+
Name: name,
20
+
Path: path,
21
+
IsDirectory: isDir,
22
+
Children: make(map[string]*FileTreeNode),
23
+
}
24
+
}
25
+
26
+
func FileTree(files []string) *FileTreeNode {
27
+
rootNode := newNode("", "", true)
28
+
29
+
sort.Strings(files)
30
+
31
+
for _, file := range files {
32
+
if file == "" {
33
+
continue
34
+
}
35
+
36
+
parts := strings.Split(filepath.Clean(file), "/")
37
+
if len(parts) == 0 {
38
+
continue
39
+
}
40
+
41
+
currentNode := rootNode
42
+
currentPath := ""
43
+
44
+
for i, part := range parts {
45
+
if currentPath == "" {
46
+
currentPath = part
47
+
} else {
48
+
currentPath = filepath.Join(currentPath, part)
49
+
}
50
+
51
+
isDir := i < len(parts)-1
52
+
53
+
if _, exists := currentNode.Children[part]; !exists {
54
+
currentNode.Children[part] = newNode(part, currentPath, isDir)
55
+
}
56
+
57
+
currentNode = currentNode.Children[part]
58
+
}
59
+
}
60
+
61
+
return rootNode
62
+
}
+2
appview/pages/funcmap.go
+2
appview/pages/funcmap.go
+6
-5
appview/pages/pages.go
+6
-5
appview/pages/pages.go
···
505
}
506
507
type RepoCommitParams struct {
508
-
LoggedInUser *auth.User
509
-
RepoInfo RepoInfo
510
-
Active string
511
types.RepoCommitResponse
512
-
EmailToDidOrHandle map[string]string
513
}
514
515
func (p *Pages) RepoCommit(w io.Writer, params RepoCommitParams) error {
···
784
DidHandleMap map[string]string
785
RepoInfo RepoInfo
786
Pull *db.Pull
787
-
Diff types.NiceDiff
788
Round int
789
Submission *db.PullSubmission
790
}
···
505
}
506
507
type RepoCommitParams struct {
508
+
LoggedInUser *auth.User
509
+
RepoInfo RepoInfo
510
+
Active string
511
+
EmailToDidOrHandle map[string]string
512
+
513
types.RepoCommitResponse
514
}
515
516
func (p *Pages) RepoCommit(w io.Writer, params RepoCommitParams) error {
···
785
DidHandleMap map[string]string
786
RepoInfo RepoInfo
787
Pull *db.Pull
788
+
Diff *types.NiceDiff
789
Round int
790
Submission *db.PullSubmission
791
}
+4
-17
appview/pages/templates/repo/fragments/diff.html
+4
-17
appview/pages/templates/repo/fragments/diff.html
···
3
{{ $diff := index . 1 }}
4
{{ $commit := $diff.Commit }}
5
{{ $stat := $diff.Stat }}
6
{{ $diff := $diff.Diff }}
7
8
{{ $this := $commit.This }}
···
14
<strong class="text-sm uppercase dark:text-gray-200">Changed files</strong>
15
{{ block "statPill" $stat }} {{ end }}
16
</div>
17
-
<div class="overflow-x-auto">
18
-
{{ range $diff }}
19
-
<ul class="dark:text-gray-200">
20
-
{{ if .IsDelete }}
21
-
<li><a href="#file-{{ .Name.Old }}" class="dark:hover:text-gray-300">{{ .Name.Old }}</a></li>
22
-
{{ else }}
23
-
<li><a href="#file-{{ .Name.New }}" class="dark:hover:text-gray-300">{{ .Name.New }}</a></li>
24
-
{{ end }}
25
-
</ul>
26
-
{{ end }}
27
-
</div>
28
</div>
29
</section>
30
···
38
<summary class="list-none cursor-pointer sticky top-0">
39
<div id="diff-file-header" class="rounded cursor-pointer bg-white dark:bg-gray-800 flex justify-between">
40
<div id="left-side-items" class="p-2 flex gap-2 items-center overflow-x-auto">
41
-
<div class="flex gap-1 items-center" style="direction: ltr;">
42
{{ $markerstyle := "diff-type p-1 mr-1 font-mono text-sm rounded select-none" }}
43
{{ if .IsNew }}
44
<span class="bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400 {{ $markerstyle }}">ADDED</span>
···
55
{{ block "statPill" .Stats }} {{ end }}
56
</div>
57
58
-
<div class="flex gap-2 items-center overflow-x-auto" style="direction: rtl;">
59
{{ if .IsDelete }}
60
<a class="dark:text-white whitespace-nowrap overflow-x-auto" {{if $this }}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.Old }}"{{end}}>
61
{{ .Name.Old }}
···
101
{{ else if .IsCopy }}
102
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
103
This file has been copied.
104
-
</p>
105
-
{{ else if .IsRename }}
106
-
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
107
-
This file has been renamed.
108
</p>
109
{{ else if .IsBinary }}
110
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
···
3
{{ $diff := index . 1 }}
4
{{ $commit := $diff.Commit }}
5
{{ $stat := $diff.Stat }}
6
+
{{ $fileTree := fileTree $diff.ChangedFiles }}
7
{{ $diff := $diff.Diff }}
8
9
{{ $this := $commit.This }}
···
15
<strong class="text-sm uppercase dark:text-gray-200">Changed files</strong>
16
{{ block "statPill" $stat }} {{ end }}
17
</div>
18
+
{{ block "fileTree" $fileTree }} {{ end }}
19
</div>
20
</section>
21
···
29
<summary class="list-none cursor-pointer sticky top-0">
30
<div id="diff-file-header" class="rounded cursor-pointer bg-white dark:bg-gray-800 flex justify-between">
31
<div id="left-side-items" class="p-2 flex gap-2 items-center overflow-x-auto">
32
+
<div class="flex gap-1 items-center">
33
{{ $markerstyle := "diff-type p-1 mr-1 font-mono text-sm rounded select-none" }}
34
{{ if .IsNew }}
35
<span class="bg-green-100 text-green-700 dark:bg-green-800/50 dark:text-green-400 {{ $markerstyle }}">ADDED</span>
···
46
{{ block "statPill" .Stats }} {{ end }}
47
</div>
48
49
+
<div class="flex gap-2 items-center overflow-x-auto">
50
{{ if .IsDelete }}
51
<a class="dark:text-white whitespace-nowrap overflow-x-auto" {{if $this }}href="/{{ $repo }}/blob/{{ $this }}/{{ .Name.Old }}"{{end}}>
52
{{ .Name.Old }}
···
92
{{ else if .IsCopy }}
93
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
94
This file has been copied.
95
</p>
96
{{ else if .IsBinary }}
97
<p class="text-center text-gray-400 dark:text-gray-500 p-4">
+27
appview/pages/templates/repo/fragments/filetree.html
+27
appview/pages/templates/repo/fragments/filetree.html
···
···
1
+
{{ define "fileTree" }}
2
+
{{ if and .Name .IsDirectory }}
3
+
<details open>
4
+
<summary class="cursor-pointer list-none pt-1">
5
+
<span class="inline-flex items-center gap-2 ">
6
+
{{ i "folder" "w-3 h-3 fill-current" }}
7
+
<span class="text-black dark:text-white">{{ .Name }}</span>
8
+
</span>
9
+
</summary>
10
+
<div class="ml-1 pl-4 border-l border-gray-200 dark:border-gray-700">
11
+
{{ range $child := .Children }}
12
+
{{ block "fileTree" $child }} {{ end }}
13
+
{{ end }}
14
+
</div>
15
+
</details>
16
+
{{ else if .Name }}
17
+
<div class="flex items-center gap-2 pt-1">
18
+
{{ i "file" "w-3 h-3" }}
19
+
<a href="#file-{{ .Path }}" class="text-black dark:text-white no-underline hover:underline">{{ .Name }}</a>
20
+
</div>
21
+
{{ else }}
22
+
{{ range $child := .Children }}
23
+
{{ block "fileTree" $child }} {{ end }}
24
+
{{ end }}
25
+
{{ end }}
26
+
{{ end }}
27
+
+2
-7
appview/pages/templates/repo/fragments/interdiff.html
+2
-7
appview/pages/templates/repo/fragments/interdiff.html
···
1
{{ define "repo/fragments/interdiff" }}
2
{{ $repo := index . 0 }}
3
{{ $x := index . 1 }}
4
{{ $diff := $x.Files }}
5
6
<section class="mt-6 p-6 border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
···
8
<div class="flex gap-2 items-center">
9
<strong class="text-sm uppercase dark:text-gray-200">files</strong>
10
</div>
11
-
<div class="overflow-x-auto">
12
-
<ul class="dark:text-gray-200">
13
-
{{ range $diff }}
14
-
<li><a href="#file-{{ .Name }}" class="dark:hover:text-gray-300">{{ .Name }}</a></li>
15
-
{{ end }}
16
-
</ul>
17
-
</div>
18
</div>
19
</section>
20
···
1
{{ define "repo/fragments/interdiff" }}
2
{{ $repo := index . 0 }}
3
{{ $x := index . 1 }}
4
+
{{ $fileTree := fileTree $x.AffectedFiles }}
5
{{ $diff := $x.Files }}
6
7
<section class="mt-6 p-6 border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm">
···
9
<div class="flex gap-2 items-center">
10
<strong class="text-sm uppercase dark:text-gray-200">files</strong>
11
</div>
12
+
{{ block "fileTree" $fileTree }} {{ end }}
13
</div>
14
</section>
15
+3
-1
appview/state/pull.go
+3
-1
appview/state/pull.go
···
284
}
285
}
286
287
s.pages.RepoPullPatchPage(w, pages.RepoPullPatchParams{
288
LoggedInUser: user,
289
DidHandleMap: didHandleMap,
···
291
Pull: pull,
292
Round: roundIdInt,
293
Submission: pull.Submissions[roundIdInt],
294
-
Diff: pull.Submissions[roundIdInt].AsNiceDiff(pull.TargetBranch),
295
})
296
297
}
···
284
}
285
}
286
287
+
diff := pull.Submissions[roundIdInt].AsNiceDiff(pull.TargetBranch)
288
+
289
s.pages.RepoPullPatchPage(w, pages.RepoPullPatchParams{
290
LoggedInUser: user,
291
DidHandleMap: didHandleMap,
···
293
Pull: pull,
294
Round: roundIdInt,
295
Submission: pull.Submissions[roundIdInt],
296
+
Diff: &diff,
297
})
298
299
}
+8
patchutil/interdiff.go
+8
patchutil/interdiff.go
···
11
Files []*InterdiffFile
12
}
13
14
+
func (i *InterdiffResult) AffectedFiles() []string {
15
+
files := make([]string, len(i.Files))
16
+
for _, f := range i.Files {
17
+
files = append(files, f.Name)
18
+
}
19
+
return files
20
+
}
21
+
22
func (i *InterdiffResult) String() string {
23
var b strings.Builder
24
for _, f := range i.Files {
+14
types/diff.go
+14
types/diff.go
···
59
Patch string `json:"patch"`
60
Diff []*gitdiff.File `json:"diff"`
61
}
62
+
63
+
func (d *NiceDiff) ChangedFiles() []string {
64
+
files := make([]string, len(d.Diff))
65
+
66
+
for i, f := range d.Diff {
67
+
if f.IsDelete {
68
+
files[i] = f.Name.Old
69
+
} else {
70
+
files[i] = f.Name.New
71
+
}
72
+
}
73
+
74
+
return files
75
+
}