diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-04-03 16:15:50 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-04-03 16:16:55 +0900 |
| commit | 5093a06026b0f4abe6b16ccf5381a19caf594166 (patch) | |
| tree | c68bfce417b1ba13b3f0d01ba8849086ec5eb36d /internal/pkg/pkg.go | |
| parent | 50c1d7f8806de519161bbc07bbc6f73b69f6bece (diff) | |
internal/pkg: cache flags
This is cleaner for extending the API.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/pkg/pkg.go')
| -rw-r--r-- | internal/pkg/pkg.go | 90 |
1 files changed, 25 insertions, 65 deletions
diff --git a/internal/pkg/pkg.go b/internal/pkg/pkg.go index ea7ac815..a542f3d2 100644 --- a/internal/pkg/pkg.go +++ b/internal/pkg/pkg.go @@ -13,7 +13,6 @@ import ( "hash" "io" "io/fs" - "iter" "maps" "os" "path/filepath" @@ -331,23 +330,6 @@ type FloodArtifact interface { Artifact } -// Flood returns an iterator over the dependency tree of an [Artifact]. -func Flood(a Artifact) iter.Seq[Artifact] { - return func(yield func(Artifact) bool) { - for _, d := range a.Dependencies() { - if !yield(d) { - return - } - - for d0 := range Flood(d) { - if !yield(d0) { - return - } - } - } - } -} - // TrivialArtifact refers to an [Artifact] that cures without requiring that // any other [Artifact] is cured before it. Its dependency tree is ignored after // computing its identifier. @@ -506,6 +488,23 @@ type pendingArtifactDep struct { *sync.WaitGroup } +const ( + // CValidateKnown arranges for [KnownChecksum] outcomes to be validated to + // match its intended checksum. + // + // A correct implementation of [KnownChecksum] does not successfully cure + // with output not matching its intended checksum. When an implementation + // fails to perform this validation correctly, the on-disk format enters + // an inconsistent state (correctable by [Cache.Scrub]). + // + // This flag causes [Cache.Cure] to always compute the checksum, and reject + // a cure if it does not match the intended checksum. + // + // This behaviour significantly reduces performance and is not recommended + // outside of testing a custom [Artifact] implementation. + CValidateKnown = 1 << iota +) + // Cache is a support layer that implementations of [Artifact] can use to store // cured [Artifact] data in a content addressed fashion. type Cache struct { @@ -525,12 +524,8 @@ type Cache struct { // Directory where all [Cache] related files are placed. base *check.Absolute - - // Whether to validate [FileArtifact.Cure] for a [KnownChecksum] file. This - // significantly reduces performance. - strict bool - // Maximum size of a dependency graph. - threshold uintptr + // Immutable cure options set by [Open]. + flags int // Artifact to [unique.Handle] of identifier cache. artifact sync.Map @@ -563,22 +558,6 @@ type Cache struct { inExec atomic.Bool } -// IsStrict returns whether the [Cache] strictly verifies checksums. -func (c *Cache) IsStrict() bool { return c.strict } - -// SetStrict sets whether the [Cache] strictly verifies checksums, even when -// the implementation promises to validate them internally. This significantly -// reduces performance and is not recommended outside of testing. -// -// This method is not safe for concurrent use with any other method. -func (c *Cache) SetStrict(strict bool) { c.strict = strict } - -// SetThreshold imposes a maximum size on the dependency graph, checked on every -// call to Cure. The zero value disables this check entirely. -// -// This method is not safe for concurrent use with any other method. -func (c *Cache) SetThreshold(threshold uintptr) { c.threshold = threshold } - // extIdent is a [Kind] concatenated with [ID]. type extIdent [wordSize + len(ID{})]byte @@ -1229,14 +1208,6 @@ func (e InvalidArtifactError) Error() string { return "artifact " + Encode(e) + " cannot be cured" } -// DependencyError refers to an artifact with a dependency tree larger than the -// threshold specified by a previous call to [Cache.SetThreshold]. -type DependencyError struct{ A Artifact } - -func (e DependencyError) Error() string { - return "artifact has too many dependencies" -} - // Cure cures the [Artifact] and returns its pathname and [Checksum]. Direct // calls to Cure are not subject to the cures limit. func (c *Cache) Cure(a Artifact) ( @@ -1252,18 +1223,6 @@ func (c *Cache) Cure(a Artifact) ( default: } - if c.threshold > 0 { - var n uintptr - for range Flood(a) { - if n == c.threshold { - err = DependencyError{a} - return - } - n++ - } - c.msg.Verbosef("visited %d artifacts", n) - } - return c.cure(a, true) } @@ -1586,7 +1545,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) ( } r, err = f.Cure(&RContext{common{c}}) if err == nil { - if checksumPathname == nil || c.IsStrict() { + if checksumPathname == nil || c.flags&CValidateKnown != 0 { h := sha512.New384() hbw := c.getWriter(h) _, err = io.Copy(w, io.TeeReader(r, hbw)) @@ -1603,7 +1562,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) ( if checksumPathname == nil { checksum = unique.Make(Checksum(buf[:])) checksums = Encode(Checksum(buf[:])) - } else if c.IsStrict() { + } else if c.flags&CValidateKnown != 0 { if got := Checksum(buf[:]); got != checksum.Value() { err = &ChecksumMismatchError{ Got: got, @@ -1841,10 +1800,10 @@ func (c *Cache) Close() { func Open( ctx context.Context, msg message.Msg, - cures int, + flags, cures int, base *check.Absolute, ) (*Cache, error) { - return open(ctx, msg, cures, base, true) + return open(ctx, msg, flags, cures, base, true) } // open implements Open but allows omitting the [lockedfile] lock when called @@ -1852,7 +1811,7 @@ func Open( func open( ctx context.Context, msg message.Msg, - cures int, + flags, cures int, base *check.Absolute, lock bool, ) (*Cache, error) { @@ -1874,6 +1833,7 @@ func open( c := Cache{ cures: make(chan struct{}, cures), + flags: flags, msg: msg, base: base, |
