aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/format/config/option.go
blob: cad394810a15901d1eb60d5931058ede58326fd4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package config

import (
	"fmt"
	"strings"
)

// Option defines a key/value entity in a config file.
type Option struct {
	// Key preserving original caseness.
	// Use IsKey instead to compare key regardless of caseness.
	Key string
	// Original value as string, could be not normalized.
	Value string
}

type Options []*Option

// IsKey returns true if the given key matches
// this option's key in a case-insensitive comparison.
func (o *Option) IsKey(key string) bool {
	return strings.EqualFold(o.Key, key)
}

func (opts Options) GoString() string {
	var strs []string
	for _, opt := range opts {
		strs = append(strs, fmt.Sprintf("%#v", opt))
	}

	return strings.Join(strs, ", ")
}

// Get gets the value for the given key if set,
// otherwise it returns the empty string.
//
// Note that there is no difference
//
// This matches git behaviour since git v1.8.1-rc1,
// if there are multiple definitions of a key, the
// last one wins.
//
// See: http://article.gmane.org/gmane.linux.kernel/1407184
//
// In order to get all possible values for the same key,
// use GetAll.
func (opts Options) Get(key string) string {
	for i := len(opts) - 1; i >= 0; i-- {
		o := opts[i]
		if o.IsKey(key) {
			return o.Value
		}
	}
	return ""
}

// Has checks if an Option exist with the given key.
func (opts Options) Has(key string) bool {
	for _, o := range opts {
		if o.IsKey(key) {
			return true
		}
	}
	return false
}

// GetAll returns all possible values for the same key.
func (opts Options) GetAll(key string) []string {
	result := []string{}
	for _, o := range opts {
		if o.IsKey(key) {
			result = append(result, o.Value)
		}
	}
	return result
}

func (opts Options) withoutOption(key string) Options {
	result := Options{}
	for _, o := range opts {
		if !o.IsKey(key) {
			result = append(result, o)
		}
	}
	return result
}

func (opts Options) withAddedOption(key string, value string) Options {
	return append(opts, &Option{key, value})
}

func (opts Options) withSettedOption(key string, values ...string) Options {
	var result Options
	var added []string
	for _, o := range opts {
		if !o.IsKey(key) {
			result = append(result, o)
			continue
		}

		if contains(values, o.Value) {
			added = append(added, o.Value)
			result = append(result, o)
			continue
		}
	}

	for _, value := range values {
		if contains(added, value) {
			continue
		}

		result = result.withAddedOption(key, value)
	}

	return result
}

func contains(haystack []string, needle string) bool {
	for _, s := range haystack {
		if s == needle {
			return true
		}
	}

	return false
}