mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-08 22:31:04 +00:00
parent
16698b12b1
commit
c101a04179
@ -139,10 +139,12 @@ The following are valid values for the STTRACE variable:
|
|||||||
%s`
|
%s`
|
||||||
)
|
)
|
||||||
|
|
||||||
// Environment options
|
|
||||||
var (
|
var (
|
||||||
|
// Environment options
|
||||||
innerProcess = os.Getenv("STNORESTART") != "" || os.Getenv("STMONITORED") != ""
|
innerProcess = os.Getenv("STNORESTART") != "" || os.Getenv("STMONITORED") != ""
|
||||||
noDefaultFolder = os.Getenv("STNODEFAULTFOLDER") != ""
|
noDefaultFolder = os.Getenv("STNODEFAULTFOLDER") != ""
|
||||||
|
|
||||||
|
errConcurrentUpgrade = errors.New("upgrade prevented by other running Syncthing instance")
|
||||||
)
|
)
|
||||||
|
|
||||||
type RuntimeOptions struct {
|
type RuntimeOptions struct {
|
||||||
@ -359,14 +361,24 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if options.doUpgradeCheck {
|
if options.doUpgradeCheck {
|
||||||
checkUpgrade()
|
if _, err := checkUpgrade(); err != nil {
|
||||||
|
l.Warnln("Checking for upgrade:", err)
|
||||||
|
os.Exit(exitCodeForUpgrade(err))
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.doUpgrade {
|
if options.doUpgrade {
|
||||||
release := checkUpgrade()
|
release, err := checkUpgrade()
|
||||||
performUpgrade(release)
|
if err == nil {
|
||||||
return
|
err = performUpgrade(release)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
l.Warnln("Upgrade:", err)
|
||||||
|
os.Exit(exitCodeForUpgrade(err))
|
||||||
|
}
|
||||||
|
l.Infof("Upgraded to %q", release.Tag)
|
||||||
|
os.Exit(syncthing.ExitUpgrade.AsInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.resetDatabase {
|
if options.resetDatabase {
|
||||||
@ -462,45 +474,47 @@ func debugFacilities() string {
|
|||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkUpgrade() upgrade.Release {
|
type errNoUpgrade struct {
|
||||||
|
current, latest string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e errNoUpgrade) Error() string {
|
||||||
|
return fmt.Sprintf("no upgrade available (current %q >= latest %q).", e.current, e.latest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkUpgrade() (upgrade.Release, error) {
|
||||||
cfg, _ := loadOrDefaultConfig(protocol.EmptyDeviceID, events.NoopLogger)
|
cfg, _ := loadOrDefaultConfig(protocol.EmptyDeviceID, events.NoopLogger)
|
||||||
opts := cfg.Options()
|
opts := cfg.Options()
|
||||||
release, err := upgrade.LatestRelease(opts.ReleasesURL, build.Version, opts.UpgradeToPreReleases)
|
release, err := upgrade.LatestRelease(opts.ReleasesURL, build.Version, opts.UpgradeToPreReleases)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Warnln("Upgrade:", err)
|
return upgrade.Release{}, err
|
||||||
os.Exit(syncthing.ExitError.AsInt())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if upgrade.CompareVersions(release.Tag, build.Version) <= 0 {
|
if upgrade.CompareVersions(release.Tag, build.Version) <= 0 {
|
||||||
noUpgradeMessage := "No upgrade available (current %q >= latest %q)."
|
return upgrade.Release{}, errNoUpgrade{build.Version, release.Tag}
|
||||||
l.Infof(noUpgradeMessage, build.Version, release.Tag)
|
|
||||||
os.Exit(syncthing.ExitNoUpgradeAvailable.AsInt())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Infof("Upgrade available (current %q < latest %q)", build.Version, release.Tag)
|
l.Infof("Upgrade available (current %q < latest %q)", build.Version, release.Tag)
|
||||||
return release
|
return release, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func performUpgrade(release upgrade.Release) {
|
func performUpgradeDirect(release upgrade.Release) error {
|
||||||
// Use leveldb database locks to protect against concurrent upgrades
|
// Use leveldb database locks to protect against concurrent upgrades
|
||||||
_, err := syncthing.OpenDBBackend(locations.Get(locations.Database), config.TuningAuto)
|
if _, err := syncthing.OpenDBBackend(locations.Get(locations.Database), config.TuningAuto); err != nil {
|
||||||
if err == nil {
|
return errConcurrentUpgrade
|
||||||
err = upgrade.To(release)
|
}
|
||||||
if err != nil {
|
return upgrade.To(release)
|
||||||
l.Warnln("Upgrade:", err)
|
}
|
||||||
os.Exit(syncthing.ExitError.AsInt())
|
|
||||||
|
func performUpgrade(release upgrade.Release) error {
|
||||||
|
if err := performUpgradeDirect(release); err != nil {
|
||||||
|
if err != errConcurrentUpgrade {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
l.Infof("Upgraded to %q", release.Tag)
|
|
||||||
} else {
|
|
||||||
l.Infoln("Attempting upgrade through running Syncthing...")
|
l.Infoln("Attempting upgrade through running Syncthing...")
|
||||||
err = upgradeViaRest()
|
return upgradeViaRest()
|
||||||
if err != nil {
|
|
||||||
l.Warnln("Upgrade:", err)
|
|
||||||
os.Exit(syncthing.ExitError.AsInt())
|
|
||||||
}
|
|
||||||
l.Infoln("Syncthing upgrading")
|
|
||||||
os.Exit(syncthing.ExitUpgrade.AsInt())
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func upgradeViaRest() error {
|
func upgradeViaRest() error {
|
||||||
@ -568,6 +582,45 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
os.Exit(syncthing.ExitError.AsInt())
|
os.Exit(syncthing.ExitError.AsInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Candidate builds should auto upgrade. Make sure the option is set,
|
||||||
|
// unless we are in a build where it's disabled or the STNOUPGRADE
|
||||||
|
// environment variable is set.
|
||||||
|
|
||||||
|
if build.IsCandidate && !upgrade.DisabledByCompilation && !runtimeOptions.NoUpgrade {
|
||||||
|
l.Infoln("Automatic upgrade is always enabled for candidate releases.")
|
||||||
|
if opts := cfg.Options(); opts.AutoUpgradeIntervalH == 0 || opts.AutoUpgradeIntervalH > 24 {
|
||||||
|
opts.AutoUpgradeIntervalH = 12
|
||||||
|
// Set the option into the config as well, as the auto upgrade
|
||||||
|
// loop expects to read a valid interval from there.
|
||||||
|
cfg.SetOptions(opts)
|
||||||
|
cfg.Save()
|
||||||
|
}
|
||||||
|
// We don't tweak the user's choice of upgrading to pre-releases or
|
||||||
|
// not, as otherwise they cannot step off the candidate channel.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if auto-upgrades should be done and if yes, do an initial
|
||||||
|
// upgrade immedately. The auto-upgrade routine can only be started
|
||||||
|
// later after App is initialised.
|
||||||
|
|
||||||
|
shouldAutoUpgrade := shouldUpgrade(cfg, runtimeOptions)
|
||||||
|
if shouldAutoUpgrade {
|
||||||
|
// Try to do upgrade directly
|
||||||
|
release, err := checkUpgrade()
|
||||||
|
if err == nil {
|
||||||
|
if err = performUpgradeDirect(release); err == nil {
|
||||||
|
l.Infof("Upgraded to %q, exiting now.", release.Tag)
|
||||||
|
os.Exit(syncthing.ExitUpgrade.AsInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Log the error if relevant.
|
||||||
|
if err != nil {
|
||||||
|
if _, ok := err.(errNoUpgrade); !ok {
|
||||||
|
l.Infoln("Initial automatic upgrade:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if runtimeOptions.unpaused {
|
if runtimeOptions.unpaused {
|
||||||
setPauseState(cfg, false)
|
setPauseState(cfg, false)
|
||||||
} else if runtimeOptions.paused {
|
} else if runtimeOptions.paused {
|
||||||
@ -592,6 +645,10 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
|
|
||||||
app := syncthing.New(cfg, ldb, evLogger, cert, appOpts)
|
app := syncthing.New(cfg, ldb, evLogger, cert, appOpts)
|
||||||
|
|
||||||
|
if shouldAutoUpgrade {
|
||||||
|
go autoUpgrade(cfg, app, evLogger)
|
||||||
|
}
|
||||||
|
|
||||||
setupSignalHandling(app)
|
setupSignalHandling(app)
|
||||||
|
|
||||||
if len(os.Getenv("GOMAXPROCS")) == 0 {
|
if len(os.Getenv("GOMAXPROCS")) == 0 {
|
||||||
@ -614,31 +671,6 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
|||||||
go standbyMonitor(app)
|
go standbyMonitor(app)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Candidate builds should auto upgrade. Make sure the option is set,
|
|
||||||
// unless we are in a build where it's disabled or the STNOUPGRADE
|
|
||||||
// environment variable is set.
|
|
||||||
|
|
||||||
if build.IsCandidate && !upgrade.DisabledByCompilation && !runtimeOptions.NoUpgrade {
|
|
||||||
l.Infoln("Automatic upgrade is always enabled for candidate releases.")
|
|
||||||
if opts := cfg.Options(); opts.AutoUpgradeIntervalH == 0 || opts.AutoUpgradeIntervalH > 24 {
|
|
||||||
opts.AutoUpgradeIntervalH = 12
|
|
||||||
// Set the option into the config as well, as the auto upgrade
|
|
||||||
// loop expects to read a valid interval from there.
|
|
||||||
cfg.SetOptions(opts)
|
|
||||||
cfg.Save()
|
|
||||||
}
|
|
||||||
// We don't tweak the user's choice of upgrading to pre-releases or
|
|
||||||
// not, as otherwise they cannot step off the candidate channel.
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts := cfg.Options(); opts.AutoUpgradeIntervalH > 0 {
|
|
||||||
if runtimeOptions.NoUpgrade {
|
|
||||||
l.Infof("No automatic upgrades; STNOUPGRADE environment variable defined.")
|
|
||||||
} else {
|
|
||||||
go autoUpgrade(cfg, app, evLogger)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := app.Start(); err != nil {
|
if err := app.Start(); err != nil {
|
||||||
os.Exit(syncthing.ExitError.AsInt())
|
os.Exit(syncthing.ExitError.AsInt())
|
||||||
}
|
}
|
||||||
@ -771,6 +803,20 @@ func standbyMonitor(app *syncthing.App) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func shouldUpgrade(cfg config.Wrapper, runtimeOptions RuntimeOptions) bool {
|
||||||
|
if upgrade.DisabledByCompilation {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if opts := cfg.Options(); opts.AutoUpgradeIntervalH < 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if runtimeOptions.NoUpgrade {
|
||||||
|
l.Infof("No automatic upgrades; STNOUPGRADE environment variable defined.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func autoUpgrade(cfg config.Wrapper, app *syncthing.App, evLogger events.Logger) {
|
func autoUpgrade(cfg config.Wrapper, app *syncthing.App, evLogger events.Logger) {
|
||||||
timer := time.NewTimer(0)
|
timer := time.NewTimer(0)
|
||||||
sub := evLogger.Subscribe(events.DeviceConnected)
|
sub := evLogger.Subscribe(events.DeviceConnected)
|
||||||
@ -893,3 +939,10 @@ func setPauseState(cfg config.Wrapper, paused bool) {
|
|||||||
os.Exit(syncthing.ExitError.AsInt())
|
os.Exit(syncthing.ExitError.AsInt())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func exitCodeForUpgrade(err error) int {
|
||||||
|
if _, ok := err.(errNoUpgrade); ok {
|
||||||
|
return syncthing.ExitNoUpgradeAvailable.AsInt()
|
||||||
|
}
|
||||||
|
return syncthing.ExitError.AsInt()
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user