talos
132 строки · 2.5 Кб
1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5package argsbuilder6
7import (8"fmt"9"sort"10"strings"11
12"github.com/siderolabs/gen/maps"13)
14
15// Key represents an arg key.
16type Key = string17
18// Value represents an arg value.
19type Value = string20
21// Args represents a set of args.
22type Args map[Key]Value23
24// MustMerge implements the ArgsBuilder interface.
25func (a Args) MustMerge(args Args, setters ...MergeOption) {26if err := a.Merge(args, setters...); err != nil {27panic(err)28}29}
30
31// Merge implements the ArgsBuilder interface.
32//
33//nolint:gocyclo
34func (a Args) Merge(args Args, setters ...MergeOption) error {35var opts MergeOptions36
37for _, s := range setters {38s(&opts)39}40
41policies := opts.Policies42if policies == nil {43policies = MergePolicies{}44}45
46for key, val := range args {47policy := policies[key]48
49switch policy {50case MergeDenied:51return NewDenylistError(key)52case MergeAdditive:53values := strings.Split(a[key], ",")54definedValues := map[string]struct{}{}55
56i := 057
58for _, v := range values {59definedValues[strings.TrimSpace(v)] = struct{}{}60
61if v != "" {62values[i] = v63i++64}65}66
67values = values[:i]68
69for _, v := range strings.Split(val, ",") {70v = strings.TrimSpace(v)71if _, defined := definedValues[v]; !defined {72values = append(values, v)73}74}75
76a[key] = strings.Join(values, ",")77case MergeOverwrite:78a[key] = val79}80}81
82return nil83}
84
85// Set implements the ArgsBuilder interface.
86func (a Args) Set(k, v Key) ArgsBuilder {87a[k] = v88
89return a90}
91
92// Args implements the ArgsBuilder interface.
93func (a Args) Args() []string {94keys := maps.Keys(a)95sort.Strings(keys)96
97args := []string{}98
99for _, key := range keys {100args = append(args, fmt.Sprintf("--%s=%s", key, a[key]))101}102
103return args104}
105
106// Get returns an args value.
107func (a Args) Get(k Key) Value {108return a[k]109}
110
111// Contains checks if an arg key exists.
112func (a Args) Contains(k Key) bool {113_, ok := a[k]114
115return ok116}
117
118// DenyListError represents an error indicating that an argument was supplied
119// that is not allowed.
120type DenyListError struct {121s string122}
123
124// NewDenylistError returns a DenyListError.
125func NewDenylistError(s string) error {126return &DenyListError{s}127}
128
129// Error implements the Error interface.
130func (b *DenyListError) Error() string {131return fmt.Sprintf("extra arg %q is not allowed", b.s)132}
133