Commit 20bce474 authored by Peter Borzov's avatar Peter Borzov Committed by Juan Batiz-Benet

ipfs config cmd with git-style get/set

Adds "ipfs config" command designed in git style.
See specific config's values with:

        $ipfs config datastore.path
        ~/.go-ipfs/datastore

Assign a new value with:

        $ipfs config datastore.path ~/.go-ipfs/datastore

Open the config file in your default $EDITOR:

        ipfs config edit
parent 4b1bae8b
package main
import (
"github.com/jbenet/commander"
config "github.com/jbenet/go-ipfs/config"
u "github.com/jbenet/go-ipfs/util"
"os"
"os/exec"
)
var cmdIpfsConfig = &commander.Command{
UsageLine: "config",
Short: "See and Edit ipfs options",
Long: `ipfs config - See or Edit ipfs configuration.
See specific config's values with:
ipfs config datastore.path
Assign a new value with:
ipfs config datastore.path ~/.go-ipfs/datastore
Open the config file in your editor(from $EDITOR):
ipfs config edit
`,
Run: configCmd,
Subcommands: []*commander.Command{
cmdIpfsConfigEdit,
},
}
var cmdIpfsConfigEdit = &commander.Command{
UsageLine: "edit",
Short: "Opens the configuration file in the editor.",
Long: `Looks up environment variable $EDITOR and
attempts to open the config file with it.
`,
Run: configEditCmd,
}
func configCmd(c *commander.Command, inp []string) error {
if len(inp) == 0 {
// "ipfs config" run without parameters
u.POut(c.Long + "\n")
return nil
}
if len(inp) == 1 {
// "ipfs config" run without one parameter, so this is a value getter
value, err := config.GetValueInConfigFile(inp[0])
if err != nil {
u.POut("Failed to get config value: " + err.Error() + "\n")
} else {
u.POut(value + "\n")
}
return nil
}
// "ipfs config" run without two parameter, so this is a value setter
err := config.SetValueInConfigFile(inp[0], inp[1:])
if err != nil {
u.POut("Failed to set config value: " + err.Error() + "\n")
}
return nil
}
func configEditCmd(c *commander.Command, _ []string) error {
if editor := os.Getenv("EDITOR"); editor == "" {
u.POut("ENVIRON variable $EDITOR is not assigned \n")
} else {
exec.Command("sh", "-c", editor+" "+config.DefaultConfigFilePath).Start()
}
return nil
}
......@@ -41,6 +41,7 @@ Use "ipfs help <command>" for more information about a command.
cmdIpfsCat,
cmdIpfsLs,
cmdIpfsRefs,
cmdIpfsConfig,
cmdIpfsVersion,
cmdIpfsCommands,
cmdIpfsMount,
......
package config
import (
"os"
u "github.com/jbenet/go-ipfs/util"
"os"
)
// Identity tracks the configuration of the local node's identity.
......@@ -22,7 +22,7 @@ type Config struct {
Datastore *Datastore
}
var defaultConfigFilePath = "~/.go-ipfs/config"
var DefaultConfigFilePath = "~/.go-ipfs/config"
var defaultConfigFile = `{
"identity": {},
"datastore": {
......@@ -35,7 +35,7 @@ var defaultConfigFile = `{
// LoadConfig reads given file and returns the read config, or error.
func LoadConfig(filename string) (*Config, error) {
if len(filename) == 0 {
filename = defaultConfigFilePath
filename = DefaultConfigFilePath
}
// tilde expansion on config file
......
......@@ -2,9 +2,13 @@ package config
import (
"encoding/json"
"errors"
"fmt"
u "github.com/jbenet/go-ipfs/util"
"io/ioutil"
"os"
"path"
"strings"
)
// WriteFile writes the given buffer `buf` into file named `filename`.
......@@ -36,3 +40,82 @@ func WriteConfigFile(filename string, cfg *Config) error {
return WriteFile(filename, buf)
}
// WriteConfigFile writes the config from `cfg` into `filename`.
func GetValueInConfigFile(key string) (value string, err error) {
// reading config file
attrs := strings.Split(key, ".")
filename, _ := u.TildeExpansion(DefaultConfigFilePath)
buf, err := ioutil.ReadFile(filename)
if err != nil {
return "", err
}
// deserializing json
var cfg interface{}
var exists bool
err = json.Unmarshal(buf, &cfg)
if err != nil {
return "", err
}
for i := range attrs {
cfgMap, isMap := cfg.(map[string]interface{})
if !isMap {
return "", errors.New(fmt.Sprintf("%s has no attributes", strings.Join(attrs[:i], ".")))
}
cfg, exists = cfgMap[attrs[i]]
if !exists {
return "", errors.New(fmt.Sprintf("Configuration option key \"%s\" not recognized", strings.Join(attrs[:i+1], ".")))
}
val, is_string := cfg.(string)
if is_string {
return val, nil
}
}
return "", errors.New(fmt.Sprintf("%s is not a string", key))
}
// WriteConfigFile writes the config from `cfg` into `filename`.
func SetValueInConfigFile(key string, values []string) error {
assignee := strings.Join(values, " ")
attrs := strings.Split(key, ".")
filename, _ := u.TildeExpansion(DefaultConfigFilePath)
buf, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
// deserializing json
var cfg, orig interface{}
var exists, isMap bool
cfgMap := make(map[string]interface{})
err = json.Unmarshal(buf, &orig)
cfg = orig
if err != nil {
return err
}
for i := 0; i < len(attrs); i++ {
cfgMap, isMap = cfg.(map[string]interface{})
// curs = append(curs, cfgMap)
if !isMap {
return errors.New(fmt.Sprintf("%s has no attributes", strings.Join(attrs[:i], ".")))
}
cfg, exists = cfgMap[attrs[i]]
if !exists {
return errors.New(fmt.Sprintf("Configuration option key \"%s\" not recognized", strings.Join(attrs[:i+1], ".")))
}
}
cfgMap[attrs[len(attrs)-1]] = assignee
buf, err = json.MarshalIndent(orig, "", " ")
if err != nil {
return err
}
WriteFile(filename, buf)
return nil
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment