]> Cypherpunks.ru repositories - gocheese.git/blobdiff - hr.go
Metadata, mtime support. Massive refactoring
[gocheese.git] / hr.go
diff --git a/hr.go b/hr.go
new file mode 100644 (file)
index 0000000..845a13e
--- /dev/null
+++ b/hr.go
@@ -0,0 +1,184 @@
+/*
+GoCheese -- Python private package repository and caching proxy
+Copyright (C) 2019-2021 Sergey Matveev <stargrave@stargrave.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 3 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package main
+
+import (
+       "bytes"
+       "html/template"
+       "io/ioutil"
+       "log"
+       "net/http"
+       "os"
+       "sort"
+       "strings"
+)
+
+var (
+       HRRootTmpl = template.Must(template.New("hr-root").Parse(`<!DOCTYPE html>
+<html>
+  <head>
+    <title>{{.Version}}: human readable listing</title>
+  </head>
+  <body>
+    <ul>{{range .Packages}}
+      <li><a href="/hr/{{.}}/">{{.}}</a></li>
+{{- end}}
+    </ul>
+  </body>
+</html>
+`))
+       HRPkgTmpl = template.Must(template.New("hr-pkg").Parse(`<!DOCTYPE html>
+<html>
+  <head>
+    <title>{{.Version}}: package {{.PkgName}}</title>
+  </head>
+  <body>
+    <dl>
+      {{with .Info.Name}}<dt>Name</dt><dd>{{.}}</dd>{{end}}
+      {{with .Info.Version}}<dt>Version</dt><dd>{{.}}</dd>{{end}}
+
+      {{with .Info.Platform}}<dt>Platform</dt><dd><ul>
+      {{range .}}<li>{{.}}</li>
+      {{end}}</ul></dd>{{end}}
+
+      {{with .Info.SupportedPlatform}}<dt>SupportedPlatform</dt><dd><ul>
+      {{range .}}<li>{{.}}</li>
+      {{end}}</ul></dd>{{end}}
+
+      <dt>Summary</dt><dd>{{.Info.Summary}}</dd>
+      <dt>Description</dt><dd><pre>
+{{.Info.Description}}
+      </pre></dd>
+
+      {{with .Info.DescriptionContentType}}<dt>DescriptionContentType</dt><dd>{{.}}</dd>{{end}}
+      {{with .Info.Keywords}}<dt>Keywords</dt><dd>{{.}}</dd>{{end}}
+      {{with .Info.HomePage}}<dt>HomePage</dt><dd>{{.}}</dd>{{end}}
+      {{with .Info.Author}}<dt>Author</dt><dd>{{.}}</dd>{{end}}
+      {{with .Info.AuthorEmail}}<dt>AuthorEmail</dt><dd>{{.}}</dd>{{end}}
+      {{with .Info.Maintainer}}<dt>Maintainer</dt><dd>{{.}}</dd>{{end}}
+      {{with .Info.MaintainerEmail}}<dt>MaintainerEmail</dt><dd>{{.}}</dd>{{end}}
+      {{with .Info.License}}<dt>License</dt><dd>{{.}}</dd>{{end}}
+
+      {{with .Info.Classifier}}<dt>Classifier</dt><dd><ul>
+      {{range .}}<li>{{.}}</li>
+      {{end}}</ul></dd>{{end}}
+
+      {{with .Info.RequiresDist}}<dt>RequiresDist</dt><dd><ul>
+      {{range .}}<li>{{.}}</li>
+      {{end}}</ul></dd>{{end}}
+
+      {{with .Info.RequiresPython}}<dt>RequiresPython</dt><dd>{{.}}</dd>{{end}}
+
+      {{with .Info.RequiresExternal}}<dt>RequiresExternal</dt><dd><ul>
+      {{range .}}<li>{{.}}</li>
+      {{end}}</ul></dd>{{end}}
+
+      {{with .Info.ProjectURL}}<dt>ProjectURL</dt><dd><ul>
+      {{range .}}<li>{{.}}</li>
+      {{end}}</ul></dd>{{end}}
+
+      {{with .Info.ProvidesExtra}}<dt>ProvidesExtra</dt><dd><ul>
+      {{range .}}<li>{{.}}</li>
+      {{end}}</ul></dd>{{end}}
+    </dl>
+
+    <h2>Releases</h2>
+    <table border=1>
+    <tr>
+      <th>Filename</th>
+      <th>Version</th>
+      <th>Uploaded</th>
+      <th>Size</th>
+      <th>Digests</th>
+    </tr>
+    {{range .Releases}}{{if .Size}}
+    <tr>
+      <td>{{.Filename}}</th>
+      <td>{{.Version}}</th>
+      <td>{{.UploadTimeISO8601}}</th>
+      <td>{{.Size}}</th>
+      <td><ul>{{range $a, $d := .Digests}}
+        <li>{{$a}}: <tt>{{$d}}</tt></li>
+      {{end}}</ul></td>
+    </tr>{{end}}{{end}}
+    </table>
+  </body>
+</html>
+`))
+)
+
+func serveHRRoot(w http.ResponseWriter, r *http.Request) {
+       files, err := ioutil.ReadDir(*Root)
+       if err != nil {
+               log.Println("error", r.RemoteAddr, "hr-root", err)
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+       packages := make([]string, 0, len(files))
+       for _, f := range files {
+               packages = append(packages, f.Name())
+       }
+       sort.Strings(packages)
+       var buf bytes.Buffer
+       err = HRRootTmpl.Execute(&buf, struct {
+               Version  string
+               Packages []string
+       }{
+               Version:  UserAgent,
+               Packages: packages,
+       })
+       if err != nil {
+               log.Println("error", r.RemoteAddr, "hr-root", err)
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+       w.Write(buf.Bytes())
+}
+
+func serveHRPkg(w http.ResponseWriter, r *http.Request) {
+       cols := strings.Split(strings.TrimRight(r.URL.Path, "/"), "/")
+       pkgName := cols[len(cols)-1]
+       meta, releases, err := getMetadata(pkgName, "")
+       if err != nil {
+               if os.IsNotExist(err) {
+                       http.NotFound(w, r)
+               } else {
+                       log.Println("error", r.RemoteAddr, "json", pkgName, err)
+                       http.Error(w, err.Error(), http.StatusInternalServerError)
+               }
+               return
+       }
+       var buf bytes.Buffer
+       err = HRPkgTmpl.Execute(&buf, struct {
+               Version  string
+               PkgName  string
+               Info     PkgInfo
+               Releases []*PkgReleaseInfo
+       }{
+               Version:  UserAgent,
+               PkgName:  pkgName,
+               Info:     meta.Info,
+               Releases: releases,
+       })
+       if err != nil {
+               log.Println("error", r.RemoteAddr, "root", err)
+               http.Error(w, err.Error(), http.StatusInternalServerError)
+               return
+       }
+       w.Write(buf.Bytes())
+}