diff --git a/google/sdk.go b/google/sdk.go index bdc1808..b9660ca 100644 --- a/google/sdk.go +++ b/google/sdk.go @@ -5,9 +5,11 @@ package google import ( + "bufio" "encoding/json" "errors" "fmt" + "io" "net/http" "os" "os/user" @@ -18,7 +20,6 @@ import ( "golang.org/x/net/context" "golang.org/x/oauth2" - "golang.org/x/oauth2/internal" ) type sdkCredentials struct { @@ -76,7 +77,7 @@ func NewSDKConfig(account string) (*SDKConfig, error) { return nil, fmt.Errorf("oauth2/google: failed to load SDK properties: %v", err) } defer f.Close() - ini, err := internal.ParseINI(f) + ini, err := parseINI(f) if err != nil { return nil, fmt.Errorf("oauth2/google: failed to parse SDK properties %q: %v", propertiesPath, err) } @@ -146,6 +147,34 @@ func (c *SDKConfig) Scopes() []string { return c.conf.Scopes } +func parseINI(ini io.Reader) (map[string]map[string]string, error) { + result := map[string]map[string]string{ + "": {}, // root section + } + scanner := bufio.NewScanner(ini) + currentSection := "" + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if strings.HasPrefix(line, ";") { + // comment. + continue + } + if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { + currentSection = strings.TrimSpace(line[1 : len(line)-1]) + result[currentSection] = map[string]string{} + continue + } + parts := strings.SplitN(line, "=", 2) + if len(parts) == 2 && parts[0] != "" { + result[currentSection][strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) + } + } + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("error scanning ini: %v", err) + } + return result, nil +} + // sdkConfigPath tries to guess where the gcloud config is located. // It can be overridden during tests. var sdkConfigPath = func() (string, error) { diff --git a/google/sdk_test.go b/google/sdk_test.go index 4489bb9..52b8eca 100644 --- a/google/sdk_test.go +++ b/google/sdk_test.go @@ -4,7 +4,11 @@ package google -import "testing" +import ( + "reflect" + "strings" + "testing" +) func TestSDKConfig(t *testing.T) { sdkConfigPath = func() (string, error) { @@ -44,3 +48,60 @@ func TestSDKConfig(t *testing.T) { } } } + +func TestParseINI(t *testing.T) { + tests := []struct { + ini string + want map[string]map[string]string + }{ + { + `root = toor +[foo] +bar = hop +ini = nin +`, + map[string]map[string]string{ + "": {"root": "toor"}, + "foo": {"bar": "hop", "ini": "nin"}, + }, + }, + { + "\t extra \t = whitespace \t\r\n \t [everywhere] \t \r\n here \t = \t there \t \r\n", + map[string]map[string]string{ + "": {"extra": "whitespace"}, + "everywhere": {"here": "there"}, + }, + }, + { + `[empty] +[section] +empty= +`, + map[string]map[string]string{ + "": {}, + "empty": {}, + "section": {"empty": ""}, + }, + }, + { + `ignore +[invalid +=stuff +;comment=true +`, + map[string]map[string]string{ + "": {}, + }, + }, + } + for _, tt := range tests { + result, err := parseINI(strings.NewReader(tt.ini)) + if err != nil { + t.Errorf("parseINI(%q) error %v, want: no error", tt.ini, err) + continue + } + if !reflect.DeepEqual(result, tt.want) { + t.Errorf("parseINI(%q) = %#v, want: %#v", tt.ini, result, tt.want) + } + } +} diff --git a/internal/oauth2.go b/internal/oauth2.go index 6978192..1aa51be 100644 --- a/internal/oauth2.go +++ b/internal/oauth2.go @@ -5,14 +5,11 @@ package internal import ( - "bufio" "crypto/rsa" "crypto/x509" "encoding/pem" "errors" "fmt" - "io" - "strings" ) // ParseKey converts the binary contents of a private key file @@ -39,34 +36,6 @@ func ParseKey(key []byte) (*rsa.PrivateKey, error) { return parsed, nil } -func ParseINI(ini io.Reader) (map[string]map[string]string, error) { - result := map[string]map[string]string{ - "": {}, // root section - } - scanner := bufio.NewScanner(ini) - currentSection := "" - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if strings.HasPrefix(line, ";") { - // comment. - continue - } - if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { - currentSection = strings.TrimSpace(line[1 : len(line)-1]) - result[currentSection] = map[string]string{} - continue - } - parts := strings.SplitN(line, "=", 2) - if len(parts) == 2 && parts[0] != "" { - result[currentSection][strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) - } - } - if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("error scanning ini: %v", err) - } - return result, nil -} - func CondVal(v string) []string { if v == "" { return nil diff --git a/internal/oauth2_test.go b/internal/oauth2_test.go deleted file mode 100644 index 07d51c4..0000000 --- a/internal/oauth2_test.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package internal - -import ( - "reflect" - "strings" - "testing" -) - -func TestParseINI(t *testing.T) { - tests := []struct { - ini string - want map[string]map[string]string - }{ - { - `root = toor -[foo] -bar = hop -ini = nin -`, - map[string]map[string]string{ - "": {"root": "toor"}, - "foo": {"bar": "hop", "ini": "nin"}, - }, - }, - { - `[empty] -[section] -empty= -`, - map[string]map[string]string{ - "": {}, - "empty": {}, - "section": {"empty": ""}, - }, - }, - { - `ignore -[invalid -=stuff -;comment=true -`, - map[string]map[string]string{ - "": {}, - }, - }, - } - for _, tt := range tests { - result, err := ParseINI(strings.NewReader(tt.ini)) - if err != nil { - t.Errorf("ParseINI(%q) error %v, want: no error", tt.ini, err) - continue - } - if !reflect.DeepEqual(result, tt.want) { - t.Errorf("ParseINI(%q) = %#v, want: %#v", tt.ini, result, tt.want) - } - } -}