]> Cypherpunks.ru repositories - gocheese.git/blobdiff - list.go
Additional signature with my new main key
[gocheese.git] / list.go
diff --git a/list.go b/list.go
index d8bd0732459d04fc805e1f6562418d71dae4c00b..356cd6bf01874f5aaf687028d3dfd556dc56db76 100644 (file)
--- a/list.go
+++ b/list.go
@@ -1,6 +1,6 @@
 /*
 GoCheese -- Python private package repository and caching proxy
-Copyright (C) 2019-2021 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2019-2022 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
@@ -19,8 +19,10 @@ package main
 
 import (
        "bytes"
+       _ "embed"
        "encoding/hex"
        "errors"
+       "fmt"
        "html/template"
        "io/fs"
        "io/ioutil"
@@ -29,44 +31,26 @@ import (
        "os"
        "path/filepath"
        "sort"
+       "strconv"
        "strings"
        "time"
 )
 
 // https://warehouse.pypa.io/api-reference/legacy.html
 var (
-       HTMLRootTmpl = template.Must(template.New("root").Parse(`<!DOCTYPE html>
-<html>
-  <head>
-    <meta name="pypi:repository-version" content="1.0">
-    <title>Links for root</title>
-  </head>
-  <body>{{$Refresh := .RefreshURLPath}}{{range .Packages}}
-    <a href="{{$Refresh}}{{.}}/">{{.}}</a><br/>
-{{- end}}
-  </body>
-</html>
-`))
-       HTMLReleasesTmpl = template.Must(template.New("list").Parse(`<!DOCTYPE html>
-<html>
-  <head>
-    <meta name="pypi:repository-version" content="1.0">
-    <title>Links for {{.PkgName}}</title>
-  </head>
-  <body>{{$Refresh := .RefreshURLPath}}{{$PkgName := .PkgName}}{{range .Releases}}
-    <a href="{{$Refresh}}{{$PkgName}}/{{.Filename -}}
-        #{{range $a, $d := .Digests}}{{$a}}={{$d}}{{end -}}
-        {{with .HasSig}} data-gpg-sig=true{{end}}">{{.Filename}}</a><br/>
-{{- end}}
-  </body>
-</html>
-`))
-       KnownExts = []string{".tar.bz2", ".tar.gz", ".whl", ".zip", ".egg",
+       //go:embed root.tmpl
+       HTMLRootTmplRaw string
+       HTMLRootTmpl    = template.Must(template.New("root").Parse(HTMLRootTmplRaw))
+
+       //go:embed list.tmpl
+       HTMLReleasesTmplRaw string
+       HTMLReleasesTmpl    = template.Must(template.New("list").Parse(HTMLReleasesTmplRaw))
+       KnownExts           = []string{".tar.bz2", ".tar.gz", ".whl", ".zip", ".egg",
                ".exe", ".dmg", ".msi", ".rpm", ".deb", ".tgz"}
 )
 
 func listRoot(w http.ResponseWriter, r *http.Request) {
-       files, err := ioutil.ReadDir(*Root)
+       files, err := ioutil.ReadDir(Root)
        if err != nil {
                log.Println("error", r.RemoteAddr, "root", err)
                http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -137,8 +121,8 @@ func filenameToVersion(fn string) string {
        return cols[0]
 }
 
-func listDir(pkgName string, doSize bool) (int, []*PkgReleaseInfo, error) {
-       dirPath := filepath.Join(*Root, pkgName)
+func listDir(pkgName string, doSize bool) (int64, []*PkgReleaseInfo, error) {
+       dirPath := filepath.Join(Root, pkgName)
        entries, err := os.ReadDir(dirPath)
        if err != nil {
                return 0, nil, err
@@ -206,7 +190,15 @@ func listDir(pkgName string, doSize bool) (int, []*PkgReleaseInfo, error) {
                releases = append(releases, release)
        }
        sort.Sort(PkgReleaseInfoByName(releases))
-       return len(entries), releases, nil
+       fi, err := os.Stat(dirPath)
+       if err != nil {
+               return 0, nil, err
+       }
+       serial := fi.ModTime().Unix()
+       if fi, err = os.Stat(filepath.Join(dirPath, MDFile)); err == nil {
+               serial += fi.ModTime().Unix()
+       }
+       return serial, releases, nil
 }
 
 func serveListDir(
@@ -215,7 +207,7 @@ func serveListDir(
        pkgName string,
        autorefresh, gpgUpdate bool,
 ) {
-       dirPath := filepath.Join(*Root, pkgName)
+       dirPath := filepath.Join(Root, pkgName)
        if autorefresh {
                if !refreshDir(w, r, pkgName, "", gpgUpdate) {
                        return
@@ -224,7 +216,7 @@ func serveListDir(
                !refreshDir(w, r, pkgName, "", false) {
                return
        }
-       _, releases, err := listDir(pkgName, false)
+       serial, releases, err := listDir(pkgName, false)
        if err != nil {
                log.Println("error", r.RemoteAddr, "list", pkgName, err)
                http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -258,5 +250,7 @@ func serveListDir(
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
        }
+       w.Header().Set("X-PyPI-Last-Serial", strconv.FormatInt(serial, 10))
        w.Write(buf.Bytes())
+       w.Write([]byte(fmt.Sprintf("<!--SERIAL %d-->\n", serial)))
 }