gogit_config.go

  1package repository
  2
  3import (
  4	"fmt"
  5	"strconv"
  6	"strings"
  7	"time"
  8
  9	gogit "github.com/go-git/go-git/v5"
 10)
 11
 12var _ Config = &goGitConfig{}
 13
 14type goGitConfig struct {
 15	repo *gogit.Repository
 16}
 17
 18func newGoGitConfig(repo *gogit.Repository) *goGitConfig {
 19	return &goGitConfig{repo: repo}
 20}
 21
 22func (ggc *goGitConfig) StoreString(key, value string) error {
 23	cfg, err := ggc.repo.Config()
 24	if err != nil {
 25		return err
 26	}
 27
 28	split := strings.Split(key, ".")
 29
 30	switch {
 31	case len(split) <= 1:
 32		return fmt.Errorf("invalid key")
 33	case len(split) == 2:
 34		cfg.Raw.Section(split[0]).SetOption(split[1], value)
 35	default:
 36		section := split[0]
 37		subsection := strings.Join(split[1:len(split)-1], ".")
 38		option := split[len(split)-1]
 39		cfg.Raw.Section(section).Subsection(subsection).SetOption(option, value)
 40	}
 41
 42	return ggc.repo.SetConfig(cfg)
 43}
 44
 45func (ggc *goGitConfig) StoreTimestamp(key string, value time.Time) error {
 46	return ggc.StoreString(key, strconv.Itoa(int(value.Unix())))
 47}
 48
 49func (ggc *goGitConfig) StoreBool(key string, value bool) error {
 50	return ggc.StoreString(key, strconv.FormatBool(value))
 51}
 52
 53func (ggc *goGitConfig) ReadAll(keyPrefix string) (map[string]string, error) {
 54	cfg, err := ggc.repo.Config()
 55	if err != nil {
 56		return nil, err
 57	}
 58
 59	split := strings.Split(keyPrefix, ".")
 60	result := make(map[string]string)
 61
 62	switch {
 63	case keyPrefix == "":
 64		for _, section := range cfg.Raw.Sections {
 65			for _, option := range section.Options {
 66				result[fmt.Sprintf("%s.%s", section.Name, option.Key)] = option.Value
 67			}
 68			for _, subsection := range section.Subsections {
 69				for _, option := range subsection.Options {
 70					result[fmt.Sprintf("%s.%s.%s", section.Name, subsection.Name, option.Key)] = option.Value
 71				}
 72			}
 73		}
 74	case len(split) == 1:
 75		if !cfg.Raw.HasSection(split[0]) {
 76			return nil, fmt.Errorf("invalid section")
 77		}
 78		section := cfg.Raw.Section(split[0])
 79		for _, option := range section.Options {
 80			result[fmt.Sprintf("%s.%s", section.Name, option.Key)] = option.Value
 81		}
 82		for _, subsection := range section.Subsections {
 83			for _, option := range subsection.Options {
 84				result[fmt.Sprintf("%s.%s.%s", section.Name, subsection.Name, option.Key)] = option.Value
 85			}
 86		}
 87	default:
 88		if !cfg.Raw.HasSection(split[0]) {
 89			return nil, fmt.Errorf("invalid section")
 90		}
 91		section := cfg.Raw.Section(split[0])
 92		rest := strings.Join(split[1:], ".")
 93		for _, subsection := range section.Subsections {
 94			if strings.HasPrefix(subsection.Name, rest) {
 95				for _, option := range subsection.Options {
 96					result[fmt.Sprintf("%s.%s.%s", section.Name, subsection.Name, option.Key)] = option.Value
 97				}
 98			}
 99		}
100	}
101
102	if len(result) == 0 {
103		return nil, fmt.Errorf("invalid section")
104	}
105
106	return result, nil
107}
108
109func (ggc *goGitConfig) ReadBool(key string) (bool, error) {
110	val, err := ggc.ReadString(key)
111	if err != nil {
112		return false, err
113	}
114
115	return strconv.ParseBool(val)
116}
117
118func (ggc *goGitConfig) ReadString(key string) (string, error) {
119	cfg, err := ggc.repo.Config()
120	if err != nil {
121		return "", err
122	}
123
124	split := strings.Split(key, ".")
125
126	if len(split) <= 1 {
127		return "", fmt.Errorf("invalid key")
128	}
129
130	sectionName := split[0]
131	if !cfg.Raw.HasSection(sectionName) {
132		return "", ErrNoConfigEntry
133	}
134	section := cfg.Raw.Section(sectionName)
135
136	switch {
137	case len(split) == 2:
138		optionName := split[1]
139		if !section.HasOption(optionName) {
140			return "", ErrNoConfigEntry
141		}
142		if len(section.OptionAll(optionName)) > 1 {
143			return "", ErrMultipleConfigEntry
144		}
145		return section.Option(optionName), nil
146	default:
147		subsectionName := strings.Join(split[1:len(split)-2], ".")
148		optionName := split[len(split)-1]
149		if !section.HasSubsection(subsectionName) {
150			return "", ErrNoConfigEntry
151		}
152		subsection := section.Subsection(subsectionName)
153		if !subsection.HasOption(optionName) {
154			return "", ErrNoConfigEntry
155		}
156		if len(subsection.OptionAll(optionName)) > 1 {
157			return "", ErrMultipleConfigEntry
158		}
159		return subsection.Option(optionName), nil
160	}
161}
162
163func (ggc *goGitConfig) ReadTimestamp(key string) (time.Time, error) {
164	value, err := ggc.ReadString(key)
165	if err != nil {
166		return time.Time{}, err
167	}
168	return ParseTimestamp(value)
169}
170
171func (ggc *goGitConfig) RemoveAll(keyPrefix string) error {
172	cfg, err := ggc.repo.Config()
173	if err != nil {
174		return err
175	}
176
177	split := strings.Split(keyPrefix, ".")
178
179	switch {
180	case keyPrefix == "":
181		cfg.Raw.Sections = nil
182		// warning: this does not actually remove everything as go-git config hold
183		// some entries in multiple places (cfg.User ...)
184	case len(split) == 1:
185		if cfg.Raw.HasSection(split[0]) {
186			cfg.Raw.RemoveSection(split[0])
187		} else {
188			return fmt.Errorf("invalid key prefix")
189		}
190	default:
191		if !cfg.Raw.HasSection(split[0]) {
192			return fmt.Errorf("invalid key prefix")
193		}
194		section := cfg.Raw.Section(split[0])
195		rest := strings.Join(split[1:], ".")
196
197		ok := false
198		if section.HasSubsection(rest) {
199			section.RemoveSubsection(rest)
200			ok = true
201		}
202		if section.HasOption(rest) {
203			section.RemoveOption(rest)
204			ok = true
205		}
206		if !ok {
207			return fmt.Errorf("invalid key prefix")
208		}
209	}
210
211	return ggc.repo.SetConfig(cfg)
212}