From ac2e1cc0a899d18a38cd47fc3e18d830f94c2422 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Sun, 26 Sep 2021 17:01:06 +0300 Subject: [PATCH] More reliable serial calculation --- doc/storage.texi | 5 +++-- list.go | 20 ++++++++++++++++---- metadata.go | 2 +- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/doc/storage.texi b/doc/storage.texi index 215db8d..12edb70 100644 --- a/doc/storage.texi +++ b/doc/storage.texi @@ -46,7 +46,8 @@ SHA256 recalculated checksum. Also upstream has corresponding @file{private-package} is private package, because it contains @file{.internal} file. It can be uploaded and queries to it are not -proxied to upstream PyPI. You have to create it manually. If you upload -GPG signature, then it will be also stored. +proxied to upstream PyPI. You have to create it manually. Each packages release file has @code{mtime} set to its upload time. +Package's serial is a sum of @code{mtime}s of the directory and +@file{.metadata.rec} (if it exists). diff --git a/list.go b/list.go index 48a9d71..7ca9b18 100644 --- a/list.go +++ b/list.go @@ -21,6 +21,7 @@ import ( "bytes" "encoding/hex" "errors" + "fmt" "html/template" "io/fs" "io/ioutil" @@ -29,6 +30,7 @@ import ( "os" "path/filepath" "sort" + "strconv" "strings" "time" ) @@ -39,7 +41,7 @@ var ( - Links for root + Simple index {{$Refresh := .RefreshURLPath}}{{range .Packages}} {{.}}
@@ -137,7 +139,7 @@ func filenameToVersion(fn string) string { return cols[0] } -func listDir(pkgName string, doSize bool) (int, []*PkgReleaseInfo, error) { +func listDir(pkgName string, doSize bool) (int64, []*PkgReleaseInfo, error) { dirPath := filepath.Join(Root, pkgName) entries, err := os.ReadDir(dirPath) if err != nil { @@ -206,7 +208,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, MetadataFile)); err == nil { + serial += fi.ModTime().Unix() + } + return serial, releases, nil } func serveListDir( @@ -224,7 +234,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 +268,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("\n", serial))) } diff --git a/metadata.go b/metadata.go index 65080b5..87ff48a 100644 --- a/metadata.go +++ b/metadata.go @@ -108,7 +108,7 @@ type PkgReleaseInfo struct { type PkgMeta struct { Info PkgInfo `json:"info"` - LastSerial int `json:"last_serial"` + LastSerial int64 `json:"last_serial"` Releases map[string][]*PkgReleaseInfo `json:"releases"` URLs []*PkgReleaseInfo `json:"urls"` } -- 2.44.0