internal/pkg: pass cure context as single value
All checks were successful
Test / Create distribution (push) Successful in 43s
Test / Sandbox (push) Successful in 2m30s
Test / ShareFS (push) Successful in 3m45s
Test / Hpkg (push) Successful in 4m32s
Test / Sandbox (race detector) (push) Successful in 5m3s
Test / Hakurei (race detector) (push) Successful in 5m55s
Test / Hakurei (push) Successful in 2m40s
Test / Flake checks (push) Successful in 1m52s
All checks were successful
Test / Create distribution (push) Successful in 43s
Test / Sandbox (push) Successful in 2m30s
Test / ShareFS (push) Successful in 3m45s
Test / Hpkg (push) Successful in 4m32s
Test / Sandbox (race detector) (push) Successful in 5m3s
Test / Hakurei (race detector) (push) Successful in 5m55s
Test / Hakurei (push) Successful in 2m40s
Test / Flake checks (push) Successful in 1m52s
This cleans up the function signature and makes backwards compatible API changes possible. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -53,9 +53,36 @@ func MustDecode(s string) Checksum {
|
||||
}
|
||||
}
|
||||
|
||||
// CacheDataFunc tries to load [File] from [Cache], and if that fails, obtains
|
||||
// it via [File.Data] instead.
|
||||
type CacheDataFunc func(f File) (data []byte, err error)
|
||||
// CureContext is passed to [Artifact.Cure] and contains information and methods
|
||||
// useful for curing the [Artifact], like requesting the data of [File], or that
|
||||
// other artifacts be cured.
|
||||
//
|
||||
// Methods of CureContext are safe for concurrent use. CureContext is valid
|
||||
// until [Artifact.Cure] returns.
|
||||
type CureContext struct {
|
||||
// Address of underlying [Cache], should be zeroed after [Artifact.Cure]
|
||||
// returns and must not be exposed directly.
|
||||
cache *Cache
|
||||
|
||||
// Populated during [Cache.Cure].
|
||||
work, temp *check.Absolute
|
||||
}
|
||||
|
||||
// GetWorkDir returns a pathname to a directory which [Artifact] is expected to
|
||||
// write its output to. This is not the final resting place of the [Artifact]
|
||||
// and this pathname should not be directly referred to in the final contents.
|
||||
func (c *CureContext) GetWorkDir() *check.Absolute { return c.work }
|
||||
|
||||
// GetTempDir returns a pathname which implementations may use as scratch space.
|
||||
// A directory is not created automatically, implementations are expected to
|
||||
// create it if they wish to use it, using [os.MkdirAll].
|
||||
func (c *CureContext) GetTempDir() *check.Absolute { return c.temp }
|
||||
|
||||
// LoadData tries to load [File] from [Cache], and if that fails, obtains it via
|
||||
// [File.Data] instead. Notably, it does not cure [File].
|
||||
func (c *CureContext) LoadData(f File) (data []byte, err error) {
|
||||
return c.cache.loadData(f)
|
||||
}
|
||||
|
||||
// An Artifact is a read-only reference to a piece of data that may be created
|
||||
// deterministically but might not currently be available in memory or on the
|
||||
@@ -83,18 +110,15 @@ type Artifact interface {
|
||||
// Result must remain identical across multiple invocations.
|
||||
Dependencies() []Artifact
|
||||
|
||||
// Cure cures the current [Artifact] to the caller-specified temporary
|
||||
// pathname. This is not the final resting place of the [Artifact] and this
|
||||
// pathname should not be directly referred to in the final contents.
|
||||
// Cure cures the current [Artifact] to the working directory obtained via
|
||||
// [CureContext.GetWorkDir].
|
||||
//
|
||||
// If the implementation produces a single file, it must implement [File]
|
||||
// as well. In that case, Cure must produce a single regular file with
|
||||
// contents identical to that returned by [File.Data].
|
||||
//
|
||||
// Implementations may use temp as scratch space. The caller is not required
|
||||
// to create a directory here, implementations are expected to create it if
|
||||
// they wish to use it, using [os.MkdirAll].
|
||||
Cure(work, temp *check.Absolute, loadData CacheDataFunc) (err error)
|
||||
// Implementations must not retain c.
|
||||
Cure(c *CureContext) (err error)
|
||||
}
|
||||
|
||||
// KnownIdent is optionally implemented by [Artifact] and is used instead of
|
||||
@@ -515,7 +539,7 @@ func (c *Cache) finaliseIdent(
|
||||
close(done)
|
||||
}
|
||||
|
||||
// loadData provides [CacheDataFunc] for [Artifact.Cure].
|
||||
// loadData provides [CureContext.LoadData] for [Artifact.Cure].
|
||||
func (c *Cache) loadData(f File) (data []byte, err error) {
|
||||
var r *os.File
|
||||
if kc, ok := f.(KnownChecksum); ok {
|
||||
@@ -790,10 +814,14 @@ func (c *Cache) Cure(a Artifact) (
|
||||
return
|
||||
}
|
||||
|
||||
workPathname := c.base.Append(dirWork, ids)
|
||||
cc := CureContext{
|
||||
cache: c,
|
||||
work: c.base.Append(dirWork, ids),
|
||||
temp: c.base.Append(dirTemp, ids),
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
chmodErr, removeErr := removeAll(workPathname)
|
||||
chmodErr, removeErr := removeAll(cc.work)
|
||||
if chmodErr != nil || removeErr != nil {
|
||||
err = errors.Join(err, chmodErr, removeErr)
|
||||
} else if errors.Is(err, os.ErrExist) {
|
||||
@@ -803,17 +831,17 @@ func (c *Cache) Cure(a Artifact) (
|
||||
}
|
||||
}()
|
||||
|
||||
tempPathname := c.base.Append(dirTemp, ids)
|
||||
if err = a.Cure(workPathname, tempPathname, c.loadData); err != nil {
|
||||
if err = a.Cure(&cc); err != nil {
|
||||
return
|
||||
}
|
||||
if chmodErr, removeErr := removeAll(tempPathname); chmodErr != nil || removeErr != nil {
|
||||
cc.cache = nil
|
||||
if chmodErr, removeErr := removeAll(cc.temp); chmodErr != nil || removeErr != nil {
|
||||
err = errors.Join(err, chmodErr, removeErr)
|
||||
return
|
||||
}
|
||||
|
||||
var fi os.FileInfo
|
||||
if fi, err = os.Lstat(workPathname.String()); err != nil {
|
||||
if fi, err = os.Lstat(cc.work.String()); err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
err = NoOutputError{}
|
||||
}
|
||||
@@ -831,7 +859,7 @@ func (c *Cache) Cure(a Artifact) (
|
||||
|
||||
var gotChecksum Checksum
|
||||
if gotChecksum, err = HashFS(
|
||||
dotOverrideFS{os.DirFS(workPathname.String()).(dirFS)},
|
||||
dotOverrideFS{os.DirFS(cc.work.String()).(dirFS)},
|
||||
".",
|
||||
); err != nil {
|
||||
return
|
||||
@@ -854,12 +882,12 @@ func (c *Cache) Cure(a Artifact) (
|
||||
}
|
||||
}
|
||||
|
||||
if err = os.Chmod(workPathname.String(), 0700); err != nil {
|
||||
if err = os.Chmod(cc.work.String(), 0700); err != nil {
|
||||
return
|
||||
}
|
||||
c.checksumMu.Lock()
|
||||
if err = os.Rename(
|
||||
workPathname.String(),
|
||||
cc.work.String(),
|
||||
checksumPathname.String(),
|
||||
); err != nil {
|
||||
if !errors.Is(err, os.ErrExist) {
|
||||
|
||||
Reference in New Issue
Block a user