Explorar o código

Implement manual -upgrade-to option

Jakob Borg %!s(int64=11) %!d(string=hai) anos
pai
achega
cde8ef56e5

+ 11 - 0
cmd/syncthing/main.go

@@ -182,6 +182,7 @@ var (
 	showVersion       bool
 	doUpgrade         bool
 	doUpgradeCheck    bool
+	upgradeTo         string
 	noBrowser         bool
 	noConsole         bool
 	generateDir       string
@@ -227,6 +228,7 @@ func main() {
 	flag.BoolVar(&doUpgrade, "upgrade", false, "Perform upgrade")
 	flag.BoolVar(&doUpgradeCheck, "upgrade-check", false, "Check for available upgrade")
 	flag.BoolVar(&showVersion, "version", false, "Show version")
+	flag.StringVar(&upgradeTo, "upgrade-to", upgradeTo, "Force upgrade directly from specified URL")
 
 	flag.Usage = usageFor(flag.CommandLine, usage, fmt.Sprintf(extraUsage, defConfDir))
 	flag.Parse()
@@ -315,6 +317,15 @@ func main() {
 	// Ensure that our home directory exists.
 	ensureDir(confDir, 0700)
 
+	if upgradeTo != "" {
+		err := upgrade.ToURL(upgradeTo)
+		if err != nil {
+			l.Fatalln("Upgrade:", err) // exits 1
+		}
+		l.Okln("Upgraded from", upgradeTo)
+		return
+	}
+
 	if doUpgrade || doUpgradeCheck {
 		rel, err := upgrade.LatestRelease(IsBeta)
 		if err != nil {

+ 20 - 0
internal/upgrade/upgrade_common.go

@@ -67,6 +67,26 @@ func To(rel Release) error {
 	}
 }
 
+// A wrapper around actual implementations
+func ToURL(url string) error {
+	select {
+	case <-upgradeUnlocked:
+		path, err := osext.Executable()
+		if err != nil {
+			upgradeUnlocked <- true
+			return err
+		}
+		err = upgradeToURL(path, url)
+		// If we've failed to upgrade, unlock so that another attempt could be made
+		if err != nil {
+			upgradeUnlocked <- true
+		}
+		return err
+	default:
+		return ErrUpgradeInProgress
+	}
+}
+
 // Returns 1 if a>b, -1 if a<b and 0 if they are equal
 func CompareVersions(a, b string) int {
 	arel, apre := versionParts(a)

+ 21 - 16
internal/upgrade/upgrade_supported.go

@@ -80,28 +80,33 @@ func upgradeTo(binary string, rel Release) error {
 		}
 
 		if strings.HasPrefix(assetName, expectedRelease) {
-			fname, err := readRelease(filepath.Dir(binary), asset.URL)
-			if err != nil {
-				return err
-			}
-
-			old := binary + ".old"
-			_ = os.Remove(old)
-			err = os.Rename(binary, old)
-			if err != nil {
-				return err
-			}
-			err = os.Rename(fname, binary)
-			if err != nil {
-				return err
-			}
-			return nil
+			upgradeToURL(binary, asset.URL)
 		}
 	}
 
 	return ErrVersionUnknown
 }
 
+// Upgrade to the given release, saving the previous binary with a ".old" extension.
+func upgradeToURL(binary string, url string) error {
+	fname, err := readRelease(filepath.Dir(binary), url)
+	if err != nil {
+		return err
+	}
+
+	old := binary + ".old"
+	_ = os.Remove(old)
+	err = os.Rename(binary, old)
+	if err != nil {
+		return err
+	}
+	err = os.Rename(fname, binary)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
 func readRelease(dir, url string) (string, error) {
 	if debug {
 		l.Debugf("loading %q", url)

+ 5 - 1
internal/upgrade/upgrade_unsupp.go

@@ -17,7 +17,11 @@
 
 package upgrade
 
-func upgradeTo(path string, rel Release) error {
+func upgradeTo(binary string, rel Release) error {
+	return ErrUpgradeUnsupported
+}
+
+func upgradeToURL(binary, url string) error {
 	return ErrUpgradeUnsupported
 }