From 4b57821f52f649cd507b4514ed2593c694a9dc4a Mon Sep 17 00:00:00 2001 From: Audrius Butkevicius Date: Sat, 6 Sep 2014 13:11:18 +0100 Subject: [PATCH] Allow saving config from anywhere --- cmd/syncthing/gui.go | 3 +- cmd/syncthing/main.go | 48 ++--------------------- config/config.go | 89 +++++++++++++++++++++++++++++++++---------- 3 files changed, 73 insertions(+), 67 deletions(-) diff --git a/cmd/syncthing/gui.go b/cmd/syncthing/gui.go index 682d37002..c159e0045 100644 --- a/cmd/syncthing/gui.go +++ b/cmd/syncthing/gui.go @@ -361,8 +361,9 @@ func restPostConfig(m *model.Model, w http.ResponseWriter, r *http.Request) { // Activate and save + newCfg.Location = cfg.Location + newCfg.Save() cfg = newCfg - saveConfig() } } diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index 61f3d6784..70ec15d67 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -33,7 +33,6 @@ import ( "github.com/syncthing/syncthing/files" "github.com/syncthing/syncthing/logger" "github.com/syncthing/syncthing/model" - "github.com/syncthing/syncthing/osutil" "github.com/syncthing/syncthing/protocol" "github.com/syncthing/syncthing/upgrade" "github.com/syncthing/syncthing/upnp" @@ -310,21 +309,14 @@ func syncthingMain() { // Prepare to be able to save configuration cfgFile := filepath.Join(confDir, "config.xml") - go saveConfigLoop(cfgFile) var myName string // Load the configuration file, if it exists. // If it does not, create a template. - cf, err := os.Open(cfgFile) + cfg, err = config.Load(cfgFile, myID) if err == nil { - // Read config.xml - cfg, err = config.Load(cf, myID) - if err != nil { - l.Fatalln(err) - } - cf.Close() myCfg := cfg.GetNodeConfiguration(myID) if myCfg == nil || myCfg.Name == "" { myName, _ = os.Hostname() @@ -336,7 +328,7 @@ func syncthingMain() { myName, _ = os.Hostname() defaultRepo := filepath.Join(getHomeDir(), "Sync") - cfg, err = config.Load(nil, myID) + cfg = config.New(cfgFile, myID) cfg.Repositories = []config.RepositoryConfiguration{ { ID: "default", @@ -361,7 +353,7 @@ func syncthingMain() { l.FatalErr(err) cfg.Options.ListenAddress = []string{fmt.Sprintf("0.0.0.0:%d", port)} - saveConfig() + cfg.Save() l.Infof("Edit %s to taste or use the GUI\n", cfgFile) } @@ -745,40 +737,6 @@ func shutdown() { stop <- exitSuccess } -var saveConfigCh = make(chan struct{}) - -func saveConfigLoop(cfgFile string) { - for _ = range saveConfigCh { - fd, err := os.Create(cfgFile + ".tmp") - if err != nil { - l.Warnln("Saving config:", err) - continue - } - - err = config.Save(fd, cfg) - if err != nil { - l.Warnln("Saving config:", err) - fd.Close() - continue - } - - err = fd.Close() - if err != nil { - l.Warnln("Saving config:", err) - continue - } - - err = osutil.Rename(cfgFile+".tmp", cfgFile) - if err != nil { - l.Warnln("Saving config:", err) - } - } -} - -func saveConfig() { - saveConfigCh <- struct{}{} -} - func listenConnect(myID protocol.NodeID, m *model.Model, tlsCfg *tls.Config) { var conns = make(chan *tls.Conn) diff --git a/config/config.go b/config/config.go index ec61c2668..126845383 100644 --- a/config/config.go +++ b/config/config.go @@ -8,7 +8,6 @@ package config import ( "encoding/xml" "fmt" - "io" "os" "reflect" "sort" @@ -16,12 +15,14 @@ import ( "code.google.com/p/go.crypto/bcrypt" "github.com/syncthing/syncthing/logger" + "github.com/syncthing/syncthing/osutil" "github.com/syncthing/syncthing/protocol" ) var l = logger.DefaultLogger type Configuration struct { + Location string `xml:"-" json:"-"` Version int `xml:"version,attr" default:"3"` Repositories []RepositoryConfiguration `xml:"repository"` Nodes []NodeConfiguration `xml:"node"` @@ -227,14 +228,38 @@ func fillNilSlices(data interface{}) error { return nil } -func Save(wr io.Writer, cfg Configuration) error { - e := xml.NewEncoder(wr) - e.Indent("", " ") - err := e.Encode(cfg) +func (cfg *Configuration) Save() error { + fd, err := os.Create(cfg.Location + ".tmp") if err != nil { + l.Warnln("Saving config:", err) return err } - _, err = wr.Write([]byte("\n")) + + e := xml.NewEncoder(fd) + e.Indent("", " ") + err = e.Encode(cfg) + if err != nil { + fd.Close() + return err + } + _, err = fd.Write([]byte("\n")) + + if err != nil { + l.Warnln("Saving config:", err) + fd.Close() + return err + } + + err = fd.Close() + if err != nil { + l.Warnln("Saving config:", err) + return err + } + + err = osutil.Rename(cfg.Location+".tmp", cfg.Location) + if err != nil { + l.Warnln("Saving config:", err) + } return err } @@ -252,18 +277,7 @@ func uniqueStrings(ss []string) []string { return us } -func Load(rd io.Reader, myID protocol.NodeID) (Configuration, error) { - var cfg Configuration - - setDefaults(&cfg) - setDefaults(&cfg.Options) - setDefaults(&cfg.GUI) - - var err error - if rd != nil { - err = xml.NewDecoder(rd).Decode(&cfg) - } - +func (cfg *Configuration) prepare(myID protocol.NodeID) { fillNilSlices(&cfg.Options) cfg.Options.ListenAddress = uniqueStrings(cfg.Options.ListenAddress) @@ -312,17 +326,17 @@ func Load(rd io.Reader, myID protocol.NodeID) (Configuration, error) { // Upgrade to v2 configuration if appropriate if cfg.Version == 1 { - convertV1V2(&cfg) + convertV1V2(cfg) } // Upgrade to v3 configuration if appropriate if cfg.Version == 2 { - convertV2V3(&cfg) + convertV2V3(cfg) } // Upgrade to v4 configuration if appropriate if cfg.Version == 3 { - convertV3V4(&cfg) + convertV3V4(cfg) } // Hash old cleartext passwords @@ -368,6 +382,39 @@ func Load(rd io.Reader, myID protocol.NodeID) (Configuration, error) { n.Addresses = []string{"dynamic"} } } +} + +func New(location string, myID protocol.NodeID) Configuration { + var cfg Configuration + + cfg.Location = location + + setDefaults(&cfg) + setDefaults(&cfg.Options) + setDefaults(&cfg.GUI) + + cfg.prepare(myID) + + return cfg +} + +func Load(location string, myID protocol.NodeID) (Configuration, error) { + var cfg Configuration + + cfg.Location = location + + setDefaults(&cfg) + setDefaults(&cfg.Options) + setDefaults(&cfg.GUI) + + fd, err := os.Open(location) + if err != nil { + return Configuration{}, err + } + err = xml.NewDecoder(fd).Decode(&cfg) + fd.Close() + + cfg.prepare(myID) return cfg, err }