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	"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	// TODO: return ErrNoConfigEntry and ErrMultipleConfigEntry
109	// Can use forked go-git: https://github.com/go-git/go-git/pull/112
110
111	switch {
112	case len(split) <= 1:
113		return "", fmt.Errorf("invalid key")
114	case len(split) == 2:
115		return cfg.Raw.Section(split[0]).Option(split[1]), nil
116	default:
117		section := split[0]
118		subsection := strings.Join(split[1:len(split)-2], ".")
119		option := split[len(split)-1]
120		return cfg.Raw.Section(section).Subsection(subsection).Option(option), nil
121	}
122}
123
124func (ggc *goGitConfig) ReadTimestamp(key string) (time.Time, error) {
125	value, err := ggc.ReadString(key)
126	if err != nil {
127		return time.Time{}, err
128	}
129	return ParseTimestamp(value)
130}
131
132func (ggc *goGitConfig) RemoveAll(keyPrefix string) error {
133	cfg, err := ggc.repo.Config()
134	if err != nil {
135		return err
136	}
137
138	split := strings.Split(keyPrefix, ".")
139
140	// missing in go-git
141	hasOption := func(options config.Options, key string) bool {
142		for _, option := range options {
143			if option.IsKey(key) {
144				return true
145			}
146		}
147		return false
148	}
149
150	switch {
151	case len(split) < 1:
152		return fmt.Errorf("invalid key prefix")
153	case len(split) == 1:
154		if len(cfg.Raw.Section(split[0]).Options) > 0 {
155			cfg.Raw.RemoveSection(split[0])
156		} else {
157			return fmt.Errorf("invalid key prefix")
158		}
159	default:
160		section := split[0]
161		rest := strings.Join(split[1:], ".")
162
163		if cfg.Raw.Section(section).HasSubsection(rest) {
164			cfg.Raw.RemoveSubsection(section, rest)
165		} else {
166			if hasOption(cfg.Raw.Section(section).Options, rest) {
167				cfg.Raw.Section(section).RemoveOption(rest)
168			} else {
169				return fmt.Errorf("invalid key prefix")
170			}
171		}
172	}
173
174	return ggc.repo.SetConfig(cfg)
175}