Centralize effective artifact selection
This commit is contained in:
98
internal/artifacts/effective_set.go
Normal file
98
internal/artifacts/effective_set.go
Normal file
@@ -0,0 +1,98 @@
|
||||
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}
|
||||
}
|
||||
Reference in New Issue
Block a user