git.go 3.5 KiB raw
1
package main
2
3
import (
4
	"sort"
5
	"strings"
6
	"time"
7
)
8
9
type RepoInfo struct {
10
	Name        string
11
	Path        string
12
	GitDir      string
13
	Description string
14
	Owner       string
15
	LastUpdated time.Time
16
	Git         *gitCLIBackend
17
}
18
19
type CommitInfo struct {
20
	Hash        string
21
	ShortHash   string
22
	Subject     string
23
	Body        string
24
	Author      string
25
	AuthorEmail string
26
	AuthorDate  time.Time
27
	Parents     []string
28
}
29
30
type TreeEntryInfo struct {
31
	Name  string
32
	IsDir bool
33
	Size  int64
34
	Mode  string
35
	Hash  string
36
}
37
38
type BlobInfo struct {
39
	Name     string
40
	Size     int64
41
	IsBinary bool
42
	Lines    []string
43
	Content  string
44
}
45
46
type RefInfo struct {
47
	Name      string
48
	Hash      string
49
	ShortHash string
50
	Subject   string
51
	Author    string
52
	Date      time.Time
53
	IsTag     bool
54
}
55
56
type DiffFile struct {
57
	OldName  string
58
	NewName  string
59
	Status   string
60
	Hunks    []DiffHunk
61
	IsBinary bool
62
	Stats    DiffStats
63
}
64
65
type DiffStats struct {
66
	Added   int
67
	Deleted int
68
}
69
70
type DiffHunk struct {
71
	Header string
72
	Lines  []DiffLine
73
}
74
75
type DiffLine struct {
76
	Type    string // "context", "add", "del"
77
	Content string
78
	OldNum  int
79
	NewNum  int
80
}
81
82
type TreeNode struct {
83
	Name     string
84
	IsDir    bool
85
	Size     int64
86
	Path     string
87
	Depth    int
88
	IsOpen   bool
89
	IsActive bool
90
}
91
92
const maxBlobDisplaySize = 1 << 20 // 1MB
93
const diffContextLines = 5
94
const maxDiffFiles = 256 // max files rendered per commit
95
96
func sortTreeEntries(entries []TreeEntryInfo) {
97
	sort.Slice(entries, func(i, j int) bool {
98
		if entries[i].IsDir != entries[j].IsDir {
99
			return entries[i].IsDir
100
		}
101
		return entries[i].Name < entries[j].Name
102
	})
103
}
104
105
// collapseContext takes a flat list of diff lines and splits them into
106
// hunks, keeping only diffContextLines of context around add/del lines.
107
func collapseContext(lines []DiffLine) []DiffHunk {
108
	if len(lines) == 0 {
109
		return nil
110
	}
111
112
	// Mark which lines to keep: diffContextLines around each changed line.
113
	keep := make([]bool, len(lines))
114
	for i, l := range lines {
115
		if l.Type == "add" || l.Type == "del" {
116
			start := i - diffContextLines
117
			if start < 0 {
118
				start = 0
119
			}
120
			end := i + diffContextLines
121
			if end >= len(lines) {
122
				end = len(lines) - 1
123
			}
124
			for j := start; j <= end; j++ {
125
				keep[j] = true
126
			}
127
		}
128
	}
129
130
	// Build hunks from contiguous kept ranges.
131
	var hunks []DiffHunk
132
	var current *DiffHunk
133
	for i, l := range lines {
134
		if keep[i] {
135
			if current == nil {
136
				current = &DiffHunk{}
137
			}
138
			current.Lines = append(current.Lines, l)
139
		} else {
140
			if current != nil {
141
				hunks = append(hunks, *current)
142
				current = nil
143
			}
144
		}
145
	}
146
	if current != nil {
147
		hunks = append(hunks, *current)
148
	}
149
150
	return hunks
151
}
152
153
var mimeTypes = map[string]string{
154
	".txt":  "text/plain; charset=utf-8",
155
	".md":   "text/plain; charset=utf-8",
156
	".go":   "text/plain; charset=utf-8",
157
	".rs":   "text/plain; charset=utf-8",
158
	".py":   "text/plain; charset=utf-8",
159
	".js":   "text/plain; charset=utf-8",
160
	".ts":   "text/plain; charset=utf-8",
161
	".c":    "text/plain; charset=utf-8",
162
	".h":    "text/plain; charset=utf-8",
163
	".css":  "text/css; charset=utf-8",
164
	".html": "text/html; charset=utf-8",
165
	".json": "application/json",
166
	".xml":  "application/xml",
167
	".png":  "image/png",
168
	".jpg":  "image/jpeg",
169
	".jpeg": "image/jpeg",
170
	".gif":  "image/gif",
171
	".svg":  "image/svg+xml",
172
	".pdf":  "application/pdf",
173
}
174
175
func mimeFromPath(path string) string {
176
	idx := strings.LastIndex(path, ".")
177
	if idx < 0 {
178
		return ""
179
	}
180
	ext := strings.ToLower(path[idx:])
181
	if t, ok := mimeTypes[ext]; ok {
182
		return t
183
	}
184
	return ""
185
}