mirror of
https://github.com/rclone/rclone.git
synced 2025-12-11 22:14:05 +01:00
config: add more human readable configmap.Simple output
Before this, String() quoted every part of the config map even if it wasn't necessary. The new Human() method removes the quoting and adds the special case for "true" values.
This commit is contained in:
@@ -136,9 +136,11 @@ func (c Simple) Set(key, value string) {
|
||||
c[key] = value
|
||||
}
|
||||
|
||||
// String the map value the same way the config parser does, but with
|
||||
// string the map value the same way the config parser does, but with
|
||||
// sorted keys for reproducibility.
|
||||
func (c Simple) String() string {
|
||||
//
|
||||
// If human is set then use fewer quotes.
|
||||
func (c Simple) string(human bool) string {
|
||||
var ks = make([]string, 0, len(c))
|
||||
for k := range c {
|
||||
ks = append(ks, k)
|
||||
@@ -150,9 +152,14 @@ func (c Simple) String() string {
|
||||
out.WriteRune(',')
|
||||
}
|
||||
out.WriteString(k)
|
||||
v := c[k]
|
||||
if human && v == "true" {
|
||||
continue
|
||||
}
|
||||
out.WriteRune('=')
|
||||
if !human || strings.ContainsAny(v, `'":=,`) {
|
||||
out.WriteRune('\'')
|
||||
for _, ch := range c[k] {
|
||||
for _, ch := range v {
|
||||
out.WriteRune(ch)
|
||||
// Escape ' as ''
|
||||
if ch == '\'' {
|
||||
@@ -160,10 +167,26 @@ func (c Simple) String() string {
|
||||
}
|
||||
}
|
||||
out.WriteRune('\'')
|
||||
} else {
|
||||
out.WriteString(v)
|
||||
}
|
||||
}
|
||||
return out.String()
|
||||
}
|
||||
|
||||
// Human converts the map value the same way the config parser does,
|
||||
// but with sorted keys for reproducibility. This does it in human
|
||||
// readable form with fewer quotes.
|
||||
func (c Simple) Human() string {
|
||||
return c.string(true)
|
||||
}
|
||||
|
||||
// String the map value the same way the config parser does, but with
|
||||
// sorted keys for reproducibility.
|
||||
func (c Simple) String() string {
|
||||
return c.string(false)
|
||||
}
|
||||
|
||||
// Encode from c into a string suitable for putting on the command line
|
||||
func (c Simple) Encode() (string, error) {
|
||||
if len(c) == 0 {
|
||||
|
||||
121
fs/config/configmap/configmap_external_test.go
Normal file
121
fs/config/configmap/configmap_external_test.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package configmap_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/rclone/rclone/fs/config/configmap"
|
||||
"github.com/rclone/rclone/fs/fspath"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSimpleString(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
want string
|
||||
in configmap.Simple
|
||||
}{
|
||||
{name: "Nil", want: "", in: configmap.Simple(nil)},
|
||||
{name: "Empty", want: "", in: configmap.Simple{}},
|
||||
{name: "Basic", want: "config1='one'", in: configmap.Simple{
|
||||
"config1": "one",
|
||||
}},
|
||||
{name: "Truthy", want: "config1='true',config2='true'", in: configmap.Simple{
|
||||
"config1": "true",
|
||||
"config2": "true",
|
||||
}},
|
||||
{name: "Quotable", want: `config1='"one"',config2=':two:',config3='''three''',config4='=four=',config5=',five,'`, in: configmap.Simple{
|
||||
"config1": `"one"`,
|
||||
"config2": `:two:`,
|
||||
"config3": `'three'`,
|
||||
"config4": `=four=`,
|
||||
"config5": `,five,`,
|
||||
}},
|
||||
{name: "Order", want: "config1='one',config2='two',config3='three',config4='four',config5='five'", in: configmap.Simple{
|
||||
"config5": "five",
|
||||
"config4": "four",
|
||||
"config3": "three",
|
||||
"config2": "two",
|
||||
"config1": "one",
|
||||
}},
|
||||
{name: "Escaping", want: "apple='',config1='o''n''e'", in: configmap.Simple{
|
||||
"config1": "o'n'e",
|
||||
"apple": "",
|
||||
}},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Check forwards
|
||||
params := tt.in.String()
|
||||
assert.Equal(t, tt.want, params)
|
||||
|
||||
// Check config round trips through config parser
|
||||
remote := ":local," + params + ":"
|
||||
if params == "" {
|
||||
remote = ":local:"
|
||||
}
|
||||
what := fmt.Sprintf("remote = %q", remote)
|
||||
parsed, err := fspath.Parse(remote)
|
||||
require.NoError(t, err, what)
|
||||
if len(parsed.Config) != 0 || len(tt.in) != 0 {
|
||||
assert.Equal(t, tt.in, parsed.Config, what)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSimpleHuman(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
want string
|
||||
in configmap.Simple
|
||||
}{
|
||||
{name: "Nil", want: "", in: configmap.Simple(nil)},
|
||||
{name: "Empty", want: "", in: configmap.Simple{}},
|
||||
{name: "Basic", want: "config1=one", in: configmap.Simple{
|
||||
"config1": "one",
|
||||
}},
|
||||
{name: "Truthy", want: "config1,config2", in: configmap.Simple{
|
||||
"config1": "true",
|
||||
"config2": "true",
|
||||
}},
|
||||
{name: "Quotable", want: `config1='"one"',config2=':two:',config3='''three''',config4='=four=',config5=',five,'`, in: configmap.Simple{
|
||||
"config1": `"one"`,
|
||||
"config2": `:two:`,
|
||||
"config3": `'three'`,
|
||||
"config4": `=four=`,
|
||||
"config5": `,five,`,
|
||||
}},
|
||||
{name: "Order", want: "config1=one,config2=two,config3=three,config4=four,config5=five", in: configmap.Simple{
|
||||
"config5": "five",
|
||||
"config4": "four",
|
||||
"config3": "three",
|
||||
"config2": "two",
|
||||
"config1": "one",
|
||||
}},
|
||||
{name: "Escaping", want: "apple=,config1='o''n''e'", in: configmap.Simple{
|
||||
"config1": "o'n'e",
|
||||
"apple": "",
|
||||
}},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Check forwards
|
||||
params := tt.in.Human()
|
||||
assert.Equal(t, tt.want, params)
|
||||
|
||||
// Check config round trips through config parser
|
||||
remote := ":local," + params + ":"
|
||||
if params == "" {
|
||||
remote = ":local:"
|
||||
}
|
||||
what := fmt.Sprintf("remote = %q", remote)
|
||||
parsed, err := fspath.Parse(remote)
|
||||
require.NoError(t, err, what)
|
||||
if len(parsed.Config) != 0 || len(tt.in) != 0 {
|
||||
assert.Equal(t, tt.in, parsed.Config, what)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -246,30 +246,6 @@ func TestConfigMapClearSetters(t *testing.T) {
|
||||
assert.Equal(t, []Setter(nil), m.setters)
|
||||
}
|
||||
|
||||
func TestSimpleString(t *testing.T) {
|
||||
// Basic
|
||||
assert.Equal(t, "", Simple(nil).String())
|
||||
assert.Equal(t, "", Simple{}.String())
|
||||
assert.Equal(t, "config1='one'", Simple{
|
||||
"config1": "one",
|
||||
}.String())
|
||||
|
||||
// Check ordering
|
||||
assert.Equal(t, "config1='one',config2='two',config3='three',config4='four',config5='five'", Simple{
|
||||
"config5": "five",
|
||||
"config4": "four",
|
||||
"config3": "three",
|
||||
"config2": "two",
|
||||
"config1": "one",
|
||||
}.String())
|
||||
|
||||
// Check escaping
|
||||
assert.Equal(t, "apple='',config1='o''n''e'", Simple{
|
||||
"config1": "o'n'e",
|
||||
"apple": "",
|
||||
}.String())
|
||||
}
|
||||
|
||||
func TestSimpleEncode(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
in Simple
|
||||
|
||||
Reference in New Issue
Block a user