1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-09-10 22:49:13 +08:00

refactor(config, repo): all writes go through FSRepo. next: privatize these

This commit is contained in:
Brian Tiger Chow
2015-01-12 15:00:03 -08:00
parent c2877b2045
commit 405afd2a02
11 changed files with 81 additions and 75 deletions

View File

@ -23,6 +23,7 @@ import (
daemon "github.com/jbenet/go-ipfs/core/daemon" daemon "github.com/jbenet/go-ipfs/core/daemon"
repo "github.com/jbenet/go-ipfs/repo" repo "github.com/jbenet/go-ipfs/repo"
config "github.com/jbenet/go-ipfs/repo/config" config "github.com/jbenet/go-ipfs/repo/config"
fsrepo "github.com/jbenet/go-ipfs/repo/fsrepo"
updates "github.com/jbenet/go-ipfs/updates" updates "github.com/jbenet/go-ipfs/updates"
u "github.com/jbenet/go-ipfs/util" u "github.com/jbenet/go-ipfs/util"
"github.com/jbenet/go-ipfs/util/debugerror" "github.com/jbenet/go-ipfs/util/debugerror"
@ -449,7 +450,7 @@ func loadConfig(path string) (*config.Config, error) {
return nil, err return nil, err
} }
return config.Load(configFile) return fsrepo.Load(configFile)
} }
// startProfiling begins CPU profiling and returns a `stop` function to be // startProfiling begins CPU profiling and returns a `stop` function to be

View File

