-
Notifications
You must be signed in to change notification settings - Fork 2
/
http_index.go
146 lines (126 loc) · 3.51 KB
/
http_index.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// This file is part of *kellner*
//
// Copyright (C) 2015, Travelping GmbH <copyright@travelping.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package main
import (
"log"
"net/http"
"os"
"path"
"path/filepath"
"sort"
"text/template"
"time"
)
const _Template = `<!doctype html>
<title>{{.Title}}</title>
<style type="text/css">
body { font-family: monospace }
td, th { padding: auto 2em }
.col-size { text-align: right }
.col-modtime { white-space: nowrap }
.col-descr { white-space: nowrap }
footer { margin-top: 1em; padding-top: 1em; border-top: 1px dotted silver }
</style>
<p>
This repository contains {{.Entries|len}} packages with an accumulated size of {{.SumFileSize}} bytes.
</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Last Modified</th>
<th>Size</th>
<th>Description</th>
</tr>
</thead>
<tbody>
{{range .Entries}}
<tr>
<td class="col-link"><a href="{{.Href}}">{{.Name}}</a></td>
<td class="col-modtime">{{.ModTime.Format "2006-01-02T15:04:05Z07:00" }}</td>
<td class="col-size">{{.Size}}</td>
<td class="col-descr"><a href="{{.Href}}.control" title="{{.RawDescr | html }}">{{.Descr}}</td>
</tr>
{{end}}
</tbody>
</table>
<footer>{{.Version}} - generated at {{.Date}}</footer>
`
var indexTemplate = template.Must(template.New("index").Parse(_Template))
type dirEntry struct {
Name string
Href string
ModTime time.Time
Size int64
RawDescr string
Descr string
}
type dirEntryByName []dirEntry
func (a dirEntryByName) Len() int { return len(a) }
func (a dirEntryByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a dirEntryByName) Less(i, j int) bool { return a[i].Name < a[j].Name }
type renderCtx struct {
Title string
Entries []dirEntry
SumFileSize int64
Date time.Time
Version string
}
func renderIndex(w http.ResponseWriter, r *http.Request, root, cache string) {
var reqPath = filepath.Join(root, r.URL.Path)
var ctx = renderCtx{
Title: r.URL.Path + " - kellner",
Version: versionString,
Date: time.Now()}
var dir, err = os.Open(reqPath)
if err != nil {
http.NotFound(w, r)
return
}
defer dir.Close()
var entry os.FileInfo
var entries []os.FileInfo
entries, err = dir.Readdir(-1)
if entry, err = os.Stat(filepath.Join(cache, r.URL.Path, "Packages")); err == nil {
entries = append(entries, entry)
}
if entry, err = os.Stat(filepath.Join(cache, r.URL.Path, "Packages.gz")); err == nil {
entries = append(entries, entry)
}
if entry, err = os.Stat(filepath.Join(cache, r.URL.Path, "Packages.stamps")); err == nil {
entries = append(entries, entry)
}
ctx.Entries = make([]dirEntry, len(entries)+1)
var i int
for i, entry = range entries {
ctx.Entries[i] = dirEntry{
Name: entry.Name(),
Href: path.Join(r.URL.Path, entry.Name()),
ModTime: entry.ModTime(),
Size: int64(entry.Size()),
}
/* TODO: re-enable
var raw, _ = ioutil.ReadFile(filepath.Join(cache, entry.Name()))
ctx.Entries[i].RawDescr = string(raw)
*/
ctx.SumFileSize += entry.Size()
}
if reqPath == root {
ctx.Entries = ctx.Entries[:len(ctx.Entries)-1]
} else {
ctx.Entries[len(ctx.Entries)-1] = dirEntry{
Name: "..",
Href: path.Join(r.URL.Path, ".."),
ModTime: ctx.Date,
}
}
sort.Sort(dirEntryByName(ctx.Entries))
if err = indexTemplate.Execute(w, ctx); err != nil {
log.Println("error: rendering %q: %v", r.URL.Path, err)
}
}