Merge pull request #645 from AudriusButkevicius/cfg
Allow saving config from anywhere
This commit is contained in:
commit
78c6a68db9
@ -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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,8 +5,6 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
@ -40,10 +38,7 @@ func TestDefaultValues(t *testing.T) {
|
|||||||
UPnPRenewal: 30,
|
UPnPRenewal: 30,
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := Load(bytes.NewReader(nil), node1)
|
cfg := New("test", node1)
|
||||||
if err != io.EOF {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(cfg.Options, expected) {
|
if !reflect.DeepEqual(cfg.Options, expected) {
|
||||||
t.Errorf("Default config differs;\n E: %#v\n A: %#v", expected, cfg.Options)
|
t.Errorf("Default config differs;\n E: %#v\n A: %#v", expected, cfg.Options)
|
||||||
@ -51,84 +46,8 @@ func TestDefaultValues(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNodeConfig(t *testing.T) {
|
func TestNodeConfig(t *testing.T) {
|
||||||
v1data := []byte(`
|
for i, ver := range []string{"v1", "v2", "v3", "v4"} {
|
||||||
<configuration version="1">
|
cfg, err := Load("testdata/"+ver+".xml", node1)
|
||||||
<repository id="test" directory="~/Sync">
|
|
||||||
<node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ" name="node one">
|
|
||||||
<address>a</address>
|
|
||||||
</node>
|
|
||||||
<node id="P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ" name="node two">
|
|
||||||
<address>b</address>
|
|
||||||
</node>
|
|
||||||
<node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ" name="node one">
|
|
||||||
<address>a</address>
|
|
||||||
</node>
|
|
||||||
<node id="P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ" name="node two">
|
|
||||||
<address>b</address>
|
|
||||||
</node>
|
|
||||||
</repository>
|
|
||||||
<options>
|
|
||||||
<readOnly>true</readOnly>
|
|
||||||
<rescanIntervalS>600</rescanIntervalS>
|
|
||||||
</options>
|
|
||||||
</configuration>
|
|
||||||
`)
|
|
||||||
|
|
||||||
v2data := []byte(`
|
|
||||||
<configuration version="2">
|
|
||||||
<repository id="test" directory="~/Sync" ro="true">
|
|
||||||
<node id="P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ"/>
|
|
||||||
<node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ"/>
|
|
||||||
<node id="C4YBIESWDUAIGU62GOSRXCRAAJDWVE3TKCPMURZE2LH5QHAF576A"/>
|
|
||||||
<node id="P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ"/>
|
|
||||||
<node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ"/>
|
|
||||||
<node id="C4YBIESWDUAIGU62GOSRXCRAAJDWVE3TKCPMURZE2LH5QHAF576A"/>
|
|
||||||
</repository>
|
|
||||||
<node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ" name="node one">
|
|
||||||
<address>a</address>
|
|
||||||
</node>
|
|
||||||
<node id="P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ" name="node two">
|
|
||||||
<address>b</address>
|
|
||||||
</node>
|
|
||||||
<options>
|
|
||||||
<rescanIntervalS>600</rescanIntervalS>
|
|
||||||
</options>
|
|
||||||
</configuration>
|
|
||||||
`)
|
|
||||||
|
|
||||||
v3data := []byte(`
|
|
||||||
<configuration version="3">
|
|
||||||
<repository id="test" directory="~/Sync" ro="true" ignorePerms="false">
|
|
||||||
<node id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR" compression="false"></node>
|
|
||||||
<node id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2" compression="false"></node>
|
|
||||||
</repository>
|
|
||||||
<node id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR" name="node one" compression="true">
|
|
||||||
<address>a</address>
|
|
||||||
</node>
|
|
||||||
<node id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2" name="node two" compression="true">
|
|
||||||
<address>b</address>
|
|
||||||
</node>
|
|
||||||
<options>
|
|
||||||
<rescanIntervalS>600</rescanIntervalS>
|
|
||||||
</options>
|
|
||||||
</configuration>`)
|
|
||||||
|
|
||||||
v4data := []byte(`
|
|
||||||
<configuration version="4">
|
|
||||||
<repository id="test" directory="~/Sync" ro="true" ignorePerms="false" rescanIntervalS="600">
|
|
||||||
<node id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></node>
|
|
||||||
<node id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></node>
|
|
||||||
</repository>
|
|
||||||
<node id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR" name="node one" compression="true">
|
|
||||||
<address>a</address>
|
|
||||||
</node>
|
|
||||||
<node id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2" name="node two" compression="true">
|
|
||||||
<address>b</address>
|
|
||||||
</node>
|
|
||||||
</configuration>`)
|
|
||||||
|
|
||||||
for i, data := range [][]byte{v1data, v2data, v3data, v4data} {
|
|
||||||
cfg, err := Load(bytes.NewReader(data), node1)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -181,14 +100,7 @@ func TestNodeConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNoListenAddress(t *testing.T) {
|
func TestNoListenAddress(t *testing.T) {
|
||||||
data := []byte(`<configuration version="1">
|
cfg, err := Load("testdata/nolistenaddress.xml", node1)
|
||||||
<options>
|
|
||||||
<listenAddress></listenAddress>
|
|
||||||
</options>
|
|
||||||
</configuration>
|
|
||||||
`)
|
|
||||||
|
|
||||||
cfg, err := Load(bytes.NewReader(data), node1)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -200,26 +112,6 @@ func TestNoListenAddress(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestOverriddenValues(t *testing.T) {
|
func TestOverriddenValues(t *testing.T) {
|
||||||
data := []byte(`<configuration version="2">
|
|
||||||
<options>
|
|
||||||
<listenAddress>:23000</listenAddress>
|
|
||||||
<allowDelete>false</allowDelete>
|
|
||||||
<globalAnnounceServer>syncthing.nym.se:22026</globalAnnounceServer>
|
|
||||||
<globalAnnounceEnabled>false</globalAnnounceEnabled>
|
|
||||||
<localAnnounceEnabled>false</localAnnounceEnabled>
|
|
||||||
<localAnnouncePort>42123</localAnnouncePort>
|
|
||||||
<localAnnounceMCAddr>quux:3232</localAnnounceMCAddr>
|
|
||||||
<parallelRequests>32</parallelRequests>
|
|
||||||
<maxSendKbps>1234</maxSendKbps>
|
|
||||||
<reconnectionIntervalS>6000</reconnectionIntervalS>
|
|
||||||
<startBrowser>false</startBrowser>
|
|
||||||
<upnpEnabled>false</upnpEnabled>
|
|
||||||
<upnpLeaseMinutes>60</upnpLeaseMinutes>
|
|
||||||
<upnpRenewalMinutes>15</upnpRenewalMinutes>
|
|
||||||
</options>
|
|
||||||
</configuration>
|
|
||||||
`)
|
|
||||||
|
|
||||||
expected := OptionsConfiguration{
|
expected := OptionsConfiguration{
|
||||||
ListenAddress: []string{":23000"},
|
ListenAddress: []string{":23000"},
|
||||||
GlobalAnnServer: "syncthing.nym.se:22026",
|
GlobalAnnServer: "syncthing.nym.se:22026",
|
||||||
@ -236,7 +128,7 @@ func TestOverriddenValues(t *testing.T) {
|
|||||||
UPnPRenewal: 15,
|
UPnPRenewal: 15,
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := Load(bytes.NewReader(data), node1)
|
cfg, err := Load("testdata/overridenvalues.xml", node1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -247,19 +139,6 @@ func TestOverriddenValues(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNodeAddressesDynamic(t *testing.T) {
|
func TestNodeAddressesDynamic(t *testing.T) {
|
||||||
data := []byte(`
|
|
||||||
<configuration version="2">
|
|
||||||
<node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ">
|
|
||||||
<address></address>
|
|
||||||
</node>
|
|
||||||
<node id="GYRZZQBIRNPV4T7TC52WEQYJ3TFDQW6MWDFLMU4SSSU6EMFBK2VA">
|
|
||||||
</node>
|
|
||||||
<node id="LGFPDIT7SKNNJVJZA4FC7QNCRKCE753K72BW5QD2FOZ7FRFEP57Q">
|
|
||||||
<address>dynamic</address>
|
|
||||||
</node>
|
|
||||||
</configuration>
|
|
||||||
`)
|
|
||||||
|
|
||||||
name, _ := os.Hostname()
|
name, _ := os.Hostname()
|
||||||
expected := []NodeConfiguration{
|
expected := []NodeConfiguration{
|
||||||
{
|
{
|
||||||
@ -284,7 +163,7 @@ func TestNodeAddressesDynamic(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := Load(bytes.NewReader(data), node4)
|
cfg, err := Load("testdata/nodeaddressesdynamic.xml", node4)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -295,23 +174,6 @@ func TestNodeAddressesDynamic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNodeAddressesStatic(t *testing.T) {
|
func TestNodeAddressesStatic(t *testing.T) {
|
||||||
data := []byte(`
|
|
||||||
<configuration version="3">
|
|
||||||
<node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ">
|
|
||||||
<address>192.0.2.1</address>
|
|
||||||
<address>192.0.2.2</address>
|
|
||||||
</node>
|
|
||||||
<node id="GYRZZQBIRNPV4T7TC52WEQYJ3TFDQW6MWDFLMU4SSSU6EMFBK2VA">
|
|
||||||
<address>192.0.2.3:6070</address>
|
|
||||||
<address>[2001:db8::42]:4242</address>
|
|
||||||
</node>
|
|
||||||
<node id="LGFPDIT7SKNNJVJZA4FC7QNCRKCE753K72BW5QD2FOZ7FRFEP57Q">
|
|
||||||
<address>[2001:db8::44]:4444</address>
|
|
||||||
<address>192.0.2.4:6090</address>
|
|
||||||
</node>
|
|
||||||
</configuration>
|
|
||||||
`)
|
|
||||||
|
|
||||||
name, _ := os.Hostname()
|
name, _ := os.Hostname()
|
||||||
expected := []NodeConfiguration{
|
expected := []NodeConfiguration{
|
||||||
{
|
{
|
||||||
@ -333,7 +195,7 @@ func TestNodeAddressesStatic(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, err := Load(bytes.NewReader(data), node4)
|
cfg, err := Load("testdata/nodeaddressesstatic.xml", node4)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -344,18 +206,7 @@ func TestNodeAddressesStatic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestVersioningConfig(t *testing.T) {
|
func TestVersioningConfig(t *testing.T) {
|
||||||
data := []byte(`
|
cfg, err := Load("testdata/versioningconfig.xml", node4)
|
||||||
<configuration version="2">
|
|
||||||
<repository id="test" directory="~/Sync" ro="true">
|
|
||||||
<versioning type="simple">
|
|
||||||
<param key="foo" val="bar"/>
|
|
||||||
<param key="baz" val="quux"/>
|
|
||||||
</versioning>
|
|
||||||
</repository>
|
|
||||||
</configuration>
|
|
||||||
`)
|
|
||||||
|
|
||||||
cfg, err := Load(bytes.NewReader(data), node4)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -376,3 +227,67 @@ func TestVersioningConfig(t *testing.T) {
|
|||||||
t.Errorf("vc.Params differ;\n E: %#v\n A: %#v", expected, vc.Params)
|
t.Errorf("vc.Params differ;\n E: %#v\n A: %#v", expected, vc.Params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewSaveLoad(t *testing.T) {
|
||||||
|
path := "testdata/temp.xml"
|
||||||
|
os.Remove(path)
|
||||||
|
|
||||||
|
exists := func(path string) bool {
|
||||||
|
_, err := os.Stat(path)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg := New(path, node1)
|
||||||
|
|
||||||
|
// To make the equality pass later
|
||||||
|
cfg.XMLName.Local = "configuration"
|
||||||
|
|
||||||
|
if exists(path) {
|
||||||
|
t.Error(path, "exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
err := cfg.Save()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !exists(path) {
|
||||||
|
t.Error(path, "does not exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg2, err := Load(path, node1)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(cfg, cfg2) {
|
||||||
|
t.Errorf("Configs are not equal;\n E: %#v\n A: %#v", cfg, cfg2)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.GUI.User = "test"
|
||||||
|
cfg.Save()
|
||||||
|
|
||||||
|
cfg2, err = Load(path, node1)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg2.GUI.User != "test" || !reflect.DeepEqual(cfg, cfg2) {
|
||||||
|
t.Errorf("Configs are not equal;\n E: %#v\n A: %#v", cfg, cfg2)
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Remove(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrepare(t *testing.T) {
|
||||||
|
var cfg Configuration
|
||||||
|
|
||||||
|
if cfg.Repositories != nil || cfg.Nodes != nil || cfg.Options.ListenAddress != nil {
|
||||||
|
t.Error("Expected nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.prepare(node1)
|
||||||
|
|
||||||
|
if cfg.Repositories == nil || cfg.Nodes == nil || cfg.Options.ListenAddress == nil {
|
||||||
|
t.Error("Unexpected nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
10
config/testdata/nodeaddressesdynamic.xml
vendored
Executable file
10
config/testdata/nodeaddressesdynamic.xml
vendored
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
<configuration version="2">
|
||||||
|
<node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ">
|
||||||
|
<address></address>
|
||||||
|
</node>
|
||||||
|
<node id="GYRZZQBIRNPV4T7TC52WEQYJ3TFDQW6MWDFLMU4SSSU6EMFBK2VA">
|
||||||
|
</node>
|
||||||
|
<node id="LGFPDIT7SKNNJVJZA4FC7QNCRKCE753K72BW5QD2FOZ7FRFEP57Q">
|
||||||
|
<address>dynamic</address>
|
||||||
|
</node>
|
||||||
|
</configuration>
|
||||||
14
config/testdata/nodeaddressesstatic.xml
vendored
Executable file
14
config/testdata/nodeaddressesstatic.xml
vendored
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
<configuration version="3">
|
||||||
|
<node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ">
|
||||||
|
<address>192.0.2.1</address>
|
||||||
|
<address>192.0.2.2</address>
|
||||||
|
</node>
|
||||||
|
<node id="GYRZZQBIRNPV4T7TC52WEQYJ3TFDQW6MWDFLMU4SSSU6EMFBK2VA">
|
||||||
|
<address>192.0.2.3:6070</address>
|
||||||
|
<address>[2001:db8::42]:4242</address>
|
||||||
|
</node>
|
||||||
|
<node id="LGFPDIT7SKNNJVJZA4FC7QNCRKCE753K72BW5QD2FOZ7FRFEP57Q">
|
||||||
|
<address>[2001:db8::44]:4444</address>
|
||||||
|
<address>192.0.2.4:6090</address>
|
||||||
|
</node>
|
||||||
|
</configuration>
|
||||||
5
config/testdata/nolistenaddress.xml
vendored
Executable file
5
config/testdata/nolistenaddress.xml
vendored
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
<configuration version="1">
|
||||||
|
<options>
|
||||||
|
<listenAddress></listenAddress>
|
||||||
|
</options>
|
||||||
|
</configuration>
|
||||||
18
config/testdata/overridenvalues.xml
vendored
Executable file
18
config/testdata/overridenvalues.xml
vendored
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
<configuration version="2">
|
||||||
|
<options>
|
||||||
|
<listenAddress>:23000</listenAddress>
|
||||||
|
<allowDelete>false</allowDelete>
|
||||||
|
<globalAnnounceServer>syncthing.nym.se:22026</globalAnnounceServer>
|
||||||
|
<globalAnnounceEnabled>false</globalAnnounceEnabled>
|
||||||
|
<localAnnounceEnabled>false</localAnnounceEnabled>
|
||||||
|
<localAnnouncePort>42123</localAnnouncePort>
|
||||||
|
<localAnnounceMCAddr>quux:3232</localAnnounceMCAddr>
|
||||||
|
<parallelRequests>32</parallelRequests>
|
||||||
|
<maxSendKbps>1234</maxSendKbps>
|
||||||
|
<reconnectionIntervalS>6000</reconnectionIntervalS>
|
||||||
|
<startBrowser>false</startBrowser>
|
||||||
|
<upnpEnabled>false</upnpEnabled>
|
||||||
|
<upnpLeaseMinutes>60</upnpLeaseMinutes>
|
||||||
|
<upnpRenewalMinutes>15</upnpRenewalMinutes>
|
||||||
|
</options>
|
||||||
|
</configuration>
|
||||||
20
config/testdata/v1.xml
vendored
Executable file
20
config/testdata/v1.xml
vendored
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
<configuration version="1">
|
||||||
|
<repository id="test" directory="~/Sync">
|
||||||
|
<node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ" name="node one">
|
||||||
|
<address>a</address>
|
||||||
|
</node>
|
||||||
|
<node id="P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ" name="node two">
|
||||||
|
<address>b</address>
|
||||||
|
</node>
|
||||||
|
<node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ" name="node one">
|
||||||
|
<address>a</address>
|
||||||
|
</node>
|
||||||
|
<node id="P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ" name="node two">
|
||||||
|
<address>b</address>
|
||||||
|
</node>
|
||||||
|
</repository>
|
||||||
|
<options>
|
||||||
|
<readOnly>true</readOnly>
|
||||||
|
<rescanIntervalS>600</rescanIntervalS>
|
||||||
|
</options>
|
||||||
|
</configuration>
|
||||||
19
config/testdata/v2.xml
vendored
Executable file
19
config/testdata/v2.xml
vendored
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
<configuration version="2">
|
||||||
|
<repository id="test" directory="~/Sync" ro="true">
|
||||||
|
<node id="P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ"/>
|
||||||
|
<node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ"/>
|
||||||
|
<node id="C4YBIESWDUAIGU62GOSRXCRAAJDWVE3TKCPMURZE2LH5QHAF576A"/>
|
||||||
|
<node id="P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ"/>
|
||||||
|
<node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ"/>
|
||||||
|
<node id="C4YBIESWDUAIGU62GOSRXCRAAJDWVE3TKCPMURZE2LH5QHAF576A"/>
|
||||||
|
</repository>
|
||||||
|
<node id="AIR6LPZ7K4PTTUXQSMUUCPQ5YWOEDFIIQJUG7772YQXXR5YD6AWQ" name="node one">
|
||||||
|
<address>a</address>
|
||||||
|
</node>
|
||||||
|
<node id="P56IOI7MZJNU2IQGDREYDM2MGTMGL3BXNPQ6W5BTBBZ4TJXZWICQ" name="node two">
|
||||||
|
<address>b</address>
|
||||||
|
</node>
|
||||||
|
<options>
|
||||||
|
<rescanIntervalS>600</rescanIntervalS>
|
||||||
|
</options>
|
||||||
|
</configuration>
|
||||||
15
config/testdata/v3.xml
vendored
Executable file
15
config/testdata/v3.xml
vendored
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
<configuration version="3">
|
||||||
|
<repository id="test" directory="~/Sync" ro="true" ignorePerms="false">
|
||||||
|
<node id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR" compression="false"></node>
|
||||||
|
<node id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2" compression="false"></node>
|
||||||
|
</repository>
|
||||||
|
<node id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR" name="node one" compression="true">
|
||||||
|
<address>a</address>
|
||||||
|
</node>
|
||||||
|
<node id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2" name="node two" compression="true">
|
||||||
|
<address>b</address>
|
||||||
|
</node>
|
||||||
|
<options>
|
||||||
|
<rescanIntervalS>600</rescanIntervalS>
|
||||||
|
</options>
|
||||||
|
</configuration>
|
||||||
12
config/testdata/v4.xml
vendored
Executable file
12
config/testdata/v4.xml
vendored
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
<configuration version="4">
|
||||||
|
<repository id="test" directory="~/Sync" ro="true" ignorePerms="false" rescanIntervalS="600">
|
||||||
|
<node id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></node>
|
||||||
|
<node id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></node>
|
||||||
|
</repository>
|
||||||
|
<node id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR" name="node one" compression="true">
|
||||||
|
<address>a</address>
|
||||||
|
</node>
|
||||||
|
<node id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2" name="node two" compression="true">
|
||||||
|
<address>b</address>
|
||||||
|
</node>
|
||||||
|
</configuration>
|
||||||
8
config/testdata/versioningconfig.xml
vendored
Executable file
8
config/testdata/versioningconfig.xml
vendored
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
<configuration version="2">
|
||||||
|
<repository id="test" directory="~/Sync" ro="true">
|
||||||
|
<versioning type="simple">
|
||||||
|
<param key="foo" val="bar"/>
|
||||||
|
<param key="baz" val="quux"/>
|
||||||
|
</versioning>
|
||||||
|
</repository>
|
||||||
|
</configuration>
|
||||||
@ -266,7 +266,7 @@ func TestNodeRename(t *testing.T) {
|
|||||||
ClientVersion: "v0.9.4",
|
ClientVersion: "v0.9.4",
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg, _ := config.Load(nil, node1)
|
cfg := config.New("test", node1)
|
||||||
cfg.Nodes = []config.NodeConfiguration{
|
cfg.Nodes = []config.NodeConfiguration{
|
||||||
{
|
{
|
||||||
NodeID: node1,
|
NodeID: node1,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user