Update dependencies

- uses newer version of go-ethereum required for go1.11
This commit is contained in:
Rob Mulholand
2018-09-13 16:14:35 -05:00
parent 939ead0c82
commit 560305f601
2356 changed files with 331656 additions and 128304 deletions
+1
View File
@@ -6,4 +6,5 @@ go:
- 1.7.x
- 1.8.x
- 1.9.x
- "1.10.x"
- tip
+52 -23
View File
@@ -1,63 +1,92 @@
## Changelog
### [1.7.4](https://github.com/magiconair/properties/tags/v1.7.4) - 31 Oct 2017
### [1.8](https://github.com/magiconair/properties/tree/v1.8) - 15 May 2018
* [PR #26](https://github.com/magiconair/properties/pull/26): Disable expansion during loading
This adds the option to disable property expansion during loading.
Thanks to [@kmala](https://github.com/kmala) for the patch.
### [1.7.6](https://github.com/magiconair/properties/tree/v1.7.6) - 14 Feb 2018
* [PR #29](https://github.com/magiconair/properties/pull/29): Reworked expansion logic to handle more complex cases.
See PR for an example.
Thanks to [@yobert](https://github.com/yobert) for the fix.
### [1.7.5](https://github.com/magiconair/properties/tree/v1.7.5) - 13 Feb 2018
* [PR #28](https://github.com/magiconair/properties/pull/28): Support duplicate expansions in the same value
Values which expand the same key multiple times (e.g. `key=${a} ${a}`) will no longer fail
with a `circular reference error`.
Thanks to [@yobert](https://github.com/yobert) for the fix.
### [1.7.4](https://github.com/magiconair/properties/tree/v1.7.4) - 31 Oct 2017
* [Issue #23](https://github.com/magiconair/properties/issues/23): Ignore blank lines with whitespaces
* [PR #24](https://github.com/magiconair/properties/pull/24): Update keys when DisableExpansion is enabled
Thanks to @mgurov for the fix.
### [1.7.3](https://github.com/magiconair/properties/tags/v1.7.3) - 10 Jul 2017
* [PR #24](https://github.com/magiconair/properties/pull/24): Update keys when DisableExpansion is enabled
Thanks to [@mgurov](https://github.com/mgurov) for the fix.
### [1.7.3](https://github.com/magiconair/properties/tree/v1.7.3) - 10 Jul 2017
* [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically
* [Issue #22](https://github.com/magiconair/properties/issues/22): Add [LoadMap()](http://godoc.org/github.com/magiconair/properties#LoadMap) function to load properties from a string map
### [1.7.2](https://github.com/magiconair/properties/tags/v1.7.2) - 20 Mar 2017
### [1.7.2](https://github.com/magiconair/properties/tree/v1.7.2) - 20 Mar 2017
* [Issue #15](https://github.com/magiconair/properties/issues/15): Drop gocheck dependency
* [PR #21](https://github.com/magiconair/properties/pull/21): Add [Map()](http://godoc.org/github.com/magiconair/properties#Properties.Map) and [FilterFunc()](http://godoc.org/github.com/magiconair/properties#Properties.FilterFunc)
### [1.7.1](https://github.com/magiconair/properties/tags/v1.7.1) - 13 Jan 2017
### [1.7.1](https://github.com/magiconair/properties/tree/v1.7.1) - 13 Jan 2017
* [Issue #14](https://github.com/magiconair/properties/issues/14): Decouple TestLoadExpandedFile from `$USER`
* [PR #12](https://github.com/magiconair/properties/pull/12): Load from files and URLs
* [PR #16](https://github.com/magiconair/properties/pull/16): Keep gofmt happy
* [PR #18](https://github.com/magiconair/properties/pull/18): Fix Delete() function
### [1.7.0](https://github.com/magiconair/properties/tags/v1.7.0) - 20 Mar 2016
### [1.7.0](https://github.com/magiconair/properties/tree/v1.7.0) - 20 Mar 2016
* [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#LoadURL) method to load properties from a URL.
* [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#LoadString) method to load properties from an UTF8 string.
* [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe)
### [1.6.0](https://github.com/magiconair/properties/tags/v1.6.0) - 11 Dec 2015
### [1.6.0](https://github.com/magiconair/properties/tree/v1.6.0) - 11 Dec 2015
* Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags.
### [1.5.6](https://github.com/magiconair/properties/tags/v1.5.6) - 18 Oct 2015
### [1.5.6](https://github.com/magiconair/properties/tree/v1.5.6) - 18 Oct 2015
* Vendored in gopkg.in/check.v1
### [1.5.5](https://github.com/magiconair/properties/tags/v1.5.5) - 31 Jul 2015
### [1.5.5](https://github.com/magiconair/properties/tree/v1.5.5) - 31 Jul 2015
* [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs)
### [1.5.4](https://github.com/magiconair/properties/tags/v1.5.4) - 23 Jun 2015
### [1.5.4](https://github.com/magiconair/properties/tree/v1.5.4) - 23 Jun 2015
* [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references.
### [1.5.3](https://github.com/magiconair/properties/tags/v1.5.3) - 02 Jun 2015
### [1.5.3](https://github.com/magiconair/properties/tree/v1.5.3) - 02 Jun 2015
* [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp)
### [1.5.2](https://github.com/magiconair/properties/tags/v1.5.2) - 10 Apr 2015
### [1.5.2](https://github.com/magiconair/properties/tree/v1.5.2) - 10 Apr 2015
* [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty
* Add clickable links to README
### [1.5.1](https://github.com/magiconair/properties/tags/v1.5.1) - 08 Dec 2014
### [1.5.1](https://github.com/magiconair/properties/tree/v1.5.1) - 08 Dec 2014
* Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with
[time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration).
### [1.5.0](https://github.com/magiconair/properties/tags/v1.5.0) - 18 Nov 2014
### [1.5.0](https://github.com/magiconair/properties/tree/v1.5.0) - 18 Nov 2014
* Added support for single and multi-line comments (reading, writing and updating)
* The order of keys is now preserved
@@ -65,31 +94,31 @@
* Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method
* Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1)
### [1.4.2](https://github.com/magiconair/properties/tags/v1.4.2) - 15 Nov 2014
### [1.4.2](https://github.com/magiconair/properties/tree/v1.4.2) - 15 Nov 2014
* [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one
### [1.4.1](https://github.com/magiconair/properties/tags/v1.4.1) - 13 Nov 2014
### [1.4.1](https://github.com/magiconair/properties/tree/v1.4.1) - 13 Nov 2014
* [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string
### [1.4.0](https://github.com/magiconair/properties/tags/v1.4.0) - 23 Sep 2014
### [1.4.0](https://github.com/magiconair/properties/tree/v1.4.0) - 23 Sep 2014
* Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys
* Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties
### [1.3.0](https://github.com/magiconair/properties/tags/v1.3.0) - 18 Mar 2014
### [1.3.0](https://github.com/magiconair/properties/tree/v1.3.0) - 18 Mar 2014
* Added support for time.Duration
* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tags/vior configurable (log.Fatal, panic) - custom)
* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tree/vior configurable (log.Fatal, panic) - custom)
* Changed default of MustXXX() failure from panic to log.Fatal
### [1.2.0](https://github.com/magiconair/properties/tags/v1.2.0) - 05 Mar 2014
### [1.2.0](https://github.com/magiconair/properties/tree/v1.2.0) - 05 Mar 2014
* Added MustGet... functions
* Added support for int and uint with range checks on 32 bit platforms
### [1.1.0](https://github.com/magiconair/properties/tags/v1.1.0) - 20 Jan 2014
### [1.1.0](https://github.com/magiconair/properties/tree/v1.1.0) - 20 Jan 2014
* Renamed from goproperties to properties
* Added support for expansion of environment vars in
@@ -97,6 +126,6 @@
* Fixed bug where value expressions were not at the
start of the string
### [1.0.0](https://github.com/magiconair/properties/tags/v1.0.0) - 7 Jan 2014
### [1.0.0](https://github.com/magiconair/properties/tree/v1.0.0) - 7 Jan 2014
* Initial release
+1 -1
View File
@@ -1,6 +1,6 @@
goproperties - properties file decoder for Go
Copyright (c) 2013-2014 - Frank Schroeder
Copyright (c) 2013-2018 - Frank Schroeder
All rights reserved.
+40 -11
View File
@@ -1,7 +1,12 @@
Overview [![Build Status](https://travis-ci.org/magiconair/properties.svg?branch=master)](https://travis-ci.org/magiconair/properties)
========
[![](https://img.shields.io/github/tag/magiconair/properties.svg?style=flat-square&label=release)](https://github.com/magiconair/properties/releases)
[![Travis CI Status](https://img.shields.io/travis/magiconair/properties.svg?branch=master&style=flat-square&label=travis)](https://travis-ci.org/magiconair/properties)
[![Codeship CI Status](https://img.shields.io/codeship/16aaf660-f615-0135-b8f0-7e33b70920c0/master.svg?label=codeship&style=flat-square)](https://app.codeship.com/projects/274177")
[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg?style=flat-square)](https://raw.githubusercontent.com/magiconair/properties/master/LICENSE)
[![GoDoc](http://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/magiconair/properties)
#### Current version: 1.7.4
# Overview
#### Please run `git pull --tags` to update the tags. See [below](#updated-git-tags) why.
properties is a Go library for reading and writing properties files.
@@ -27,8 +32,7 @@ details.
Read the full documentation on [GoDoc](https://godoc.org/github.com/magiconair/properties) [![GoDoc](https://godoc.org/github.com/magiconair/properties?status.png)](https://godoc.org/github.com/magiconair/properties)
Getting Started
---------------
## Getting Started
```go
import (
@@ -83,18 +87,43 @@ func main() {
```
Installation and Upgrade
------------------------
## Installation and Upgrade
```
$ go get -u github.com/magiconair/properties
```
License
-------
## License
2 clause BSD license. See [LICENSE](https://github.com/magiconair/properties/blob/master/LICENSE) file for details.
ToDo
----
## ToDo
* Dump contents with passwords and secrets obscured
## Updated Git tags
#### 13 Feb 2018
I realized that all of the git tags I had pushed before v1.7.5 were lightweight tags
and I've only recently learned that this doesn't play well with `git describe` 😞
I have replaced all lightweight tags with signed tags using this script which should
retain the commit date, name and email address. Please run `git pull --tags` to update them.
Worst case you have to reclone the repo.
```shell
#!/bin/bash
tag=$1
echo "Updating $tag"
date=$(git show ${tag}^0 --format=%aD | head -1)
email=$(git show ${tag}^0 --format=%aE | head -1)
name=$(git show ${tag}^0 --format=%aN | head -1)
GIT_COMMITTER_DATE="$date" GIT_COMMITTER_NAME="$name" GIT_COMMITTER_EMAIL="$email" git tag -s -f ${tag} ${tag}^0 -m ${tag}
```
I apologize for the inconvenience.
Frank
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+3 -3
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -73,7 +73,7 @@
// # refers to the users' home dir
// home = ${HOME}
//
// # local key takes precendence over env var: u = foo
// # local key takes precedence over env var: u = foo
// USER = foo
// u = ${USER}
//
@@ -102,7 +102,7 @@
// v = p.GetString("key", "def")
// v = p.GetDuration("key", 999)
//
// As an alterantive properties may be applied with the standard
// As an alternative properties may be applied with the standard
// library's flag implementation at any time.
//
// # Standard configuration
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+2 -2
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -52,7 +52,7 @@ func TestFlagOverride(t *testing.T) {
t.Errorf("Got customized b=%d, want %d", *gotB, want)
}
if want := 4; *gotC != want {
t.Errorf("Got overriden c=%d, want %d", *gotC, want)
t.Errorf("Got overridden c=%d, want %d", *gotC, want)
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
+155 -104
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -16,21 +16,157 @@ import (
type Encoding uint
const (
// utf8Default is a private placeholder for the zero value of Encoding to
// ensure that it has the correct meaning. UTF8 is the default encoding but
// was assigned a non-zero value which cannot be changed without breaking
// existing code. Clients should continue to use the public constants.
utf8Default Encoding = iota
// UTF8 interprets the input data as UTF-8.
UTF8 Encoding = 1 << iota
UTF8
// ISO_8859_1 interprets the input data as ISO-8859-1.
ISO_8859_1
)
type Loader struct {
// Encoding determines how the data from files and byte buffers
// is interpreted. For URLs the Content-Type header is used
// to determine the encoding of the data.
Encoding Encoding
// DisableExpansion configures the property expansion of the
// returned property object. When set to true, the property values
// will not be expanded and the Property object will not be checked
// for invalid expansion expressions.
DisableExpansion bool
// IgnoreMissing configures whether missing files or URLs which return
// 404 are reported as errors. When set to true, missing files and 404
// status codes are not reported as errors.
IgnoreMissing bool
}
// Load reads a buffer into a Properties struct.
func (l *Loader) LoadBytes(buf []byte) (*Properties, error) {
return l.loadBytes(buf, l.Encoding)
}
// LoadAll reads the content of multiple URLs or files in the given order into
// a Properties struct. If IgnoreMissing is true then a 404 status code or
// missing file will not be reported as error. Encoding sets the encoding for
// files. For the URLs see LoadURL for the Content-Type header and the
// encoding.
func (l *Loader) LoadAll(names []string) (*Properties, error) {
all := NewProperties()
for _, name := range names {
n, err := expandName(name)
if err != nil {
return nil, err
}
var p *Properties
switch {
case strings.HasPrefix(n, "http://"):
p, err = l.LoadURL(n)
case strings.HasPrefix(n, "https://"):
p, err = l.LoadURL(n)
default:
p, err = l.LoadFile(n)
}
if err != nil {
return nil, err
}
all.Merge(p)
}
all.DisableExpansion = l.DisableExpansion
if all.DisableExpansion {
return all, nil
}
return all, all.check()
}
// LoadFile reads a file into a Properties struct.
// If IgnoreMissing is true then a missing file will not be
// reported as error.
func (l *Loader) LoadFile(filename string) (*Properties, error) {
data, err := ioutil.ReadFile(filename)
if err != nil {
if l.IgnoreMissing && os.IsNotExist(err) {
LogPrintf("properties: %s not found. skipping", filename)
return NewProperties(), nil
}
return nil, err
}
return l.loadBytes(data, l.Encoding)
}
// LoadURL reads the content of the URL into a Properties struct.
//
// The encoding is determined via the Content-Type header which
// should be set to 'text/plain'. If the 'charset' parameter is
// missing, 'iso-8859-1' or 'latin1' the encoding is set to
// ISO-8859-1. If the 'charset' parameter is set to 'utf-8' the
// encoding is set to UTF-8. A missing content type header is
// interpreted as 'text/plain; charset=utf-8'.
func (l *Loader) LoadURL(url string) (*Properties, error) {
resp, err := http.Get(url)
if err != nil {
return nil, fmt.Errorf("properties: error fetching %q. %s", url, err)
}
if resp.StatusCode == 404 && l.IgnoreMissing {
LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode)
return NewProperties(), nil
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("properties: %s error reading response. %s", url, err)
}
defer resp.Body.Close()
ct := resp.Header.Get("Content-Type")
var enc Encoding
switch strings.ToLower(ct) {
case "text/plain", "text/plain; charset=iso-8859-1", "text/plain; charset=latin1":
enc = ISO_8859_1
case "", "text/plain; charset=utf-8":
enc = UTF8
default:
return nil, fmt.Errorf("properties: invalid content type %s", ct)
}
return l.loadBytes(body, enc)
}
func (l *Loader) loadBytes(buf []byte, enc Encoding) (*Properties, error) {
p, err := parse(convert(buf, enc))
if err != nil {
return nil, err
}
p.DisableExpansion = l.DisableExpansion
if p.DisableExpansion {
return p, nil
}
return p, p.check()
}
// Load reads a buffer into a Properties struct.
func Load(buf []byte, enc Encoding) (*Properties, error) {
return loadBuf(buf, enc)
l := &Loader{Encoding: enc}
return l.LoadBytes(buf)
}
// LoadString reads an UTF8 string into a properties struct.
func LoadString(s string) (*Properties, error) {
return loadBuf([]byte(s), UTF8)
l := &Loader{Encoding: UTF8}
return l.LoadBytes([]byte(s))
}
// LoadMap creates a new Properties struct from a string map.
@@ -44,34 +180,32 @@ func LoadMap(m map[string]string) *Properties {
// LoadFile reads a file into a Properties struct.
func LoadFile(filename string, enc Encoding) (*Properties, error) {
return loadAll([]string{filename}, enc, false)
l := &Loader{Encoding: enc}
return l.LoadAll([]string{filename})
}
// LoadFiles reads multiple files in the given order into
// a Properties struct. If 'ignoreMissing' is true then
// non-existent files will not be reported as error.
func LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
return loadAll(filenames, enc, ignoreMissing)
l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing}
return l.LoadAll(filenames)
}
// LoadURL reads the content of the URL into a Properties struct.
//
// The encoding is determined via the Content-Type header which
// should be set to 'text/plain'. If the 'charset' parameter is
// missing, 'iso-8859-1' or 'latin1' the encoding is set to
// ISO-8859-1. If the 'charset' parameter is set to 'utf-8' the
// encoding is set to UTF-8. A missing content type header is
// interpreted as 'text/plain; charset=utf-8'.
// See Loader#LoadURL for details.
func LoadURL(url string) (*Properties, error) {
return loadAll([]string{url}, UTF8, false)
l := &Loader{Encoding: UTF8}
return l.LoadAll([]string{url})
}
// LoadURLs reads the content of multiple URLs in the given order into a
// Properties struct. If 'ignoreMissing' is true then a 404 status code will
// not be reported as error. See LoadURL for the Content-Type header
// Properties struct. If IgnoreMissing is true then a 404 status code will
// not be reported as error. See Loader#LoadURL for the Content-Type header
// and the encoding.
func LoadURLs(urls []string, ignoreMissing bool) (*Properties, error) {
return loadAll(urls, UTF8, ignoreMissing)
l := &Loader{Encoding: UTF8, IgnoreMissing: ignoreMissing}
return l.LoadAll(urls)
}
// LoadAll reads the content of multiple URLs or files in the given order into a
@@ -79,7 +213,8 @@ func LoadURLs(urls []string, ignoreMissing bool) (*Properties, error) {
// not be reported as error. Encoding sets the encoding for files. For the URLs please see
// LoadURL for the Content-Type header and the encoding.
func LoadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
return loadAll(names, enc, ignoreMissing)
l := &Loader{Encoding: enc, IgnoreMissing: ignoreMissing}
return l.LoadAll(names)
}
// MustLoadString reads an UTF8 string into a Properties struct and
@@ -122,90 +257,6 @@ func MustLoadAll(names []string, enc Encoding, ignoreMissing bool) *Properties {
return must(LoadAll(names, enc, ignoreMissing))
}
func loadBuf(buf []byte, enc Encoding) (*Properties, error) {
p, err := parse(convert(buf, enc))
if err != nil {
return nil, err
}
return p, p.check()
}
func loadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
result := NewProperties()
for _, name := range names {
n, err := expandName(name)
if err != nil {
return nil, err
}
var p *Properties
if strings.HasPrefix(n, "http://") || strings.HasPrefix(n, "https://") {
p, err = loadURL(n, ignoreMissing)
} else {
p, err = loadFile(n, enc, ignoreMissing)
}
if err != nil {
return nil, err
}
result.Merge(p)
}
return result, result.check()
}
func loadFile(filename string, enc Encoding, ignoreMissing bool) (*Properties, error) {
data, err := ioutil.ReadFile(filename)
if err != nil {
if ignoreMissing && os.IsNotExist(err) {
LogPrintf("properties: %s not found. skipping", filename)
return NewProperties(), nil
}
return nil, err
}
p, err := parse(convert(data, enc))
if err != nil {
return nil, err
}
return p, nil
}
func loadURL(url string, ignoreMissing bool) (*Properties, error) {
resp, err := http.Get(url)
if err != nil {
return nil, fmt.Errorf("properties: error fetching %q. %s", url, err)
}
if resp.StatusCode == 404 && ignoreMissing {
LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode)
return NewProperties(), nil
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("properties: %s error reading response. %s", url, err)
}
if err = resp.Body.Close(); err != nil {
return nil, fmt.Errorf("properties: %s error reading response. %s", url, err)
}
ct := resp.Header.Get("Content-Type")
var enc Encoding
switch strings.ToLower(ct) {
case "text/plain", "text/plain; charset=iso-8859-1", "text/plain; charset=latin1":
enc = ISO_8859_1
case "", "text/plain; charset=utf-8":
enc = UTF8
default:
return nil, fmt.Errorf("properties: invalid content type %s", ct)
}
p, err := parse(convert(body, enc))
if err != nil {
return nil, err
}
return p, nil
}
func must(p *Properties, err error) *Properties {
if err != nil {
ErrorHandler(err)
@@ -218,7 +269,7 @@ func must(p *Properties, err error) *Properties {
// with an empty string. Malformed expressions like "${ENV_VAR" will
// be reported as error.
func expandName(name string) (string, error) {
return expand(name, make(map[string]bool), "${", "}", make(map[string]string))
return expand(name, []string{}, "${", "}", make(map[string]string))
}
// Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string.
@@ -226,7 +277,7 @@ func expandName(name string) (string, error) {
// first 256 unicode code points cover ISO-8859-1.
func convert(buf []byte, enc Encoding) string {
switch enc {
case UTF8:
case utf8Default, UTF8:
return string(buf)
case ISO_8859_1:
runes := make([]rune, len(buf))
+13 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -16,6 +16,18 @@ import (
"github.com/magiconair/properties/assert"
)
func TestEncoding(t *testing.T) {
if got, want := utf8Default, Encoding(0); got != want {
t.Fatalf("got encoding %d want %d", got, want)
}
if got, want := UTF8, Encoding(1); got != want {
t.Fatalf("got encoding %d want %d", got, want)
}
if got, want := ISO_8859_1, Encoding(2); got != want {
t.Fatalf("got encoding %d want %d", got, want)
}
}
func TestLoadFailsWithNotExistingFile(t *testing.T) {
_, err := LoadFile("doesnotexist.properties", ISO_8859_1)
assert.Equal(t, err != nil, true, "")
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+56 -34
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -19,6 +19,8 @@ import (
"unicode/utf8"
)
const maxExpansionDepth = 64
// ErrorHandlerFunc defines the type of function which handles failures
// of the MustXXX() functions. An error handler function must exit
// the application after handling the error.
@@ -81,6 +83,17 @@ func NewProperties() *Properties {
}
}
// Load reads a buffer into the given Properties struct.
func (p *Properties) Load(buf []byte, enc Encoding) error {
l := &Loader{Encoding: enc, DisableExpansion: p.DisableExpansion}
newProperties, err := l.LoadBytes(buf)
if err != nil {
return err
}
p.Merge(newProperties)
return nil
}
// Get returns the expanded value for the given key if exists.
// Otherwise, ok is false.
func (p *Properties) Get(key string) (value string, ok bool) {
@@ -92,7 +105,7 @@ func (p *Properties) Get(key string) (value string, ok bool) {
return "", false
}
expanded, err := p.expand(v)
expanded, err := p.expand(key, v)
// we guarantee that the expanded value is free of
// circular references and malformed expressions
@@ -525,7 +538,7 @@ func (p *Properties) Set(key, value string) (prev string, ok bool, err error) {
p.m[key] = value
// now check for a circular reference
_, err = p.expand(value)
_, err = p.expand(key, value)
if err != nil {
// revert to the previous state
@@ -696,56 +709,65 @@ outer:
// check expands all values and returns an error if a circular reference or
// a malformed expression was found.
func (p *Properties) check() error {
for _, value := range p.m {
if _, err := p.expand(value); err != nil {
for key, value := range p.m {
if _, err := p.expand(key, value); err != nil {
return err
}
}
return nil
}
func (p *Properties) expand(input string) (string, error) {
func (p *Properties) expand(key, input string) (string, error) {
// no pre/postfix -> nothing to expand
if p.Prefix == "" && p.Postfix == "" {
return input, nil
}
return expand(input, make(map[string]bool), p.Prefix, p.Postfix, p.m)
return expand(input, []string{key}, p.Prefix, p.Postfix, p.m)
}
// expand recursively expands expressions of '(prefix)key(postfix)' to their corresponding values.
// The function keeps track of the keys that were already expanded and stops if it
// detects a circular reference or a malformed expression of the form '(prefix)key'.
func expand(s string, keys map[string]bool, prefix, postfix string, values map[string]string) (string, error) {
start := strings.Index(s, prefix)
if start == -1 {
return s, nil
func expand(s string, keys []string, prefix, postfix string, values map[string]string) (string, error) {
if len(keys) > maxExpansionDepth {
return "", fmt.Errorf("expansion too deep")
}
keyStart := start + len(prefix)
keyLen := strings.Index(s[keyStart:], postfix)
if keyLen == -1 {
return "", fmt.Errorf("malformed expression")
for {
start := strings.Index(s, prefix)
if start == -1 {
return s, nil
}
keyStart := start + len(prefix)
keyLen := strings.Index(s[keyStart:], postfix)
if keyLen == -1 {
return "", fmt.Errorf("malformed expression")
}
end := keyStart + keyLen + len(postfix) - 1
key := s[keyStart : keyStart+keyLen]
// fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key)
for _, k := range keys {
if key == k {
return "", fmt.Errorf("circular reference")
}
}
val, ok := values[key]
if !ok {
val = os.Getenv(key)
}
new_val, err := expand(val, append(keys, key), prefix, postfix, values)
if err != nil {
return "", err
}
s = s[:start] + new_val + s[end+1:]
}
end := keyStart + keyLen + len(postfix) - 1
key := s[keyStart : keyStart+keyLen]
// fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key)
if _, ok := keys[key]; ok {
return "", fmt.Errorf("circular reference")
}
val, ok := values[key]
if !ok {
val = os.Getenv(key)
}
// remember that we've seen the key
keys[key] = true
return expand(s[:start]+val+s[end+1:], keys, prefix, postfix, values)
return s, nil
}
// encode encodes a UTF-8 string to ISO-8859-1 and escapes some characters.
+37 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -90,6 +90,10 @@ var complexTests = [][]string{
{"key=value\nkey2=${key}bb", "key", "value", "key2", "valuebb"},
{"key=value\nkey2=aa${key}bb", "key", "value", "key2", "aavaluebb"},
{"key=value\nkey2=${key}\nkey3=${key2}", "key", "value", "key2", "value", "key3", "value"},
{"key=value\nkey2=${key}${key}", "key", "value", "key2", "valuevalue"},
{"key=value\nkey2=${key}${key}${key}${key}", "key", "value", "key2", "valuevaluevaluevalue"},
{"key=value\nkey2=${key}${key3}\nkey3=${key}", "key", "value", "key2", "valuevalue", "key3", "value"},
{"key=value\nkey2=${key3}${key}${key4}\nkey3=${key}\nkey4=${key}", "key", "value", "key2", "valuevaluevalue", "key3", "value", "key4", "value"},
{"key=${USER}", "key", os.Getenv("USER")},
{"key=${USER}\nUSER=value", "key", "value", "USER", "value"},
}
@@ -446,6 +450,30 @@ func TestErrors(t *testing.T) {
}
}
func TestVeryDeep(t *testing.T) {
input := "key0=value\n"
prefix := "${"
postfix := "}"
i := 0
for i = 0; i < maxExpansionDepth-1; i++ {
input += fmt.Sprintf("key%d=%skey%d%s\n", i+1, prefix, i, postfix)
}
p, err := Load([]byte(input), ISO_8859_1)
assert.Equal(t, err, nil)
p.Prefix = prefix
p.Postfix = postfix
assert.Equal(t, p.MustGet(fmt.Sprintf("key%d", i)), "value")
// Nudge input over the edge
input += fmt.Sprintf("key%d=%skey%d%s\n", i+1, prefix, i, postfix)
_, err = Load([]byte(input), ISO_8859_1)
assert.Equal(t, err != nil, true, "want error")
assert.Equal(t, strings.Contains(err.Error(), "expansion too deep"), true)
}
func TestDisableExpansion(t *testing.T) {
input := "key=value\nkey2=${key}"
p := mustParse(t, input)
@@ -875,6 +903,14 @@ func TestFilterFunc(t *testing.T) {
assert.Equal(t, pp.Map(), m)
}
func TestLoad(t *testing.T) {
x := "key=${value}\nvalue=${key}"
p := NewProperties()
p.DisableExpansion = true
err := p.Load([]byte(x), UTF8)
assert.Equal(t, err, nil)
}
// ----------------------------------------------------------------------------
// tests all combinations of delimiters, leading and/or trailing whitespace and newlines.
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2017 Frank Schroeder. All rights reserved.
// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.