doc/Storage | 10 ++++++++++ fileutils.go | 43 ++++++++++++++++++++++++++++++++++++++++--- go.mod | 6 +++--- go.sum | 12 ++++++------ hr-pkg.tmpl | 3 ++- hr-root.tmpl | 2 +- hr.go | 33 ++++++++++++++++----------------- integrity.go | 25 +++++++++++++++++++++++++ json.go | 8 ++++---- list.go | 70 +++++++++++++++++++++++++++++++++++++++++++---------- main.go | 81 +++++++++++++++++++++++++++++++++++++++++++++++++---- refresh.go | 57 +++++++++++++++++++---------------------------------- root.tmpl | 2 +- upload.go | 4 ++-- usage.go | 6 ++++++ diff --git a/doc/Storage b/doc/Storage index 76d21a944375f8cc34fe702e5995409ce664339fb10c4c3029fdaf8c26e2bfca..64b11fbb2a55d90a7c5af54b748db7e4153100687c64873331f4ee5d7a6c034b 100644 --- a/doc/Storage +++ b/doc/Storage @@ -50,3 +50,13 @@ Each packages release file has mtime set to its upload time. Package's serial is a sum of mtime's of the directory and .metadata.rec (if it exists). Optional .reqpy file contains the PEP-345's Requires-Python string. + + Hashed names + ============ + +-hashed-names option enables hashed directories names usage. +"private-package" becomes: + 5b/bb/084be0364debf741a81516cbf97de062c4c95acabbcaa098da49e7d72f3e +It is BLAKE2b-256 hash of the name, with two subdirectories levels. +Additional "name" file is placed in each package directory with original +name. diff --git a/fileutils.go b/fileutils.go index 6cad06855a3618233d0a58bf4d4da45dbb9181da1ab7babe9a1f6664b487410f..c0d82acb952d1597cbea79b9a6cf707a51b3ec9a578db316dab61e28d5c31f4b 100644 --- a/fileutils.go +++ b/fileutils.go @@ -16,11 +16,14 @@ package main import ( + "encoding/hex" "log" "net/http" "os" "path/filepath" "time" + + "golang.org/x/crypto/blake2b" ) var ( @@ -84,13 +87,47 @@ } return DirSync(dirPath) } -func mkdirForPkg(w http.ResponseWriter, r *http.Request, pkgName string) bool { - path := filepath.Join(Root, pkgName) +type PkgName struct { + n string + fs string +} + +func (p *PkgName) String() string { + return p.n +} + +func hashedName(n string) string { + h := blake2b.Sum256([]byte(n)) + s := hex.EncodeToString(h[:]) + return s[:2] + "/" + s[2:4] + "/" + s[4:] +} + +func (p *PkgName) FS() string { + if p.fs == "" { + if !*HashedNames { + return p.n + } + p.fs = hashedName(p.n) + } + return p.fs +} + +func mkdirForPkg(w http.ResponseWriter, r *http.Request, pkgName PkgName) bool { + path := filepath.Join(Root, pkgName.FS()) if _, err := os.Stat(path); os.IsNotExist(err) { - if err = os.Mkdir(path, os.FileMode(0o777)); err != nil { + if err = os.MkdirAll(path, os.FileMode(0o777)); err != nil { log.Println("error", r.RemoteAddr, "mkdir", pkgName, err) http.Error(w, err.Error(), http.StatusInternalServerError) return false + } + if err = os.WriteFile( + filepath.Join(path, "name"), + append([]byte(pkgName.n), '\n'), + os.FileMode(0o666), + ); err != nil { + os.RemoveAll(path) + log.Println("error", r.RemoteAddr, "save name", pkgName, err) + http.Error(w, err.Error(), http.StatusInternalServerError) } log.Println(r.RemoteAddr, "mkdir", pkgName) } diff --git a/go.mod b/go.mod index c3ebb1530cd847835dad68ac3934da06a0a7a90b6deb1538c3b632e3df9a7654..c8e324447de846ed09a2d85b3637aa5584380da1c60eb3b1028da6b84d4224d8 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ go 1.26.0 require ( go.stargrave.org/recfile/v4 v4.0.0 - golang.org/x/crypto v0.57.0 - golang.org/x/net v0.60.0 + golang.org/x/crypto v0.58.0 + golang.org/x/net v0.61.0 ) -require golang.org/x/sys v0.48.0 // indirect +require golang.org/x/sys v0.49.0 // indirect diff --git a/go.sum b/go.sum index 3332189fdcc4b5e0c6bd3d471f6ef6584c1904ce9ad83a7187dd98994ef48a1a..acffcf3a4ef5b5bf6b9d25b88f37de1c04b940e1fb9156f42284da7274222d4e 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,8 @@ go.stargrave.org/recfile/v4 v4.0.0 h1:v9kZnW/e64oPfOqArGMNZacuT57lDibd24xhEiBDQ/c= go.stargrave.org/recfile/v4 v4.0.0/go.mod h1:IGi8kMociIlDoR8iOssyUG/uix+wmsqvBuiDeQXsIuE= -golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M= -golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA= -golang.org/x/net v0.60.0 h1:79p50tfZlm0J9YfoDsSi639qSXNGVwEzOPLCxM2FsYU= -golang.org/x/net v0.60.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg= -golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo= -golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= +golang.org/x/crypto v0.58.0 h1:COkYLr4k7nDI4r6QtMML2AfzeIswWHAJthLS6K/M/54= +golang.org/x/crypto v0.58.0/go.mod h1:Xh+kl5A+M0gMiWDytH2Hhr5Z7WbNCpv/eB/EFgfSk+w= +golang.org/x/net v0.61.0 h1:RR+6j/BTBCrggOLugxa+66R8FvoN6MHlzDlZIbN9YFw= +golang.org/x/net v0.61.0/go.mod h1:WgDCOTH8iwtB66T4/GfI94AHo/hhdb7Hah9NDseQfiI= +golang.org/x/sys v0.49.0 h1:XbzkgYJHdqh/8m2Uu0W/dQv8nktxx4BFHp1M0gROTXA= +golang.org/x/sys v0.49.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= diff --git a/hr-pkg.tmpl b/hr-pkg.tmpl index 389f61859f24aeb5ed679c22badc5f1d39245274512ec1d1f5b5af7e1f7105ed..de37ec4cc8b8ce3d3934207d10e21182c6f47fff9a7796ab8fe6ac7b85a79cb2 100644 --- a/hr-pkg.tmpl +++ b/hr-pkg.tmpl @@ -65,7 +65,7 @@