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 "", newErrNoConfigEntry(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}