carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1// Program history — the box half of D2 (spec §3.2). Every Go main package
2// path this box has pointed live for a route, in the bake directory. A build
3// whose program is in its route's history is never "the wrong program", which
4// is what lets a deliberate A -> B change be rolled back to A.
5package release
6
7import (
8 "encoding/json"
9 "path/filepath"
10 "slices"
11 "strings"
12
13 "github.com/carlosframework/platform/internal/safefile"
14)
15
16func programPath(bakeDir, host string) string {
17 return filepath.Join(bakeDir, "programs", host+".json")
18}
19
20func ReadPrograms(bakeDir, host string) []string {
21 if strings.ContainsAny(host, `/\`) {
22 return nil
23 }
24 b, err := safefile.ReadFile(programPath(bakeDir, host))
25 if err != nil {
26 return nil
27 }
28 var rec struct {
29 Programs []string `json:"programs"`
30 }
31 if json.Unmarshal(b, &rec) != nil {
32 return nil
33 }
34 return rec.Programs
35}
36
37func RecordProgram(bakeDir, host, program string) error {
38 if program == "" || strings.ContainsAny(host, `/\`) {
39 return nil
40 }
41 have := ReadPrograms(bakeDir, host)
42 if slices.Contains(have, program) {
43 return nil
44 }
45 b, err := json.Marshal(struct {
46 Schema int `json:"schema"`
47 Programs []string `json:"programs"`
48 }{1, append(have, program)})
49 if err != nil {
50 return err
51 }
52 p := programPath(bakeDir, host)
53 if err := safefile.MkdirAll(filepath.Dir(p), 0o755); err != nil {
54 return err
55 }
56 return safefile.WriteFile(p, b, 0o644)
57}
58