Files
narratio/internal/artifacts/effective_set.go

99 lines
3.1 KiB
Go

package artifacts
import (
"fmt"
"sort"
"strings"
"gitea.maximumdirect.net/eric/narratio/internal/artifactpolicy"
"gitea.maximumdirect.net/eric/narratio/internal/config"
)
// EffectiveArtifactSet is the resolved set of configured artifacts that an
// analyze invocation will execute.
type EffectiveArtifactSet struct {
keys []string
resolved bool
}
// ResolveEffectiveArtifactSet applies an explicit artifact selection when one
// is supplied; otherwise it selects the configured enabled artifacts.
func ResolveEffectiveArtifactSet(
configured map[string]ConfiguredArtifactDefinition,
selected []string,
) (EffectiveArtifactSet, error) {
configuredKeys := make(map[string]ConfiguredArtifactDefinition, len(configured))
for key, definition := range configured {
trimmed := strings.TrimSpace(key)
if !artifactpolicy.IsConfiguredKey(trimmed) {
return EffectiveArtifactSet{}, fmt.Errorf("configured artifact key %q must match ^[a-z][a-z0-9_]*$", key)
}
configuredKeys[trimmed] = definition
}
if len(selected) > 0 {
set := make(map[string]struct{}, len(selected))
for _, key := range selected {
trimmed := strings.TrimSpace(key)
if !artifactpolicy.IsConfiguredKey(trimmed) {
return EffectiveArtifactSet{}, fmt.Errorf("selected artifact key %q must match ^[a-z][a-z0-9_]*$", key)
}
if _, ok := configuredKeys[trimmed]; !ok {
return EffectiveArtifactSet{}, fmt.Errorf("selected artifact %q is not configured", trimmed)
}
set[trimmed] = struct{}{}
}
return newEffectiveArtifactSet(set), nil
}
set := make(map[string]struct{}, len(configuredKeys))
for key, definition := range configuredKeys {
if definition.Enabled {
set[key] = struct{}{}
}
}
return newEffectiveArtifactSet(set), nil
}
// ConfiguredArtifactDefinitions converts Scriptorium configuration into the
// definition form used by the runtime catalog.
func ConfiguredArtifactDefinitions(items map[string]config.ScriptoriumArtifactConfig) map[string]ConfiguredArtifactDefinition {
if len(items) == 0 {
return nil
}
definitions := make(map[string]ConfiguredArtifactDefinition, len(items))
for key, item := range items {
definitions[key] = ConfiguredArtifactDefinition{
Enabled: item.Enabled,
OutputPath: item.OutputPath,
}
}
return definitions
}
// Keys returns the selected configured artifact keys in deterministic order.
func (s EffectiveArtifactSet) Keys() []string {
return append([]string(nil), s.keys...)
}
// Includes reports whether a configured artifact belongs to the effective set.
func (s EffectiveArtifactSet) Includes(key string) bool {
trimmed := strings.TrimSpace(key)
index := sort.SearchStrings(s.keys, trimmed)
return index < len(s.keys) && s.keys[index] == trimmed
}
// Resolved reports whether the set was created by ResolveEffectiveArtifactSet.
func (s EffectiveArtifactSet) Resolved() bool {
return s.resolved
}
func newEffectiveArtifactSet(set map[string]struct{}) EffectiveArtifactSet {
keys := make([]string, 0, len(set))
for key := range set {
keys = append(keys, key)
}
sort.Strings(keys)
return EffectiveArtifactSet{keys: keys, resolved: true}
}