From cd4d0548873c3319e452bd98e258aa5feccec611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zlatko=20=C4=8Calu=C5=A1i=C4=87?= Date: Mon, 22 Jan 2018 17:13:01 +0100 Subject: [PATCH] Introduce ListBlobsV2() Returns not only blob names, but also their sizes. References: https://github.com/restic/restic/issues/1567 https://github.com/restic/restic/pull/1571 --- handlers.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++ mux.go | 2 ++ 2 files changed, 62 insertions(+) diff --git a/handlers.go b/handlers.go index 262c3b6..f4299a6 100644 --- a/handlers.go +++ b/handlers.go @@ -308,6 +308,66 @@ func ListBlobs(w http.ResponseWriter, r *http.Request) { _, _ = w.Write(data) } +// Blob represents a single blob, its name and its size. +type Blob struct { + Name string `json:"name"` + Size int64 `json:"size"` +} + +// ListBlobsV2 lists all blobs of a given type, together with their sizes, in an arbitrary order. +func ListBlobsV2(w http.ResponseWriter, r *http.Request) { + if Config.Debug { + log.Println("ListBlobsV2()") + } + fileType := pat.Param(r, "type") + path, err := getPath(r, fileType) + if err != nil { + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + + items, err := ioutil.ReadDir(path) + if err != nil { + if Config.Debug { + log.Print(err) + } + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return + } + + var blobs []Blob + for _, i := range items { + if isHashed(fileType) { + subpath := filepath.Join(path, i.Name()) + var subitems []os.FileInfo + subitems, err = ioutil.ReadDir(subpath) + if err != nil { + if Config.Debug { + log.Print(err) + } + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return + } + for _, f := range subitems { + blobs = append(blobs, Blob{Name: f.Name(), Size: f.Size()}) + } + } else { + blobs = append(blobs, Blob{Name: i.Name(), Size: i.Size()}) + } + } + + data, err := json.Marshal(blobs) + if err != nil { + if Config.Debug { + log.Print(err) + } + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + + _, _ = w.Write(data) +} + // CheckBlob tests whether a blob exists. func CheckBlob(w http.ResponseWriter, r *http.Request) { if Config.Debug { diff --git a/mux.go b/mux.go index 591f8b3..307a403 100644 --- a/mux.go +++ b/mux.go @@ -72,6 +72,8 @@ func NewMux() *goji.Mux { mux.HandleFunc(pat.Post("/:repo/config"), SaveConfig) mux.HandleFunc(pat.Delete("/config"), DeleteConfig) mux.HandleFunc(pat.Delete("/:repo/config"), DeleteConfig) + mux.HandleFunc(pat.Get("/v2/:type/"), ListBlobsV2) + mux.HandleFunc(pat.Get("/v2/:repo/:type/"), ListBlobsV2) mux.HandleFunc(pat.Get("/:type/"), ListBlobs) mux.HandleFunc(pat.Get("/:repo/:type/"), ListBlobs) mux.HandleFunc(pat.Head("/:type/:name"), CheckBlob)