internal/pkg: optional shallow external cure
Test / Create distribution (push) Successful in 1m0s
Test / Sandbox (push) Successful in 2m54s
Test / ShareFS (push) Successful in 4m6s
Test / Hakurei (push) Successful in 4m12s
Test / Sandbox (race detector) (push) Successful in 5m49s
Test / Hakurei (race detector) (push) Successful in 6m51s
Test / Flake checks (push) Successful in 1m22s

This saves time and is often more practical even for package maintainers.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
2026-07-07 16:35:08 +09:00
parent b08feac26c
commit aa5d38981d
3 changed files with 258 additions and 32 deletions
+20 -19
View File
@@ -90,7 +90,7 @@ type IContext struct {
// returns and must not be exposed directly.
w io.Writer
// Optional [Artifact] to cureRes cache, replaces [IRKindIdent] with
// checksum values if non-nil.
// checksum values if non-nil. The pathname field may not be populated.
inputs map[Artifact]cureRes
}
@@ -173,7 +173,7 @@ func (i *IContext) mustWrite(p []byte) {
// WriteIdent writes the identifier of [Artifact] to the IR. The behaviour of
// WriteIdent is not defined for an [Artifact] not part of the slice returned by
// [Artifact.Dependencies].
// [Artifact.Inputs].
func (i *IContext) WriteIdent(a Artifact) {
buf := i.ic.getIdentBuf()
defer i.ic.putIdentBuf(buf)
@@ -235,7 +235,8 @@ func (ic *irCache) Encode(w io.Writer, a Artifact) (err error) {
}
// encode implements Encode but replaces identifiers with their cured checksums
// for a non-nil ident. Caller must acquire Cache.identMu.
// for a non-nil ident. The pathname field is unused. Caller must acquire
// Cache.identMu.
func (ic *irCache) encode(
w io.Writer,
a Artifact,
@@ -432,9 +433,9 @@ type (
// Common buffer for word-sized reads.
buf [wordSize]byte
// Dependencies sent before params, sorted by identifier. Resliced on
// Inputs sent before params, sorted by identifier. Resliced on
// each call to Next and checked to be depleted during Finalise.
deps []*extIdent
inputs []*extIdent
// Number of values already read, -1 denotes a finalised IRReader.
count int
@@ -518,7 +519,7 @@ const (
irMaxValues = 1 << 12
// irMaxDeps is the arbitrary maximum number of direct dependencies allowed
// to be returned by [Artifact.Dependencies] and subsequently decoded by
// to be returned by [Artifact.Inputs] and subsequently decoded by
// [IRDecoder].
irMaxDeps = 1 << 10
)
@@ -603,17 +604,17 @@ func (ir *IRReader) mustReadHeader(k IRValueKind) {
// putAll returns all dependency buffers to the underlying [Cache].
func (ir *IRReader) putAll() {
for _, buf := range ir.deps {
for _, buf := range ir.inputs {
ir.d.c.putIdentBuf(buf)
}
ir.deps = nil
ir.inputs = nil
}
// DiscardAll discards all unstructured dependencies. This is useful to
// implementations that encode dependencies as [IRKindIdent] which are read back
// via ReadIdent.
func (ir *IRReader) DiscardAll() {
if ir.deps == nil {
if ir.inputs == nil {
panic("attempting to discard dependencies twice")
}
ir.putAll()
@@ -625,13 +626,13 @@ var ErrDependencyDepleted = errors.New("reading past end of dependencies")
// Next returns the next unstructured dependency.
func (ir *IRReader) Next() Artifact {
if len(ir.deps) == 0 {
if len(ir.inputs) == 0 {
panic(ErrDependencyDepleted)
}
id := unique.Make(ID(ir.deps[0][wordSize:]))
ir.d.c.putIdentBuf(ir.deps[0])
ir.deps = ir.deps[1:]
id := unique.Make(ID(ir.inputs[0][wordSize:]))
ir.d.c.putIdentBuf(ir.inputs[0])
ir.inputs = ir.inputs[1:]
if a, ok := ir.d.ident[id]; !ok {
ir.putAll()
@@ -684,8 +685,8 @@ func (ir *IRReader) Finalise() (checksum unique.Handle[Checksum], ok bool) {
}
ir.r, ir.ibw = nil, nil
if len(ir.deps) != 0 {
panic(MissedDependencyError(len(ir.deps)))
if len(ir.inputs) != 0 {
panic(MissedDependencyError(len(ir.inputs)))
}
return
@@ -778,11 +779,11 @@ func (d *IRDecoder) decode() (a Artifact, err error) {
err = ErrIRDepend
return
}
ir.deps = make([]*extIdent, sz)
for i := range ir.deps {
ir.deps[i] = d.c.getIdentBuf()
ir.inputs = make([]*extIdent, sz)
for i := range ir.inputs {
ir.inputs[i] = d.c.getIdentBuf()
}
for _, buf := range ir.deps {
for _, buf := range ir.inputs {
ir.mustRead(buf[:])
}