- admin-protected client config (flag > AGENT_LIB_CONFIG > platform default), token used for basic auth only, redacted from all errors and files - work-repo pull via go-git (bare cache clone + fetch, remote re-pointed on config change), clean failure keeps previous state - inventory: own items + external areas from lockfile; MCP inventoried but never deployed - manifest v1 records name/type/origin/revision/content-hash per item, deterministic bytes; folder hashes over sorted relpath+filehash lines so tree and disk hashes agree - shared deploy package (atomic temp+rename, exec-bit preserving) now backs both curator materialization and client deployment - sync validates and hashes everything before the first mutation; second run is a byte-level no-op
67 lines
1.6 KiB
Go
67 lines
1.6 KiB
Go
package discovery
|
|
|
|
import (
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
// PrefixTree narrows a Tree to the subtree below Prefix; paths passed in and
|
|
// reported back are relative to that subtree.
|
|
type PrefixTree struct {
|
|
Tree Tree
|
|
Prefix string
|
|
}
|
|
|
|
func (p *PrefixTree) Walk(fn func(rel string, isDir bool) error) error {
|
|
prefix := strings.TrimSuffix(p.Prefix, "/") + "/"
|
|
return p.Tree.Walk(func(rel string, isDir bool) error {
|
|
if rel == p.Prefix || strings.HasPrefix(rel, prefix) {
|
|
sub := strings.TrimPrefix(rel, prefix)
|
|
if sub == "" {
|
|
return nil
|
|
}
|
|
return fn(sub, isDir)
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (p *PrefixTree) ReadFile(rel string) ([]byte, error) {
|
|
return p.Tree.ReadFile(p.Prefix + "/" + rel)
|
|
}
|
|
|
|
// FilesUnder delegates to the underlying tree with the prefix reapplied.
|
|
func (p *PrefixTree) FilesUnder(prefix string) ([]string, error) {
|
|
lister, ok := p.Tree.(interface {
|
|
FilesUnder(prefix string) ([]string, error)
|
|
})
|
|
if !ok {
|
|
return nil, os.ErrNotExist
|
|
}
|
|
full := prefix
|
|
if p.Prefix != "" {
|
|
full = p.Prefix + "/" + strings.TrimSuffix(prefix, "/")
|
|
}
|
|
files, err := lister.FilesUnder(full)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
trim := p.Prefix + "/"
|
|
out := make([]string, 0, len(files))
|
|
for _, f := range files {
|
|
out = append(out, strings.TrimPrefix(f, trim))
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
// MaterializeFile delegates to the underlying tree with the prefix reapplied.
|
|
func (p *PrefixTree) MaterializeFile(rel, dst string) error {
|
|
mt, ok := p.Tree.(interface {
|
|
MaterializeFile(rel, dst string) error
|
|
})
|
|
if !ok {
|
|
return os.ErrNotExist
|
|
}
|
|
return mt.MaterializeFile(p.Prefix+"/"+rel, dst)
|
|
}
|