10 "github.com/git-lfs/git-lfs/git"
13 type GitFetcher struct {
15 vals map[string][]string
18 func readGitConfig(configs ...*git.ConfigurationSource) (gf *GitFetcher, extensions map[string]Extension, uniqRemotes map[string]bool) {
19 vals := make(map[string][]string)
20 ignored := make([]string, 0)
22 extensions = make(map[string]Extension)
23 uniqRemotes = make(map[string]bool)
25 for _, gc := range configs {
26 uniqKeys := make(map[string]string)
28 for _, line := range gc.Lines {
29 pieces := strings.SplitN(line, "=", 2)
34 allowed := !gc.OnlySafeKeys
35 key, val := strings.ToLower(pieces[0]), pieces[1]
37 if origKey, ok := uniqKeys[key]; ok {
38 if ShowConfigWarnings && len(vals[key]) > 0 && vals[key][len(vals[key])-1] != val && strings.HasPrefix(key, gitConfigWarningPrefix) {
39 fmt.Fprintf(os.Stderr, "WARNING: These git config values clash:\n")
40 fmt.Fprintf(os.Stderr, " git config %q = %q\n", origKey, vals[key])
41 fmt.Fprintf(os.Stderr, " git config %q = %q\n", pieces[0], val)
44 uniqKeys[key] = pieces[0]
47 parts := strings.Split(key, ".")
48 if len(parts) == 4 && parts[0] == "lfs" && parts[1] == "extension" {
49 // prop: lfs.extension.<name>.<prop>
53 ext := extensions[name]
59 ignored = append(ignored, key)
65 ignored = append(ignored, key)
71 p, err := strconv.Atoi(val)
72 if err == nil && p >= 0 {
77 extensions[name] = ext
78 } else if len(parts) > 1 && parts[0] == "remote" {
79 if gc.OnlySafeKeys && (len(parts) == 3 && parts[2] != "lfsurl") {
80 ignored = append(ignored, key)
86 uniqRemotes[remote] = remote == "origin"
87 } else if len(parts) > 2 && parts[len(parts)-1] == "access" {
91 if !allowed && keyIsUnsafe(key) {
92 ignored = append(ignored, key)
96 vals[key] = append(vals[key], val)
100 if len(ignored) > 0 {
101 fmt.Fprintf(os.Stderr, "WARNING: These unsafe lfsconfig keys were ignored:\n\n")
102 for _, key := range ignored {
103 fmt.Fprintf(os.Stderr, " %s\n", key)
107 gf = &GitFetcher{vals: vals}
112 // Get implements the Fetcher interface, and returns the value associated with
113 // a given key and true, signaling that the value was present. Otherwise, an
114 // empty string and false will be returned, signaling that the value was
117 // Map lookup by key is case-insensitive, as per the .gitconfig specification.
119 // Get is safe to call across multiple goroutines.
120 func (g *GitFetcher) Get(key string) (val string, ok bool) {
126 return all[len(all)-1], true
129 func (g *GitFetcher) GetAll(key string) []string {
131 defer g.vmu.RUnlock()
133 return g.vals[strings.ToLower(key)]
136 func (g *GitFetcher) All() map[string][]string {
137 newmap := make(map[string][]string)
140 defer g.vmu.RUnlock()
142 for key, values := range g.vals {
143 for _, value := range values {
144 newmap[key] = append(newmap[key], value)
151 func keyIsUnsafe(key string) bool {
152 for _, safe := range safeKeys {
160 var safeKeys = []string{