diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index 69527508..daf749a7 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -131,10 +131,12 @@ func main() { var reset bool var showVersion bool var doUpgrade bool + var doUpgradeCheck bool flag.StringVar(&confDir, "home", getDefaultConfDir(), "Set configuration directory") flag.BoolVar(&reset, "reset", false, "Prepare to resync from cluster") flag.BoolVar(&showVersion, "version", false, "Show version") flag.BoolVar(&doUpgrade, "upgrade", false, "Perform upgrade") + flag.BoolVar(&doUpgradeCheck, "upgrade-check", false, "Check for available upgrade") flag.IntVar(&logFlags, "logflags", logFlags, "Set log flags") flag.Usage = usageFor(flag.CommandLine, usage, extraUsage) flag.Parse() @@ -148,12 +150,34 @@ func main() { if doUpgrade { err := upgrade() + if err == errVersionUpToDate { + os.Exit(2) + } if err != nil { - l.Fatalln(err) + l.Fatalln(err) // exits 1 } return } + if doUpgradeCheck { + rel, err := currentRelease() + if err != nil { + log.Fatalln(err) // exits 1 + } + + switch compareVersions(rel.Tag, Version) { + case -1: + l.Okf("Current version %s is newer than latest release %s.", Version, rel.Tag) + os.Exit(2) + case 0: + l.Okf("Already running the latest version, %s. Not upgrading.", Version) + os.Exit(2) + default: + l.Infof("An upgrade to %s is available.", rel.Tag) + os.Exit(0) + } + } + if len(os.Getenv("GOGC")) == 0 { debug.SetGCPercent(25) } diff --git a/cmd/syncthing/upgrade_supported.go b/cmd/syncthing/upgrade_supported.go index 49b8d66c..09613786 100644 --- a/cmd/syncthing/upgrade_supported.go +++ b/cmd/syncthing/upgrade_supported.go @@ -26,6 +26,11 @@ import ( var GoArchExtra string // "", "v5", "v6", "v7" +var ( + errVersionUpToDate = errors.New("current version is up to date") + errVersionUnknown = errors.New("couldn't fetch release information") +) + func upgrade() error { if runtime.GOOS == "windows" { return errors.New("Upgrade currently unsupported on Windows") @@ -44,10 +49,10 @@ func upgrade() error { switch compareVersions(rel.Tag, Version) { case -1: l.Okf("Current version %s is newer than latest release %s. Not upgrading.", Version, rel.Tag) - return nil + return errVersionUpToDate case 0: l.Okf("Already running the latest version, %s. Not upgrading.", Version) - return nil + return errVersionUpToDate default: l.Infof("Attempting upgrade to %s...", rel.Tag) } @@ -80,7 +85,7 @@ func upgrade() error { } } - return fmt.Errorf("Found no asset for %q", expectedRelease) + return errVersionUnknown } func currentRelease() (githubRelease, error) { @@ -88,13 +93,16 @@ func currentRelease() (githubRelease, error) { if err != nil { return githubRelease{}, err } + if resp.StatusCode > 299 { + return githubRelease{}, fmt.Errorf("API call returned HTTP error: %s", resp.Status) + } var rels []githubRelease json.NewDecoder(resp.Body).Decode(&rels) resp.Body.Close() if len(rels) == 0 { - return githubRelease{}, errors.New("no releases found") + return githubRelease{}, errVersionUnknown } if strings.Contains(Version, "-beta") { @@ -113,7 +121,7 @@ func currentRelease() (githubRelease, error) { return rel, nil } } - return githubRelease{}, errors.New("no suitable release found") + return githubRelease{}, errVersionUnknown } } diff --git a/logger/logger.go b/logger/logger.go index c753ef4d..1be60438 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -128,7 +128,7 @@ func (l *Logger) Fatalln(vals ...interface{}) { s := fmt.Sprintln(vals...) l.logger.Output(2, "FATAL: "+s) l.callHandlers(LevelFatal, s) - os.Exit(3) + os.Exit(1) } func (l *Logger) Fatalf(format string, vals ...interface{}) { @@ -137,7 +137,7 @@ func (l *Logger) Fatalf(format string, vals ...interface{}) { s := fmt.Sprintf(format, vals...) l.logger.Output(2, "FATAL: "+s) l.callHandlers(LevelFatal, s) - os.Exit(3) + os.Exit(1) } func (l *Logger) FatalErr(err error) { @@ -147,6 +147,6 @@ func (l *Logger) FatalErr(err error) { l.logger.SetFlags(l.logger.Flags() | log.Lshortfile) l.logger.Output(2, "FATAL: "+err.Error()) l.callHandlers(LevelFatal, err.Error()) - os.Exit(3) + os.Exit(1) } }