Skip to content
Snippets Groups Projects
Commit a873a2e4 authored by q3k's avatar q3k
Browse files

dist: serve targz, update every 5min

parent 24d5a5c1
Branches
No related tags found
No related merge requests found
......@@ -32,6 +32,7 @@ func main() {
http.HandleFunc("/api/releases.json", s.handleReleases)
http.HandleFunc("/api/release/", s.handleReleaseMirror)
http.HandleFunc("/api/apps/zip/", s.handleAppZip)
http.HandleFunc("/api/apps/tar/", s.handleAppTargz)
log.Printf("Listening on %s...", flagListen)
http.ListenAndServe(flagListen, nil)
}
......@@ -35,7 +35,7 @@ func (s *server) run(ctx context.Context) {
log.Fatalf("Initial app fetch failed: %v", err)
}
t := time.NewTicker(60 * time.Second)
t := time.NewTicker(5 * 60 * time.Second)
for {
select {
case r := <-s.reqC:
......
package main
import (
"archive/tar"
"archive/zip"
"bytes"
"compress/gzip"
"context"
"encoding/json"
"fmt"
......@@ -40,6 +42,7 @@ type appInfo struct {
commitObj *object.Commit
zip []byte
targz []byte
}
type GLProject struct {
......@@ -128,6 +131,65 @@ func (s *server) zipApp(ctx context.Context, name, pathInRepo, repo string, obj
return buf.Bytes(), nil
}
func (s *server) targzApp(ctx context.Context, name, pathInRepo, repo string, obj *object.Commit) ([]byte, error) {
fi, err := obj.Files()
if err != nil {
return nil, fmt.Errorf("listing files: %w", err)
}
buf := bytes.NewBuffer(nil)
gz := gzip.NewWriter(buf)
t := tar.NewWriter(gz)
for {
f, err := fi.Next()
if err == io.EOF {
break
}
if err != nil {
return nil, fmt.Errorf("fi.Next: %w", err)
}
prefix := ""
if pathInRepo != "" {
prefix = pathInRepo + "/"
}
if !strings.HasPrefix(f.Name, prefix) {
continue
}
if !f.Mode.IsFile() {
continue
}
p := f.Name[len(prefix):]
prefix = strings.ReplaceAll(repo, "/", "-")
outPath := path.Join(prefix, p)
err = t.WriteHeader(&tar.Header{
Name: outPath,
Typeflag: tar.TypeReg,
Size: f.Size,
})
if err != nil {
return nil, fmt.Errorf("Create(%q): %w", outPath, err)
}
if f.Size+int64(buf.Len()) > 10<<20 {
return nil, fmt.Errorf("archive too large")
}
rdr, err := f.Blob.Reader()
if err != nil {
return nil, fmt.Errorf("Blob.Reader: %w", err)
}
_, err = io.Copy(t, rdr)
rdr.Close()
if err != nil {
return nil, fmt.Errorf("when copying: %w", err)
}
}
if err := t.Close(); err != nil {
return nil, fmt.Errorf("when closing tar: %w", err)
}
if err := gz.Close(); err != nil {
return nil, fmt.Errorf("when closing gz: %w", err)
}
return buf.Bytes(), nil
}
func (s *server) parseAppToml(ctx context.Context, pathInRepo string, obj *object.Commit) (*appInfo, error) {
p := path.Join(pathInRepo, "flow3r.toml")
f, err := obj.File(p)
......@@ -268,6 +330,11 @@ func (s *server) getAppInfo(ctx context.Context, pathInRepo, repo string) (*appI
return nil, fmt.Errorf("zipping failed: %w", err)
}
app.zip = zbytes
tbytes, err := s.targzApp(ctx, app.name, pathInRepo, repo, app.commitObj)
if err != nil {
return nil, fmt.Errorf("targzing failed: %w", err)
}
app.targz = tbytes
return app, nil
}
......@@ -376,6 +443,7 @@ func (s *server) handleApps(w http.ResponseWriter, r *http.Request) {
RepoURL string `json:"repoUrl"`
Commit string `json:"commit"`
DownloadURL string `json:"downloadUrl"`
TarDownloadURL string `json:"tarDownloadUrl"`
Name string `json:"name"`
Menu string `json:"menu"`
Author string `json:"author"`
......@@ -401,6 +469,7 @@ func (s *server) handleApps(w http.ResponseWriter, r *http.Request) {
RepoURL: "https://git.flow3r.garden/" + a.repository,
Commit: a.appInfo.commit,
DownloadURL: fmt.Sprintf("%sapps/zip/%s.zip", flagBaseURL, a.repository),
TarDownloadURL: fmt.Sprintf("%sapps/tar/%s.tar.gz", flagBaseURL, a.repository),
Name: a.appInfo.name,
Menu: a.appInfo.menu,
Author: a.appInfo.author,
......@@ -416,7 +485,8 @@ func (s *server) handleApps(w http.ResponseWriter, r *http.Request) {
}
var (
reAppZipURL = regexp.MustCompile("^/api/apps/zip/([^/]+)/([^/]+).zip$")
reAppZipURL = regexp.MustCompile(`^/api/apps/zip/([^/]+)/([^/]+)\.zip$`)
reAppTargzURL = regexp.MustCompile(`^/api/apps/tar/([^/]+)/([^/]+)\.tar\.gz$`)
)
func (s *server) handleAppZip(w http.ResponseWriter, r *http.Request) {
......@@ -445,3 +515,30 @@ func (s *server) handleAppZip(w http.ResponseWriter, r *http.Request) {
http.NotFound(w, r)
}
func (s *server) handleAppTargz(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
matches := reAppTargzURL.FindStringSubmatch(r.URL.Path)
if matches == nil {
http.NotFound(w, r)
return
}
orga := matches[1]
repo := matches[2]
apps, err := s.getApps(ctx)
if err != nil {
return
}
for _, app := range apps {
if app.repository == fmt.Sprintf("%s/%s", orga, repo) {
w.Header().Add("Content-Type", "application/x-gzip")
w.Write(app.appInfo.targz)
return
}
}
http.NotFound(w, r)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment