diff --git a/internal/config/alias_config.go b/internal/config/alias_config.go index 23499f229..434b74f20 100644 --- a/internal/config/alias_config.go +++ b/internal/config/alias_config.go @@ -1,10 +1,7 @@ package config import ( - "errors" "fmt" - - "gopkg.in/yaml.v3" ) type AliasConfig struct { @@ -28,44 +25,6 @@ func (a *AliasConfig) Get(alias string) string { } func (a *AliasConfig) Add(alias, expansion string) error { - if a.Root == nil { - // TODO awful hack bad type conversion i'm sorry. this is to support an empty aliases key and - // ought to be generalized into ConfigMap or fileConfig (via Config interface) itself. - entry, err := a.Parent.(*fileConfig).FindEntry("aliases") - - var notFound *NotFoundError - - if err != nil && !errors.As(err, ¬Found) { - return err - } - valueNode := &yaml.Node{ - Kind: yaml.MappingNode, - Value: "", - } - - a.Root = valueNode - if errors.As(err, ¬Found) { - // No aliases: key; just append new aliases key and empty map to end - keyNode := &yaml.Node{ - Kind: yaml.ScalarNode, - Value: "aliases", - } - a.Parent.Root().Content = append(a.Parent.Root().Content, keyNode, valueNode) - } else { - // Empty aliases; inject new value node after existing aliases key - newContent := []*yaml.Node{} - for i := 0; i < len(a.Parent.Root().Content); i++ { - if i == entry.Index { - newContent = append(newContent, entry.KeyNode, valueNode) - i++ - } else { - newContent = append(newContent, a.Parent.Root().Content[i]) - } - } - a.Parent.Root().Content = newContent - } - } - err := a.SetStringValue(alias, expansion) if err != nil { return fmt.Errorf("failed to update config: %w", err) diff --git a/internal/config/config_type.go b/internal/config/config_type.go index 55bba7d5b..39765bd8a 100644 --- a/internal/config/config_type.go +++ b/internal/config/config_type.go @@ -191,34 +191,57 @@ func (c *fileConfig) Write() error { } func (c *fileConfig) Aliases() (*AliasConfig, error) { + // The complexity here is for dealing with either a missing or empty aliases key. It's something + // we'll likely want for other config sections at some point. entry, err := c.FindEntry("aliases") var nfe *NotFoundError - if err != nil && errors.As(err, &nfe) { - // TODO does this make sense at all? want to simulate existing but empty key. - return &AliasConfig{Parent: c}, nil - } - - aliasConfig, err := c.parseAliasConfig(entry.ValueNode) - if err != nil { + notFound := errors.As(err, &nfe) + if err != nil && !notFound { return nil, err } - return aliasConfig, nil -} + toInsert := []*yaml.Node{} -func (c *fileConfig) parseAliasConfig(aliasesEntry *yaml.Node) (*AliasConfig, error) { - if aliasesEntry.Kind != yaml.MappingNode { - return &AliasConfig{ - Parent: c, - }, nil + keyNode := entry.KeyNode + valueNode := entry.ValueNode + + if keyNode == nil { + keyNode = &yaml.Node{ + Kind: yaml.ScalarNode, + Value: "aliases", + } + toInsert = append(toInsert, keyNode) } - aliasConfig := AliasConfig{ + if valueNode == nil || valueNode.Kind != yaml.MappingNode { + valueNode = &yaml.Node{ + Kind: yaml.MappingNode, + Value: "", + } + toInsert = append(toInsert, valueNode) + } + + if len(toInsert) > 0 { + newContent := []*yaml.Node{} + if notFound { + newContent = append(c.Root().Content, keyNode, valueNode) + } else { + for i := 0; i < len(c.Root().Content); i++ { + if i == entry.Index { + newContent = append(newContent, keyNode, valueNode) + i++ + } else { + newContent = append(newContent, c.Root().Content[i]) + } + } + } + c.Root().Content = newContent + } + + return &AliasConfig{ Parent: c, - ConfigMap: ConfigMap{Root: aliasesEntry}, - } - - return &aliasConfig, nil + ConfigMap: ConfigMap{Root: valueNode}, + }, nil } func (c *fileConfig) Hosts() ([]*HostConfig, error) {