From 22d0ed82251cc9ae9f5272cd57d6e2a1209817bb Mon Sep 17 00:00:00 2001 From: Anderson Mesquita Date: Sun, 20 Dec 2015 11:58:51 -0500 Subject: [PATCH 1/3] Fix typo --- cmd/syncthing/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index 3917c42e..6856921e 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -603,7 +603,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) { } if err := checkShortIDs(cfg); err != nil { - l.Fatalln("Short device IDs are in conflict. Unlucky!\n Regenerate the device ID of one if the following:\n ", err) + l.Fatalln("Short device IDs are in conflict. Unlucky!\n Regenerate the device ID of one of the following:\n ", err) } if len(runtimeOptions.profiler) > 0 { From 9b9912ba9e56b525d595049567bb525531b5b037 Mon Sep 17 00:00:00 2001 From: Anderson Mesquita Date: Fri, 18 Dec 2015 18:39:36 -0500 Subject: [PATCH 2/3] Centralize config loading logic This gets rid of redundant checks and centralizes the logic of loading the config files so that we don't have to keep doing the same thing in multiple places. --- cmd/syncthing/main.go | 97 ++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 56 deletions(-) diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index 6856921e..3e59d69d 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -359,10 +359,7 @@ func main() { } func openGUI() { - cfg, _, err := loadConfig(locations[locConfigFile]) - if err != nil { - l.Fatalln("Config:", err) - } + cfg, _ := loadConfig() if cfg.GUI().Enabled { openURL(cfg.GUI().URL()) } else { @@ -433,10 +430,8 @@ func debugFacilities() string { } func checkUpgrade() upgrade.Release { - releasesURL := "https://api.github.com/repos/syncthing/syncthing/releases?per_page=30" - if cfg, _, err := loadConfig(locations[locConfigFile]); err == nil { - releasesURL = cfg.Options().ReleasesURL - } + cfg, _ := loadConfig() + releasesURL := cfg.Options().ReleasesURL release, err := upgrade.LatestRelease(releasesURL, Version) if err != nil { l.Fatalln("Upgrade:", err) @@ -473,10 +468,7 @@ func performUpgrade(release upgrade.Release) { } func upgradeViaRest() error { - cfg, err := config.Load(locations[locConfigFile], protocol.LocalDeviceID) - if err != nil { - return err - } + cfg, _ := loadConfig() target := cfg.GUI().URL() r, _ := http.NewRequest("POST", target+"/rest/system/upgrade", nil) r.Header.Set("X-API-Key", cfg.GUI().APIKey()) @@ -573,34 +565,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) { "myID": myID.String(), }) - // Prepare to be able to save configuration - - cfgFile := locations[locConfigFile] - - // Load the configuration file, if it exists. - // If it does not, create a template. - - cfg, myName, err := loadConfig(cfgFile) - if err != nil { - if os.IsNotExist(err) { - l.Infoln("No config file; starting with empty defaults") - myName, _ = os.Hostname() - newCfg := defaultConfig(myName) - cfg = config.Wrap(cfgFile, newCfg) - cfg.Save() - l.Infof("Edit %s to taste or use the GUI\n", cfgFile) - } else { - l.Fatalln("Loading config:", err) - } - } - - if cfg.Raw().OriginalVersion != config.CurrentVersion { - l.Infoln("Archiving a copy of old config file format") - // Archive a copy - osutil.Rename(cfgFile, cfgFile+fmt.Sprintf(".v%d", cfg.Raw().OriginalVersion)) - // Save the new version - cfg.Save() - } + cfg := loadOrCreateConfig() if err := checkShortIDs(cfg); err != nil { l.Fatalln("Short device IDs are in conflict. Unlucky!\n Regenerate the device ID of one of the following:\n ", err) @@ -693,7 +658,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) { l.Infoln("Compacting database:", err) } - m := model.NewModel(cfg, myID, myName, "syncthing", Version, ldb, protectedFiles) + m := model.NewModel(cfg, myID, myDeviceName(cfg), "syncthing", Version, ldb, protectedFiles) cfg.Subscribe(m) if t := os.Getenv("STDEADLOCKTIMEOUT"); len(t) > 0 { @@ -886,6 +851,15 @@ func syncthingMain(runtimeOptions RuntimeOptions) { os.Exit(code) } +func myDeviceName(cfg *config.Wrapper) string { + devices := cfg.Devices() + myName := devices[myID].Name + if myName == "" { + myName, _ = os.Hostname() + } + return myName +} + func setupSignalHandling() { // Exit cleanly with "restarting" code on SIGHUP. @@ -924,27 +898,38 @@ func printHashRate() { l.Infof("Single thread hash performance is ~%.*f MB/s", decimals, hashRate) } -func loadConfig(cfgFile string) (*config.Wrapper, string, error) { - info, err := os.Stat(cfgFile) - if err != nil { - return nil, "", err - } - if !info.Mode().IsRegular() { - return nil, "", errors.New("configuration is not a file") - } - +func loadConfig() (*config.Wrapper, error) { + cfgFile := locations[locConfigFile] cfg, err := config.Load(cfgFile, myID) + if err != nil { - return nil, "", err + l.Infoln("Error loading config file; using defaults for now") + myName, _ := os.Hostname() + newCfg := defaultConfig(myName) + cfg = config.Wrap(cfgFile, newCfg) } - myCfg := cfg.Devices()[myID] - myName := myCfg.Name - if myName == "" { - myName, _ = os.Hostname() + return cfg, err +} + +func loadOrCreateConfig() *config.Wrapper { + cfg, err := loadConfig() + if os.IsNotExist(err) { + cfg.Save() + l.Infof("Defaults saved. Edit %s to taste or use the GUI\n", cfg.ConfigPath()) + } else if err != nil { + l.Fatalln("Config:", err) } - return cfg, myName, nil + if cfg.Raw().OriginalVersion != config.CurrentVersion { + // Archive previous version and save new one + archivePath := cfg.ConfigPath() + fmt.Sprintf(".v%d", cfg.Raw().OriginalVersion) + l.Infoln("Archiving a copy of old config file format at:", archivePath) + osutil.Rename(cfg.ConfigPath(), archivePath) + cfg.Save() + } + + return cfg } func startAuditing(mainService *suture.Supervisor) { From 8eb06874077a93f9633841b871a338471598e3bb Mon Sep 17 00:00:00 2001 From: Anderson Mesquita Date: Wed, 23 Dec 2015 19:12:24 -0500 Subject: [PATCH 3/3] Update mtime of config file before upgrading (fixes #2509) This updates the modified time of the config file before archiving it during an update so that the clean up routine doesn't delete it if it's too old, preventing the user from being able to rollback after an upgrade. --- cmd/syncthing/main.go | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index 3e59d69d..59e8fee3 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -922,16 +922,33 @@ func loadOrCreateConfig() *config.Wrapper { } if cfg.Raw().OriginalVersion != config.CurrentVersion { - // Archive previous version and save new one - archivePath := cfg.ConfigPath() + fmt.Sprintf(".v%d", cfg.Raw().OriginalVersion) - l.Infoln("Archiving a copy of old config file format at:", archivePath) - osutil.Rename(cfg.ConfigPath(), archivePath) - cfg.Save() + err = archiveAndSaveConfig(cfg) + if err != nil { + l.Fatalln("Config archive:", err) + } } return cfg } +func archiveAndSaveConfig(cfg *config.Wrapper) error { + // To prevent previous config from being cleaned up, quickly touch it too + now := time.Now() + err := os.Chtimes(cfg.ConfigPath(), now, now) + if err != nil { + return err + } + + archivePath := cfg.ConfigPath() + fmt.Sprintf(".v%d", cfg.Raw().OriginalVersion) + l.Infoln("Archiving a copy of old config file format at:", archivePath) + err = osutil.Rename(cfg.ConfigPath(), archivePath) + if err != nil { + return err + } + + return cfg.Save() +} + func startAuditing(mainService *suture.Supervisor) { auditFile := timestampedLoc(locAuditLog) fd, err := os.OpenFile(auditFile, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)