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}