1package repository
2
3import (
4 "fmt"
5 "strconv"
6 "strings"
7 "time"
8)
9
10var _ Config = &MemConfig{}
11
12type MemConfig struct {
13 config map[string]string
14}
15
16func NewMemConfig() *MemConfig {
17 return &MemConfig{
18 config: make(map[string]string),
19 }
20}
21
22func (mc *MemConfig) StoreString(key, value string) error {
23 key = normalizeKey(key)
24 mc.config[key] = value
25 return nil
26}
27
28func (mc *MemConfig) StoreBool(key string, value bool) error {
29 return mc.StoreString(key, strconv.FormatBool(value))
30}
31
32func (mc *MemConfig) StoreTimestamp(key string, value time.Time) error {
33 return mc.StoreString(key, strconv.Itoa(int(value.Unix())))
34}
35
36func (mc *MemConfig) ReadAll(keyPrefix string) (map[string]string, error) {
37 keyPrefix = normalizeKey(keyPrefix)
38 result := make(map[string]string)
39 for key, val := range mc.config {
40 if strings.HasPrefix(key, keyPrefix) {
41 result[key] = val
42 }
43 }
44 return result, nil
45}
46
47func (mc *MemConfig) ReadString(key string) (string, error) {
48 // unlike git, the mock can only store one value for the same key
49 key = normalizeKey(key)
50 val, ok := mc.config[key]
51 if !ok {
52 return "", fmt.Errorf("%w: missing key %s", ErrNoConfigEntry, key)
53 }
54
55 return val, nil
56}
57
58func (mc *MemConfig) ReadBool(key string) (bool, error) {
59 // unlike git, the mock can only store one value for the same key
60 val, err := mc.ReadString(key)
61 if err != nil {
62 return false, err
63 }
64
65 return strconv.ParseBool(val)
66}
67
68func (mc *MemConfig) ReadTimestamp(key string) (time.Time, error) {
69 value, err := mc.ReadString(key)
70 if err != nil {
71 return time.Time{}, err
72 }
73
74 timestamp, err := strconv.Atoi(value)
75 if err != nil {
76 return time.Time{}, err
77 }
78
79 return time.Unix(int64(timestamp), 0), nil
80}
81
82// RmConfigs remove all key/value pair matching the key prefix
83func (mc *MemConfig) RemoveAll(keyPrefix string) error {
84 keyPrefix = normalizeKey(keyPrefix)
85 found := false
86 for key := range mc.config {
87 if strings.HasPrefix(key, keyPrefix) {
88 delete(mc.config, key)
89 found = true
90 }
91 }
92
93 if !found {
94 return fmt.Errorf("section not found")
95 }
96
97 return nil
98}
99
100func normalizeKey(key string) string {
101 // this feels so wrong, but that's apparently how git behave.
102 // only section and final segment are case insensitive, subsection in between are not.
103 s := strings.Split(key, ".")
104 s[0] = strings.ToLower(s[0])
105 s[len(s)-1] = strings.ToLower(s[len(s)-1])
106 return strings.Join(s, ".")
107}