Allow saving config from anywhere

This commit is contained in:
Audrius Butkevicius 2014-09-06 13:11:18 +01:00
parent 74271a479f
commit 4b57821f52
3 changed files with 73 additions and 67 deletions

View File

@ -361,8 +361,9 @@ func restPostConfig(m *model.Model, w http.ResponseWriter, r *http.Request) {
// Activate and save // Activate and save
newCfg.Location = cfg.Location
newCfg.Save()
cfg = newCfg cfg = newCfg
saveConfig()
} }
} }

View File

@ -33,7 +33,6 @@ import (
"github.com/syncthing/syncthing/files" "github.com/syncthing/syncthing/files"
"github.com/syncthing/syncthing/logger" "github.com/syncthing/syncthing/logger"
"github.com/syncthing/syncthing/model" "github.com/syncthing/syncthing/model"
"github.com/syncthing/syncthing/osutil"
"github.com/syncthing/syncthing/protocol" "github.com/syncthing/syncthing/protocol"
"github.com/syncthing/syncthing/upgrade" "github.com/syncthing/syncthing/upgrade"
"github.com/syncthing/syncthing/upnp" "github.com/syncthing/syncthing/upnp"
@ -310,21 +309,14 @@ func syncthingMain() {
// Prepare to be able to save configuration // Prepare to be able to save configuration
cfgFile := filepath.Join(confDir, "config.xml") cfgFile := filepath.Join(confDir, "config.xml")
go saveConfigLoop(cfgFile)
var myName string var myName string
// Load the configuration file, if it exists. // Load the configuration file, if it exists.
// If it does not, create a template. // If it does not, create a template.
cf, err := os.Open(cfgFile) cfg, err = config.Load(cfgFile, myID)
if err == nil { if err == nil {
// Read config.xml
cfg, err = config.Load(cf, myID)
if err != nil {
l.Fatalln(err)
}
cf.Close()
myCfg := cfg.GetNodeConfiguration(myID) myCfg := cfg.GetNodeConfiguration(myID)
if myCfg == nil || myCfg.Name == "" { if myCfg == nil || myCfg.Name == "" {
myName, _ = os.Hostname() myName, _ = os.Hostname()
@ -336,7 +328,7 @@ func syncthingMain() {
myName, _ = os.Hostname() myName, _ = os.Hostname()
defaultRepo := filepath.Join(getHomeDir(), "Sync") defaultRepo := filepath.Join(getHomeDir(), "Sync")
cfg, err = config.Load(nil, myID) cfg = config.New(cfgFile, myID)
cfg.Repositories = []config.RepositoryConfiguration{ cfg.Repositories = []config.RepositoryConfiguration{
{ {
ID: "default", ID: "default",
@ -361,7 +353,7 @@ func syncthingMain() {
l.FatalErr(err) l.FatalErr(err)
cfg.Options.ListenAddress = []string{fmt.Sprintf("0.0.0.0:%d", port)} 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) l.Infof("Edit %s to taste or use the GUI\n", cfgFile)
} }
@ -745,40 +737,6 @@ func shutdown() {
stop <- exitSuccess 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) { func listenConnect(myID protocol.NodeID, m *model.Model, tlsCfg *tls.Config) {
var conns = make(chan *tls.Conn) var conns = make(chan *tls.Conn)

View File

@ -8,7 +8,6 @@ package config
import ( import (
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"io"
"os" "os"
"reflect" "reflect"
"sort" "sort"
@ -16,12 +15,14 @@ import (
"code.google.com/p/go.crypto/bcrypt" "code.google.com/p/go.crypto/bcrypt"
"github.com/syncthing/syncthing/logger" "github.com/syncthing/syncthing/logger"
"github.com/syncthing/syncthing/osutil"
"github.com/syncthing/syncthing/protocol" "github.com/syncthing/syncthing/protocol"
) )
var l = logger.DefaultLogger var l = logger.DefaultLogger
type Configuration struct { type Configuration struct {
Location string `xml:"-" json:"-"`
Version int `xml:"version,attr" default:"3"` Version int `xml:"version,attr" default:"3"`
Repositories []RepositoryConfiguration `xml:"repository"` Repositories []RepositoryConfiguration `xml:"repository"`
Nodes []NodeConfiguration `xml:"node"` Nodes []NodeConfiguration `xml:"node"`
@ -227,14 +228,38 @@ func fillNilSlices(data interface{}) error {
return nil return nil
} }
func Save(wr io.Writer, cfg Configuration) error { func (cfg *Configuration) Save() error {
e := xml.NewEncoder(wr) fd, err := os.Create(cfg.Location + ".tmp")
e.Indent("", " ")
err := e.Encode(cfg)
if err != nil { if err != nil {
l.Warnln("Saving config:", err)
return 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 return err
} }
@ -252,18 +277,7 @@ func uniqueStrings(ss []string) []string {
return us return us
} }
func Load(rd io.Reader, myID protocol.NodeID) (Configuration, error) { func (cfg *Configuration) prepare(myID protocol.NodeID) {
var cfg Configuration
setDefaults(&cfg)
setDefaults(&cfg.Options)
setDefaults(&cfg.GUI)
var err error
if rd != nil {
err = xml.NewDecoder(rd).Decode(&cfg)
}
fillNilSlices(&cfg.Options) fillNilSlices(&cfg.Options)
cfg.Options.ListenAddress = uniqueStrings(cfg.Options.ListenAddress) 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 // Upgrade to v2 configuration if appropriate
if cfg.Version == 1 { if cfg.Version == 1 {
convertV1V2(&cfg) convertV1V2(cfg)
} }
// Upgrade to v3 configuration if appropriate // Upgrade to v3 configuration if appropriate
if cfg.Version == 2 { if cfg.Version == 2 {
convertV2V3(&cfg) convertV2V3(cfg)
} }
// Upgrade to v4 configuration if appropriate // Upgrade to v4 configuration if appropriate
if cfg.Version == 3 { if cfg.Version == 3 {
convertV3V4(&cfg) convertV3V4(cfg)
} }
// Hash old cleartext passwords // Hash old cleartext passwords
@ -368,6 +382,39 @@ func Load(rd io.Reader, myID protocol.NodeID) (Configuration, error) {
n.Addresses = []string{"dynamic"} 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 return cfg, err
} }