Files
mesh-catalog/modules/artifact-store-tools/cmd/artifact-store-tools/view.go
T
jochen 24ce702360
mesh/merge-gate pass: builds distribution, new: modules/artifact-store-tools → novox; no bus step; every machine composes with the change as it did without…
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery failed: its walk failed: a gate on a first machine (what it carried put back), a build, a machine
Move the artifact store's tools into a module beside it, as the controller requires
A module that provides the artifact store cannot build an artifact: building publishes to the store,
so the store would be needed to create itself, and the module check refuses it. The tools become
artifact-store-tools, assigned beside the store, and read manifests from the store's files through its
container as they already read the listing, so they need no address for the store's door. Named for
the artifact store, because "store" alone is the database server (hq glossary).
2026-10-08 12:04:33 +02:00

130 lines
3.2 KiB
Go

package main
import (
"sort"
)
// View is the store at one moment: its files, and every manifest's content that could be read.
type View struct {
L *Listing
// M is each manifest read, by Key.
M map[string]*Manifest
// Unread is each manifest that could not be read, by Key, with why.
Unread map[string]string
}
// Marks are the blobs one manifest keeps from the store's collector: its own content, its
// configuration and its layers, and for an index the manifests it lists. A manifest that could not be
// read marks only itself here, and the answers that rest on it say so.
func (v *View) Marks(repo, digest string) []string {
out := []string{digest}
if m := v.M[Key(repo, digest)]; m != nil {
out = append(out, m.Refs...)
out = append(out, m.Children...)
}
return out
}
// Marked is every blob some manifest marks, leaving out the manifests named in without — the
// collector's own mark, and the mark it would make once those are gone.
func (v *View) Marked(without map[string]bool) map[string]bool {
marked := map[string]bool{}
for name, r := range v.L.Repos {
for d := range r.Revisions {
if without[Key(name, d)] {
continue
}
for _, b := range v.Marks(name, d) {
marked[b] = true
}
}
}
return marked
}
// Bytes is the size of these blobs, as the store holds them; a blob the store does not hold counts
// nothing.
func (v *View) Bytes(blobs map[string]bool) int64 {
var n int64
for b := range blobs {
n += v.L.Blobs[b]
}
return n
}
// Total is the size of every blob the store holds.
func (v *View) Total() int64 {
var n int64
for _, s := range v.L.Blobs {
n += s
}
return n
}
// Unmarked is the bytes and count of the blobs no manifest marks, once the manifests in without are
// gone: what the nightly collector frees.
func (v *View) Unmarked(without map[string]bool) (int64, int) {
marked := v.Marked(without)
var n int64
count := 0
for b, s := range v.L.Blobs {
if !marked[b] {
n += s
count++
}
}
return n, count
}
// RepoBlobs are the blobs one repository's manifests mark.
func (v *View) RepoBlobs(name string) map[string]bool {
out := map[string]bool{}
if r := v.L.Repos[name]; r != nil {
for d := range r.Revisions {
for _, b := range v.Marks(name, d) {
out[b] = true
}
}
}
return out
}
// Shared are the blobs that the manifests of more than one repository mark.
func (v *View) Shared() map[string]bool {
seen := map[string]string{}
shared := map[string]bool{}
for _, name := range v.L.RepoNames() {
for b := range v.RepoBlobs(name) {
if first, ok := seen[b]; ok && first != name {
shared[b] = true
} else {
seen[b] = name
}
}
}
return shared
}
// tagsOf is a repository's tags, in order, with what each names.
func tagsOf(r *Repo) []map[string]string {
names := make([]string, 0, len(r.Tags))
for t := range r.Tags {
names = append(names, t)
}
sort.Strings(names)
out := make([]map[string]string, 0, len(names))
for _, t := range names {
out = append(out, map[string]string{"tag": t, "digest": r.Tags[t]})
}
return out
}
// taggedDigests are the manifests some tag names, in one repository.
func taggedDigests(r *Repo) map[string]bool {
out := map[string]bool{}
for _, d := range r.Tags {
out[d] = true
}
return out
}