@ -10,6 +10,7 @@ import (
cmds "github.com/jbenet/go-ipfs/commands" cmds "github.com/jbenet/go-ipfs/commands"
config "github.com/jbenet/go-ipfs/repo/config" config "github.com/jbenet/go-ipfs/repo/config"
tour "github.com/jbenet/go-ipfs/tour" tour "github.com/jbenet/go-ipfs/tour"
fsrepo "github.com/jbenet/go-ipfs/repo/fsrepo"
) )
var tourCmd = &cmds.Command{ var tourCmd = &cmds.Command{
@ -191,5 +192,5 @@ func writeConfig(path string, cfg *config.Config) error {
if err != nil { if err != nil {
return err return err
} }
return config.WriteConfigFile(filename, cfg) return fsrepo.WriteConfigFile(filename, cfg)
} }

View File

@ -6,6 +6,7 @@ import (
cmds "github.com/jbenet/go-ipfs/commands" cmds "github.com/jbenet/go-ipfs/commands"
config "github.com/jbenet/go-ipfs/repo/config" config "github.com/jbenet/go-ipfs/repo/config"
"github.com/jbenet/go-ipfs/repo/fsrepo"
u "github.com/jbenet/go-ipfs/util" u "github.com/jbenet/go-ipfs/util"
errors "github.com/jbenet/go-ipfs/util/debugerror" errors "github.com/jbenet/go-ipfs/util/debugerror"
) )
@ -250,7 +251,7 @@ func bootstrapAdd(filename string, cfg *config.Config, peers []config.BootstrapP
} }
} }
err := config.WriteConfigFile(filename, cfg) err := fsrepo.WriteConfigFile(filename, cfg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -278,7 +279,7 @@ func bootstrapRemove(filename string, cfg *config.Config, toRemove []config.Boot
} }
cfg.Bootstrap = keep cfg.Bootstrap = keep
err := config.WriteConfigFile(filename, cfg) err := fsrepo.WriteConfigFile(filename, cfg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -291,7 +292,7 @@ func bootstrapRemoveAll(filename string, cfg *config.Config) ([]config.Bootstrap
copy(removed, cfg.Bootstrap) copy(removed, cfg.Bootstrap)
cfg.Bootstrap = nil cfg.Bootstrap = nil
err := config.WriteConfigFile(filename, cfg) err := fsrepo.WriteConfigFile(filename, cfg)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -11,6 +11,7 @@ import (
cmds "github.com/jbenet/go-ipfs/commands" cmds "github.com/jbenet/go-ipfs/commands"
config "github.com/jbenet/go-ipfs/repo/config" config "github.com/jbenet/go-ipfs/repo/config"
fsrepo "github.com/jbenet/go-ipfs/repo/fsrepo"
u "github.com/jbenet/go-ipfs/util" u "github.com/jbenet/go-ipfs/util"
) )
@ -141,7 +142,7 @@ variable set to your preferred text editor.
} }
func getConfig(filename string, key string) (*ConfigField, error) { func getConfig(filename string, key string) (*ConfigField, error) {
value, err := config.ReadConfigKey(filename, key) value, err := fsrepo.ReadConfigKey(filename, key)
if err != nil { if err != nil {
return nil, fmt.Errorf("Failed to get config value: %s", err) return nil, fmt.Errorf("Failed to get config value: %s", err)
} }
@ -153,7 +154,7 @@ func getConfig(filename string, key string) (*ConfigField, error) {
} }
func setConfig(filename string, key, value string) (*ConfigField, error) { func setConfig(filename string, key, value string) (*ConfigField, error) {
err := config.WriteConfigKey(filename, key, value) err := fsrepo.WriteConfigKey(filename, key, value)
if err != nil { if err != nil {
return nil, fmt.Errorf("Failed to set config value: %s", err) return nil, fmt.Errorf("Failed to set config value: %s", err)
} }

View File

@ -3,6 +3,7 @@ package config
import ( import (
"encoding/base64" "encoding/base64"
"encoding/json"
"errors" "errors"
"os" "os"
"path/filepath" "path/filepath"
@ -13,7 +14,6 @@ import (
ic "github.com/jbenet/go-ipfs/p2p/crypto" ic "github.com/jbenet/go-ipfs/p2p/crypto"
u "github.com/jbenet/go-ipfs/util" u "github.com/jbenet/go-ipfs/util"
"github.com/jbenet/go-ipfs/util/debugerror"
) )
var log = u.Logger("config") var log = u.Logger("config")
@ -191,29 +191,17 @@ func (i *Identity) DecodePrivateKey(passphrase string) (ic.PrivKey, error) {
return ic.UnmarshalPrivateKey(pkb) return ic.UnmarshalPrivateKey(pkb)
} }
// Load reads given file and returns the read config, or error. // HumanOutput gets a config value ready for printing
func Load(filename string) (*Config, error) { func HumanOutput(value interface{}) ([]byte, error) {
// if nothing is there, fail. User must run 'ipfs init' s, ok := value.(string)
if !u.FileExists(filename) { if ok {
return nil, debugerror.New("ipfs not initialized, please run 'ipfs init'") return []byte(strings.Trim(s, "\n")), nil
} }
return Marshal(value)
var cfg Config
err := ReadConfigFile(filename, &cfg)
if err != nil {
return nil, err
}
// tilde expansion on datastore path
cfg.Datastore.Path, err = u.TildeExpansion(cfg.Datastore.Path)
if err != nil {
return nil, err
}
return &cfg, err
} }
// Set sets the value of a particular config key // Marshal configuration with JSON
func Set(filename, key, value string) error { func Marshal(value interface{}) ([]byte, error) {
return WriteConfigKey(filename, key, value) // need to prettyprint, hence MarshalIndent, instead of Encoder
return json.MarshalIndent(value, "", " ")
} }

View File

@ -120,19 +120,6 @@ func (v *Version) ShouldCheckForUpdate() bool {
return true return true
} }
// RecordUpdateCheck is called to record that an update check was performed,
// showing that the running version is the most recent one.
func RecordUpdateCheck(cfg *Config, filename string) {
cfg.Version.CheckDate = time.Now()
if cfg.Version.CheckPeriod == "" {
// CheckPeriod was not initialized for some reason (e.g. config file broken)
log.Error("config.Version.CheckPeriod not set. config broken?")
}
WriteConfigFile(filename, cfg)
}
// VersionDefaultValue returns the default version config value (for init). // VersionDefaultValue returns the default version config value (for init).
func VersionDefaultValue() Version { func VersionDefaultValue() Version {
return Version{ return Version{

View File

@ -1,6 +1,7 @@
package config package config
import ( import (
"encoding/json"
"strings" "strings"
"testing" "testing"
) )
@ -23,8 +24,7 @@ func TestAutoUpdateValues(t *testing.T) {
} }
for i, tc := range tests { for i, tc := range tests {
err := Decode(strings.NewReader(tc.input), &tval) if err := json.NewDecoder(strings.NewReader(tc.input)).Decode(&tval); err != tc.err {
if err != tc.err {
t.Fatalf("%d failed - got err %q wanted %v", i, err, tc.err) t.Fatalf("%d failed - got err %q wanted %v", i, err, tc.err)
} }
@ -32,5 +32,4 @@ func TestAutoUpdateValues(t *testing.T) {
t.Fatalf("%d failed - got val %q where we wanted %q", i, tval.AutoUpdate, tc.val) t.Fatalf("%d failed - got val %q where we wanted %q", i, tval.AutoUpdate, tc.val)
} }
} }
} }

View File

@ -54,7 +54,7 @@ func (r *FSRepo) SetConfig(conf *config.Config) error {
if err != nil { if err != nil {
return err return err
} }
if err := config.WriteConfigFile(configFilename, conf); err != nil { if err := WriteConfigFile(configFilename, conf); err != nil {
return err return err
} }
r.config = *conf // copy so caller cannot modify the private config r.config = *conf // copy so caller cannot modify the private config

View File

@ -1,4 +1,4 @@
package config package fsrepo
import ( import (
"encoding/json" "encoding/json"
@ -7,8 +7,15 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"time"
"github.com/jbenet/go-ipfs/repo/config"
"github.com/jbenet/go-ipfs/util"
"github.com/jbenet/go-ipfs/util/debugerror"
) )
var log = util.Logger("fsrepo")
// ReadConfigFile reads the config from `filename` into `cfg`. // ReadConfigFile reads the config from `filename` into `cfg`.
func ReadConfigFile(filename string, cfg interface{}) error { func ReadConfigFile(filename string, cfg interface{}) error {
f, err := os.Open(filename) f, err := os.Open(filename)
@ -16,8 +23,7 @@ func ReadConfigFile(filename string, cfg interface{}) error {
return err return err
} }
defer f.Close() defer f.Close()
if err := json.NewDecoder(f).Decode(cfg); err != nil {
if err := Decode(f, cfg); err != nil {
return fmt.Errorf("Failure to decode config: %s", err) return fmt.Errorf("Failure to decode config: %s", err)
} }
return nil return nil
@ -56,38 +62,17 @@ func WriteFile(filename string, buf []byte) error {
return err return err
} }
// HumanOutput gets a config value ready for printing
func HumanOutput(value interface{}) ([]byte, error) {
s, ok := value.(string)
if ok {
return []byte(strings.Trim(s, "\n")), nil
}
return Marshal(value)
}
// Marshal configuration with JSON
func Marshal(value interface{}) ([]byte, error) {
// need to prettyprint, hence MarshalIndent, instead of Encoder
return json.MarshalIndent(value, "", " ")
}
// Encode configuration with JSON // Encode configuration with JSON
func Encode(w io.Writer, value interface{}) error { func Encode(w io.Writer, value interface{}) error {
// need to prettyprint, hence MarshalIndent, instead of Encoder // need to prettyprint, hence MarshalIndent, instead of Encoder
buf, err := Marshal(value) buf, err := config.Marshal(value)
if err != nil { if err != nil {
return err return err
} }
_, err = w.Write(buf) _, err = w.Write(buf)
return err return err
} }
// Decode configuration with JSON
func Decode(r io.Reader, value interface{}) error {
return json.NewDecoder(r).Decode(value)
}
// ReadConfigKey retrieves only the value of a particular key // ReadConfigKey retrieves only the value of a particular key
func ReadConfigKey(filename, key string) (interface{}, error) { func ReadConfigKey(filename, key string) (interface{}, error) {
var cfg interface{} var cfg interface{}
@ -142,3 +127,43 @@ func WriteConfigKey(filename, key string, value interface{}) error {
return WriteConfigFile(filename, cfg) return WriteConfigFile(filename, cfg)
} }
// Load reads given file and returns the read config, or error.
func Load(filename string) (*config.Config, error) {
// if nothing is there, fail. User must run 'ipfs init'
if !util.FileExists(filename) {
return nil, debugerror.New("ipfs not initialized, please run 'ipfs init'")
}
var cfg config.Config
err := ReadConfigFile(filename, &cfg)
if err != nil {
return nil, err
}
// tilde expansion on datastore path
cfg.Datastore.Path, err = util.TildeExpansion(cfg.Datastore.Path)
if err != nil {
return nil, err
}
return &cfg, err
}
// Set sets the value of a particular config key
func Set(filename, key, value string) error {
return WriteConfigKey(filename, key, value)
}
// RecordUpdateCheck is called to record that an update check was performed,
// showing that the running version is the most recent one.
func RecordUpdateCheck(cfg *config.Config, filename string) {
cfg.Version.CheckDate = time.Now()
if cfg.Version.CheckPeriod == "" {
// CheckPeriod was not initialized for some reason (e.g. config file broken)
log.Error("config.Version.CheckPeriod not set. config broken?")
}
WriteConfigFile(filename, cfg)
}

View File

@ -1,13 +1,15 @@
package config package fsrepo
import ( import (
"testing" "testing"
config "github.com/jbenet/go-ipfs/repo/config"
) )
func TestConfig(t *testing.T) { func TestConfig(t *testing.T) {
const filename = ".ipfsconfig" const filename = ".ipfsconfig"
const dsPath = "/path/to/datastore" const dsPath = "/path/to/datastore"
cfgWritten := new(Config) cfgWritten := new(config.Config)
cfgWritten.Datastore.Path = dsPath cfgWritten.Datastore.Path = dsPath
err := WriteConfigFile(filename, cfgWritten) err := WriteConfigFile(filename, cfgWritten)
if err != nil { if err != nil {

View File

@ -6,6 +6,7 @@ import (
"time" "time"
config "github.com/jbenet/go-ipfs/repo/config" config "github.com/jbenet/go-ipfs/repo/config"
fsrepo "github.com/jbenet/go-ipfs/repo/fsrepo"
u "github.com/jbenet/go-ipfs/util" u "github.com/jbenet/go-ipfs/util"
semver "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/coreos/go-semver/semver" semver "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/coreos/go-semver/semver"
@ -209,7 +210,7 @@ func CliCheckForUpdates(cfg *config.Config, confFile string) error {
// if there is no update available, record it, and exit. // if there is no update available, record it, and exit.
if err == ErrNoUpdateAvailable { if err == ErrNoUpdateAvailable {
log.Noticef("No update available, checked on %s", time.Now()) log.Noticef("No update available, checked on %s", time.Now())
config.RecordUpdateCheck(cfg, confFile) // only record if we checked successfully. fsrepo.RecordUpdateCheck(cfg, confFile) // only record if we checked successfully.
return nil return nil
} }