internal/pkg: garbage collection
All checks were successful
Test / Create distribution (push) Successful in 2m53s
Test / Sandbox (push) Successful in 7m2s
Test / ShareFS (push) Successful in 3m51s
Test / Hakurei (push) Successful in 3m58s
Test / Sandbox (race detector) (push) Successful in 5m32s
Test / Hakurei (race detector) (push) Successful in 6m35s
Test / Flake checks (push) Successful in 2m13s
All checks were successful
Test / Create distribution (push) Successful in 2m53s
Test / Sandbox (push) Successful in 7m2s
Test / ShareFS (push) Successful in 3m51s
Test / Hakurei (push) Successful in 3m58s
Test / Sandbox (race detector) (push) Successful in 5m32s
Test / Hakurei (race detector) (push) Successful in 6m35s
Test / Flake checks (push) Successful in 2m13s
This destroys cache entries not referred to by user-specified artifacts and optionally their inputs. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
138
internal/pkg/clean.go
Normal file
138
internal/pkg/clean.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"unique"
|
||||
)
|
||||
|
||||
// Clean destroys checksum backing entries without any identifier or substitute
|
||||
// entry referring to it. If at least one keep [Artifact] is specified,
|
||||
// identifier and substitute entries not kept alive by them are destroyed first.
|
||||
func (c *Cache) Clean(dry, inputs bool, keep ...Artifact) (
|
||||
[]unique.Handle[ID],
|
||||
[]unique.Handle[Checksum],
|
||||
error,
|
||||
) {
|
||||
c.identMu.Lock()
|
||||
defer c.identMu.Unlock()
|
||||
|
||||
c.checksumMu.Lock()
|
||||
defer c.checksumMu.Unlock()
|
||||
|
||||
dents, err := os.ReadDir(c.base.Append(dirChecksum).String())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
checksums := make(map[unique.Handle[Checksum]]string, len(dents))
|
||||
var buf Checksum
|
||||
for _, dent := range dents {
|
||||
name := dent.Name()
|
||||
if err = Decode(&buf, name); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
checksums[unique.Make(buf)] = name
|
||||
}
|
||||
|
||||
type identPair struct {
|
||||
id unique.Handle[ID]
|
||||
name string
|
||||
}
|
||||
dents, err = os.ReadDir(c.base.Append(dirIdentifier).String())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
keepIdents := make(map[unique.Handle[ID]]struct{})
|
||||
if inputs {
|
||||
for _, id := range Inputs((*Collect)(&keep)) {
|
||||
keepIdents[id] = struct{}{}
|
||||
}
|
||||
} else {
|
||||
for _, a := range keep {
|
||||
keepIdents[c.Ident(a)] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
idents := make([]identPair, 0, len(dents))
|
||||
for _, dent := range dents {
|
||||
name := dent.Name()
|
||||
if err = Decode(&buf, name); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
id := unique.Make(ID(buf))
|
||||
|
||||
if _, ok := keepIdents[id]; len(keep) == 0 || ok {
|
||||
if err = readlinkChecksum(c.base.Append(
|
||||
dirIdentifier,
|
||||
name,
|
||||
), &buf); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
delete(checksums, unique.Make(buf))
|
||||
continue
|
||||
}
|
||||
|
||||
c.msg.Verbosef("arranging for destruction of %s...", name)
|
||||
idents = append(idents, identPair{id, name})
|
||||
}
|
||||
|
||||
destroyedIdents := make([]unique.Handle[ID], 0, len(idents))
|
||||
for _, pair := range idents {
|
||||
if !dry {
|
||||
if err = os.Remove(c.base.Append(
|
||||
dirIdentifier,
|
||||
pair.name,
|
||||
).String()); err != nil {
|
||||
return destroyedIdents, nil, err
|
||||
}
|
||||
}
|
||||
destroyedIdents = append(destroyedIdents, pair.id)
|
||||
}
|
||||
|
||||
destroyedChecksums := make([]unique.Handle[Checksum], 0, len(checksums))
|
||||
for checksum, name := range checksums {
|
||||
if err = c.parent.Err(); err != nil {
|
||||
return destroyedIdents, destroyedChecksums, err
|
||||
}
|
||||
c.msg.Verbosef("destroying checksum %s...", name)
|
||||
if !dry {
|
||||
if err = errors.Join(removeAll(c.base.Append(
|
||||
dirChecksum,
|
||||
name,
|
||||
))); err != nil {
|
||||
return destroyedIdents, destroyedChecksums, err
|
||||
}
|
||||
}
|
||||
destroyedChecksums = append(destroyedChecksums, checksum)
|
||||
}
|
||||
|
||||
dents, err = os.ReadDir(c.base.Append(dirSubstitute).String())
|
||||
if err != nil {
|
||||
return destroyedIdents, destroyedChecksums, err
|
||||
}
|
||||
for _, dent := range dents {
|
||||
name := dent.Name()
|
||||
if err = readlinkChecksum(c.base.Append(
|
||||
dirSubstitute,
|
||||
name,
|
||||
), &buf); err != nil {
|
||||
return destroyedIdents, destroyedChecksums, err
|
||||
}
|
||||
if _, ok := checksums[unique.Make(buf)]; !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
c.msg.Verbosef("destroying substitute %s...", name)
|
||||
if !dry {
|
||||
if err = os.Remove(c.base.Append(
|
||||
dirSubstitute,
|
||||
name,
|
||||
).String()); err != nil {
|
||||
return destroyedIdents, destroyedChecksums, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return destroyedIdents, destroyedChecksums, nil
|
||||
}
|
||||
Reference in New Issue
Block a user