Files
proton-bridge/internal/bridge/updates.go
2022-11-23 16:08:27 +01:00

157 lines
4.0 KiB
Go

// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
package bridge
import (
"context"
"errors"
"github.com/ProtonMail/proton-bridge/v3/internal/events"
"github.com/ProtonMail/proton-bridge/v3/internal/safe"
"github.com/ProtonMail/proton-bridge/v3/internal/updater"
"github.com/sirupsen/logrus"
)
func (bridge *Bridge) CheckForUpdates() {
bridge.goUpdate()
}
func (bridge *Bridge) InstallUpdate(version updater.VersionInfo) {
log := logrus.WithFields(logrus.Fields{
"version": version.Version,
"current": bridge.curVersion,
"channel": bridge.vault.GetUpdateChannel(),
})
select {
case bridge.installCh <- installJob{version: version, silent: false}:
log.Info("The update will be installed manually")
default:
log.Info("An update is already being installed")
}
}
func (bridge *Bridge) handleUpdate(version updater.VersionInfo) {
log := logrus.WithFields(logrus.Fields{
"version": version.Version,
"current": bridge.curVersion,
"channel": bridge.vault.GetUpdateChannel(),
})
bridge.publish(events.UpdateLatest{
Version: version,
})
switch {
case !version.Version.GreaterThan(bridge.curVersion):
log.Debug("No update available")
bridge.publish(events.UpdateNotAvailable{})
case version.RolloutProportion < bridge.vault.GetUpdateRollout():
log.Info("An update is available but has not been rolled out yet")
bridge.publish(events.UpdateNotAvailable{})
case bridge.curVersion.LessThan(version.MinAuto):
log.Info("An update is available but is incompatible with this version")
bridge.publish(events.UpdateAvailable{
Version: version,
Compatible: false,
Silent: false,
})
case !bridge.vault.GetAutoUpdate():
log.Info("An update is available but auto-update is disabled")
bridge.publish(events.UpdateAvailable{
Version: version,
Compatible: true,
Silent: false,
})
default:
safe.RLock(func() {
if version.Version.GreaterThan(bridge.newVersion) {
log.Info("An update is available")
select {
case bridge.installCh <- installJob{version: version, silent: true}:
log.Info("The update will be installed silently")
default:
log.Info("An update is already being installed")
}
}
}, bridge.newVersionLock)
}
}
type installJob struct {
version updater.VersionInfo
silent bool
}
func (bridge *Bridge) installUpdate(ctx context.Context, job installJob) {
safe.Lock(func() {
log := logrus.WithFields(logrus.Fields{
"version": job.version.Version,
"current": bridge.curVersion,
"channel": bridge.vault.GetUpdateChannel(),
})
bridge.publish(events.UpdateAvailable{
Version: job.version,
Compatible: true,
Silent: job.silent,
})
bridge.publish(events.UpdateInstalling{
Version: job.version,
Silent: job.silent,
})
err := bridge.updater.InstallUpdate(ctx, bridge.api, job.version)
switch {
case errors.Is(err, updater.ErrUpdateAlreadyInstalled):
log.Info("The update was already installed")
case err != nil:
log.WithError(err).Error("The update could not be installed")
bridge.publish(events.UpdateFailed{
Version: job.version,
Silent: job.silent,
Error: err,
})
default:
log.Info("The update was installed successfully")
bridge.publish(events.UpdateInstalled{
Version: job.version,
Silent: job.silent,
})
bridge.newVersion = job.version.Version
}
}, bridge.newVersionLock)
}