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