/
templates.go
124 lines (108 loc) · 2.69 KB
/
templates.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package main
import (
"bytes"
"embed"
"errors"
"fmt"
alpm "github.com/remyoudompheng/go-alpm"
"html/template"
"io"
"net/http"
"runtime/debug"
"time"
)
var pacwebTemplate *template.Template
// TEMPLATE FUNCTIONS
// TimeFormat formats time according to a chosen format.
func TimeFormat(t time.Time) string { return t.Format(time.RFC1123) }
// HumanSize formats a file size for human readability.
func HumanSize(n int64) string {
switch {
case n > 1<<20:
return fmt.Sprintf("%.2f MiB", float64(n)/float64(1<<20))
default:
return fmt.Sprintf("%.0f kiB", float64(n)/float64(1<<10))
}
panic("impossible")
}
func IsLocal(p *alpm.Package) bool {
return p.DB().Name() == "local"
}
func InstallStatus(p *alpm.Package) string {
alpmHandleLock.RLock()
defer alpmHandleLock.RUnlock()
localdb, err := getAlpm().LocalDb()
if err != nil {
return "could not found local DB"
}
localp, err := localdb.PkgByName(p.Name())
if err == nil && localp != nil {
switch cmp := alpm.VerCmp(p.Version(), localp.Version()); {
case cmp > 0:
return "Upgradable"
case cmp == 0:
return "Installed"
case cmp < 0:
return "Local version is newer"
}
}
return "Not installed"
}
//go:embed templates
var templateData embed.FS
func init() {
// parse templates.
t := template.New("root")
t.Funcs(template.FuncMap{
"timeFmt": TimeFormat,
"httpStatusText": http.StatusText,
"isLocal": IsLocal,
"installStatus": InstallStatus,
"humanSize": HumanSize,
})
pacwebTemplate = template.Must(t.ParseFS(templateData, "templates/*.tpl"))
}
type TplInput struct {
Common CommonData
Contents interface{}
}
type CommonData struct {
SysMessage string
}
func Execute(tplName string, common CommonData, contents interface{}) ([]byte, error) {
buf := bytes.NewBuffer(nil)
err := pacwebTemplate.ExecuteTemplate(buf, tplName, TplInput{common, contents})
if err != nil {
logger.Printf("template error: %s", err)
}
return buf.Bytes(), err
}
type ErrorData struct {
StatusCode int
Error error
Stack string
}
func ErrorPage(w io.Writer, common CommonData, code int, err error) error {
if err == nil {
err = nilError
}
contents := ErrorData{code, err, string(debug.Stack())}
logger.Printf("error: %v", err)
err = pacwebTemplate.ExecuteTemplate(w, "error", TplInput{common, contents})
if err != nil {
logger.Printf("template error: %s", err)
}
return err
}
var nilError = errors.New("nil")
func PanicPage(w io.Writer, panicData interface{}) {
switch x := panicData.(type) {
case error:
if x == nil {
x = nilError
}
ErrorPage(w, CommonData{}, http.StatusInternalServerError, x)
default:
ErrorPage(w, CommonData{}, http.StatusInternalServerError, fmt.Errorf("%+v", x))
}
}