mirror of
https://github.com/spf13/viper
synced 2025-05-10 22:27:18 +00:00
Add support to save file with no extension
The suppport introduced for files with no file extension is only partial as trying to save the config file would fail with `<file name> equires valid extensio` This adds support to saving such files
This commit is contained in:
parent
eabbc68a3e
commit
b1b6c1d559
2 changed files with 154 additions and 4 deletions
15
viper.go
15
viper.go
|
@ -1418,11 +1418,18 @@ func (v *Viper) SafeWriteConfigAs(filename string) error {
|
||||||
|
|
||||||
func (v *Viper) writeConfig(filename string, force bool) error {
|
func (v *Viper) writeConfig(filename string, force bool) error {
|
||||||
jww.INFO.Println("Attempting to write configuration to file.")
|
jww.INFO.Println("Attempting to write configuration to file.")
|
||||||
ext := filepath.Ext(filename)
|
var configType string
|
||||||
if len(ext) <= 1 {
|
|
||||||
return fmt.Errorf("filename: %s requires valid extension", filename)
|
if v.configType != "" {
|
||||||
|
configType = v.configType
|
||||||
|
} else {
|
||||||
|
ext := filepath.Ext(filename)
|
||||||
|
if len(ext) <= 1 {
|
||||||
|
return fmt.Errorf("filename: %s requires valid extension", filename)
|
||||||
|
}
|
||||||
|
configType = ext[1:]
|
||||||
}
|
}
|
||||||
configType := ext[1:]
|
|
||||||
if !stringInSlice(configType, SupportedExts) {
|
if !stringInSlice(configType, SupportedExts) {
|
||||||
return UnsupportedConfigError(configType)
|
return UnsupportedConfigError(configType)
|
||||||
}
|
}
|
||||||
|
|
143
viper_test.go
143
viper_test.go
|
@ -1281,6 +1281,26 @@ func TestWriteConfigHCL(t *testing.T) {
|
||||||
assert.Equal(t, hclWriteExpected, read)
|
assert.Equal(t, hclWriteExpected, read)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWriteConfigHCLWithoutFileExtension(t *testing.T) {
|
||||||
|
v := New()
|
||||||
|
fs := afero.NewMemMapFs()
|
||||||
|
v.SetFs(fs)
|
||||||
|
v.SetConfigName("c")
|
||||||
|
v.SetConfigType("hcl")
|
||||||
|
err := v.ReadConfig(bytes.NewBuffer(hclExample))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := v.WriteConfigAs("c"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
read, err := afero.ReadFile(fs, "c")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, hclWriteExpected, read)
|
||||||
|
}
|
||||||
|
|
||||||
var jsonWriteExpected = []byte(`{
|
var jsonWriteExpected = []byte(`{
|
||||||
"batters": {
|
"batters": {
|
||||||
"batter": [
|
"batter": [
|
||||||
|
@ -1324,6 +1344,26 @@ func TestWriteConfigJson(t *testing.T) {
|
||||||
assert.Equal(t, jsonWriteExpected, read)
|
assert.Equal(t, jsonWriteExpected, read)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWriteConfigJsonWithoutFileExtension(t *testing.T) {
|
||||||
|
v := New()
|
||||||
|
fs := afero.NewMemMapFs()
|
||||||
|
v.SetFs(fs)
|
||||||
|
v.SetConfigName("c")
|
||||||
|
v.SetConfigType("json")
|
||||||
|
err := v.ReadConfig(bytes.NewBuffer(jsonExample))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := v.WriteConfigAs("c"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
read, err := afero.ReadFile(fs, "c")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, jsonWriteExpected, read)
|
||||||
|
}
|
||||||
|
|
||||||
var propertiesWriteExpected = []byte(`p_id = 0001
|
var propertiesWriteExpected = []byte(`p_id = 0001
|
||||||
p_type = donut
|
p_type = donut
|
||||||
p_name = Cake
|
p_name = Cake
|
||||||
|
@ -1351,6 +1391,26 @@ func TestWriteConfigProperties(t *testing.T) {
|
||||||
assert.Equal(t, propertiesWriteExpected, read)
|
assert.Equal(t, propertiesWriteExpected, read)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWriteConfigPropertiesWithoutFileExtension(t *testing.T) {
|
||||||
|
v := New()
|
||||||
|
fs := afero.NewMemMapFs()
|
||||||
|
v.SetFs(fs)
|
||||||
|
v.SetConfigName("c")
|
||||||
|
v.SetConfigType("properties")
|
||||||
|
err := v.ReadConfig(bytes.NewBuffer(propertiesExample))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := v.WriteConfigAs("c.properties"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
read, err := afero.ReadFile(fs, "c.properties")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, propertiesWriteExpected, read)
|
||||||
|
}
|
||||||
|
|
||||||
func TestWriteConfigTOML(t *testing.T) {
|
func TestWriteConfigTOML(t *testing.T) {
|
||||||
fs := afero.NewMemMapFs()
|
fs := afero.NewMemMapFs()
|
||||||
v := New()
|
v := New()
|
||||||
|
@ -1383,6 +1443,38 @@ func TestWriteConfigTOML(t *testing.T) {
|
||||||
assert.Equal(t, v.GetString("owner.organization"), v2.GetString("owner.organization"))
|
assert.Equal(t, v.GetString("owner.organization"), v2.GetString("owner.organization"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWriteConfigTOMLWithoutFileExtension(t *testing.T) {
|
||||||
|
fs := afero.NewMemMapFs()
|
||||||
|
v := New()
|
||||||
|
v.SetFs(fs)
|
||||||
|
v.SetConfigName("c")
|
||||||
|
v.SetConfigType("toml")
|
||||||
|
err := v.ReadConfig(bytes.NewBuffer(tomlExample))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := v.WriteConfigAs("c"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The TOML String method does not order the contents.
|
||||||
|
// Therefore, we must read the generated file and compare the data.
|
||||||
|
v2 := New()
|
||||||
|
v2.SetFs(fs)
|
||||||
|
v2.SetConfigName("c")
|
||||||
|
v2.SetConfigType("toml")
|
||||||
|
v2.SetConfigFile("c")
|
||||||
|
err = v2.ReadInConfig()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, v.GetString("title"), v2.GetString("title"))
|
||||||
|
assert.Equal(t, v.GetString("owner.bio"), v2.GetString("owner.bio"))
|
||||||
|
assert.Equal(t, v.GetString("owner.dob"), v2.GetString("owner.dob"))
|
||||||
|
assert.Equal(t, v.GetString("owner.organization"), v2.GetString("owner.organization"))
|
||||||
|
}
|
||||||
|
|
||||||
var dotenvWriteExpected = []byte(`
|
var dotenvWriteExpected = []byte(`
|
||||||
TITLE="DotEnv Write Example"
|
TITLE="DotEnv Write Example"
|
||||||
NAME=Oreo
|
NAME=Oreo
|
||||||
|
@ -1420,6 +1512,37 @@ func TestWriteConfigDotEnv(t *testing.T) {
|
||||||
assert.Equal(t, v.GetString("kind"), v2.GetString("kind"))
|
assert.Equal(t, v.GetString("kind"), v2.GetString("kind"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWriteConfigDotEnvWithoutFileExtension(t *testing.T) {
|
||||||
|
fs := afero.NewMemMapFs()
|
||||||
|
v := New()
|
||||||
|
v.SetFs(fs)
|
||||||
|
v.SetConfigName("c")
|
||||||
|
v.SetConfigType("env")
|
||||||
|
err := v.ReadConfig(bytes.NewBuffer(dotenvWriteExpected))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := v.WriteConfigAs("c"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The TOML String method does not order the contents.
|
||||||
|
// Therefore, we must read the generated file and compare the data.
|
||||||
|
v2 := New()
|
||||||
|
v2.SetFs(fs)
|
||||||
|
v2.SetConfigName("c")
|
||||||
|
v2.SetConfigType("env")
|
||||||
|
v2.SetConfigFile("c")
|
||||||
|
err = v2.ReadInConfig()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, v.GetString("title"), v2.GetString("title"))
|
||||||
|
assert.Equal(t, v.GetString("type"), v2.GetString("type"))
|
||||||
|
assert.Equal(t, v.GetString("kind"), v2.GetString("kind"))
|
||||||
|
}
|
||||||
|
|
||||||
var yamlWriteExpected = []byte(`age: 35
|
var yamlWriteExpected = []byte(`age: 35
|
||||||
beard: true
|
beard: true
|
||||||
clothing:
|
clothing:
|
||||||
|
@ -1456,6 +1579,26 @@ func TestWriteConfigYAML(t *testing.T) {
|
||||||
assert.Equal(t, yamlWriteExpected, read)
|
assert.Equal(t, yamlWriteExpected, read)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWriteConfigYAMLWithoutFileExtension(t *testing.T) {
|
||||||
|
v := New()
|
||||||
|
fs := afero.NewMemMapFs()
|
||||||
|
v.SetFs(fs)
|
||||||
|
v.SetConfigName("c")
|
||||||
|
v.SetConfigType("yaml")
|
||||||
|
err := v.ReadConfig(bytes.NewBuffer(yamlExample))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := v.WriteConfigAs("c"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
read, err := afero.ReadFile(fs, "c")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, yamlWriteExpected, read)
|
||||||
|
}
|
||||||
|
|
||||||
func TestSafeWriteConfig(t *testing.T) {
|
func TestSafeWriteConfig(t *testing.T) {
|
||||||
v := New()
|
v := New()
|
||||||
fs := afero.NewMemMapFs()
|
fs := afero.NewMemMapFs()
|
||||||
|
|
Loading…
Add table
Reference in a new issue