// Program history — the box half of D2 (spec §3.2). Every Go main package // path this box has pointed live for a route, in the bake directory. A build // whose program is in its route's history is never "the wrong program", which // is what lets a deliberate A -> B change be rolled back to A. package release import ( "encoding/json" "path/filepath" "slices" "strings" "github.com/carlosframework/platform/internal/safefile" ) func programPath(bakeDir, host string) string { return filepath.Join(bakeDir, "programs", host+".json") } func ReadPrograms(bakeDir, host string) []string { if strings.ContainsAny(host, `/\`) { return nil } b, err := safefile.ReadFile(programPath(bakeDir, host)) if err != nil { return nil } var rec struct { Programs []string `json:"programs"` } if json.Unmarshal(b, &rec) != nil { return nil } return rec.Programs } func RecordProgram(bakeDir, host, program string) error { if program == "" || strings.ContainsAny(host, `/\`) { return nil } have := ReadPrograms(bakeDir, host) if slices.Contains(have, program) { return nil } b, err := json.Marshal(struct { Schema int `json:"schema"` Programs []string `json:"programs"` }{1, append(have, program)}) if err != nil { return err } p := programPath(bakeDir, host) if err := safefile.MkdirAll(filepath.Dir(p), 0o755); err != nil { return err } return safefile.WriteFile(p, b, 0o644) }