forked from rosa/hakurei
internal/pkg: expose cure whence
Useful for cure determinism validation of KindExec. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
+62
-7
@@ -303,7 +303,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); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -356,12 +356,12 @@ func (f *FContext) linkSubstitute(ids, substitutes string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// InvalidLookupError is the identifier of non-dependency [Artifact] looked up
|
||||
// InvalidLookupError is the identifier of non-input [Artifact] looked up
|
||||
// via [FContext.GetArtifact] by a misbehaving [Artifact] implementation.
|
||||
type InvalidLookupError ID
|
||||
|
||||
func (e InvalidLookupError) Error() string {
|
||||
return "attempting to look up non-dependency artifact " + Encode(e)
|
||||
return "attempting to look up non-input artifact " + Encode(e)
|
||||
}
|
||||
|
||||
var _ error = InvalidLookupError{}
|
||||
@@ -602,7 +602,7 @@ type cureRes struct {
|
||||
checksum unique.Handle[Checksum]
|
||||
}
|
||||
|
||||
// A pendingArtifactDep is a dependency [Artifact] pending concurrent curing,
|
||||
// A pendingArtifactDep is an input [Artifact] pending concurrent curing,
|
||||
// subject to the cures limit. Values pointed to by result addresses are safe
|
||||
// to access after the [sync.WaitGroup] associated with this pendingArtifactDep
|
||||
// is done. pendingArtifactDep must not be reused or modified after it is sent
|
||||
@@ -676,7 +676,7 @@ const (
|
||||
// suppressed regardless of [message.Msg] state.
|
||||
CSuppressInit
|
||||
|
||||
// CIgnoreSubstitutes disables content-based dependency substitution.
|
||||
// CIgnoreSubstitutes disables content-based input substitution.
|
||||
CIgnoreSubstitutes
|
||||
|
||||
// CExternShallow arranges for only non-flood inputs to be fetched when
|
||||
@@ -733,7 +733,7 @@ type Cache struct {
|
||||
parent context.Context
|
||||
// For deriving curing context, must not be accessed directly.
|
||||
toplevel atomic.Pointer[toplevel]
|
||||
// For waiting on dependency curing goroutines.
|
||||
// For waiting on input curing goroutines.
|
||||
wg sync.WaitGroup
|
||||
// Reports new cures and passed to [Artifact].
|
||||
msg message.Msg
|
||||
@@ -1633,6 +1633,24 @@ func (c *Cache) Cure(a Artifact) (
|
||||
return
|
||||
}
|
||||
|
||||
pathname, checksum, _, err = c.cure(a, true)
|
||||
return
|
||||
}
|
||||
|
||||
// CureWhence is like Cure, but returns the whence value.
|
||||
func (c *Cache) CureWhence(a Artifact) (
|
||||
pathname *check.Absolute,
|
||||
checksum unique.Handle[Checksum],
|
||||
whence int,
|
||||
err error,
|
||||
) {
|
||||
c.abortMu.RLock()
|
||||
defer c.abortMu.RUnlock()
|
||||
|
||||
if err = c.toplevel.Load().ctx.Err(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return c.cure(a, true)
|
||||
}
|
||||
|
||||
@@ -1971,11 +1989,41 @@ func (e HangingInputError) Error() string {
|
||||
return Encode(unique.Handle[ID](e).Value()) + " is unavailable"
|
||||
}
|
||||
|
||||
const (
|
||||
// WNew indicates a cure entering the implementation.
|
||||
WNew = iota
|
||||
// WCache indicates an [Artifact] present in the cache.
|
||||
WCache
|
||||
// WSubstitute indicates an [Artifact] hitting a content-based input
|
||||
// substitution.
|
||||
WSubstitute
|
||||
// WExternal indicates a cure entering the external cache.
|
||||
WExternal
|
||||
)
|
||||
|
||||
// WhenceString returns a printable string for a whence value.
|
||||
func WhenceString(whence int) string {
|
||||
switch whence {
|
||||
case WNew:
|
||||
return "new"
|
||||
case WCache:
|
||||
return "cache"
|
||||
case WSubstitute:
|
||||
return "substitute"
|
||||
case WExternal:
|
||||
return "external"
|
||||
|
||||
default:
|
||||
return "invalid whence " + strconv.Itoa(whence)
|
||||
}
|
||||
}
|
||||
|
||||
// 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) (
|
||||
pathname *check.Absolute,
|
||||
checksum unique.Handle[Checksum],
|
||||
whence int,
|
||||
err error,
|
||||
) {
|
||||
id := c.Ident(a)
|
||||
@@ -2001,6 +2049,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
)
|
||||
ctx, done, checksum, err = c.loadOrStoreIdent(id)
|
||||
if done == nil {
|
||||
whence = WCache
|
||||
return
|
||||
} else {
|
||||
defer func() { c.finaliseIdent(done, id, checksum, err) }()
|
||||
@@ -2008,6 +2057,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
|
||||
checksum, err = c.tryChecksum(pathname)
|
||||
if err == nil || !errors.Is(err, os.ErrNotExist) {
|
||||
whence = WCache
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2077,6 +2127,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
}
|
||||
}
|
||||
|
||||
whence = WNew
|
||||
if c.msg.IsVerbose() {
|
||||
rn := reportName(a, id)
|
||||
c.msg.Verbosef("curing %s...", rn)
|
||||
@@ -2095,6 +2146,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
// cure FileArtifact outside type switch to skip TContext initialisation
|
||||
if f, ok := a.(FileArtifact); ok {
|
||||
if checksumFi != nil {
|
||||
whence = WCache
|
||||
if !checksumFi.Mode().IsRegular() {
|
||||
// unreachable
|
||||
err = InvalidFileModeError(checksumFi.Mode())
|
||||
@@ -2199,6 +2251,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
}
|
||||
|
||||
if checksumFi != nil {
|
||||
whence = WCache
|
||||
if !checksumFi.Mode().IsDir() {
|
||||
// unreachable
|
||||
err = InvalidFileModeError(checksumFi.Mode())
|
||||
@@ -2308,6 +2361,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
return
|
||||
}
|
||||
if substituteChecksum != zeroChecksum {
|
||||
whence = WSubstitute
|
||||
checksum = substituteChecksum
|
||||
checksums = Encode(checksum.Value())
|
||||
checksumPathname = c.base.Append(
|
||||
@@ -2332,6 +2386,7 @@ func (c *Cache) cure(a Artifact, curesExempt bool) (
|
||||
defer f.destroy(&err)
|
||||
|
||||
if extern {
|
||||
whence = WExternal
|
||||
if checksum != zeroChecksum && externChecksum != checksum {
|
||||
err = &ChecksumMismatchError{externChecksum.Value(), checksum.Value()}
|
||||
if c.msg.IsVerbose() {
|
||||
@@ -2471,7 +2526,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)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user