aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/pkg/pkg.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-04-03 16:15:50 +0900
committerOphestra <cat@gensokyo.uk>2026-04-03 16:16:55 +0900
commit5093a06026b0f4abe6b16ccf5381a19caf594166 (patch)
treec68bfce417b1ba13b3f0d01ba8849086ec5eb36d /internal/pkg/pkg.go
parent50c1d7f8806de519161bbc07bbc6f73b69f6bece (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.go90
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,