v0.297.0: burn-down round 2 — 24 small rows (R-591 R-568 R-567 R-363 R-547 R-10 R-552 R-251 R-104 R-619 R-362 R-675 R-256 R-257 R-240 R-365 R-425 R-565 R-564 R-603 R-454 R-208 R-457-swept) + the banner countdown and deepCopyStack twins; MinAgent 0.131.0
gates / gates (push) Failing after 50s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-05 20:12:56 +02:00
parent 114ff2761a
commit 1453cfc69b
68 changed files with 3953 additions and 116 deletions
+66
View File
@@ -1210,6 +1210,60 @@ func deepCopyStack(s *Stack) Stack {
cp.Meta.InitialCreds = &icCopy
}
// R-591 follow-up: every other reference in Meta. Pinned by TestDeepCopyStackMetaSharesNoReference,
// which fills every pointer/slice/map reachable from Meta and fails on any the copy still shares —
// so a field added to Metadata later fails there until it is copied here.
cp.Meta.AppInfo.UseCases = cloneStrs(s.Meta.AppInfo.UseCases)
cp.Meta.AppInfo.FirstSteps = cloneStrs(s.Meta.AppInfo.FirstSteps)
cp.Meta.AppInfo.Prerequisites = cloneStrs(s.Meta.AppInfo.Prerequisites)
cp.Meta.FamilyGateExcept = cloneStrs(s.Meta.FamilyGateExcept)
if s.Meta.DataPaths != nil {
cp.Meta.DataPaths = make([]DataPath, len(s.Meta.DataPaths))
copy(cp.Meta.DataPaths, s.Meta.DataPaths)
}
if s.Meta.AfterLoad != nil {
al := *s.Meta.AfterLoad
al.Command = cloneStrs(al.Command)
cp.Meta.AfterLoad = &al
}
if s.Meta.AfterInstall != nil {
ai := *s.Meta.AfterInstall
ai.Env, ai.Command = cloneStrs(ai.Env), cloneStrs(ai.Command)
cp.Meta.AfterInstall = &ai
}
if s.Meta.AfterSetup != nil {
as := *s.Meta.AfterSetup
as.Env = cloneStrMap(as.Env)
as.Args, as.Command = cloneStrs(as.Args), cloneStrs(as.Command)
cp.Meta.AfterSetup = &as
}
if s.Meta.SetupDoneProbe != nil {
sp := *s.Meta.SetupDoneProbe
cp.Meta.SetupDoneProbe = &sp
}
if s.Meta.SMTPMapping != nil {
sm := *s.Meta.SMTPMapping
sm.Extra = cloneStrMap(sm.Extra)
cp.Meta.SMTPMapping = &sm
}
if s.Meta.Backup != nil {
b := *s.Meta.Backup
b.Userdata = append([]appbackup.BindSpec(nil), b.Userdata...)
b.HDD = append([]appbackup.BindSpec(nil), b.HDD...)
b.Import = append([]appbackup.BindSpec(nil), b.Import...)
cp.Meta.Backup = &b
}
// Deep-copy Meta.I18n (R-591): the struct assignment above leaves the map — and every pointer
// and slice inside each overlay — shared with the original. Pinned by
// TestDeepCopyStackI18nIsNotShared.
if s.Meta.I18n != nil {
cp.Meta.I18n = make(map[string]MetadataOverlay, len(s.Meta.I18n))
for lang, ov := range s.Meta.I18n {
cp.Meta.I18n[lang] = ov.Clone()
}
}
return cp
}
@@ -1755,3 +1809,15 @@ func AggregateStateForTest(containers []ContainerInfo) ContainerState {
// SetKeptUnitFinder wires the backup side's removed-app unit lookup (INIT-ONLY; main.go).
func (m *Manager) SetKeptUnitFinder(fn func(app, drive string) string) { m.keptUnitFn = fn }
// cloneStrMap returns a fresh copy of in, keeping nil as nil.
func cloneStrMap(in map[string]string) map[string]string {
if in == nil {
return nil
}
out := make(map[string]string, len(in))
for k, v := range in {
out[k] = v
}
return out
}