restic: let a restore point taken by hand go only after a night recorded good, say a missing hand= as a file to push, and say what a failed thinning already let go (novox/hq issue 453)
mesh/merge-gate pass: builds restic → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery delivered

This commit is contained in:
2026-10-11 17:57:43 +02:00
parent 879bc4bca2
commit 7211227c76
8 changed files with 193 additions and 28 deletions
+14 -5
View File
@@ -379,6 +379,9 @@ func (b *Backups) backUp(ctx context.Context, only string, hand bool) (map[strin
for _, d := range chosen {
outcome[d.Module] = b.one(ctx, d, hand)
b.record(d.Module, outcome[d.Module])
if n := outcome[d.Module]; !hand && n.OK && n.Snapshot != "" {
b.recordGoodNight(d.Module, n.Snapshot)
}
}
// A retention that does not read thins nothing: keeping too much costs space, thinning by a value
// nobody meant loses restore points (novox/hq issue 416).
@@ -388,8 +391,13 @@ func (b *Backups) backUp(ctx context.Context, only string, hand bool) (map[strin
thinned.Refused = err.Error()
b.Say("the retention does not read, so nothing is thinned and every restore point is kept: %v", err)
} else if letGo, err := b.thin(ctx, keep); err != nil {
thinned.Kept, thinned.Error = &keep, err.Error()
b.Say("thinning the restore points failed, and every one is kept: %v", err)
thinned.Kept, thinned.Error, thinned.LetGo = &keep, err.Error(), letGo
if len(letGo) > 0 {
b.Say("thinning the restore points failed after letting go %s, taken by hand; every other one is kept: %v",
strings.Join(letGo, ", "), err)
} else {
b.Say("thinning the restore points failed, and every one is kept: %v", err)
}
} else {
thinned.Kept, thinned.OK, thinned.LetGo = &keep, true, letGo
}
@@ -400,7 +408,7 @@ func (b *Backups) backUp(ctx context.Context, only string, hand bool) (map[strin
// thin forgets the restore points taken by hand that are past their days and have a later night of their
// module, by id, then thins the rest by the counts, keeping every one still tagged as taken by hand (novox/hq
// issue 453). It answers the short ids it let go. A list that does not read thins nothing: a restore point
// issue 453). It answers the short ids it let go — on an error of the counts' thinning too, for those are gone. A list that does not read thins nothing: a restore point
// taken by hand is never lost to a list nobody could read.
func (b *Backups) thin(ctx context.Context, keep Retention) ([]string, error) {
snaps, err := b.Snapshots(ctx, "")
@@ -408,7 +416,7 @@ func (b *Backups) thin(ctx context.Context, keep Retention) ([]string, error) {
return nil, fmt.Errorf("the restore points could not be listed: %w", err)
}
var ids, letGo []string
for _, s := range handLetGo(snaps, b.Now(), keep.Hand) {
for _, s := range handLetGo(snaps, b.GoodNights(), b.Now(), keep.Hand) {
ids, letGo = append(ids, s.ID), append(letGo, s.ShortID)
}
if len(ids) > 0 {
@@ -524,6 +532,7 @@ func (b *Backups) BackedUp(ctx context.Context, module string) ([]ModuleBackups,
measured := b.Measurements()
snaps, _ := b.Snapshots(ctx, module)
inForce := b.inForce(ctx)
goodNights := b.GoodNights()
thinned := b.LastRun().Thinned
out := []ModuleBackups{}
listed := map[string]bool{}
@@ -534,7 +543,7 @@ func (b *Backups) BackedUp(ctx context.Context, module string) ([]ModuleBackups,
listed[d.Module] = true
m := ModuleBackups{Module: d.Module, Runs: len(d.Runs), Paths: d.Paths, Retention: inForce, Thinned: thinned,
Data: itemReports(items[d.Module], measured[d.Module], d.Paths, good[d.Module]),
HandTaken: handKept(d.Module, snaps, inForce)}
HandTaken: handKept(d.Module, snaps, goodNights, inForce)}
if n, ok := nights[d.Module]; ok {
m.LastNight = &n
}