diff --git a/internal/pkg/pkg.go b/internal/pkg/pkg.go index 03528cc0..b81abe08 100644 --- a/internal/pkg/pkg.go +++ b/internal/pkg/pkg.go @@ -509,36 +509,32 @@ const ( ) const ( - // fileLock is the file name appended to Cache.base for guaranteeing - // exclusive access to the cache directory. + // fileLock is the lock file for exclusive access to the cache directory. fileLock = "lock" - // fileVariant is the file name appended to Cache.base holding the variant - // identification string set by a prior call to [SetExtension]. + // fileVariant is a file holding the variant identification string set by a + // prior call to [SetExtension]. fileVariant = "variant" - // dirSubstitute is the directory name appended to Cache.base for linking - // artifacts named after their substitute identifier. + // dirSubstitute holds symlinks to artifacts by checksum, named after their + // substitute identifier. dirSubstitute = "substitute" - // dirIdentifier is the directory name appended to Cache.base for storing - // artifacts named after their [ID]. + // dirIdentifier holds symlinks to artifacts by checksum, named after their + // IR-based identifier. dirIdentifier = "identifier" - // dirChecksum is the directory name appended to Cache.base for storing - // artifacts named after their [Checksum]. + // dirChecksum holds artifacts named after their [Checksum]. dirChecksum = "checksum" - // dirStatus is the directory name appended to Cache.base for storing - // artifact metadata and logs named after their [ID]. + // dirStatus holds artifact metadata and logs named after their IR-based + // identifier. For [FloodArtifact], the same file is also available under + // its substitute identifier. dirStatus = "status" - // dirWork is the directory name appended to Cache.base for working - // pathnames set up during [Cache.Cure]. + // dirWork holds working pathnames set up during [Cache.Cure]. dirWork = "work" - // dirTemp is the directory name appended to Cache.base for scratch space - // pathnames allocated during [Cache.Cure]. + // dirTemp holds scratch space allocated during [Cache.Cure]. dirTemp = "temp" - // dirExecScratch is the directory name appended to Cache.base for scratch - // space setting up the container started by [Cache.EnterExec]. Exclusivity - // via Cache.inExec. + // dirExecScratch is scratch space set up for the container started by + // [Cache.EnterExec]. Exclusivity via Cache.inExec. dirExecScratch = "scratch" // checksumLinknamePrefix is prepended to the encoded [Checksum] value @@ -1995,10 +1991,11 @@ func (c *Cache) cure(a Artifact, curesExempt bool) ( buf := c.getIdentBuf() sh.Sum(buf[wordSize:wordSize]) substitute = unique.Make(ID(buf[wordSize:])) + substitutes := Encode(substitute.Value()) c.putIdentBuf(buf) alternative = c.base.Append( dirSubstitute, - Encode(substitute.Value()), + substitutes, ) if c.flags&CIgnoreSubstitutes == 0 { @@ -2014,6 +2011,17 @@ func (c *Cache) cure(a Artifact, curesExempt bool) ( dirChecksum, checksums, ) + if _, err = os.Lstat(c.base.Append( + dirStatus, + substitutes, + ).String()); err == nil { + err = os.Symlink(substitutes, c.base.Append( + dirStatus, + ids, + ).String()) + } else if errors.Is(err, os.ErrNotExist) { + err = nil + } return } } @@ -2023,6 +2031,15 @@ func (c *Cache) cure(a Artifact, curesExempt bool) ( return } err = ca.Cure(&f) + if err == nil && f.status != nil { + err = os.Link(c.base.Append( + dirStatus, + ids, + ).String(), c.base.Append( + dirStatus, + substitutes, + ).String()) + } c.exitCure(a, curesExempt) if err != nil { return diff --git a/internal/pkg/pkg_test.go b/internal/pkg/pkg_test.go index 9d6757c7..96eda8ad 100644 --- a/internal/pkg/pkg_test.go +++ b/internal/pkg/pkg_test.go @@ -1059,8 +1059,14 @@ func TestCache(t *testing.T) { "_EmV5nsYZ2UWHgRmLDMU8i-rJWDx-kv5_1pFrzQI7vMMCM5mAXivO8UZtVfOqMR_", ), want, nil}, }) - } + + if dents, err := os.ReadDir(base.Append("status").String()); err != nil { + t.Fatal(err) + } else if len(dents) > 0 { + t.Errorf("ReadDir: %v", dents) + } + }, expectsFS{ ".": {Mode: fs.ModeDir | 0700},