11package goconfig
22
33import (
4+ "sort"
45 "strconv"
56 "strings"
67)
78
9+ // Scope is used to mark where config variable comes from
10+ type Scope int
11+
12+ // Define scopes for config variables
13+ const (
14+ ScopeInclude = 1 << iota
15+ ScopeSystem
16+ ScopeGlobal
17+ ScopeSelf
18+
19+ ScopeAll = 0xFFFF
20+ ScopeMask = ^ ScopeInclude
21+ )
22+
23+ // String show user friendly display of scope
24+ func (v * Scope ) String () string {
25+ i := int (* v )
26+ inc := ""
27+ if i & ScopeInclude == ScopeInclude {
28+ inc = "-inc"
29+ }
30+
31+ if i & ScopeSystem == ScopeSystem {
32+ return "system" + inc
33+ } else if i & ScopeGlobal == ScopeGlobal {
34+ return "global" + inc
35+ } else if i & ScopeSelf == ScopeSelf {
36+ return "self" + inc
37+ }
38+ return "unknown" + inc
39+ }
40+
841// GitConfig maps section to key-value pairs
942type GitConfig map [string ]GitConfigKeys
1043
1144// GitConfigKeys maps key to values
12- type GitConfigKeys map [string ][]string
45+ type GitConfigKeys map [string ][]* GitConfigValue
46+
47+ // GitConfigValue holds value and its scope
48+ type GitConfigValue struct {
49+ scope Scope
50+ value string
51+ }
52+
53+ // Set is used to set value
54+ func (v * GitConfigValue ) Set (value string ) {
55+ v .value = value
56+ }
57+
58+ // Value is used to show value
59+ func (v * GitConfigValue ) Value () string {
60+ return v .value
61+ }
62+
63+ // Scope is used to show user friendly scope
64+ func (v * GitConfigValue ) Scope () string {
65+ return v .scope .String ()
66+ }
1367
1468// NewGitConfig returns GitConfig with initialized maps
1569func NewGitConfig () GitConfig {
@@ -25,6 +79,7 @@ func (v GitConfig) Keys() []string {
2579 allKeys = append (allKeys , s + "." + key )
2680 }
2781 }
82+ sort .Strings (allKeys )
2883 return allKeys
2984}
3085
@@ -42,9 +97,9 @@ func (v GitConfig) _add(section, key, value string) {
4297 }
4398
4499 if _ , ok := v [section ][key ]; ! ok {
45- v [section ][key ] = []string {}
100+ v [section ][key ] = []* GitConfigValue {}
46101 }
47- v [section ][key ] = append (v [section ][key ], value )
102+ v [section ][key ] = append (v [section ][key ], & GitConfigValue { value : value } )
48103}
49104
50105// Get value from key
@@ -106,9 +161,25 @@ func (v GitConfig) GetUint64(key string, defaultValue uint64) (uint64, error) {
106161func (v GitConfig ) GetAll (key string ) []string {
107162 section , key := toSectionKey (key )
108163
109- keys := v [section ]
110- if keys != nil {
111- return keys [key ]
164+ values := []string {}
165+
166+ if v [section ] != nil && v [section ][key ] != nil {
167+ for _ , value := range v [section ][key ] {
168+ if value != nil {
169+ values = append (values , value .value )
170+ }
171+ }
172+ return values
173+ }
174+ return nil
175+ }
176+
177+ // GetRaw gets all values of a key
178+ func (v GitConfig ) GetRaw (key string ) []* GitConfigValue {
179+ section , key := toSectionKey (key )
180+
181+ if v [section ] != nil && v [section ][key ] != nil {
182+ return v [section ][key ]
112183 }
113184 return nil
114185}
@@ -141,16 +212,26 @@ func toSectionKey(name string) (string, string) {
141212
142213// Merge will merge another GitConfig, and new value(s) of the same key will
143214// append to the end of value list, and new value has higher priority.
144- func (v GitConfig ) Merge (c GitConfig ) GitConfig {
215+ func (v GitConfig ) Merge (c GitConfig , scope Scope ) GitConfig {
145216 for sec , keys := range c {
146217 if _ , ok := v [sec ]; ! ok {
147218 v [sec ] = make (GitConfigKeys )
148219 }
149220 for key , values := range keys {
150221 if v [sec ][key ] == nil {
151- v [sec ][key ] = []string {}
222+ v [sec ][key ] = []* GitConfigValue {}
223+ }
224+ for _ , value := range values {
225+ if value == nil {
226+ continue
227+ }
228+ v [sec ][key ] = append (v [sec ][key ],
229+ & GitConfigValue {
230+ scope : (value .scope & ^ ScopeMask ) | scope ,
231+ value : value .Value (),
232+ })
233+
152234 }
153- v [sec ][key ] = append (v [sec ][key ], values ... )
154235 }
155236 }
156237 return v
0 commit comments