summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/go-ini/ini
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2017-11-13 09:09:58 -0800
committerGitHub <noreply@github.com>2017-11-13 09:09:58 -0800
commit1329aa51b605cb54ba9aae3a82a0a87b881fb7b3 (patch)
tree93cbf354ab894a560fc2cef8ef685d681b4ff889 /vendor/github.com/go-ini/ini
parent7304a61ef597970be3031b14e652fb3a4df44304 (diff)
downloadchat-1329aa51b605cb54ba9aae3a82a0a87b881fb7b3.tar.gz
chat-1329aa51b605cb54ba9aae3a82a0a87b881fb7b3.tar.bz2
chat-1329aa51b605cb54ba9aae3a82a0a87b881fb7b3.zip
Updating server dependancies. (#7816)
Diffstat (limited to 'vendor/github.com/go-ini/ini')
-rw-r--r--vendor/github.com/go-ini/ini/.github/ISSUE_TEMPLATE.md5
-rw-r--r--vendor/github.com/go-ini/ini/.github/PULL_REQUEST_TEMPLATE.md3
-rw-r--r--vendor/github.com/go-ini/ini/.gitignore1
-rw-r--r--vendor/github.com/go-ini/ini/.travis.yml4
-rw-r--r--vendor/github.com/go-ini/ini/LICENSE2
-rw-r--r--vendor/github.com/go-ini/ini/Makefile5
-rw-r--r--vendor/github.com/go-ini/ini/README.md29
-rw-r--r--vendor/github.com/go-ini/ini/README_ZH.md29
-rw-r--r--vendor/github.com/go-ini/ini/bench_test.go118
-rw-r--r--vendor/github.com/go-ini/ini/file.go392
-rw-r--r--vendor/github.com/go-ini/ini/file_test.go355
-rw-r--r--vendor/github.com/go-ini/ini/ini.go376
-rw-r--r--vendor/github.com/go-ini/ini/ini_internal_test.go35
-rw-r--r--vendor/github.com/go-ini/ini/ini_test.go672
-rw-r--r--vendor/github.com/go-ini/ini/key.go40
-rw-r--r--vendor/github.com/go-ini/ini/key_test.go391
-rw-r--r--vendor/github.com/go-ini/ini/parser.go25
-rw-r--r--vendor/github.com/go-ini/ini/parser_test.go49
-rw-r--r--vendor/github.com/go-ini/ini/section.go9
-rw-r--r--vendor/github.com/go-ini/ini/section_test.go306
-rw-r--r--vendor/github.com/go-ini/ini/struct.go16
-rw-r--r--vendor/github.com/go-ini/ini/struct_test.go99
-rw-r--r--vendor/github.com/go-ini/ini/testdata/aicc.ini11
-rw-r--r--vendor/github.com/go-ini/ini/testdata/full.ini83
-rw-r--r--vendor/github.com/go-ini/ini/testdata/minimal.ini (renamed from vendor/github.com/go-ini/ini/testdata/conf.ini)0
25 files changed, 1908 insertions, 1147 deletions
diff --git a/vendor/github.com/go-ini/ini/.github/ISSUE_TEMPLATE.md b/vendor/github.com/go-ini/ini/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 000000000..849f69f4b
--- /dev/null
+++ b/vendor/github.com/go-ini/ini/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,5 @@
+### Please give general description of the problem
+
+### Please provide code snippets to reproduce the problem described above
+
+### Do you have any suggestion to fix the problem? \ No newline at end of file
diff --git a/vendor/github.com/go-ini/ini/.github/PULL_REQUEST_TEMPLATE.md b/vendor/github.com/go-ini/ini/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 000000000..b4565aeb5
--- /dev/null
+++ b/vendor/github.com/go-ini/ini/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,3 @@
+### What problem should be fixed?
+
+### Have you added test cases to catch the problem?
diff --git a/vendor/github.com/go-ini/ini/.gitignore b/vendor/github.com/go-ini/ini/.gitignore
index c5203bf6e..12411127b 100644
--- a/vendor/github.com/go-ini/ini/.gitignore
+++ b/vendor/github.com/go-ini/ini/.gitignore
@@ -3,3 +3,4 @@ ini.sublime-project
ini.sublime-workspace
testdata/conf_reflect.ini
.idea
+/.vscode
diff --git a/vendor/github.com/go-ini/ini/.travis.yml b/vendor/github.com/go-ini/ini/.travis.yml
index d9d1b8ffa..b097527e1 100644
--- a/vendor/github.com/go-ini/ini/.travis.yml
+++ b/vendor/github.com/go-ini/ini/.travis.yml
@@ -5,9 +5,11 @@ go:
- 1.6.x
- 1.7.x
- 1.8.x
- - master
+ - 1.9.x
script:
- go get golang.org/x/tools/cmd/cover
- go get github.com/smartystreets/goconvey
+ - mkdir -p $HOME/gopath/src/gopkg.in
+ - ln -s $HOME/gopath/src/github.com/go-ini/ini $HOME/gopath/src/gopkg.in/ini.v1
- go test -v -cover -race
diff --git a/vendor/github.com/go-ini/ini/LICENSE b/vendor/github.com/go-ini/ini/LICENSE
index 37ec93a14..d361bbcdf 100644
--- a/vendor/github.com/go-ini/ini/LICENSE
+++ b/vendor/github.com/go-ini/ini/LICENSE
@@ -176,7 +176,7 @@ recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
- Copyright [yyyy] [name of copyright owner]
+ Copyright 2014 Unknwon
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/vendor/github.com/go-ini/ini/Makefile b/vendor/github.com/go-ini/ini/Makefile
index ac034e525..1316911d2 100644
--- a/vendor/github.com/go-ini/ini/Makefile
+++ b/vendor/github.com/go-ini/ini/Makefile
@@ -1,4 +1,4 @@
-.PHONY: build test bench vet
+.PHONY: build test bench vet coverage
build: vet bench
@@ -10,3 +10,6 @@ bench:
vet:
go vet
+
+coverage:
+ go test -coverprofile=c.out && go tool cover -html=c.out && rm c.out \ No newline at end of file
diff --git a/vendor/github.com/go-ini/ini/README.md b/vendor/github.com/go-ini/ini/README.md
index e67d51f32..f4ff27cd3 100644
--- a/vendor/github.com/go-ini/ini/README.md
+++ b/vendor/github.com/go-ini/ini/README.md
@@ -101,7 +101,7 @@ skip-name-resolve
By default, this is considered as missing value. But if you know you're going to deal with those cases, you can assign advanced load options:
```go
-cfg, err := LoadSources(LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
+cfg, err := ini.LoadSources(ini.LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
```
The value of those keys are always `true`, and when you save to a file, it will keep in the same foramt as you read.
@@ -125,7 +125,7 @@ If you want to save a value with `#` or `;`, please quote them with ``` ` ``` or
Alternatively, you can use following `LoadOptions` to completely ignore inline comments:
```go
-cfg, err := LoadSources(LoadOptions{IgnoreInlineComment: true}, "app.ini"))
+cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, "app.ini"))
```
### Working with sections
@@ -329,6 +329,20 @@ foo = "some value" // foo: some value
bar = 'some value' // bar: some value
```
+Sometimes you downloaded file from [Crowdin](https://crowdin.com/) has values like the following (value is surrounded by double quotes and quotes in the value are escaped):
+
+```ini
+create_repo="created repository <a href=\"%s\">%s</a>"
+```
+
+How do you transform this to regular format automatically?
+
+```go
+cfg, err := ini.LoadSources(ini.LoadOptions{UnescapeValueDoubleQuotes: true}, "en-US.ini"))
+cfg.Section("<name of your section>").Key("create_repo").String()
+// You got: created repository <a href="%s">%s</a>
+```
+
That's all? Hmm, no.
#### Helper methods of working with values
@@ -480,7 +494,7 @@ cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
Sometimes, you have sections that do not contain key-value pairs but raw content, to handle such case, you can use `LoadOptions.UnparsableSections`:
```go
-cfg, err := LoadSources(LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
+cfg, err := ini.LoadSources(ini.LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
body := cfg.Section("COMMENTS").Body()
@@ -573,7 +587,7 @@ Why not?
```go
type Embeded struct {
- Dates []time.Time `delim:"|"`
+ Dates []time.Time `delim:"|" comment:"Time data"`
Places []string `ini:"places,omitempty"`
None []int `ini:",omitempty"`
}
@@ -581,10 +595,10 @@ type Embeded struct {
type Author struct {
Name string `ini:"NAME"`
Male bool
- Age int
+ Age int `comment:"Author's age"`
GPA float64
NeverMind string `ini:"-"`
- *Embeded
+ *Embeded `comment:"Embeded section"`
}
func main() {
@@ -605,10 +619,13 @@ So, what do I get?
```ini
NAME = Unknwon
Male = true
+; Author's age
Age = 21
GPA = 2.8
+; Embeded section
[Embeded]
+; Time data
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
places = HangZhou,Boston
```
diff --git a/vendor/github.com/go-ini/ini/README_ZH.md b/vendor/github.com/go-ini/ini/README_ZH.md
index 0cf419449..69aefef12 100644
--- a/vendor/github.com/go-ini/ini/README_ZH.md
+++ b/vendor/github.com/go-ini/ini/README_ZH.md
@@ -94,7 +94,7 @@ skip-name-resolve
默认情况下这被认为是缺失值而无法完成解析,但可以通过高级的加载选项对它们进行处理:
```go
-cfg, err := LoadSources(LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
+cfg, err := ini.LoadSources(ini.LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
```
这些键的值永远为 `true`,且在保存到文件时也只会输出键名。
@@ -118,7 +118,7 @@ key, err := sec.NewBooleanKey("skip-host-cache")
除此之外,您还可以通过 `LoadOptions` 完全忽略行内注释:
```go
-cfg, err := LoadSources(LoadOptions{IgnoreInlineComment: true}, "app.ini"))
+cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, "app.ini"))
```
### 操作分区(Section)
@@ -322,6 +322,20 @@ foo = "some value" // foo: some value
bar = 'some value' // bar: some value
```
+有时您会获得像从 [Crowdin](https://crowdin.com/) 网站下载的文件那样具有特殊格式的值(值使用双引号括起来,内部的双引号被转义):
+
+```ini
+create_repo="创建了仓库 <a href=\"%s\">%s</a>"
+```
+
+那么,怎么自动地将这类值进行处理呢?
+
+```go
+cfg, err := ini.LoadSources(ini.LoadOptions{UnescapeValueDoubleQuotes: true}, "en-US.ini"))
+cfg.Section("<name of your section>").Key("create_repo").String()
+// You got: 创建了仓库 <a href="%s">%s</a>
+```
+
这就是全部了?哈哈,当然不是。
#### 操作键值的辅助方法
@@ -473,7 +487,7 @@ cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
如果遇到一些比较特殊的分区,它们不包含常见的键值对,而是没有固定格式的纯文本,则可以使用 `LoadOptions.UnparsableSections` 进行处理:
```go
-cfg, err := LoadSources(LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
+cfg, err := LoadSources(ini.LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
body := cfg.Section("COMMENTS").Body()
@@ -564,7 +578,7 @@ p := &Person{
```go
type Embeded struct {
- Dates []time.Time `delim:"|"`
+ Dates []time.Time `delim:"|" comment:"Time data"`
Places []string `ini:"places,omitempty"`
None []int `ini:",omitempty"`
}
@@ -572,10 +586,10 @@ type Embeded struct {
type Author struct {
Name string `ini:"NAME"`
Male bool
- Age int
+ Age int `comment:"Author's age"`
GPA float64
NeverMind string `ini:"-"`
- *Embeded
+ *Embeded `comment:"Embeded section"`
}
func main() {
@@ -596,10 +610,13 @@ func main() {
```ini
NAME = Unknwon
Male = true
+; Author's age
Age = 21
GPA = 2.8
+; Embeded section
[Embeded]
+; Time data
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
places = HangZhou,Boston
```
diff --git a/vendor/github.com/go-ini/ini/bench_test.go b/vendor/github.com/go-ini/ini/bench_test.go
new file mode 100644
index 000000000..fc1802469
--- /dev/null
+++ b/vendor/github.com/go-ini/ini/bench_test.go
@@ -0,0 +1,118 @@
+// Copyright 2017 Unknwon
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package ini_test
+
+import (
+ "testing"
+
+ "gopkg.in/ini.v1"
+)
+
+func newTestFile(block bool) *ini.File {
+ c, _ := ini.Load([]byte(_CONF_DATA))
+ c.BlockMode = block
+ return c
+}
+
+func Benchmark_Key_Value(b *testing.B) {
+ c := newTestFile(true)
+ for i := 0; i < b.N; i++ {
+ c.Section("").Key("NAME").Value()
+ }
+}
+
+func Benchmark_Key_Value_NonBlock(b *testing.B) {
+ c := newTestFile(false)
+ for i := 0; i < b.N; i++ {
+ c.Section("").Key("NAME").Value()
+ }
+}
+
+func Benchmark_Key_Value_ViaSection(b *testing.B) {
+ c := newTestFile(true)
+ sec := c.Section("")
+ for i := 0; i < b.N; i++ {
+ sec.Key("NAME").Value()
+ }
+}
+
+func Benchmark_Key_Value_ViaSection_NonBlock(b *testing.B) {
+ c := newTestFile(false)
+ sec := c.Section("")
+ for i := 0; i < b.N; i++ {
+ sec.Key("NAME").Value()
+ }
+}
+
+func Benchmark_Key_Value_Direct(b *testing.B) {
+ c := newTestFile(true)
+ key := c.Section("").Key("NAME")
+ for i := 0; i < b.N; i++ {
+ key.Value()
+ }
+}
+
+func Benchmark_Key_Value_Direct_NonBlock(b *testing.B) {
+ c := newTestFile(false)
+ key := c.Section("").Key("NAME")
+ for i := 0; i < b.N; i++ {
+ key.Value()
+ }
+}
+
+func Benchmark_Key_String(b *testing.B) {
+ c := newTestFile(true)
+ for i := 0; i < b.N; i++ {
+ _ = c.Section("").Key("NAME").String()
+ }
+}
+
+func Benchmark_Key_String_NonBlock(b *testing.B) {
+ c := newTestFile(false)
+ for i := 0; i < b.N; i++ {
+ _ = c.Section("").Key("NAME").String()
+ }
+}
+
+func Benchmark_Key_String_ViaSection(b *testing.B) {
+ c := newTestFile(true)
+ sec := c.Section("")
+ for i := 0; i < b.N; i++ {
+ _ = sec.Key("NAME").String()
+ }
+}
+
+func Benchmark_Key_String_ViaSection_NonBlock(b *testing.B) {
+ c := newTestFile(false)
+ sec := c.Section("")
+ for i := 0; i < b.N; i++ {
+ _ = sec.Key("NAME").String()
+ }
+}
+
+func Benchmark_Key_SetValue(b *testing.B) {
+ c := newTestFile(true)
+ for i := 0; i < b.N; i++ {
+ c.Section("").Key("NAME").SetValue("10")
+ }
+}
+
+func Benchmark_Key_SetValue_VisSection(b *testing.B) {
+ c := newTestFile(true)
+ sec := c.Section("")
+ for i := 0; i < b.N; i++ {
+ sec.Key("NAME").SetValue("10")
+ }
+}
diff --git a/vendor/github.com/go-ini/ini/file.go b/vendor/github.com/go-ini/ini/file.go
new file mode 100644
index 000000000..93ac50836
--- /dev/null
+++ b/vendor/github.com/go-ini/ini/file.go
@@ -0,0 +1,392 @@
+// Copyright 2017 Unknwon
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package ini
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "strings"
+ "sync"
+)
+
+// File represents a combination of a or more INI file(s) in memory.
+type File struct {
+ options LoadOptions
+ dataSources []dataSource
+
+ // Should make things safe, but sometimes doesn't matter.
+ BlockMode bool
+ lock sync.RWMutex
+
+ // To keep data in order.
+ sectionList []string
+ // Actual data is stored here.
+ sections map[string]*Section
+
+ NameMapper
+ ValueMapper
+}
+
+// newFile initializes File object with given data sources.
+func newFile(dataSources []dataSource, opts LoadOptions) *File {
+ return &File{
+ BlockMode: true,
+ dataSources: dataSources,
+ sections: make(map[string]*Section),
+ sectionList: make([]string, 0, 10),
+ options: opts,
+ }
+}
+
+// Empty returns an empty file object.
+func Empty() *File {
+ // Ignore error here, we sure our data is good.
+ f, _ := Load([]byte(""))
+ return f
+}
+
+// NewSection creates a new section.
+func (f *File) NewSection(name string) (*Section, error) {
+ if len(name) == 0 {
+ return nil, errors.New("error creating new section: empty section name")
+ } else if f.options.Insensitive && name != DEFAULT_SECTION {
+ name = strings.ToLower(name)
+ }
+
+ if f.BlockMode {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+ }
+
+ if inSlice(name, f.sectionList) {
+ return f.sections[name], nil
+ }
+
+ f.sectionList = append(f.sectionList, name)
+ f.sections[name] = newSection(f, name)
+ return f.sections[name], nil
+}
+
+// NewRawSection creates a new section with an unparseable body.
+func (f *File) NewRawSection(name, body string) (*Section, error) {
+ section, err := f.NewSection(name)
+ if err != nil {
+ return nil, err
+ }
+
+ section.isRawSection = true
+ section.rawBody = body
+ return section, nil
+}
+
+// NewSections creates a list of sections.
+func (f *File) NewSections(names ...string) (err error) {
+ for _, name := range names {
+ if _, err = f.NewSection(name); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// GetSection returns section by given name.
+func (f *File) GetSection(name string) (*Section, error) {
+ if len(name) == 0 {
+ name = DEFAULT_SECTION
+ }
+ if f.options.Insensitive {
+ name = strings.ToLower(name)
+ }
+
+ if f.BlockMode {
+ f.lock.RLock()
+ defer f.lock.RUnlock()
+ }
+
+ sec := f.sections[name]
+ if sec == nil {
+ return nil, fmt.Errorf("section '%s' does not exist", name)
+ }
+ return sec, nil
+}
+
+// Section assumes named section exists and returns a zero-value when not.
+func (f *File) Section(name string) *Section {
+ sec, err := f.GetSection(name)
+ if err != nil {
+ // Note: It's OK here because the only possible error is empty section name,
+ // but if it's empty, this piece of code won't be executed.
+ sec, _ = f.NewSection(name)
+ return sec
+ }
+ return sec
+}
+
+// Section returns list of Section.
+func (f *File) Sections() []*Section {
+ sections := make([]*Section, len(f.sectionList))
+ for i := range f.sectionList {
+ sections[i] = f.Section(f.sectionList[i])
+ }
+ return sections
+}
+
+// ChildSections returns a list of child sections of given section name.
+func (f *File) ChildSections(name string) []*Section {
+ return f.Section(name).ChildSections()
+}
+
+// SectionStrings returns list of section names.
+func (f *File) SectionStrings() []string {
+ list := make([]string, len(f.sectionList))
+ copy(list, f.sectionList)
+ return list
+}
+
+// DeleteSection deletes a section.
+func (f *File) DeleteSection(name string) {
+ if f.BlockMode {
+ f.lock.Lock()
+ defer f.lock.Unlock()
+ }
+
+ if len(name) == 0 {
+ name = DEFAULT_SECTION
+ }
+
+ for i, s := range f.sectionList {
+ if s == name {
+ f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...)
+ delete(f.sections, name)
+ return
+ }
+ }
+}
+
+func (f *File) reload(s dataSource) error {
+ r, err := s.ReadCloser()
+ if err != nil {
+ return err
+ }
+ defer r.Close()
+
+ return f.parse(r)
+}
+
+// Reload reloads and parses all data sources.
+func (f *File) Reload() (err error) {
+ for _, s := range f.dataSources {
+ if err = f.reload(s); err != nil {
+ // In loose mode, we create an empty default section for nonexistent files.
+ if os.IsNotExist(err) && f.options.Loose {
+ f.parse(bytes.NewBuffer(nil))
+ continue
+ }
+ return err
+ }
+ }
+ return nil
+}
+
+// Append appends one or more data sources and reloads automatically.
+func (f *File) Append(source interface{}, others ...interface{}) error {
+ ds, err := parseDataSource(source)
+ if err != nil {
+ return err
+ }
+ f.dataSources = append(f.dataSources, ds)
+ for _, s := range others {
+ ds, err = parseDataSource(s)
+ if err != nil {
+ return err
+ }
+ f.dataSources = append(f.dataSources, ds)
+ }
+ return f.Reload()
+}
+
+func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
+ equalSign := "="
+ if PrettyFormat {
+ equalSign = " = "
+ }
+
+ // Use buffer to make sure target is safe until finish encoding.
+ buf := bytes.NewBuffer(nil)
+ for i, sname := range f.sectionList {
+ sec := f.Section(sname)
+ if len(sec.Comment) > 0 {
+ if sec.Comment[0] != '#' && sec.Comment[0] != ';' {
+ sec.Comment = "; " + sec.Comment
+ } else {
+ sec.Comment = sec.Comment[:1] + " " + strings.TrimSpace(sec.Comment[1:])
+ }
+ if _, err := buf.WriteString(sec.Comment + LineBreak); err != nil {
+ return nil, err
+ }
+ }
+
+ if i > 0 || DefaultHeader {
+ if _, err := buf.WriteString("[" + sname + "]" + LineBreak); err != nil {
+ return nil, err
+ }
+ } else {
+ // Write nothing if default section is empty
+ if len(sec.keyList) == 0 {
+ continue
+ }
+ }
+
+ if sec.isRawSection {
+ if _, err := buf.WriteString(sec.rawBody); err != nil {
+ return nil, err
+ }
+
+ if PrettySection {
+ // Put a line between sections
+ if _, err := buf.WriteString(LineBreak); err != nil {
+ return nil, err
+ }
+ }
+ continue
+ }
+
+ // Count and generate alignment length and buffer spaces using the
+ // longest key. Keys may be modifed if they contain certain characters so
+ // we need to take that into account in our calculation.
+ alignLength := 0
+ if PrettyFormat {
+ for _, kname := range sec.keyList {
+ keyLength := len(kname)
+ // First case will surround key by ` and second by """
+ if strings.ContainsAny(kname, "\"=:") {
+ keyLength += 2
+ } else if strings.Contains(kname, "`") {
+ keyLength += 6
+ }
+
+ if keyLength > alignLength {
+ alignLength = keyLength
+ }
+ }
+ }
+ alignSpaces := bytes.Repeat([]byte(" "), alignLength)
+
+ KEY_LIST:
+ for _, kname := range sec.keyList {
+ key := sec.Key(kname)
+ if len(key.Comment) > 0 {
+ if len(indent) > 0 && sname != DEFAULT_SECTION {
+ buf.WriteString(indent)
+ }
+ if key.Comment[0] != '#' && key.Comment[0] != ';' {
+ key.Comment = "; " + key.Comment
+ } else {
+ key.Comment = key.Comment[:1] + " " + strings.TrimSpace(key.Comment[1:])
+ }
+ if _, err := buf.WriteString(key.Comment + LineBreak); err != nil {
+ return nil, err
+ }
+ }
+
+ if len(indent) > 0 && sname != DEFAULT_SECTION {
+ buf.WriteString(indent)
+ }
+
+ switch {
+ case key.isAutoIncrement:
+ kname = "-"
+ case strings.ContainsAny(kname, "\"=:"):
+ kname = "`" + kname + "`"
+ case strings.Contains(kname, "`"):
+ kname = `"""` + kname + `"""`
+ }
+
+ for _, val := range key.ValueWithShadows() {
+ if _, err := buf.WriteString(kname); err != nil {
+ return nil, err
+ }
+
+ if key.isBooleanType {
+ if kname != sec.keyList[len(sec.keyList)-1] {
+ buf.WriteString(LineBreak)
+ }
+ continue KEY_LIST
+ }
+
+ // Write out alignment spaces before "=" sign
+ if PrettyFormat {
+ buf.Write(alignSpaces[:alignLength-len(kname)])
+ }
+
+ // In case key value contains "\n", "`", "\"", "#" or ";"
+ if strings.ContainsAny(val, "\n`") {
+ val = `"""` + val + `"""`
+ } else if !f.options.IgnoreInlineComment && strings.ContainsAny(val, "#;") {
+ val = "`" + val + "`"
+ }
+ if _, err := buf.WriteString(equalSign + val + LineBreak); err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ if PrettySection {
+ // Put a line between sections
+ if _, err := buf.WriteString(LineBreak); err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ return buf, nil
+}
+
+// WriteToIndent writes content into io.Writer with given indention.
+// If PrettyFormat has been set to be true,
+// it will align "=" sign with spaces under each section.
+func (f *File) WriteToIndent(w io.Writer, indent string) (int64, error) {
+ buf, err := f.writeToBuffer(indent)
+ if err != nil {
+ return 0, err
+ }
+ return buf.WriteTo(w)
+}
+
+// WriteTo writes file content into io.Writer.
+func (f *File) WriteTo(w io.Writer) (int64, error) {
+ return f.WriteToIndent(w, "")
+}
+
+// SaveToIndent writes content to file system with given value indention.
+func (f *File) SaveToIndent(filename, indent string) error {
+ // Note: Because we are truncating with os.Create,
+ // so it's safer to save to a temporary file location and rename afte done.
+ buf, err := f.writeToBuffer(indent)
+ if err != nil {
+ return err
+ }
+
+ return ioutil.WriteFile(filename, buf.Bytes(), 0666)
+}
+
+// SaveTo writes content to file system.
+func (f *File) SaveTo(filename string) error {
+ return f.SaveToIndent(filename, "")
+}
diff --git a/vendor/github.com/go-ini/ini/file_test.go b/vendor/github.com/go-ini/ini/file_test.go
new file mode 100644
index 000000000..11612eb9a
--- /dev/null
+++ b/vendor/github.com/go-ini/ini/file_test.go
@@ -0,0 +1,355 @@
+// Copyright 2017 Unknwon
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package ini_test
+
+import (
+ "bytes"
+ "testing"
+
+ . "github.com/smartystreets/goconvey/convey"
+ "gopkg.in/ini.v1"
+)
+
+func TestEmpty(t *testing.T) {
+ Convey("Create an empty object", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ // Should only have the default section
+ So(len(f.Sections()), ShouldEqual, 1)
+
+ // Default section should not contain any key
+ So(len(f.Section("").Keys()), ShouldBeZeroValue)
+ })
+}
+
+func TestFile_NewSection(t *testing.T) {
+ Convey("Create a new section", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ sec, err := f.NewSection("author")
+ So(err, ShouldBeNil)
+ So(sec, ShouldNotBeNil)
+ So(sec.Name(), ShouldEqual, "author")
+
+ So(f.SectionStrings(), ShouldResemble, []string{ini.DEFAULT_SECTION, "author"})
+
+ Convey("With duplicated name", func() {
+ sec, err := f.NewSection("author")
+ So(err, ShouldBeNil)
+ So(sec, ShouldNotBeNil)
+
+ // Does nothing if section already exists
+ So(f.SectionStrings(), ShouldResemble, []string{ini.DEFAULT_SECTION, "author"})
+ })
+
+ Convey("With empty string", func() {
+ _, err := f.NewSection("")
+ So(err, ShouldNotBeNil)
+ })
+ })
+}
+
+func TestFile_NewRawSection(t *testing.T) {
+ Convey("Create a new raw section", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ sec, err := f.NewRawSection("comments", `1111111111111111111000000000000000001110000
+111111111111111111100000000000111000000000`)
+ So(err, ShouldBeNil)
+ So(sec, ShouldNotBeNil)
+ So(sec.Name(), ShouldEqual, "comments")
+
+ So(f.SectionStrings(), ShouldResemble, []string{ini.DEFAULT_SECTION, "comments"})
+ So(f.Section("comments").Body(), ShouldEqual, `1111111111111111111000000000000000001110000
+111111111111111111100000000000111000000000`)
+
+ Convey("With duplicated name", func() {
+ sec, err := f.NewRawSection("comments", `1111111111111111111000000000000000001110000`)
+ So(err, ShouldBeNil)
+ So(sec, ShouldNotBeNil)
+ So(f.SectionStrings(), ShouldResemble, []string{ini.DEFAULT_SECTION, "comments"})
+
+ // Overwrite previous existed section
+ So(f.Section("comments").Body(), ShouldEqual, `1111111111111111111000000000000000001110000`)
+ })
+
+ Convey("With empty string", func() {
+ _, err := f.NewRawSection("", "")
+ So(err, ShouldNotBeNil)
+ })
+ })
+}
+
+func TestFile_NewSections(t *testing.T) {
+ Convey("Create new sections", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ So(f.NewSections("package", "author"), ShouldBeNil)
+ So(f.SectionStrings(), ShouldResemble, []string{ini.DEFAULT_SECTION, "package", "author"})
+
+ Convey("With duplicated name", func() {
+ So(f.NewSections("author", "features"), ShouldBeNil)
+
+ // Ignore section already exists
+ So(f.SectionStrings(), ShouldResemble, []string{ini.DEFAULT_SECTION, "package", "author", "features"})
+ })
+
+ Convey("With empty string", func() {
+ So(f.NewSections("", ""), ShouldNotBeNil)
+ })
+ })
+}
+
+func TestFile_GetSection(t *testing.T) {
+ Convey("Get a section", t, func() {
+ f, err := ini.Load(_FULL_CONF)
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ sec, err := f.GetSection("author")
+ So(err, ShouldBeNil)
+ So(sec, ShouldNotBeNil)
+ So(sec.Name(), ShouldEqual, "author")
+
+ Convey("Section not exists", func() {
+ _, err := f.GetSection("404")
+ So(err, ShouldNotBeNil)
+ })
+ })
+}
+
+func TestFile_Section(t *testing.T) {
+ Convey("Get a section", t, func() {
+ f, err := ini.Load(_FULL_CONF)
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ sec := f.Section("author")
+ So(sec, ShouldNotBeNil)
+ So(sec.Name(), ShouldEqual, "author")
+
+ Convey("Section not exists", func() {
+ sec := f.Section("404")
+ So(sec, ShouldNotBeNil)
+ So(sec.Name(), ShouldEqual, "404")
+ })
+ })
+
+ Convey("Get default section in lower case with insensitive load", t, func() {
+ f, err := ini.InsensitiveLoad([]byte(`
+[default]
+NAME = ini
+VERSION = v1`))
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ So(f.Section("").Key("name").String(), ShouldEqual, "ini")
+ So(f.Section("").Key("version").String(), ShouldEqual, "v1")
+ })
+}
+
+func TestFile_Sections(t *testing.T) {
+ Convey("Get all sections", t, func() {
+ f, err := ini.Load(_FULL_CONF)
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ secs := f.Sections()
+ names := []string{ini.DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"}
+ So(len(secs), ShouldEqual, len(names))
+ for i, name := range names {
+ So(secs[i].Name(), ShouldEqual, name)
+ }
+ })
+}
+
+func TestFile_ChildSections(t *testing.T) {
+ Convey("Get child sections by parent name", t, func() {
+ f, err := ini.Load([]byte(`
+[node]
+[node.biz1]
+[node.biz2]
+[node.biz3]
+[node.bizN]
+`))
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ children := f.ChildSections("node")
+ names := []string{"node.biz1", "node.biz2", "node.biz3", "node.bizN"}
+ So(len(children), ShouldEqual, len(names))
+ for i, name := range names {
+ So(children[i].Name(), ShouldEqual, name)
+ }
+ })
+}
+
+func TestFile_SectionStrings(t *testing.T) {
+ Convey("Get all section names", t, func() {
+ f, err := ini.Load(_FULL_CONF)
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ So(f.SectionStrings(), ShouldResemble, []string{ini.DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"})
+ })
+}
+
+func TestFile_DeleteSection(t *testing.T) {
+ Convey("Delete a section", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ f.NewSections("author", "package", "features")
+ f.DeleteSection("features")
+ f.DeleteSection("")
+ So(f.SectionStrings(), ShouldResemble, []string{"author", "package"})
+ })
+}
+
+func TestFile_Append(t *testing.T) {
+ Convey("Append a data source", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ So(f.Append(_MINIMAL_CONF, []byte(`
+[author]
+NAME = Unknwon`)), ShouldBeNil)
+
+ Convey("With bad input", func() {
+ So(f.Append(123), ShouldNotBeNil)
+ So(f.Append(_MINIMAL_CONF, 123), ShouldNotBeNil)
+ })
+ })
+}
+
+func TestFile_WriteTo(t *testing.T) {
+ Convey("Write content to somewhere", t, func() {
+ f, err := ini.Load(_FULL_CONF)
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ f.Section("author").Comment = `Information about package author
+# Bio can be written in multiple lines.`
+ f.Section("author").Key("NAME").Comment = "This is author name"
+ f.Section("note").NewBooleanKey("boolean_key")
+ f.Section("note").NewKey("more", "notes")
+
+ var buf bytes.Buffer
+ _, err = f.WriteTo(&buf)
+ So(err, ShouldBeNil)
+ So(buf.String(), ShouldEqual, `; Package name
+NAME = ini
+; Package version
+VERSION = v1
+; Package import path
+IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
+
+; Information about package author
+# Bio can be written in multiple lines.
+[author]
+; This is author name
+NAME = Unknwon
+E-MAIL = u@gogs.io
+GITHUB = https://github.com/%(NAME)s
+# Succeeding comment
+BIO = """Gopher.
+Coding addict.
+Good man.
+"""
+
+[package]
+CLONE_URL = https://%(IMPORT_PATH)s
+
+[package.sub]
+UNUSED_KEY = should be deleted
+
+[features]
+- = Support read/write comments of keys and sections
+- = Support auto-increment of key names
+- = Support load multiple files to overwrite key values
+
+[types]
+STRING = str
+BOOL = true
+BOOL_FALSE = false
+FLOAT64 = 1.25
+INT = 10
+TIME = 2015-01-01T20:17:05Z
+DURATION = 2h45m
+UINT = 3
+
+[array]
+STRINGS = en, zh, de
+FLOAT64S = 1.1, 2.2, 3.3
+INTS = 1, 2, 3
+UINTS = 1, 2, 3
+TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z
+
+[note]
+empty_lines = next line is empty
+boolean_key
+more = notes
+
+; Comment before the section
+; This is a comment for the section too
+[comments]
+; Comment before key
+key = value
+; This is a comment for key2
+key2 = value2
+key3 = "one", "two", "three"
+
+[string escapes]
+key1 = value1, value2, value3
+key2 = value1\, value2
+key3 = val\ue1, value2
+key4 = value1\\, value\\\\2
+key5 = value1\,, value2
+key6 = aaa bbb\ and\ space ccc
+
+[advance]
+value with quotes = some value
+value quote2 again = some value
+includes comment sign = `+"`"+"my#password"+"`"+`
+includes comment sign2 = `+"`"+"my;password"+"`"+`
+true = 2+3=5
+`+"`"+`1+1=2`+"`"+` = true
+`+"`"+`6+1=7`+"`"+` = true
+"""`+"`"+`5+5`+"`"+`""" = 10
+`+"`"+`"6+6"`+"`"+` = 12
+`+"`"+`7-2=4`+"`"+` = false
+ADDRESS = """404 road,
+NotFound, State, 50000"""
+two_lines = how about continuation lines?
+lots_of_lines = 1 2 3 4
+
+`)
+ })
+}
+
+func TestFile_SaveTo(t *testing.T) {
+ Convey("Write content to somewhere", t, func() {
+ f, err := ini.Load(_FULL_CONF)
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ So(f.SaveTo("testdata/conf_out.ini"), ShouldBeNil)
+ So(f.SaveToIndent("testdata/conf_out.ini", "\t"), ShouldBeNil)
+ })
+}
diff --git a/vendor/github.com/go-ini/ini/ini.go b/vendor/github.com/go-ini/ini/ini.go
index 7f3c4d1ed..508d60c19 100644
--- a/vendor/github.com/go-ini/ini/ini.go
+++ b/vendor/github.com/go-ini/ini/ini.go
@@ -17,15 +17,12 @@ package ini
import (
"bytes"
- "errors"
"fmt"
"io"
"io/ioutil"
"os"
"regexp"
"runtime"
- "strings"
- "sync"
)
const (
@@ -35,7 +32,7 @@ const (
// Maximum allowed depth when recursively substituing variable names.
_DEPTH_VALUES = 99
- _VERSION = "1.28.2"
+ _VERSION = "1.30.3"
)
// Version returns current package version literal.
@@ -92,18 +89,6 @@ func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) {
return os.Open(s.name)
}
-type bytesReadCloser struct {
- reader io.Reader
-}
-
-func (rc *bytesReadCloser) Read(p []byte) (n int, err error) {
- return rc.reader.Read(p)
-}
-
-func (rc *bytesReadCloser) Close() error {
- return nil
-}
-
// sourceData represents an object that contains content in memory.
type sourceData struct {
data []byte
@@ -122,38 +107,6 @@ func (s *sourceReadCloser) ReadCloser() (io.ReadCloser, error) {
return s.reader, nil
}
-// File represents a combination of a or more INI file(s) in memory.
-type File struct {
- // Should make things safe, but sometimes doesn't matter.
- BlockMode bool
- // Make sure data is safe in multiple goroutines.
- lock sync.RWMutex
-
- // Allow combination of multiple data sources.
- dataSources []dataSource
- // Actual data is stored here.
- sections map[string]*Section
-
- // To keep data in order.
- sectionList []string
-
- options LoadOptions
-
- NameMapper
- ValueMapper
-}
-
-// newFile initializes File object with given data sources.
-func newFile(dataSources []dataSource, opts LoadOptions) *File {
- return &File{
- BlockMode: true,
- dataSources: dataSources,
- sections: make(map[string]*Section),
- sectionList: make([]string, 0, 10),
- options: opts,
- }
-}
-
func parseDataSource(source interface{}) (dataSource, error) {
switch s := source.(type) {
case string:
@@ -181,6 +134,8 @@ type LoadOptions struct {
AllowBooleanKeys bool
// AllowShadows indicates whether to keep track of keys with same name under same section.
AllowShadows bool
+ // UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value"
+ UnescapeValueDoubleQuotes bool
// Some INI formats allow group blocks that store a block of raw content that doesn't otherwise
// conform to key/value pairs. Specify the names of those blocks here.
UnparseableSections []string
@@ -229,328 +184,3 @@ func InsensitiveLoad(source interface{}, others ...interface{}) (*File, error) {
func ShadowLoad(source interface{}, others ...interface{}) (*File, error) {
return LoadSources(LoadOptions{AllowShadows: true}, source, others...)
}
-
-// Empty returns an empty file object.
-func Empty() *File {
- // Ignore error here, we sure our data is good.
- f, _ := Load([]byte(""))
- return f
-}
-
-// NewSection creates a new section.
-func (f *File) NewSection(name string) (*Section, error) {
- if len(name) == 0 {
- return nil, errors.New("error creating new section: empty section name")
- } else if f.options.Insensitive && name != DEFAULT_SECTION {
- name = strings.ToLower(name)
- }
-
- if f.BlockMode {
- f.lock.Lock()
- defer f.lock.Unlock()
- }
-
- if inSlice(name, f.sectionList) {
- return f.sections[name], nil
- }
-
- f.sectionList = append(f.sectionList, name)
- f.sections[name] = newSection(f, name)
- return f.sections[name], nil
-}
-
-// NewRawSection creates a new section with an unparseable body.
-func (f *File) NewRawSection(name, body string) (*Section, error) {
- section, err := f.NewSection(name)
- if err != nil {
- return nil, err
- }
-
- section.isRawSection = true
- section.rawBody = body
- return section, nil
-}
-
-// NewSections creates a list of sections.
-func (f *File) NewSections(names ...string) (err error) {
- for _, name := range names {
- if _, err = f.NewSection(name); err != nil {
- return err
- }
- }
- return nil
-}
-
-// GetSection returns section by given name.
-func (f *File) GetSection(name string) (*Section, error) {
- if len(name) == 0 {
- name = DEFAULT_SECTION
- } else if f.options.Insensitive {
- name = strings.ToLower(name)
- }
-
- if f.BlockMode {
- f.lock.RLock()
- defer f.lock.RUnlock()
- }
-
- sec := f.sections[name]
- if sec == nil {
- return nil, fmt.Errorf("section '%s' does not exist", name)
- }
- return sec, nil
-}
-
-// Section assumes named section exists and returns a zero-value when not.
-func (f *File) Section(name string) *Section {
- sec, err := f.GetSection(name)
- if err != nil {
- // Note: It's OK here because the only possible error is empty section name,
- // but if it's empty, this piece of code won't be executed.
- sec, _ = f.NewSection(name)
- return sec
- }
- return sec
-}
-
-// Section returns list of Section.
-func (f *File) Sections() []*Section {
- sections := make([]*Section, len(f.sectionList))
- for i := range f.sectionList {
- sections[i] = f.Section(f.sectionList[i])
- }
- return sections
-}
-
-// ChildSections returns a list of child sections of given section name.
-func (f *File) ChildSections(name string) []*Section {
- return f.Section(name).ChildSections()
-}
-
-// SectionStrings returns list of section names.
-func (f *File) SectionStrings() []string {
- list := make([]string, len(f.sectionList))
- copy(list, f.sectionList)
- return list
-}
-
-// DeleteSection deletes a section.
-func (f *File) DeleteSection(name string) {
- if f.BlockMode {
- f.lock.Lock()
- defer f.lock.Unlock()
- }
-
- if len(name) == 0 {
- name = DEFAULT_SECTION
- }
-
- for i, s := range f.sectionList {
- if s == name {
- f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...)
- delete(f.sections, name)
- return
- }
- }
-}
-
-func (f *File) reload(s dataSource) error {
- r, err := s.ReadCloser()
- if err != nil {
- return err
- }
- defer r.Close()
-
- return f.parse(r)
-}
-
-// Reload reloads and parses all data sources.
-func (f *File) Reload() (err error) {
- for _, s := range f.dataSources {
- if err = f.reload(s); err != nil {
- // In loose mode, we create an empty default section for nonexistent files.
- if os.IsNotExist(err) && f.options.Loose {
- f.parse(bytes.NewBuffer(nil))
- continue
- }
- return err
- }
- }
- return nil
-}
-
-// Append appends one or more data sources and reloads automatically.
-func (f *File) Append(source interface{}, others ...interface{}) error {
- ds, err := parseDataSource(source)
- if err != nil {
- return err
- }
- f.dataSources = append(f.dataSources, ds)
- for _, s := range others {
- ds, err = parseDataSource(s)
- if err != nil {
- return err
- }
- f.dataSources = append(f.dataSources, ds)
- }
- return f.Reload()
-}
-
-func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
- equalSign := "="
- if PrettyFormat {
- equalSign = " = "
- }
-
- // Use buffer to make sure target is safe until finish encoding.
- buf := bytes.NewBuffer(nil)
- for i, sname := range f.sectionList {
- sec := f.Section(sname)
- if len(sec.Comment) > 0 {
- if sec.Comment[0] != '#' && sec.Comment[0] != ';' {
- sec.Comment = "; " + sec.Comment
- }
- if _, err := buf.WriteString(sec.Comment + LineBreak); err != nil {
- return nil, err
- }
- }
-
- if i > 0 || DefaultHeader {
- if _, err := buf.WriteString("[" + sname + "]" + LineBreak); err != nil {
- return nil, err
- }
- } else {
- // Write nothing if default section is empty
- if len(sec.keyList) == 0 {
- continue
- }
- }
-
- if sec.isRawSection {
- if _, err := buf.WriteString(sec.rawBody); err != nil {
- return nil, err
- }
- continue
- }
-
- // Count and generate alignment length and buffer spaces using the
- // longest key. Keys may be modifed if they contain certain characters so
- // we need to take that into account in our calculation.
- alignLength := 0
- if PrettyFormat {
- for _, kname := range sec.keyList {
- keyLength := len(kname)
- // First case will surround key by ` and second by """
- if strings.ContainsAny(kname, "\"=:") {
- keyLength += 2
- } else if strings.Contains(kname, "`") {
- keyLength += 6
- }
-
- if keyLength > alignLength {
- alignLength = keyLength
- }
- }
- }
- alignSpaces := bytes.Repeat([]byte(" "), alignLength)
-
- KEY_LIST:
- for _, kname := range sec.keyList {
- key := sec.Key(kname)
- if len(key.Comment) > 0 {
- if len(indent) > 0 && sname != DEFAULT_SECTION {
- buf.WriteString(indent)
- }
- if key.Comment[0] != '#' && key.Comment[0] != ';' {
- key.Comment = "; " + key.Comment
- }
- if _, err := buf.WriteString(key.Comment + LineBreak); err != nil {
- return nil, err
- }
- }
-
- if len(indent) > 0 && sname != DEFAULT_SECTION {
- buf.WriteString(indent)
- }
-
- switch {
- case key.isAutoIncrement:
- kname = "-"
- case strings.ContainsAny(kname, "\"=:"):
- kname = "`" + kname + "`"
- case strings.Contains(kname, "`"):
- kname = `"""` + kname + `"""`
- }
-
- for _, val := range key.ValueWithShadows() {
- if _, err := buf.WriteString(kname); err != nil {
- return nil, err
- }
-
- if key.isBooleanType {
- if kname != sec.keyList[len(sec.keyList)-1] {
- buf.WriteString(LineBreak)
- }
- continue KEY_LIST
- }
-
- // Write out alignment spaces before "=" sign
- if PrettyFormat {
- buf.Write(alignSpaces[:alignLength-len(kname)])
- }
-
- // In case key value contains "\n", "`", "\"", "#" or ";"
- if strings.ContainsAny(val, "\n`") {
- val = `"""` + val + `"""`
- } else if !f.options.IgnoreInlineComment && strings.ContainsAny(val, "#;") {
- val = "`" + val + "`"
- }
- if _, err := buf.WriteString(equalSign + val + LineBreak); err != nil {
- return nil, err
- }
- }
- }
-
- if PrettySection {
- // Put a line between sections
- if _, err := buf.WriteString(LineBreak); err != nil {
- return nil, err
- }
- }
- }
-
- return buf, nil
-}
-
-// WriteToIndent writes content into io.Writer with given indention.
-// If PrettyFormat has been set to be true,
-// it will align "=" sign with spaces under each section.
-func (f *File) WriteToIndent(w io.Writer, indent string) (int64, error) {
- buf, err := f.writeToBuffer(indent)
- if err != nil {
- return 0, err
- }
- return buf.WriteTo(w)
-}
-
-// WriteTo writes file content into io.Writer.
-func (f *File) WriteTo(w io.Writer) (int64, error) {
- return f.WriteToIndent(w, "")
-}
-
-// SaveToIndent writes content to file system with given value indention.
-func (f *File) SaveToIndent(filename, indent string) error {
- // Note: Because we are truncating with os.Create,
- // so it's safer to save to a temporary file location and rename afte done.
- buf, err := f.writeToBuffer(indent)
- if err != nil {
- return err
- }
-
- return ioutil.WriteFile(filename, buf.Bytes(), 0666)
-}
-
-// SaveTo writes content to file system.
-func (f *File) SaveTo(filename string) error {
- return f.SaveToIndent(filename, "")
-}
diff --git a/vendor/github.com/go-ini/ini/ini_internal_test.go b/vendor/github.com/go-ini/ini/ini_internal_test.go
new file mode 100644
index 000000000..257ef1ebb
--- /dev/null
+++ b/vendor/github.com/go-ini/ini/ini_internal_test.go
@@ -0,0 +1,35 @@
+// Copyright 2017 Unknwon
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package ini
+
+import (
+ "testing"
+
+ . "github.com/smartystreets/goconvey/convey"
+)
+
+func Test_Version(t *testing.T) {
+ Convey("Get version", t, func() {
+ So(Version(), ShouldEqual, _VERSION)
+ })
+}
+
+func Test_isSlice(t *testing.T) {
+ Convey("Check if a string is in the slice", t, func() {
+ ss := []string{"a", "b", "c"}
+ So(inSlice("a", ss), ShouldBeTrue)
+ So(inSlice("d", ss), ShouldBeFalse)
+ })
+}
diff --git a/vendor/github.com/go-ini/ini/ini_test.go b/vendor/github.com/go-ini/ini/ini_test.go
index b3dd217c6..7a1efe4ec 100644
--- a/vendor/github.com/go-ini/ini/ini_test.go
+++ b/vendor/github.com/go-ini/ini/ini_test.go
@@ -12,480 +12,312 @@
// License for the specific language governing permissions and limitations
// under the License.
-package ini
+package ini_test
import (
"bytes"
"io/ioutil"
- "strings"
"testing"
- "time"
. "github.com/smartystreets/goconvey/convey"
+ "gopkg.in/ini.v1"
)
-func Test_Version(t *testing.T) {
- Convey("Get version", t, func() {
- So(Version(), ShouldEqual, _VERSION)
- })
-}
-
-const _CONF_DATA = `
-; Package name
-NAME = ini
-; Package version
-VERSION = v1
-; Package import path
-IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
+const (
+ _CONF_DATA = `
+ ; Package name
+ NAME = ini
+ ; Package version
+ VERSION = v1
+ ; Package import path
+ IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
+
+ # Information about package author
+ # Bio can be written in multiple lines.
+ [author]
+ NAME = Unknwon ; Succeeding comment
+ E-MAIL = fake@localhost
+ GITHUB = https://github.com/%(NAME)s
+ BIO = """Gopher.
+ Coding addict.
+ Good man.
+ """ # Succeeding comment`
+ _MINIMAL_CONF = "testdata/minimal.ini"
+ _FULL_CONF = "testdata/full.ini"
+ _NOT_FOUND_CONF = "testdata/404.ini"
+)
-# Information about package author
-# Bio can be written in multiple lines.
+func TestLoad(t *testing.T) {
+ Convey("Load from good data sources", t, func() {
+ f, err := ini.Load([]byte(`
+NAME = ini
+VERSION = v1
+IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s`),
+ "testdata/minimal.ini",
+ ioutil.NopCloser(bytes.NewReader([]byte(`
[author]
-NAME = Unknwon ; Succeeding comment
-E-MAIL = fake@localhost
-GITHUB = https://github.com/%(NAME)s
-BIO = """Gopher.
-Coding addict.
-Good man.
-""" # Succeeding comment
-
-[package]
-CLONE_URL = https://%(IMPORT_PATH)s
-
-[package.sub]
-UNUSED_KEY = should be deleted
-
-[features]
--: Support read/write comments of keys and sections
--: Support auto-increment of key names
--: Support load multiple files to overwrite key values
-
-[types]
-STRING = str
-BOOL = true
-BOOL_FALSE = false
-FLOAT64 = 1.25
-INT = 10
-TIME = 2015-01-01T20:17:05Z
-DURATION = 2h45m
-UINT = 3
-
-[array]
-STRINGS = en, zh, de
-FLOAT64S = 1.1, 2.2, 3.3
-INTS = 1, 2, 3
-UINTS = 1, 2, 3
-TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z
-
-[note]
-empty_lines = next line is empty\
-
-; Comment before the section
-[comments] ; This is a comment for the section too
-; Comment before key
-key = "value"
-key2 = "value2" ; This is a comment for key2
-key3 = "one", "two", "three"
-
-[advance]
-value with quotes = "some value"
-value quote2 again = 'some value'
-includes comment sign = ` + "`" + "my#password" + "`" + `
-includes comment sign2 = ` + "`" + "my;password" + "`" + `
-true = 2+3=5
-"1+1=2" = true
-"""6+1=7""" = true
-"""` + "`" + `5+5` + "`" + `""" = 10
-` + "`" + `"6+6"` + "`" + ` = 12
-` + "`" + `7-2=4` + "`" + ` = false
-ADDRESS = ` + "`" + `404 road,
-NotFound, State, 50000` + "`" + `
-
-two_lines = how about \
- continuation lines?
-lots_of_lines = 1 \
- 2 \
- 3 \
- 4 \
-`
-
-func Test_Load(t *testing.T) {
- Convey("Load from data sources", t, func() {
-
- Convey("Load with empty data", func() {
- So(Empty(), ShouldNotBeNil)
- })
-
- Convey("Load with multiple data sources", func() {
- cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini", ioutil.NopCloser(bytes.NewReader([]byte(_CONF_DATA))))
- So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
-
- f, err := Load([]byte(_CONF_DATA), "testdata/404.ini")
- So(err, ShouldNotBeNil)
- So(f, ShouldBeNil)
- })
+NAME = Unknwon
+`))),
+ )
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
- Convey("Load with io.ReadCloser", func() {
- cfg, err := Load(ioutil.NopCloser(bytes.NewReader([]byte(_CONF_DATA))))
- So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
+ // Vaildate values make sure all sources are loaded correctly
+ sec := f.Section("")
+ So(sec.Key("NAME").String(), ShouldEqual, "ini")
+ So(sec.Key("VERSION").String(), ShouldEqual, "v1")
+ So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "gopkg.in/ini.v1")
- So(cfg.Section("").Key("NAME").String(), ShouldEqual, "ini")
- })
+ sec = f.Section("author")
+ So(sec.Key("NAME").String(), ShouldEqual, "Unknwon")
+ So(sec.Key("E-MAIL").String(), ShouldEqual, "u@gogs.io")
})
- Convey("Bad load process", t, func() {
-
- Convey("Load from invalid data sources", func() {
- _, err := Load(_CONF_DATA)
- So(err, ShouldNotBeNil)
-
- f, err := Load("testdata/404.ini")
- So(err, ShouldNotBeNil)
- So(f, ShouldBeNil)
-
- _, err = Load(1)
+ Convey("Load from bad data sources", t, func() {
+ Convey("Invalid input", func() {
+ _, err := ini.Load(_NOT_FOUND_CONF)
So(err, ShouldNotBeNil)
+ })
- _, err = Load([]byte(""), 1)
+ Convey("Unsupported type", func() {
+ _, err := ini.Load(123)
So(err, ShouldNotBeNil)
})
+ })
+}
- Convey("Load with bad section name", func() {
- _, err := Load([]byte("[]"))
- So(err, ShouldNotBeNil)
+func TestLoadSources(t *testing.T) {
+ Convey("Load from data sources with options", t, func() {
+ Convey("Ignore nonexistent files", func() {
+ f, err := ini.LooseLoad(_NOT_FOUND_CONF, _MINIMAL_CONF)
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
- _, err = Load([]byte("["))
- So(err, ShouldNotBeNil)
+ Convey("Inverse case", func() {
+ _, err = ini.Load(_NOT_FOUND_CONF)
+ So(err, ShouldNotBeNil)
+ })
})
- Convey("Load with bad keys", func() {
- _, err := Load([]byte(`"""name`))
- So(err, ShouldNotBeNil)
+ Convey("Insensitive to section and key names", func() {
+ f, err := ini.InsensitiveLoad(_MINIMAL_CONF)
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
- _, err = Load([]byte(`"""name"""`))
- So(err, ShouldNotBeNil)
+ So(f.Section("Author").Key("e-mail").String(), ShouldEqual, "u@gogs.io")
- _, err = Load([]byte(`""=1`))
- So(err, ShouldNotBeNil)
+ Convey("Write out", func() {
+ var buf bytes.Buffer
+ _, err := f.WriteTo(&buf)
+ So(err, ShouldBeNil)
+ So(buf.String(), ShouldEqual, `[author]
+e-mail = u@gogs.io
- _, err = Load([]byte(`=`))
- So(err, ShouldNotBeNil)
+`)
+ })
- _, err = Load([]byte(`name`))
- So(err, ShouldNotBeNil)
- })
+ Convey("Inverse case", func() {
+ f, err := ini.Load(_MINIMAL_CONF)
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
- Convey("Load with bad values", func() {
- _, err := Load([]byte(`name="""Unknwon`))
- So(err, ShouldNotBeNil)
+ So(f.Section("Author").Key("e-mail").String(), ShouldBeEmpty)
+ })
})
- })
- Convey("Get section and key insensitively", t, func() {
- cfg, err := InsensitiveLoad([]byte(_CONF_DATA), "testdata/conf.ini")
- So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
+ Convey("Ignore continuation lines", func() {
+ f, err := ini.LoadSources(ini.LoadOptions{
+ IgnoreContinuation: true,
+ }, []byte(`
+key1=a\b\
+key2=c\d\
+key3=value`))
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
- sec, err := cfg.GetSection("Author")
- So(err, ShouldBeNil)
- So(sec, ShouldNotBeNil)
+ So(f.Section("").Key("key1").String(), ShouldEqual, `a\b\`)
+ So(f.Section("").Key("key2").String(), ShouldEqual, `c\d\`)
+ So(f.Section("").Key("key3").String(), ShouldEqual, "value")
- key, err := sec.GetKey("E-mail")
- So(err, ShouldBeNil)
- So(key, ShouldNotBeNil)
- })
-
- Convey("Load with ignoring continuation lines", t, func() {
- cfg, err := LoadSources(LoadOptions{IgnoreContinuation: true}, []byte(`key1=a\b\
+ Convey("Inverse case", func() {
+ f, err := ini.Load([]byte(`
+key1=a\b\
key2=c\d\`))
- So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
- So(cfg.Section("").Key("key1").String(), ShouldEqual, `a\b\`)
- So(cfg.Section("").Key("key2").String(), ShouldEqual, `c\d\`)
- })
-
- Convey("Load with ignoring inline comments", t, func() {
- cfg, err := LoadSources(LoadOptions{IgnoreInlineComment: true}, []byte(`key1=value ;comment
-key2=value #comment2`))
- So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
-
- So(cfg.Section("").Key("key1").String(), ShouldEqual, `value ;comment`)
- So(cfg.Section("").Key("key2").String(), ShouldEqual, `value #comment2`)
-
- var buf bytes.Buffer
- cfg.WriteTo(&buf)
- So(buf.String(), ShouldEqual, `key1 = value ;comment
-key2 = value #comment2
+ So(f.Section("").Key("key1").String(), ShouldEqual, `a\bkey2=c\d`)
+ })
+ })
-`)
- })
+ Convey("Ignore inline comments", func() {
+ f, err := ini.LoadSources(ini.LoadOptions{
+ IgnoreInlineComment: true,
+ }, []byte(`
+key1=value ;comment
+key2=value2 #comment2`))
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ So(f.Section("").Key("key1").String(), ShouldEqual, `value ;comment`)
+ So(f.Section("").Key("key2").String(), ShouldEqual, `value2 #comment2`)
+
+ Convey("Inverse case", func() {
+ f, err := ini.Load([]byte(`
+key1=value ;comment
+key2=value2 #comment2`))
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ So(f.Section("").Key("key1").String(), ShouldEqual, `value`)
+ So(f.Section("").Key("key1").Comment, ShouldEqual, `;comment`)
+ So(f.Section("").Key("key2").String(), ShouldEqual, `value2`)
+ So(f.Section("").Key("key2").Comment, ShouldEqual, `#comment2`)
+ })
+ })
- Convey("Load with boolean type keys", t, func() {
- cfg, err := LoadSources(LoadOptions{AllowBooleanKeys: true}, []byte(`key1=hello
-key2
-#key3
-key4
-key5`))
- So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
-
- So(strings.Join(cfg.Section("").KeyStrings(), ","), ShouldEqual, "key1,key2,key4,key5")
- So(cfg.Section("").Key("key2").MustBool(false), ShouldBeTrue)
-
- var buf bytes.Buffer
- cfg.WriteTo(&buf)
- // there is always a trailing \n at the end of the section
- So(buf.String(), ShouldEqual, `key1 = hello
-key2
-#key3
-key4
-key5
+ Convey("Allow boolean type keys", func() {
+ f, err := ini.LoadSources(ini.LoadOptions{
+ AllowBooleanKeys: true,
+ }, []byte(`
+key1=hello
+#key2
+key3`))
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ So(f.Section("").KeyStrings(), ShouldResemble, []string{"key1", "key3"})
+ So(f.Section("").Key("key3").MustBool(false), ShouldBeTrue)
+
+ Convey("Write out", func() {
+ var buf bytes.Buffer
+ _, err := f.WriteTo(&buf)
+ So(err, ShouldBeNil)
+ So(buf.String(), ShouldEqual, `key1 = hello
+# key2
+key3
`)
- })
-}
-
-func Test_File_ChildSections(t *testing.T) {
- Convey("Find child sections by parent name", t, func() {
- cfg, err := Load([]byte(`
-[node]
-
-[node.biz1]
-
-[node.biz2]
-
-[node.biz3]
-
-[node.bizN]
-`))
- So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
-
- children := cfg.ChildSections("node")
- names := make([]string, len(children))
- for i := range children {
- names[i] = children[i].name
- }
- So(strings.Join(names, ","), ShouldEqual, "node.biz1,node.biz2,node.biz3,node.bizN")
- })
-}
+ })
+
+ Convey("Inverse case", func() {
+ _, err := ini.Load([]byte(`
+key1=hello
+#key2
+key3`))
+ So(err, ShouldNotBeNil)
+ })
+ })
-func Test_LooseLoad(t *testing.T) {
- Convey("Loose load from data sources", t, func() {
- Convey("Loose load mixed with nonexistent file", func() {
- cfg, err := LooseLoad("testdata/404.ini")
+ Convey("Allow shadow keys", func() {
+ f, err := ini.ShadowLoad([]byte(`
+[remote "origin"]
+url = https://github.com/Antergone/test1.git
+url = https://github.com/Antergone/test2.git
+fetch = +refs/heads/*:refs/remotes/origin/*`))
So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
- var fake struct {
- Name string `ini:"name"`
- }
- So(cfg.MapTo(&fake), ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ So(f.Section(`remote "origin"`).Key("url").String(), ShouldEqual, "https://github.com/Antergone/test1.git")
+ So(f.Section(`remote "origin"`).Key("url").ValueWithShadows(), ShouldResemble, []string{
+ "https://github.com/Antergone/test1.git",
+ "https://github.com/Antergone/test2.git",
+ })
+ So(f.Section(`remote "origin"`).Key("fetch").String(), ShouldEqual, "+refs/heads/*:refs/remotes/origin/*")
+
+ Convey("Write out", func() {
+ var buf bytes.Buffer
+ _, err := f.WriteTo(&buf)
+ So(err, ShouldBeNil)
+ So(buf.String(), ShouldEqual, `[remote "origin"]
+url = https://github.com/Antergone/test1.git
+url = https://github.com/Antergone/test2.git
+fetch = +refs/heads/*:refs/remotes/origin/*
- cfg, err = LooseLoad([]byte("name=Unknwon"), "testdata/404.ini")
- So(err, ShouldBeNil)
- So(cfg.Section("").Key("name").String(), ShouldEqual, "Unknwon")
- So(cfg.MapTo(&fake), ShouldBeNil)
- So(fake.Name, ShouldEqual, "Unknwon")
+`)
+ })
+
+ Convey("Inverse case", func() {
+ f, err := ini.Load([]byte(`
+[remote "origin"]
+url = https://github.com/Antergone/test1.git
+url = https://github.com/Antergone/test2.git`))
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ So(f.Section(`remote "origin"`).Key("url").String(), ShouldEqual, "https://github.com/Antergone/test2.git")
+ })
})
- })
-}
+ Convey("Unescape double quotes inside value", func() {
+ f, err := ini.LoadSources(ini.LoadOptions{
+ UnescapeValueDoubleQuotes: true,
+ }, []byte(`
+create_repo="创建了仓库 <a href=\"%s\">%s</a>"`))
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
-func Test_File_Append(t *testing.T) {
- Convey("Append data sources", t, func() {
- cfg, err := Load([]byte(""))
- So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
+ So(f.Section("").Key("create_repo").String(), ShouldEqual, `创建了仓库 <a href="%s">%s</a>`)
- So(cfg.Append([]byte(""), []byte("")), ShouldBeNil)
+ Convey("Inverse case", func() {
+ f, err := ini.Load([]byte(`
+create_repo="创建了仓库 <a href=\"%s\">%s</a>"`))
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
- Convey("Append bad data sources", func() {
- So(cfg.Append(1), ShouldNotBeNil)
- So(cfg.Append([]byte(""), 1), ShouldNotBeNil)
+ So(f.Section("").Key("create_repo").String(), ShouldEqual, `"创建了仓库 <a href=\"%s\">%s</a>"`)
+ })
})
- })
-}
-
-func Test_File_WriteTo(t *testing.T) {
- Convey("Write to somewhere", t, func() {
- var buf bytes.Buffer
- cfg := Empty()
- cfg.WriteTo(&buf)
- })
-}
-
-func Test_File_SaveTo_WriteTo(t *testing.T) {
- Convey("Save file", t, func() {
- cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
- So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
- cfg.Section("").Key("NAME").Comment = "Package name"
- cfg.Section("author").Comment = `Information about package author
-# Bio can be written in multiple lines.`
- cfg.Section("advanced").Key("val w/ pound").SetValue("my#password")
- cfg.Section("advanced").Key("longest key has a colon : yes/no").SetValue("yes")
- So(cfg.SaveTo("testdata/conf_out.ini"), ShouldBeNil)
+ Convey("Allow unparseable sections", func() {
+ f, err := ini.LoadSources(ini.LoadOptions{
+ Insensitive: true,
+ UnparseableSections: []string{"core_lesson", "comments"},
+ }, []byte(`
+Lesson_Location = 87
+Lesson_Status = C
+Score = 3
+Time = 00:02:30
- cfg.Section("author").Key("NAME").Comment = "This is author name"
+[CORE_LESSON]
+my lesson state data – 1111111111111111111000000000000000001110000
+111111111111111111100000000000111000000000 – end my lesson state data
- So(cfg.SaveToIndent("testdata/conf_out.ini", "\t"), ShouldBeNil)
+[COMMENTS]
+<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ So(f.Section("").Key("score").String(), ShouldEqual, "3")
+ So(f.Section("").Body(), ShouldBeEmpty)
+ So(f.Section("core_lesson").Body(), ShouldEqual, `my lesson state data – 1111111111111111111000000000000000001110000
+111111111111111111100000000000111000000000 – end my lesson state data`)
+ So(f.Section("comments").Body(), ShouldEqual, `<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`)
+
+ Convey("Write out", func() {
+ var buf bytes.Buffer
+ _, err := f.WriteTo(&buf)
+ So(err, ShouldBeNil)
+ So(buf.String(), ShouldEqual, `lesson_location = 87
+lesson_status = C
+score = 3
+time = 00:02:30
+
+[core_lesson]
+my lesson state data – 1111111111111111111000000000000000001110000
+111111111111111111100000000000111000000000 – end my lesson state data
- var buf bytes.Buffer
- _, err = cfg.WriteToIndent(&buf, "\t")
- So(err, ShouldBeNil)
- So(buf.String(), ShouldEqual, `; Package name
-NAME = ini
-; Package version
-VERSION = v1
-; Package import path
-IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
-
-; Information about package author
-# Bio can be written in multiple lines.
-[author]
- ; This is author name
- NAME = Unknwon
- E-MAIL = u@gogs.io
- GITHUB = https://github.com/%(NAME)s
- # Succeeding comment
- BIO = """Gopher.
-Coding addict.
-Good man.
-"""
-
-[package]
- CLONE_URL = https://%(IMPORT_PATH)s
-
-[package.sub]
- UNUSED_KEY = should be deleted
-
-[features]
- - = Support read/write comments of keys and sections
- - = Support auto-increment of key names
- - = Support load multiple files to overwrite key values
-
-[types]
- STRING = str
- BOOL = true
- BOOL_FALSE = false
- FLOAT64 = 1.25
- INT = 10
- TIME = 2015-01-01T20:17:05Z
- DURATION = 2h45m
- UINT = 3
-
-[array]
- STRINGS = en, zh, de
- FLOAT64S = 1.1, 2.2, 3.3
- INTS = 1, 2, 3
- UINTS = 1, 2, 3
- TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z
-
-[note]
- empty_lines = next line is empty
-
-; Comment before the section
-; This is a comment for the section too
[comments]
- ; Comment before key
- key = value
- ; This is a comment for key2
- key2 = value2
- key3 = "one", "two", "three"
-
-[advance]
- value with quotes = some value
- value quote2 again = some value
- includes comment sign = `+"`"+"my#password"+"`"+`
- includes comment sign2 = `+"`"+"my;password"+"`"+`
- true = 2+3=5
- `+"`"+`1+1=2`+"`"+` = true
- `+"`"+`6+1=7`+"`"+` = true
- """`+"`"+`5+5`+"`"+`""" = 10
- `+"`"+`"6+6"`+"`"+` = 12
- `+"`"+`7-2=4`+"`"+` = false
- ADDRESS = """404 road,
-NotFound, State, 50000"""
- two_lines = how about continuation lines?
- lots_of_lines = 1 2 3 4
-
-[advanced]
- val w/ pound = `+"`"+`my#password`+"`"+`
- `+"`"+`longest key has a colon : yes/no`+"`"+` = yes
-
+<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
`)
- })
-}
-
-func Test_File_WriteTo_SectionRaw(t *testing.T) {
- Convey("Write a INI with a raw section", t, func() {
- var buf bytes.Buffer
- cfg, err := LoadSources(
- LoadOptions{
- UnparseableSections: []string{"CORE_LESSON", "COMMENTS"},
- },
- "testdata/aicc.ini")
- So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
- cfg.WriteToIndent(&buf, "\t")
- So(buf.String(), ShouldEqual, `[Core]
- Lesson_Location = 87
- Lesson_Status = C
- Score = 3
- Time = 00:02:30
+ })
+ Convey("Inverse case", func() {
+ _, err := ini.Load([]byte(`
[CORE_LESSON]
my lesson state data – 1111111111111111111000000000000000001110000
-111111111111111111100000000000111000000000 – end my lesson state data
-[COMMENTS]
-<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
-`)
+111111111111111111100000000000111000000000 – end my lesson state data`))
+ So(err, ShouldNotBeNil)
+ })
+ })
})
}
-
-// Helpers for slice tests.
-func float64sEqual(values []float64, expected ...float64) {
- So(values, ShouldHaveLength, len(expected))
- for i, v := range expected {
- So(values[i], ShouldEqual, v)
- }
-}
-
-func intsEqual(values []int, expected ...int) {
- So(values, ShouldHaveLength, len(expected))
- for i, v := range expected {
- So(values[i], ShouldEqual, v)
- }
-}
-
-func int64sEqual(values []int64, expected ...int64) {
- So(values, ShouldHaveLength, len(expected))
- for i, v := range expected {
- So(values[i], ShouldEqual, v)
- }
-}
-
-func uintsEqual(values []uint, expected ...uint) {
- So(values, ShouldHaveLength, len(expected))
- for i, v := range expected {
- So(values[i], ShouldEqual, v)
- }
-}
-
-func uint64sEqual(values []uint64, expected ...uint64) {
- So(values, ShouldHaveLength, len(expected))
- for i, v := range expected {
- So(values[i], ShouldEqual, v)
- }
-}
-
-func timesEqual(values []time.Time, expected ...time.Time) {
- So(values, ShouldHaveLength, len(expected))
- for i, v := range expected {
- So(values[i].String(), ShouldEqual, v.String())
- }
-}
diff --git a/vendor/github.com/go-ini/ini/key.go b/vendor/github.com/go-ini/ini/key.go
index 838356af0..ab566c2c1 100644
--- a/vendor/github.com/go-ini/ini/key.go
+++ b/vendor/github.com/go-ini/ini/key.go
@@ -15,6 +15,7 @@
package ini
import (
+ "bytes"
"errors"
"fmt"
"strconv"
@@ -25,6 +26,7 @@ import (
// Key represents a key under a section.
type Key struct {
s *Section
+ Comment string
name string
value string
isAutoIncrement bool
@@ -32,8 +34,6 @@ type Key struct {
isShadow bool
shadows []*Key
-
- Comment string
}
// newKey simply return a key object with given values.
@@ -444,11 +444,39 @@ func (k *Key) Strings(delim string) []string {
return []string{}
}
- vals := strings.Split(str, delim)
- for i := range vals {
- // vals[i] = k.transformValue(strings.TrimSpace(vals[i]))
- vals[i] = strings.TrimSpace(vals[i])
+ runes := []rune(str)
+ vals := make([]string, 0, 2)
+ var buf bytes.Buffer
+ escape := false
+ idx := 0
+ for {
+ if escape {
+ escape = false
+ if runes[idx] != '\\' && !strings.HasPrefix(string(runes[idx:]), delim) {
+ buf.WriteRune('\\')
+ }
+ buf.WriteRune(runes[idx])
+ } else {
+ if runes[idx] == '\\' {
+ escape = true
+ } else if strings.HasPrefix(string(runes[idx:]), delim) {
+ idx += len(delim) - 1
+ vals = append(vals, strings.TrimSpace(buf.String()))
+ buf.Reset()
+ } else {
+ buf.WriteRune(runes[idx])
+ }
+ }
+ idx += 1
+ if idx == len(runes) {
+ break
+ }
+ }
+
+ if buf.Len() > 0 {
+ vals = append(vals, strings.TrimSpace(buf.String()))
}
+
return vals
}
diff --git a/vendor/github.com/go-ini/ini/key_test.go b/vendor/github.com/go-ini/ini/key_test.go
index 1281d5bf0..588efd429 100644
--- a/vendor/github.com/go-ini/ini/key_test.go
+++ b/vendor/github.com/go-ini/ini/key_test.go
@@ -12,26 +12,108 @@
// License for the specific language governing permissions and limitations
// under the License.
-package ini
+package ini_test
import (
- "bytes"
"fmt"
"strings"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
+ "gopkg.in/ini.v1"
)
-func Test_Key(t *testing.T) {
- Convey("Test getting and setting values", t, func() {
- cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
+func TestKey_AddShadow(t *testing.T) {
+ Convey("Add shadow to a key", t, func() {
+ f, err := ini.ShadowLoad([]byte(`
+[notes]
+-: note1`))
So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
+ So(f, ShouldNotBeNil)
- Convey("Get values in default section", func() {
- sec := cfg.Section("")
+ k, err := f.Section("").NewKey("NAME", "ini")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+
+ So(k.AddShadow("ini.v1"), ShouldBeNil)
+ So(k.ValueWithShadows(), ShouldResemble, []string{"ini", "ini.v1"})
+
+ Convey("Add shadow to boolean key", func() {
+ k, err := f.Section("").NewBooleanKey("published")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ So(k.AddShadow("beta"), ShouldNotBeNil)
+ })
+
+ Convey("Add shadow to auto-increment key", func() {
+ So(f.Section("notes").Key("#1").AddShadow("beta"), ShouldNotBeNil)
+ })
+ })
+
+ Convey("Shadow is not allowed", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ k, err := f.Section("").NewKey("NAME", "ini")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+
+ So(k.AddShadow("ini.v1"), ShouldNotBeNil)
+ })
+}
+
+// Helpers for slice tests.
+func float64sEqual(values []float64, expected ...float64) {
+ So(values, ShouldHaveLength, len(expected))
+ for i, v := range expected {
+ So(values[i], ShouldEqual, v)
+ }
+}
+
+func intsEqual(values []int, expected ...int) {
+ So(values, ShouldHaveLength, len(expected))
+ for i, v := range expected {
+ So(values[i], ShouldEqual, v)
+ }
+}
+
+func int64sEqual(values []int64, expected ...int64) {
+ So(values, ShouldHaveLength, len(expected))
+ for i, v := range expected {
+ So(values[i], ShouldEqual, v)
+ }
+}
+
+func uintsEqual(values []uint, expected ...uint) {
+ So(values, ShouldHaveLength, len(expected))
+ for i, v := range expected {
+ So(values[i], ShouldEqual, v)
+ }
+}
+
+func uint64sEqual(values []uint64, expected ...uint64) {
+ So(values, ShouldHaveLength, len(expected))
+ for i, v := range expected {
+ So(values[i], ShouldEqual, v)
+ }
+}
+
+func timesEqual(values []time.Time, expected ...time.Time) {
+ So(values, ShouldHaveLength, len(expected))
+ for i, v := range expected {
+ So(values[i].String(), ShouldEqual, v.String())
+ }
+}
+
+func TestKey_Helpers(t *testing.T) {
+ Convey("Getting and setting values", t, func() {
+ f, err := ini.Load(_FULL_CONF)
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ Convey("Get string representation", func() {
+ sec := f.Section("")
So(sec, ShouldNotBeNil)
So(sec.Key("NAME").Value(), ShouldEqual, "ini")
So(sec.Key("NAME").String(), ShouldEqual, "ini")
@@ -40,55 +122,65 @@ func Test_Key(t *testing.T) {
}), ShouldEqual, "ini")
So(sec.Key("NAME").Comment, ShouldEqual, "; Package name")
So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "gopkg.in/ini.v1")
+
+ Convey("With ValueMapper", func() {
+ f.ValueMapper = func(in string) string {
+ if in == "gopkg.in/%(NAME)s.%(VERSION)s" {
+ return "github.com/go-ini/ini"
+ }
+ return in
+ }
+ So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "github.com/go-ini/ini")
+ })
})
Convey("Get values in non-default section", func() {
- sec := cfg.Section("author")
+ sec := f.Section("author")
So(sec, ShouldNotBeNil)
So(sec.Key("NAME").String(), ShouldEqual, "Unknwon")
So(sec.Key("GITHUB").String(), ShouldEqual, "https://github.com/Unknwon")
- sec = cfg.Section("package")
+ sec = f.Section("package")
So(sec, ShouldNotBeNil)
So(sec.Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
})
Convey("Get auto-increment key names", func() {
- keys := cfg.Section("features").Keys()
+ keys := f.Section("features").Keys()
for i, k := range keys {
So(k.Name(), ShouldEqual, fmt.Sprintf("#%d", i+1))
}
})
Convey("Get parent-keys that are available to the child section", func() {
- parentKeys := cfg.Section("package.sub").ParentKeys()
+ parentKeys := f.Section("package.sub").ParentKeys()
for _, k := range parentKeys {
So(k.Name(), ShouldEqual, "CLONE_URL")
}
})
Convey("Get overwrite value", func() {
- So(cfg.Section("author").Key("E-MAIL").String(), ShouldEqual, "u@gogs.io")
+ So(f.Section("author").Key("E-MAIL").String(), ShouldEqual, "u@gogs.io")
})
Convey("Get sections", func() {
- sections := cfg.Sections()
- for i, name := range []string{DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "advance"} {
+ sections := f.Sections()
+ for i, name := range []string{ini.DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"} {
So(sections[i].Name(), ShouldEqual, name)
}
})
Convey("Get parent section value", func() {
- So(cfg.Section("package.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
- So(cfg.Section("package.fake.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
+ So(f.Section("package.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
+ So(f.Section("package.fake.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
})
Convey("Get multiple line value", func() {
- So(cfg.Section("author").Key("BIO").String(), ShouldEqual, "Gopher.\nCoding addict.\nGood man.\n")
+ So(f.Section("author").Key("BIO").String(), ShouldEqual, "Gopher.\nCoding addict.\nGood man.\n")
})
Convey("Get values with type", func() {
- sec := cfg.Section("types")
+ sec := f.Section("types")
v1, err := sec.Key("BOOL").Bool()
So(err, ShouldBeNil)
So(v1, ShouldBeTrue)
@@ -168,7 +260,7 @@ func Test_Key(t *testing.T) {
})
Convey("Get value with candidates", func() {
- sec := cfg.Section("types")
+ sec := f.Section("types")
So(sec.Key("STRING").In("", []string{"str", "arr", "types"}), ShouldEqual, "str")
So(sec.Key("FLOAT64").InFloat64(0, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25)
So(sec.Key("INT").InInt(0, []int{10, 20, 30}), ShouldEqual, 10)
@@ -194,7 +286,7 @@ func Test_Key(t *testing.T) {
})
Convey("Get values in range", func() {
- sec := cfg.Section("types")
+ sec := f.Section("types")
So(sec.Key("FLOAT64").RangeFloat64(0, 1, 2), ShouldEqual, 1.25)
So(sec.Key("INT").RangeInt(0, 10, 20), ShouldEqual, 10)
So(sec.Key("INT").RangeInt64(0, 10, 20), ShouldEqual, 10)
@@ -218,7 +310,7 @@ func Test_Key(t *testing.T) {
})
Convey("Get values into slice", func() {
- sec := cfg.Section("array")
+ sec := f.Section("array")
So(strings.Join(sec.Key("STRINGS").Strings(","), ","), ShouldEqual, "en,zh,de")
So(len(sec.Key("STRINGS_404").Strings(",")), ShouldEqual, 0)
@@ -243,8 +335,18 @@ func Test_Key(t *testing.T) {
timesEqual(vals6, t, t, t)
})
+ Convey("Test string slice escapes", func() {
+ sec := f.Section("string escapes")
+ So(sec.Key("key1").Strings(","), ShouldResemble, []string{"value1", "value2", "value3"})
+ So(sec.Key("key2").Strings(","), ShouldResemble, []string{"value1, value2"})
+ So(sec.Key("key3").Strings(","), ShouldResemble, []string{`val\ue1`, "value2"})
+ So(sec.Key("key4").Strings(","), ShouldResemble, []string{`value1\`, `value\\2`})
+ So(sec.Key("key5").Strings(",,"), ShouldResemble, []string{"value1,, value2"})
+ So(sec.Key("key6").Strings(" "), ShouldResemble, []string{"aaa", "bbb and space", "ccc"})
+ })
+
Convey("Get valid values into slice", func() {
- sec := cfg.Section("array")
+ sec := f.Section("array")
vals1 := sec.Key("FLOAT64S").ValidFloat64s(",")
float64sEqual(vals1, 1.1, 2.2, 3.3)
@@ -267,7 +369,7 @@ func Test_Key(t *testing.T) {
})
Convey("Get values one type into slice of another type", func() {
- sec := cfg.Section("array")
+ sec := f.Section("array")
vals1 := sec.Key("STRINGS").ValidFloat64s(",")
So(vals1, ShouldBeEmpty)
@@ -288,7 +390,7 @@ func Test_Key(t *testing.T) {
})
Convey("Get valid values into slice without errors", func() {
- sec := cfg.Section("array")
+ sec := f.Section("array")
vals1, err := sec.Key("FLOAT64S").StrictFloat64s(",")
So(err, ShouldBeNil)
float64sEqual(vals1, 1.1, 2.2, 3.3)
@@ -317,7 +419,7 @@ func Test_Key(t *testing.T) {
})
Convey("Get invalid values into slice", func() {
- sec := cfg.Section("array")
+ sec := f.Section("array")
vals1, err := sec.Key("STRINGS").StrictFloat64s(",")
So(vals1, ShouldBeEmpty)
So(err, ShouldNotBeNil)
@@ -342,232 +444,37 @@ func Test_Key(t *testing.T) {
So(vals6, ShouldBeEmpty)
So(err, ShouldNotBeNil)
})
-
- Convey("Get key hash", func() {
- cfg.Section("").KeysHash()
- })
-
- Convey("Set key value", func() {
- k := cfg.Section("author").Key("NAME")
- k.SetValue("无闻")
- So(k.String(), ShouldEqual, "无闻")
- })
-
- Convey("Get key strings", func() {
- So(strings.Join(cfg.Section("types").KeyStrings(), ","), ShouldEqual, "STRING,BOOL,BOOL_FALSE,FLOAT64,INT,TIME,DURATION,UINT")
- })
-
- Convey("Delete a key", func() {
- cfg.Section("package.sub").DeleteKey("UNUSED_KEY")
- _, err := cfg.Section("package.sub").GetKey("UNUSED_KEY")
- So(err, ShouldNotBeNil)
- })
-
- Convey("Has Key (backwards compatible)", func() {
- sec := cfg.Section("package.sub")
- haskey1 := sec.Haskey("UNUSED_KEY")
- haskey2 := sec.Haskey("CLONE_URL")
- haskey3 := sec.Haskey("CLONE_URL_NO")
- So(haskey1, ShouldBeTrue)
- So(haskey2, ShouldBeTrue)
- So(haskey3, ShouldBeFalse)
- })
-
- Convey("Has Key", func() {
- sec := cfg.Section("package.sub")
- haskey1 := sec.HasKey("UNUSED_KEY")
- haskey2 := sec.HasKey("CLONE_URL")
- haskey3 := sec.HasKey("CLONE_URL_NO")
- So(haskey1, ShouldBeTrue)
- So(haskey2, ShouldBeTrue)
- So(haskey3, ShouldBeFalse)
- })
-
- Convey("Has Value", func() {
- sec := cfg.Section("author")
- hasvalue1 := sec.HasValue("Unknwon")
- hasvalue2 := sec.HasValue("doc")
- So(hasvalue1, ShouldBeTrue)
- So(hasvalue2, ShouldBeFalse)
- })
})
+}
- Convey("Test getting and setting bad values", t, func() {
- cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
+func TestKey_StringsWithShadows(t *testing.T) {
+ Convey("Get strings of shadows of a key", t, func() {
+ f, err := ini.ShadowLoad([]byte(""))
So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
-
- Convey("Create new key with empty name", func() {
- k, err := cfg.Section("").NewKey("", "")
- So(err, ShouldNotBeNil)
- So(k, ShouldBeNil)
- })
-
- Convey("Create new section with empty name", func() {
- s, err := cfg.NewSection("")
- So(err, ShouldNotBeNil)
- So(s, ShouldBeNil)
- })
-
- Convey("Create new sections with empty name", func() {
- So(cfg.NewSections(""), ShouldNotBeNil)
- })
+ So(f, ShouldNotBeNil)
- Convey("Get section that not exists", func() {
- s, err := cfg.GetSection("404")
- So(err, ShouldNotBeNil)
- So(s, ShouldBeNil)
-
- s = cfg.Section("404")
- So(s, ShouldNotBeNil)
- })
- })
-
- Convey("Test key hash clone", t, func() {
- cfg, err := Load([]byte(strings.Replace("network=tcp,addr=127.0.0.1:6379,db=4,pool_size=100,idle_timeout=180", ",", "\n", -1)))
+ k, err := f.Section("").NewKey("NUMS", "1,2")
So(err, ShouldBeNil)
- for _, v := range cfg.Section("").KeysHash() {
- So(len(v), ShouldBeGreaterThan, 0)
- }
- })
-
- Convey("Key has empty value", t, func() {
- _conf := `key1=
-key2= ; comment`
- cfg, err := Load([]byte(_conf))
+ So(k, ShouldNotBeNil)
+ k, err = f.Section("").NewKey("NUMS", "4,5,6")
So(err, ShouldBeNil)
- So(cfg.Section("").Key("key1").Value(), ShouldBeEmpty)
- })
-}
-
-const _CONF_GIT_CONFIG = `
-[remote "origin"]
- url = https://github.com/Antergone/test1.git
- url = https://github.com/Antergone/test2.git
-`
-
-func Test_Key_Shadows(t *testing.T) {
- Convey("Shadows keys", t, func() {
- Convey("Disable shadows", func() {
- cfg, err := Load([]byte(_CONF_GIT_CONFIG))
- So(err, ShouldBeNil)
- So(cfg.Section(`remote "origin"`).Key("url").String(), ShouldEqual, "https://github.com/Antergone/test2.git")
- })
-
- Convey("Enable shadows", func() {
- cfg, err := ShadowLoad([]byte(_CONF_GIT_CONFIG))
- So(err, ShouldBeNil)
- So(cfg.Section(`remote "origin"`).Key("url").String(), ShouldEqual, "https://github.com/Antergone/test1.git")
- So(strings.Join(cfg.Section(`remote "origin"`).Key("url").ValueWithShadows(), " "), ShouldEqual,
- "https://github.com/Antergone/test1.git https://github.com/Antergone/test2.git")
+ So(k, ShouldNotBeNil)
- Convey("Save with shadows", func() {
- var buf bytes.Buffer
- _, err := cfg.WriteTo(&buf)
- So(err, ShouldBeNil)
- So(buf.String(), ShouldEqual, `[remote "origin"]
-url = https://github.com/Antergone/test1.git
-url = https://github.com/Antergone/test2.git
-
-`)
- })
- })
+ So(k.StringsWithShadows(","), ShouldResemble, []string{"1", "2", "4", "5", "6"})
})
}
-func newTestFile(block bool) *File {
- c, _ := Load([]byte(_CONF_DATA))
- c.BlockMode = block
- return c
-}
-
-func Benchmark_Key_Value(b *testing.B) {
- c := newTestFile(true)
- for i := 0; i < b.N; i++ {
- c.Section("").Key("NAME").Value()
- }
-}
-
-func Benchmark_Key_Value_NonBlock(b *testing.B) {
- c := newTestFile(false)
- for i := 0; i < b.N; i++ {
- c.Section("").Key("NAME").Value()
- }
-}
+func TestKey_SetValue(t *testing.T) {
+ Convey("Set value of key", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
-func Benchmark_Key_Value_ViaSection(b *testing.B) {
- c := newTestFile(true)
- sec := c.Section("")
- for i := 0; i < b.N; i++ {
- sec.Key("NAME").Value()
- }
-}
-
-func Benchmark_Key_Value_ViaSection_NonBlock(b *testing.B) {
- c := newTestFile(false)
- sec := c.Section("")
- for i := 0; i < b.N; i++ {
- sec.Key("NAME").Value()
- }
-}
-
-func Benchmark_Key_Value_Direct(b *testing.B) {
- c := newTestFile(true)
- key := c.Section("").Key("NAME")
- for i := 0; i < b.N; i++ {
- key.Value()
- }
-}
-
-func Benchmark_Key_Value_Direct_NonBlock(b *testing.B) {
- c := newTestFile(false)
- key := c.Section("").Key("NAME")
- for i := 0; i < b.N; i++ {
- key.Value()
- }
-}
-
-func Benchmark_Key_String(b *testing.B) {
- c := newTestFile(true)
- for i := 0; i < b.N; i++ {
- _ = c.Section("").Key("NAME").String()
- }
-}
-
-func Benchmark_Key_String_NonBlock(b *testing.B) {
- c := newTestFile(false)
- for i := 0; i < b.N; i++ {
- _ = c.Section("").Key("NAME").String()
- }
-}
-
-func Benchmark_Key_String_ViaSection(b *testing.B) {
- c := newTestFile(true)
- sec := c.Section("")
- for i := 0; i < b.N; i++ {
- _ = sec.Key("NAME").String()
- }
-}
-
-func Benchmark_Key_String_ViaSection_NonBlock(b *testing.B) {
- c := newTestFile(false)
- sec := c.Section("")
- for i := 0; i < b.N; i++ {
- _ = sec.Key("NAME").String()
- }
-}
-
-func Benchmark_Key_SetValue(b *testing.B) {
- c := newTestFile(true)
- for i := 0; i < b.N; i++ {
- c.Section("").Key("NAME").SetValue("10")
- }
-}
+ k, err := f.Section("").NewKey("NAME", "ini")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ So(k.Value(), ShouldEqual, "ini")
-func Benchmark_Key_SetValue_VisSection(b *testing.B) {
- c := newTestFile(true)
- sec := c.Section("")
- for i := 0; i < b.N; i++ {
- sec.Key("NAME").SetValue("10")
- }
+ k.SetValue("ini.v1")
+ So(k.Value(), ShouldEqual, "ini.v1")
+ })
}
diff --git a/vendor/github.com/go-ini/ini/parser.go b/vendor/github.com/go-ini/ini/parser.go
index 69d547627..f8ac8026a 100644
--- a/vendor/github.com/go-ini/ini/parser.go
+++ b/vendor/github.com/go-ini/ini/parser.go
@@ -193,7 +193,7 @@ func hasSurroundedQuote(in string, quote byte) bool {
strings.IndexByte(in[1:], quote) == len(in)-2
}
-func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment bool) (string, error) {
+func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment, unescapeValueDoubleQuotes bool) (string, error) {
line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
if len(line) == 0 {
return "", nil
@@ -204,6 +204,8 @@ func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment bo
valQuote = `"""`
} else if line[0] == '`' {
valQuote = "`"
+ } else if unescapeValueDoubleQuotes && line[0] == '"' {
+ valQuote = `"`
}
if len(valQuote) > 0 {
@@ -214,6 +216,9 @@ func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment bo
return p.readMultilines(line, line[startIdx:], valQuote)
}
+ if unescapeValueDoubleQuotes && valQuote == `"` {
+ return strings.Replace(line[startIdx:pos+startIdx], `\"`, `"`, -1), nil
+ }
return line[startIdx : pos+startIdx], nil
}
@@ -234,7 +239,7 @@ func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment bo
}
}
- // Trim single quotes
+ // Trim single and double quotes
if hasSurroundedQuote(line, '\'') ||
hasSurroundedQuote(line, '"') {
line = line[1 : len(line)-1]
@@ -250,7 +255,11 @@ func (f *File) parse(reader io.Reader) (err error) {
}
// Ignore error because default section name is never empty string.
- section, _ := f.NewSection(DEFAULT_SECTION)
+ name := DEFAULT_SECTION
+ if f.options.Insensitive {
+ name = strings.ToLower(DEFAULT_SECTION)
+ }
+ section, _ := f.NewSection(name)
var line []byte
var inUnparseableSection bool
@@ -321,7 +330,10 @@ func (f *File) parse(reader io.Reader) (err error) {
if err != nil {
// Treat as boolean key when desired, and whole line is key name.
if IsErrDelimiterNotFound(err) && f.options.AllowBooleanKeys {
- kname, err := p.readValue(line, f.options.IgnoreContinuation, f.options.IgnoreInlineComment)
+ kname, err := p.readValue(line,
+ f.options.IgnoreContinuation,
+ f.options.IgnoreInlineComment,
+ f.options.UnescapeValueDoubleQuotes)
if err != nil {
return err
}
@@ -344,7 +356,10 @@ func (f *File) parse(reader io.Reader) (err error) {
p.count++
}
- value, err := p.readValue(line[offset:], f.options.IgnoreContinuation, f.options.IgnoreInlineComment)
+ value, err := p.readValue(line[offset:],
+ f.options.IgnoreContinuation,
+ f.options.IgnoreInlineComment,
+ f.options.UnescapeValueDoubleQuotes)
if err != nil {
return err
}
diff --git a/vendor/github.com/go-ini/ini/parser_test.go b/vendor/github.com/go-ini/ini/parser_test.go
index 05258195b..bb0f2665e 100644
--- a/vendor/github.com/go-ini/ini/parser_test.go
+++ b/vendor/github.com/go-ini/ini/parser_test.go
@@ -12,31 +12,66 @@
// License for the specific language governing permissions and limitations
// under the License.
-package ini
+package ini_test
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
+ "gopkg.in/ini.v1"
)
-func Test_BOM(t *testing.T) {
+func TestBOM(t *testing.T) {
Convey("Test handling BOM", t, func() {
Convey("UTF-8-BOM", func() {
- cfg, err := Load("testdata/UTF-8-BOM.ini")
+ f, err := ini.Load("testdata/UTF-8-BOM.ini")
So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
+ So(f, ShouldNotBeNil)
- So(cfg.Section("author").Key("E-MAIL").String(), ShouldEqual, "u@gogs.io")
+ So(f.Section("author").Key("E-MAIL").String(), ShouldEqual, "u@gogs.io")
})
Convey("UTF-16-LE-BOM", func() {
- cfg, err := Load("testdata/UTF-16-LE-BOM.ini")
+ f, err := ini.Load("testdata/UTF-16-LE-BOM.ini")
So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
+ So(f, ShouldNotBeNil)
})
Convey("UTF-16-BE-BOM", func() {
})
})
}
+
+func TestBadLoad(t *testing.T) {
+ Convey("Load with bad data", t, func() {
+ Convey("Bad section name", func() {
+ _, err := ini.Load([]byte("[]"))
+ So(err, ShouldNotBeNil)
+
+ _, err = ini.Load([]byte("["))
+ So(err, ShouldNotBeNil)
+ })
+
+ Convey("Bad keys", func() {
+ _, err := ini.Load([]byte(`"""name`))
+ So(err, ShouldNotBeNil)
+
+ _, err = ini.Load([]byte(`"""name"""`))
+ So(err, ShouldNotBeNil)
+
+ _, err = ini.Load([]byte(`""=1`))
+ So(err, ShouldNotBeNil)
+
+ _, err = ini.Load([]byte(`=`))
+ So(err, ShouldNotBeNil)
+
+ _, err = ini.Load([]byte(`name`))
+ So(err, ShouldNotBeNil)
+ })
+
+ Convey("Bad values", func() {
+ _, err := ini.Load([]byte(`name="""Unknwon`))
+ So(err, ShouldNotBeNil)
+ })
+ })
+}
diff --git a/vendor/github.com/go-ini/ini/section.go b/vendor/github.com/go-ini/ini/section.go
index 94f7375ed..d8a402619 100644
--- a/vendor/github.com/go-ini/ini/section.go
+++ b/vendor/github.com/go-ini/ini/section.go
@@ -54,6 +54,14 @@ func (s *Section) Body() string {
return strings.TrimSpace(s.rawBody)
}
+// SetBody updates body content only if section is raw.
+func (s *Section) SetBody(body string) {
+ if !s.isRawSection {
+ return
+ }
+ s.rawBody = body
+}
+
// NewKey creates a new key to given section.
func (s *Section) NewKey(name, val string) (*Key, error) {
if len(name) == 0 {
@@ -136,6 +144,7 @@ func (s *Section) HasKey(name string) bool {
}
// Haskey is a backwards-compatible name for HasKey.
+// TODO: delete me in v2
func (s *Section) Haskey(name string) bool {
return s.HasKey(name)
}
diff --git a/vendor/github.com/go-ini/ini/section_test.go b/vendor/github.com/go-ini/ini/section_test.go
index 80282c197..e9c347881 100644
--- a/vendor/github.com/go-ini/ini/section_test.go
+++ b/vendor/github.com/go-ini/ini/section_test.go
@@ -12,64 +12,302 @@
// License for the specific language governing permissions and limitations
// under the License.
-package ini
+package ini_test
import (
- "strings"
"testing"
. "github.com/smartystreets/goconvey/convey"
+ "gopkg.in/ini.v1"
)
-func Test_Section(t *testing.T) {
- Convey("Test CRD sections", t, func() {
- cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
+func TestSection_SetBody(t *testing.T) {
+ Convey("Set body of raw section", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ sec, err := f.NewRawSection("comments", `1111111111111111111000000000000000001110000
+111111111111111111100000000000111000000000`)
+ So(err, ShouldBeNil)
+ So(sec, ShouldNotBeNil)
+ So(sec.Body(), ShouldEqual, `1111111111111111111000000000000000001110000
+111111111111111111100000000000111000000000`)
+
+ sec.SetBody("1111111111111111111000000000000000001110000")
+ So(sec.Body(), ShouldEqual, `1111111111111111111000000000000000001110000`)
+
+ Convey("Set for non-raw section", func() {
+ sec, err := f.NewSection("author")
+ So(err, ShouldBeNil)
+ So(sec, ShouldNotBeNil)
+ So(sec.Body(), ShouldBeEmpty)
+
+ sec.SetBody("1111111111111111111000000000000000001110000")
+ So(sec.Body(), ShouldBeEmpty)
+ })
+ })
+}
+
+func TestSection_NewKey(t *testing.T) {
+ Convey("Create a new key", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ k, err := f.Section("").NewKey("NAME", "ini")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ So(k.Name(), ShouldEqual, "NAME")
+ So(k.Value(), ShouldEqual, "ini")
+
+ Convey("With duplicated name", func() {
+ k, err := f.Section("").NewKey("NAME", "ini.v1")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+
+ // Overwrite previous existed key
+ So(k.Value(), ShouldEqual, "ini.v1")
+ })
+
+ Convey("With empty string", func() {
+ _, err := f.Section("").NewKey("", "")
+ So(err, ShouldNotBeNil)
+ })
+ })
+
+ Convey("Create keys with same name and allow shadow", t, func() {
+ f, err := ini.ShadowLoad([]byte(""))
+ So(err, ShouldBeNil)
+ So(f, ShouldNotBeNil)
+
+ k, err := f.Section("").NewKey("NAME", "ini")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ k, err = f.Section("").NewKey("NAME", "ini.v1")
So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
+ So(k, ShouldNotBeNil)
- Convey("Get section strings", func() {
- So(strings.Join(cfg.SectionStrings(), ","), ShouldEqual, "DEFAULT,author,package,package.sub,features,types,array,note,comments,advance")
+ So(k.ValueWithShadows(), ShouldResemble, []string{"ini", "ini.v1"})
+ })
+}
+
+func TestSection_NewBooleanKey(t *testing.T) {
+ Convey("Create a new boolean key", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ k, err := f.Section("").NewBooleanKey("start-ssh-server")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ So(k.Name(), ShouldEqual, "start-ssh-server")
+ So(k.Value(), ShouldEqual, "true")
+
+ Convey("With empty string", func() {
+ _, err := f.Section("").NewBooleanKey("")
+ So(err, ShouldNotBeNil)
})
+ })
+}
+
+func TestSection_GetKey(t *testing.T) {
+ Convey("Get a key", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
- Convey("Delete a section", func() {
- cfg.DeleteSection("")
- So(cfg.SectionStrings()[0], ShouldNotEqual, DEFAULT_SECTION)
+ k, err := f.Section("").NewKey("NAME", "ini")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+
+ k, err = f.Section("").GetKey("NAME")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ So(k.Name(), ShouldEqual, "NAME")
+ So(k.Value(), ShouldEqual, "ini")
+
+ Convey("Key not exists", func() {
+ _, err := f.Section("").GetKey("404")
+ So(err, ShouldNotBeNil)
})
- Convey("Create new sections", func() {
- cfg.NewSections("test", "test2")
- _, err := cfg.GetSection("test")
+ Convey("Key exists in parent section", func() {
+ k, err := f.Section("parent").NewKey("AGE", "18")
So(err, ShouldBeNil)
- _, err = cfg.GetSection("test2")
+ So(k, ShouldNotBeNil)
+
+ k, err = f.Section("parent.child.son").GetKey("AGE")
So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ So(k.Value(), ShouldEqual, "18")
})
})
}
-func Test_SectionRaw(t *testing.T) {
- Convey("Test section raw string", t, func() {
- cfg, err := LoadSources(
- LoadOptions{
- Insensitive: true,
- UnparseableSections: []string{"core_lesson", "comments"},
- },
- "testdata/aicc.ini")
+func TestSection_HasKey(t *testing.T) {
+ Convey("Check if a key exists", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ k, err := f.Section("").NewKey("NAME", "ini")
So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
+ So(k, ShouldNotBeNil)
+
+ So(f.Section("").HasKey("NAME"), ShouldBeTrue)
+ So(f.Section("").Haskey("NAME"), ShouldBeTrue)
+ So(f.Section("").HasKey("404"), ShouldBeFalse)
+ So(f.Section("").Haskey("404"), ShouldBeFalse)
+ })
+}
- Convey("Get section strings", func() {
- So(strings.Join(cfg.SectionStrings(), ","), ShouldEqual, "DEFAULT,core,core_lesson,comments")
+func TestSection_HasValue(t *testing.T) {
+ Convey("Check if contains a value in any key", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ k, err := f.Section("").NewKey("NAME", "ini")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+
+ So(f.Section("").HasValue("ini"), ShouldBeTrue)
+ So(f.Section("").HasValue("404"), ShouldBeFalse)
+ })
+}
+
+func TestSection_Key(t *testing.T) {
+ Convey("Get a key", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ k, err := f.Section("").NewKey("NAME", "ini")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+
+ k = f.Section("").Key("NAME")
+ So(k, ShouldNotBeNil)
+ So(k.Name(), ShouldEqual, "NAME")
+ So(k.Value(), ShouldEqual, "ini")
+
+ Convey("Key not exists", func() {
+ k := f.Section("").Key("404")
+ So(k, ShouldNotBeNil)
+ So(k.Name(), ShouldEqual, "404")
})
- Convey("Validate non-raw section", func() {
- val, err := cfg.Section("core").GetKey("lesson_status")
+ Convey("Key exists in parent section", func() {
+ k, err := f.Section("parent").NewKey("AGE", "18")
So(err, ShouldBeNil)
- So(val.String(), ShouldEqual, "C")
- })
+ So(k, ShouldNotBeNil)
- Convey("Validate raw section", func() {
- So(cfg.Section("core_lesson").Body(), ShouldEqual, `my lesson state data – 1111111111111111111000000000000000001110000
-111111111111111111100000000000111000000000 – end my lesson state data`)
+ k = f.Section("parent.child.son").Key("AGE")
+ So(k, ShouldNotBeNil)
+ So(k.Value(), ShouldEqual, "18")
})
})
-} \ No newline at end of file
+}
+
+func TestSection_Keys(t *testing.T) {
+ Convey("Get all keys in a section", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ k, err := f.Section("").NewKey("NAME", "ini")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ k, err = f.Section("").NewKey("VERSION", "v1")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ k, err = f.Section("").NewKey("IMPORT_PATH", "gopkg.in/ini.v1")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+
+ keys := f.Section("").Keys()
+ names := []string{"NAME", "VERSION", "IMPORT_PATH"}
+ So(len(keys), ShouldEqual, len(names))
+ for i, name := range names {
+ So(keys[i].Name(), ShouldEqual, name)
+ }
+ })
+}
+
+func TestSection_ParentKeys(t *testing.T) {
+ Convey("Get all keys of parent sections", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ k, err := f.Section("package").NewKey("NAME", "ini")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ k, err = f.Section("package").NewKey("VERSION", "v1")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ k, err = f.Section("package").NewKey("IMPORT_PATH", "gopkg.in/ini.v1")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+
+ keys := f.Section("package.sub.sub2").ParentKeys()
+ names := []string{"NAME", "VERSION", "IMPORT_PATH"}
+ So(len(keys), ShouldEqual, len(names))
+ for i, name := range names {
+ So(keys[i].Name(), ShouldEqual, name)
+ }
+ })
+}
+
+func TestSection_KeyStrings(t *testing.T) {
+ Convey("Get all key names in a section", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ k, err := f.Section("").NewKey("NAME", "ini")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ k, err = f.Section("").NewKey("VERSION", "v1")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ k, err = f.Section("").NewKey("IMPORT_PATH", "gopkg.in/ini.v1")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+
+ So(f.Section("").KeyStrings(), ShouldResemble, []string{"NAME", "VERSION", "IMPORT_PATH"})
+ })
+}
+
+func TestSection_KeyHash(t *testing.T) {
+ Convey("Get clone of key hash", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ k, err := f.Section("").NewKey("NAME", "ini")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ k, err = f.Section("").NewKey("VERSION", "v1")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+ k, err = f.Section("").NewKey("IMPORT_PATH", "gopkg.in/ini.v1")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+
+ hash := f.Section("").KeysHash()
+ relation := map[string]string{
+ "NAME": "ini",
+ "VERSION": "v1",
+ "IMPORT_PATH": "gopkg.in/ini.v1",
+ }
+ for k, v := range hash {
+ So(v, ShouldEqual, relation[k])
+ }
+ })
+}
+
+func TestSection_DeleteKey(t *testing.T) {
+ Convey("Delete a key", t, func() {
+ f := ini.Empty()
+ So(f, ShouldNotBeNil)
+
+ k, err := f.Section("").NewKey("NAME", "ini")
+ So(err, ShouldBeNil)
+ So(k, ShouldNotBeNil)
+
+ So(f.Section("").HasKey("NAME"), ShouldBeTrue)
+ f.Section("").DeleteKey("NAME")
+ So(f.Section("").HasKey("NAME"), ShouldBeFalse)
+ })
+}
diff --git a/vendor/github.com/go-ini/ini/struct.go b/vendor/github.com/go-ini/ini/struct.go
index eeb8dabaa..9719dc698 100644
--- a/vendor/github.com/go-ini/ini/struct.go
+++ b/vendor/github.com/go-ini/ini/struct.go
@@ -113,7 +113,7 @@ func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowSh
default:
return fmt.Errorf("unsupported type '[]%s'", sliceOf)
}
- if isStrict {
+ if err != nil && isStrict {
return err
}
@@ -166,7 +166,7 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
durationVal, err := key.Duration()
// Skip zero value
- if err == nil && int(durationVal) > 0 {
+ if err == nil && int64(durationVal) > 0 {
field.Set(reflect.ValueOf(durationVal))
return nil
}
@@ -450,6 +450,12 @@ func (s *Section) reflectFrom(val reflect.Value) error {
// Note: fieldName can never be empty here, ignore error.
sec, _ = s.f.NewSection(fieldName)
}
+
+ // Add comment from comment tag
+ if len(sec.Comment) == 0 {
+ sec.Comment = tpField.Tag.Get("comment")
+ }
+
if err = sec.reflectFrom(field); err != nil {
return fmt.Errorf("error reflecting field (%s): %v", fieldName, err)
}
@@ -461,6 +467,12 @@ func (s *Section) reflectFrom(val reflect.Value) error {
if err != nil {
key, _ = s.NewKey(fieldName, "")
}
+
+ // Add comment from comment tag
+ if len(key.Comment) == 0 {
+ key.Comment = tpField.Tag.Get("comment")
+ }
+
if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil {
return fmt.Errorf("error reflecting field (%s): %v", fieldName, err)
}
diff --git a/vendor/github.com/go-ini/ini/struct_test.go b/vendor/github.com/go-ini/ini/struct_test.go
index b8ba25293..75987ea99 100644
--- a/vendor/github.com/go-ini/ini/struct_test.go
+++ b/vendor/github.com/go-ini/ini/struct_test.go
@@ -12,7 +12,7 @@
// License for the specific language governing permissions and limitations
// under the License.
-package ini
+package ini_test
import (
"bytes"
@@ -22,6 +22,7 @@ import (
"time"
. "github.com/smartystreets/goconvey/convey"
+ "gopkg.in/ini.v1"
)
type testNested struct {
@@ -126,11 +127,11 @@ Born = nil
Cities =
`
-func Test_Struct(t *testing.T) {
+func Test_MapToStruct(t *testing.T) {
Convey("Map to struct", t, func() {
Convey("Map file to struct", func() {
ts := new(testStruct)
- So(MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil)
+ So(ini.MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil)
So(ts.Name, ShouldEqual, "Unknwon")
So(ts.Age, ShouldEqual, 21)
@@ -159,7 +160,7 @@ func Test_Struct(t *testing.T) {
Convey("Map section to struct", func() {
foobar := new(fooBar)
- f, err := Load([]byte(_CONF_DATA_STRUCT))
+ f, err := ini.Load([]byte(_CONF_DATA_STRUCT))
So(err, ShouldBeNil)
So(f.Section("foo.bar").MapTo(foobar), ShouldBeNil)
@@ -168,58 +169,58 @@ func Test_Struct(t *testing.T) {
})
Convey("Map to non-pointer struct", func() {
- cfg, err := Load([]byte(_CONF_DATA_STRUCT))
+ f, err := ini.Load([]byte(_CONF_DATA_STRUCT))
So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
+ So(f, ShouldNotBeNil)
- So(cfg.MapTo(testStruct{}), ShouldNotBeNil)
+ So(f.MapTo(testStruct{}), ShouldNotBeNil)
})
Convey("Map to unsupported type", func() {
- cfg, err := Load([]byte(_CONF_DATA_STRUCT))
+ f, err := ini.Load([]byte(_CONF_DATA_STRUCT))
So(err, ShouldBeNil)
- So(cfg, ShouldNotBeNil)
+ So(f, ShouldNotBeNil)
- cfg.NameMapper = func(raw string) string {
+ f.NameMapper = func(raw string) string {
if raw == "Byte" {
return "NAME"
}
return raw
}
- So(cfg.MapTo(&unsupport{}), ShouldNotBeNil)
- So(cfg.MapTo(&unsupport2{}), ShouldNotBeNil)
- So(cfg.MapTo(&unsupport4{}), ShouldNotBeNil)
+ So(f.MapTo(&unsupport{}), ShouldNotBeNil)
+ So(f.MapTo(&unsupport2{}), ShouldNotBeNil)
+ So(f.MapTo(&unsupport4{}), ShouldNotBeNil)
})
Convey("Map to omitempty field", func() {
ts := new(testStruct)
- So(MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil)
+ So(ini.MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil)
So(ts.Omitted, ShouldEqual, true)
})
Convey("Map with shadows", func() {
- cfg, err := LoadSources(LoadOptions{AllowShadows: true}, []byte(_CONF_DATA_STRUCT))
+ f, err := ini.LoadSources(ini.LoadOptions{AllowShadows: true}, []byte(_CONF_DATA_STRUCT))
So(err, ShouldBeNil)
ts := new(testStruct)
- So(cfg.MapTo(ts), ShouldBeNil)
+ So(f.MapTo(ts), ShouldBeNil)
So(strings.Join(ts.Shadows, " "), ShouldEqual, "1 2 3 4")
So(fmt.Sprintf("%v", ts.ShadowInts), ShouldEqual, "[1 2 3 4]")
})
Convey("Map from invalid data source", func() {
- So(MapTo(&testStruct{}, "hi"), ShouldNotBeNil)
+ So(ini.MapTo(&testStruct{}, "hi"), ShouldNotBeNil)
})
Convey("Map to wrong types and gain default values", func() {
- cfg, err := Load([]byte(_INVALID_DATA_CONF_STRUCT))
+ f, err := ini.Load([]byte(_INVALID_DATA_CONF_STRUCT))
So(err, ShouldBeNil)
t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
So(err, ShouldBeNil)
dv := &defaultValue{"Joe", 10, true, 1.25, t, []string{"HangZhou", "Boston"}}
- So(cfg.MapTo(dv), ShouldBeNil)
+ So(f.MapTo(dv), ShouldBeNil)
So(dv.Name, ShouldEqual, "Joe")
So(dv.Age, ShouldEqual, 10)
So(dv.Male, ShouldBeTrue)
@@ -230,7 +231,7 @@ func Test_Struct(t *testing.T) {
})
Convey("Map to struct in strict mode", t, func() {
- cfg, err := Load([]byte(`
+ f, err := ini.Load([]byte(`
name=bruce
age=a30`))
So(err, ShouldBeNil)
@@ -241,12 +242,28 @@ age=a30`))
}
s := new(Strict)
- So(cfg.Section("").StrictMapTo(s), ShouldNotBeNil)
+ So(f.Section("").StrictMapTo(s), ShouldNotBeNil)
})
+ Convey("Map slice in strict mode", t, func() {
+ f, err := ini.Load([]byte(`
+names=alice, bruce`))
+ So(err, ShouldBeNil)
+
+ type Strict struct {
+ Names []string `ini:"names"`
+ }
+ s := new(Strict)
+
+ So(f.Section("").StrictMapTo(s), ShouldBeNil)
+ So(fmt.Sprint(s.Names), ShouldEqual, "[alice bruce]")
+ })
+}
+
+func Test_ReflectFromStruct(t *testing.T) {
Convey("Reflect from struct", t, func() {
type Embeded struct {
- Dates []time.Time `delim:"|"`
+ Dates []time.Time `delim:"|" comment:"Time data"`
Places []string
Years []int
Numbers []int64
@@ -258,12 +275,12 @@ age=a30`))
type Author struct {
Name string `ini:"NAME"`
Male bool
- Age int
+ Age int `comment:"Author's age"`
Height uint
GPA float64
Date time.Time
NeverMind string `ini:"-"`
- *Embeded `ini:"infos"`
+ *Embeded `ini:"infos" comment:"Embeded section"`
}
t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
@@ -279,20 +296,23 @@ age=a30`))
[]float64{192.168, 10.11},
[]int{},
}}
- cfg := Empty()
- So(ReflectFrom(cfg, a), ShouldBeNil)
+ cfg := ini.Empty()
+ So(ini.ReflectFrom(cfg, a), ShouldBeNil)
var buf bytes.Buffer
_, err = cfg.WriteTo(&buf)
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `NAME = Unknwon
Male = true
+; Author's age
Age = 21
Height = 100
GPA = 2.8
Date = 1993-10-07T20:17:05Z
+; Embeded section
[infos]
+; Time data
Dates = 1993-10-07T20:17:05Z|1993-10-07T20:17:05Z
Places = HangZhou,Boston
Years = 1993,1994
@@ -305,11 +325,11 @@ None =
`)
Convey("Reflect from non-point struct", func() {
- So(ReflectFrom(cfg, Author{}), ShouldNotBeNil)
+ So(ini.ReflectFrom(cfg, Author{}), ShouldNotBeNil)
})
Convey("Reflect from struct with omitempty", func() {
- cfg := Empty()
+ cfg := ini.Empty()
type SpecialStruct struct {
FirstName string `ini:"first_name"`
LastName string `ini:"last_name"`
@@ -319,7 +339,7 @@ None =
NotEmpty int `ini:"omitempty"`
}
- So(ReflectFrom(cfg, &SpecialStruct{FirstName: "John", LastName: "Doe", NotEmpty: 9}), ShouldBeNil)
+ So(ini.ReflectFrom(cfg, &SpecialStruct{FirstName: "John", LastName: "Doe", NotEmpty: 9}), ShouldBeNil)
var buf bytes.Buffer
_, err = cfg.WriteTo(&buf)
@@ -338,15 +358,30 @@ type testMapper struct {
func Test_NameGetter(t *testing.T) {
Convey("Test name mappers", t, func() {
- So(MapToWithMapper(&testMapper{}, TitleUnderscore, []byte("packag_name=ini")), ShouldBeNil)
+ So(ini.MapToWithMapper(&testMapper{}, ini.TitleUnderscore, []byte("packag_name=ini")), ShouldBeNil)
- cfg, err := Load([]byte("PACKAGE_NAME=ini"))
+ cfg, err := ini.Load([]byte("PACKAGE_NAME=ini"))
So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil)
- cfg.NameMapper = AllCapsUnderscore
+ cfg.NameMapper = ini.AllCapsUnderscore
tg := new(testMapper)
So(cfg.MapTo(tg), ShouldBeNil)
So(tg.PackageName, ShouldEqual, "ini")
})
}
+
+type testDurationStruct struct {
+ Duration time.Duration `ini:"Duration"`
+}
+
+func Test_Duration(t *testing.T) {
+ Convey("Duration less than 16m50s", t, func() {
+ ds := new(testDurationStruct)
+ So(ini.MapTo(ds, []byte("Duration=16m49s")), ShouldBeNil)
+
+ dur, err := time.ParseDuration("16m49s")
+ So(err, ShouldBeNil)
+ So(ds.Duration.Seconds(), ShouldEqual, dur.Seconds())
+ })
+}
diff --git a/vendor/github.com/go-ini/ini/testdata/aicc.ini b/vendor/github.com/go-ini/ini/testdata/aicc.ini
deleted file mode 100644
index 59a61970d..000000000
--- a/vendor/github.com/go-ini/ini/testdata/aicc.ini
+++ /dev/null
@@ -1,11 +0,0 @@
-[Core]
- Lesson_Location = 87
-Lesson_Status = C
- Score = 3
-Time = 00:02:30
-
-[CORE_LESSON]
-my lesson state data – 1111111111111111111000000000000000001110000
-111111111111111111100000000000111000000000 – end my lesson state data
-[COMMENTS]
-<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
diff --git a/vendor/github.com/go-ini/ini/testdata/full.ini b/vendor/github.com/go-ini/ini/testdata/full.ini
new file mode 100644
index 000000000..469b1f13e
--- /dev/null
+++ b/vendor/github.com/go-ini/ini/testdata/full.ini
@@ -0,0 +1,83 @@
+; Package name
+NAME = ini
+; Package version
+VERSION = v1
+; Package import path
+IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
+
+# Information about package author
+# Bio can be written in multiple lines.
+[author]
+NAME = Unknwon
+E-MAIL = u@gogs.io
+GITHUB = https://github.com/%(NAME)s
+BIO = """Gopher.
+Coding addict.
+Good man.
+""" # Succeeding comment
+
+[package]
+CLONE_URL = https://%(IMPORT_PATH)s
+
+[package.sub]
+UNUSED_KEY = should be deleted
+
+[features]
+-: Support read/write comments of keys and sections
+-: Support auto-increment of key names
+-: Support load multiple files to overwrite key values
+
+[types]
+STRING = str
+BOOL = true
+BOOL_FALSE = false
+FLOAT64 = 1.25
+INT = 10
+TIME = 2015-01-01T20:17:05Z
+DURATION = 2h45m
+UINT = 3
+
+[array]
+STRINGS = en, zh, de
+FLOAT64S = 1.1, 2.2, 3.3
+INTS = 1, 2, 3
+UINTS = 1, 2, 3
+TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z
+
+[note]
+empty_lines = next line is empty\
+
+; Comment before the section
+[comments] ; This is a comment for the section too
+; Comment before key
+key = "value"
+key2 = "value2" ; This is a comment for key2
+key3 = "one", "two", "three"
+
+[string escapes]
+key1 = value1, value2, value3
+key2 = value1\, value2
+key3 = val\ue1, value2
+key4 = value1\\, value\\\\2
+key5 = value1\,, value2
+key6 = aaa bbb\ and\ space ccc
+
+[advance]
+value with quotes = "some value"
+value quote2 again = 'some value'
+includes comment sign = `my#password`
+includes comment sign2 = `my;password`
+true = 2+3=5
+"1+1=2" = true
+"""6+1=7""" = true
+"""`5+5`""" = 10
+`"6+6"` = 12
+`7-2=4` = false
+ADDRESS = `404 road,
+NotFound, State, 50000`
+two_lines = how about \
+ continuation lines?
+lots_of_lines = 1 \
+ 2 \
+ 3 \
+ 4 \
diff --git a/vendor/github.com/go-ini/ini/testdata/conf.ini b/vendor/github.com/go-ini/ini/testdata/minimal.ini
index f8e7ec89f..f8e7ec89f 100644
--- a/vendor/github.com/go-ini/ini/testdata/conf.ini
+++ b/vendor/github.com/go-ini/ini/testdata/minimal.ini