From 472849cfd618e6607de6bace8965c8b6e275f245 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Wed, 8 Jul 2026 15:26:42 +0900 Subject: [PATCH] internal/pkg: optionally force implementation entry For validation of build determinism. Signed-off-by: Ophestra --- cmd/mbf/main.go | 11 +++++++++- internal/pkg/pkg.go | 49 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/cmd/mbf/main.go b/cmd/mbf/main.go index a6c74a0f..37f799c8 100644 --- a/cmd/mbf/main.go +++ b/cmd/mbf/main.go @@ -696,6 +696,7 @@ func main() { flagNoReply bool flagFaults bool flagPop bool + flagRebuild bool flagBoot bool flagStd bool @@ -724,7 +725,11 @@ func main() { default: var pathname *check.Absolute err := cm.Do(func(cache *pkg.Cache) (err error) { - pathname, _, err = cache.Cure(a) + if flagRebuild { + pathname, _, err = cache.CureNew(a) + } else { + pathname, _, err = cache.Cure(a) + } return }) if err != nil { @@ -885,6 +890,10 @@ func main() { &flagPop, "pop", command.BoolFlag(false), "Display and destroy the most recent fault entry", + ).Flag( + &flagRebuild, + "rebuild", command.BoolFlag(false), + "Always enter the artifact implementation", ) } diff --git a/internal/pkg/pkg.go b/internal/pkg/pkg.go index 9d32231d..4d1d3f72 100644 --- a/internal/pkg/pkg.go +++ b/internal/pkg/pkg.go @@ -6,6 +6,7 @@ import ( "bytes" "cmp" "context" + "crypto/rand" "crypto/sha512" "encoding/base64" "encoding/binary" @@ -303,7 +304,7 @@ func (c *common) Open(a Artifact) (r io.ReadCloser, err error) { } var pathname *check.Absolute - if pathname, _, _, err = c.cache.cure(a, true); err != nil { + if pathname, _, _, err = c.cache.cure(a, true, false); err != nil { return } @@ -1633,7 +1634,7 @@ func (c *Cache) Cure(a Artifact) ( return } - pathname, checksum, _, err = c.cure(a, true) + pathname, checksum, _, err = c.cure(a, true, false) return } @@ -1651,7 +1652,29 @@ func (c *Cache) CureWhence(a Artifact) ( return } - return c.cure(a, true) + return c.cure(a, true, false) +} + +// CureNew is like Cure, but always enters the implementation. +func (c *Cache) CureNew(a Artifact) ( + pathname *check.Absolute, + checksum unique.Handle[Checksum], + err error, +) { + c.abortMu.RLock() + defer c.abortMu.RUnlock() + + if err = c.toplevel.Load().ctx.Err(); err != nil { + return + } + + var whence int +retry: + pathname, checksum, whence, err = c.cure(a, true, true) + if err != nil || whence == WNew { + return + } + goto retry } // CureError wraps a non-nil error returned attempting to cure an [Artifact]. @@ -2020,13 +2043,19 @@ func WhenceString(whence int) string { // cure implements Cure without acquiring a read lock on abortMu. cure must not // be entered during Abort. -func (c *Cache) cure(a Artifact, curesExempt bool) ( +func (c *Cache) cure(a Artifact, curesExempt, rebuild bool) ( pathname *check.Absolute, checksum unique.Handle[Checksum], whence int, err error, ) { id := c.Ident(a) + if rebuild { + var v ID + _, _ = rand.Read(v[:]) + id = unique.Make(v) + } + ids := Encode(id.Value()) pathname = c.base.Append( dirIdentifier, @@ -2354,7 +2383,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) ( substitutes, ) - if c.flags&CIgnoreSubstitutes == 0 { + if !rebuild && c.flags&CIgnoreSubstitutes == 0 { var substituteChecksum unique.Handle[Checksum] substituteChecksum, err = c.loadSubstitute(substitute) if err != nil { @@ -2419,8 +2448,10 @@ func (c *Cache) cure(a Artifact, curesExempt bool) ( return } else if err = externStatus.Close(); err != nil { return - } else if err = f.linkSubstitute(ids, substitutes); err != nil { - return + } else if !rebuild { + if err = f.linkSubstitute(ids, substitutes); err != nil { + return + } } } return @@ -2432,7 +2463,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) ( err = ca.Cure(&f) c.exitCure(a, curesExempt) - if err == nil { + if !rebuild && err == nil { err = f.linkSubstitute(ids, substitutes) } if err != nil { @@ -2526,7 +2557,7 @@ func (pending *pendingArtifactDep) cure(c *Cache) { defer pending.Done() var err error - pending.resP.pathname, pending.resP.checksum, _, err = c.cure(pending.a, false) + pending.resP.pathname, pending.resP.checksum, _, err = c.cure(pending.a, false, false) if err == nil { return }