mirror of
https://github.com/restic/restic.git
synced 2026-09-26 14:00:29 +00:00
Upadte vendored dependencies
This commit is contained in:
+5
@@ -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?
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
### What problem should be fixed?
|
||||
|
||||
### Have you added test cases to catch the problem?
|
||||
Generated
+1
@@ -3,3 +3,4 @@ ini.sublime-project
|
||||
ini.sublime-workspace
|
||||
testdata/conf_reflect.ini
|
||||
.idea
|
||||
/.vscode
|
||||
|
||||
+1
-2
@@ -1,12 +1,11 @@
|
||||
sudo: false
|
||||
language: go
|
||||
go:
|
||||
- 1.4.x
|
||||
- 1.5.x
|
||||
- 1.6.x
|
||||
- 1.7.x
|
||||
- 1.8.x
|
||||
- master
|
||||
- 1.9.x
|
||||
|
||||
script:
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
|
||||
+1
-1
@@ -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.
|
||||
|
||||
+23
-6
@@ -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
|
||||
```
|
||||
|
||||
+23
-6
@@ -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
|
||||
```
|
||||
|
||||
+7
-1
@@ -35,7 +35,7 @@ const (
|
||||
|
||||
// Maximum allowed depth when recursively substituing variable names.
|
||||
_DEPTH_VALUES = 99
|
||||
_VERSION = "1.28.2"
|
||||
_VERSION = "1.30.0"
|
||||
)
|
||||
|
||||
// Version returns current package version literal.
|
||||
@@ -181,6 +181,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
|
||||
@@ -409,6 +411,8 @@ func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
|
||||
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
|
||||
@@ -463,6 +467,8 @@ func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
|
||||
}
|
||||
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
|
||||
|
||||
+28
-1
@@ -87,6 +87,14 @@ 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'
|
||||
@@ -241,7 +249,7 @@ key5`))
|
||||
// there is always a trailing \n at the end of the section
|
||||
So(buf.String(), ShouldEqual, `key1 = hello
|
||||
key2
|
||||
#key3
|
||||
# key3
|
||||
key4
|
||||
key5
|
||||
`)
|
||||
@@ -294,6 +302,17 @@ func Test_LooseLoad(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func Test_LoadOptions_UnescapeValueDoubleQuotes(t *testing.T) {
|
||||
Convey("Load with option UnescapeValueDoubleQuotes enabled", t, func() {
|
||||
cfg, err := LoadSources(LoadOptions{UnescapeValueDoubleQuotes: true},
|
||||
[]byte(`create_repo="创建了仓库 <a href=\"%s\">%s</a>"`))
|
||||
So(err, ShouldBeNil)
|
||||
So(cfg, ShouldNotBeNil)
|
||||
|
||||
So(cfg.Section("").Key("create_repo").String(), ShouldEqual, `创建了仓库 <a href="%s">%s</a>`)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_File_Append(t *testing.T) {
|
||||
Convey("Append data sources", t, func() {
|
||||
cfg, err := Load([]byte(""))
|
||||
@@ -397,6 +416,14 @@ Good man.
|
||||
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
|
||||
|
||||
+33
-4
@@ -15,6 +15,7 @@
|
||||
package ini
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
@@ -444,11 +445,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
|
||||
}
|
||||
|
||||
|
||||
+11
-1
@@ -73,7 +73,7 @@ func Test_Key(t *testing.T) {
|
||||
|
||||
Convey("Get sections", func() {
|
||||
sections := cfg.Sections()
|
||||
for i, name := range []string{DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "advance"} {
|
||||
for i, name := range []string{DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"} {
|
||||
So(sections[i].Name(), ShouldEqual, name)
|
||||
}
|
||||
})
|
||||
@@ -243,6 +243,16 @@ func Test_Key(t *testing.T) {
|
||||
timesEqual(vals6, t, t, t)
|
||||
})
|
||||
|
||||
Convey("Test string slice escapes", func() {
|
||||
sec := cfg.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")
|
||||
vals1 := sec.Key("FLOAT64S").ValidFloat64s(",")
|
||||
|
||||
+15
-4
@@ -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]
|
||||
@@ -321,7 +326,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 +352,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
|
||||
}
|
||||
|
||||
+3
-3
@@ -28,7 +28,7 @@ func Test_Section(t *testing.T) {
|
||||
So(cfg, ShouldNotBeNil)
|
||||
|
||||
Convey("Get section strings", func() {
|
||||
So(strings.Join(cfg.SectionStrings(), ","), ShouldEqual, "DEFAULT,author,package,package.sub,features,types,array,note,comments,advance")
|
||||
So(strings.Join(cfg.SectionStrings(), ","), ShouldEqual, "DEFAULT,author,package,package.sub,features,types,array,note,comments,string escapes,advance")
|
||||
})
|
||||
|
||||
Convey("Delete a section", func() {
|
||||
@@ -50,7 +50,7 @@ func Test_SectionRaw(t *testing.T) {
|
||||
Convey("Test section raw string", t, func() {
|
||||
cfg, err := LoadSources(
|
||||
LoadOptions{
|
||||
Insensitive: true,
|
||||
Insensitive: true,
|
||||
UnparseableSections: []string{"core_lesson", "comments"},
|
||||
},
|
||||
"testdata/aicc.ini")
|
||||
@@ -72,4 +72,4 @@ func Test_SectionRaw(t *testing.T) {
|
||||
111111111111111111100000000000111000000000 – end my lesson state data`)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+13
-1
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
+20
-3
@@ -244,9 +244,23 @@ age=a30`))
|
||||
So(cfg.Section("").StrictMapTo(s), ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("Map slice in strict mode", t, func() {
|
||||
cfg, err := Load([]byte(`
|
||||
names=alice, bruce`))
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
type Strict struct {
|
||||
Names []string `ini:"names"`
|
||||
}
|
||||
s := new(Strict)
|
||||
|
||||
So(cfg.Section("").StrictMapTo(s), ShouldBeNil)
|
||||
So(fmt.Sprint(s.Names), ShouldEqual, "[alice bruce]")
|
||||
})
|
||||
|
||||
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 +272,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")
|
||||
@@ -287,12 +301,15 @@ age=a30`))
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user