chore: migrate mail themes to shared framework and locked upstream inputs
This commit is contained in:
1 parent
5c0589f6f6
commit
fec3ace600
225 files changed
+4718
-15807
No files matched your search
@@ -0,0 +1,139 @@
|
||||
package upstream
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
func CacheDir(root string) string { return filepath.Join(root, "build", "upstream") }
|
||||
|
||||
func ReadLock(root string) (Lock, error) {
|
||||
var lock Lock
|
||||
b, err := os.ReadFile(filepath.Join(root, "gitea.lock.json"))
|
||||
if err != nil {
|
||||
return lock, err
|
||||
}
|
||||
if err = json.Unmarshal(b, &lock); err != nil {
|
||||
return lock, err
|
||||
}
|
||||
return lock, lock.validateIdentity()
|
||||
}
|
||||
|
||||
func LoadPinned(root string) (*Snapshot, error) {
|
||||
lock, err := ReadLock(root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s, err := Load(CacheDir(root))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !reflect.DeepEqual(lock, s.Lock) {
|
||||
return nil, fmt.Errorf("upstream cache differs from gitea.lock.json; run upstream prepare after reviewing the lock")
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Prepare fetches immutable commit files only if the cache is absent. A corrupt
|
||||
// cache is an error, not permission to silently replace local evidence.
|
||||
func Prepare(ctx context.Context, root string) (*Snapshot, error) {
|
||||
return prepareFrom(ctx, root, "https://raw.githubusercontent.com/go-gitea/gitea/")
|
||||
}
|
||||
|
||||
func prepareFrom(ctx context.Context, root, rawBase string) (*Snapshot, error) {
|
||||
lock, err := ReadLock(root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err = os.Stat(filepath.Join(CacheDir(root), "lock.json")); err == nil {
|
||||
return LoadPinned(root)
|
||||
} else if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
client := &http.Client{Timeout: 45 * time.Second}
|
||||
s := &Snapshot{Lock: lock, Files: map[string][]byte{}}
|
||||
for name, hash := range lock.Files {
|
||||
if !SafePath(name) {
|
||||
return nil, fmt.Errorf("unsafe locked path %q", name)
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, rawBase+lock.Commit+"/"+name, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("User-Agent", "GiteaMailTemplates-locked-cache")
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, readErr := io.ReadAll(io.LimitReader(resp.Body, 16<<20))
|
||||
resp.Body.Close()
|
||||
if readErr != nil {
|
||||
return nil, readErr
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("%s: HTTP %d", name, resp.StatusCode)
|
||||
}
|
||||
if Digest(b) != hash {
|
||||
return nil, fmt.Errorf("download checksum mismatch: %s", name)
|
||||
}
|
||||
s.Files[name] = b
|
||||
}
|
||||
if err = s.validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dir := CacheDir(root)
|
||||
if err = os.MkdirAll(filepath.Dir(dir), 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stage, err := os.MkdirTemp(filepath.Dir(dir), ".upstream-cache-")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer os.RemoveAll(stage)
|
||||
for name, b := range s.Files {
|
||||
target := filepath.Join(stage, filepath.FromSlash(name))
|
||||
if err = os.MkdirAll(filepath.Dir(target), 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = os.WriteFile(target, b, 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
b, _ := json.MarshalIndent(lock, "", " ")
|
||||
if err = os.WriteFile(filepath.Join(stage, "lock.json"), append(b, '\n'), 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err = os.Stat(dir); err == nil {
|
||||
return nil, fmt.Errorf("incomplete upstream cache exists at %s; inspect it before removing it", dir)
|
||||
}
|
||||
if err = os.Rename(stage, dir); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("[PASS] Downloaded locked Gitea %s (%s) to build cache\n", lock.Tag, lock.Commit)
|
||||
return LoadPinned(root)
|
||||
}
|
||||
|
||||
func SyncRoot(ctx context.Context, tag, root string) error {
|
||||
if err := os.MkdirAll(filepath.Join(root, "build"), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Sync(ctx, tag, CacheDir(root)); err != nil {
|
||||
return err
|
||||
}
|
||||
s, err := Load(CacheDir(root))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b, err := json.MarshalIndent(s.Lock, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(filepath.Join(root, "gitea.lock.json"), append(b, '\n'), 0644)
|
||||
}
|
||||
Reference in new issue
Block a user