diff --git a/internal/bridge/bridge.go b/internal/bridge/bridge.go index b415e8d9..c6efd9e8 100644 --- a/internal/bridge/bridge.go +++ b/internal/bridge/bridge.go @@ -74,6 +74,7 @@ type Bridge struct { // updater is the bridge's updater. updater Updater curVersion *semver.Version + installCh chan installJob // focusService is used to raise the bridge window when needed. focusService *focus.Service @@ -241,6 +242,7 @@ func newBridge( updater: updater, curVersion: curVersion, + installCh: make(chan installJob, 1), focusService: focusService, autostarter: autostarter, @@ -340,18 +342,25 @@ func (bridge *Bridge) init(tlsReporter TLSReporter) error { defer bridge.goLoad() // Check for updates when triggered. - bridge.goUpdate = bridge.tasks.PeriodicOrTrigger(constants.UpdateCheckInterval, 0, func(context.Context) { + bridge.goUpdate = bridge.tasks.PeriodicOrTrigger(constants.UpdateCheckInterval, 0, func(ctx context.Context) { logrus.Info("Checking for updates") - version, err := bridge.updater.GetVersionInfo(bridge.api, bridge.vault.GetUpdateChannel()) + version, err := bridge.updater.GetVersionInfo(ctx, bridge.api, bridge.vault.GetUpdateChannel()) if err != nil { - logrus.WithError(err).Error("Failed to get version info") - } else if err := bridge.handleUpdate(version); err != nil { - logrus.WithError(err).Error("Failed to handle update") + logrus.WithError(err).Error("Failed to check for updates") + } else { + bridge.handleUpdate(version) } }) defer bridge.goUpdate() + // Install updates when available. + bridge.tasks.Once(func(ctx context.Context) { + async.RangeContext(ctx, bridge.installCh, func(job installJob) { + bridge.installUpdate(ctx, job) + }) + }) + return nil } diff --git a/internal/bridge/bridge_test.go b/internal/bridge/bridge_test.go index 9eb5c7ad..2b1754cc 100644 --- a/internal/bridge/bridge_test.go +++ b/internal/bridge/bridge_test.go @@ -237,7 +237,8 @@ func TestBridge_CheckUpdate(t *testing.T) { MinAuto: v2_3_0, RolloutProportion: 1.0, }, - CanInstall: true, + Silent: false, + Compatible: true, }, <-updateCh) }) }) @@ -259,13 +260,14 @@ func TestBridge_AutoUpdate(t *testing.T) { // Check for updates. bridge.CheckForUpdates() - // We should receive an event indicating that the update was installed. + // We should receive an event indicating that the update was silently installed. require.Equal(t, events.UpdateInstalled{ Version: updater.VersionInfo{ Version: v2_4_0, MinAuto: v2_3_0, RolloutProportion: 1.0, }, + Silent: true, }, <-updateCh) }) }) @@ -294,7 +296,8 @@ func TestBridge_ManualUpdate(t *testing.T) { MinAuto: v2_4_0, RolloutProportion: 1.0, }, - CanInstall: false, + Silent: false, + Compatible: false, }, <-updateCh) }) }) diff --git a/internal/bridge/mocks.go b/internal/bridge/mocks.go index 94efb0e8..4fbe6506 100644 --- a/internal/bridge/mocks.go +++ b/internal/bridge/mocks.go @@ -1,6 +1,7 @@ package bridge import ( + "context" "net/http" "net/url" "os" @@ -129,13 +130,13 @@ func (testUpdater *TestUpdater) SetLatestVersion(version, minAuto *semver.Versio } } -func (testUpdater *TestUpdater) GetVersionInfo(downloader updater.Downloader, channel updater.Channel) (updater.VersionInfo, error) { +func (testUpdater *TestUpdater) GetVersionInfo(ctx context.Context, downloader updater.Downloader, channel updater.Channel) (updater.VersionInfo, error) { testUpdater.lock.RLock() defer testUpdater.lock.RUnlock() return testUpdater.latest, nil } -func (testUpdater *TestUpdater) InstallUpdate(downloader updater.Downloader, update updater.VersionInfo) error { +func (testUpdater *TestUpdater) InstallUpdate(ctx context.Context, downloader updater.Downloader, update updater.VersionInfo) error { return nil } diff --git a/internal/bridge/types.go b/internal/bridge/types.go index 376187ce..b308322c 100644 --- a/internal/bridge/types.go +++ b/internal/bridge/types.go @@ -18,6 +18,8 @@ package bridge import ( + "context" + "github.com/ProtonMail/proton-bridge/v2/internal/updater" ) @@ -51,6 +53,6 @@ type Autostarter interface { } type Updater interface { - GetVersionInfo(downloader updater.Downloader, channel updater.Channel) (updater.VersionInfo, error) - InstallUpdate(downloader updater.Downloader, update updater.VersionInfo) error + GetVersionInfo(context.Context, updater.Downloader, updater.Channel) (updater.VersionInfo, error) + InstallUpdate(context.Context, updater.Downloader, updater.VersionInfo) error } diff --git a/internal/bridge/updates.go b/internal/bridge/updates.go index 4fefb080..a2c15e81 100644 --- a/internal/bridge/updates.go +++ b/internal/bridge/updates.go @@ -18,43 +18,123 @@ package bridge import ( + "context" + "github.com/ProtonMail/proton-bridge/v2/internal/events" "github.com/ProtonMail/proton-bridge/v2/internal/updater" + "github.com/sirupsen/logrus" ) func (bridge *Bridge) CheckForUpdates() { bridge.goUpdate() } -func (bridge *Bridge) handleUpdate(version updater.VersionInfo) error { +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, - CanInstall: false, + 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, - CanInstall: true, + Compatible: true, + Silent: false, }) default: - if err := bridge.updater.InstallUpdate(bridge.api, version); err != nil { - return err + log.Info("An update is available") + + bridge.publish(events.UpdateAvailable{ + Version: version, + Compatible: true, + Silent: true, + }) + + 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") } + } +} + +type installJob struct { + version updater.VersionInfo + silent bool +} + +func (bridge *Bridge) installUpdate(ctx context.Context, job installJob) { + log := logrus.WithFields(logrus.Fields{ + "version": job.version.Version, + "current": bridge.curVersion, + "channel": bridge.vault.GetUpdateChannel(), + }) + + bridge.publish(events.UpdateInstalling{ + Version: job.version, + Silent: job.silent, + }) + + if err := bridge.updater.InstallUpdate(ctx, bridge.api, job.version); err != nil { + log.Error("The update could not be installed") + + bridge.publish(events.UpdateFailed{ + Version: job.version, + Silent: job.silent, + Error: err, + }) + } else { + log.Info("The update was installed successfully") bridge.publish(events.UpdateInstalled{ - Version: version, + Version: job.version, + Silent: job.silent, }) } - - return nil } diff --git a/internal/events/events.go b/internal/events/events.go index e058c253..f8e94625 100644 --- a/internal/events/events.go +++ b/internal/events/events.go @@ -17,7 +17,11 @@ package events +import "fmt" + type Event interface { + fmt.Stringer + _isEvent() } diff --git a/internal/events/update.go b/internal/events/update.go index d1291a14..30d3ec8a 100644 --- a/internal/events/update.go +++ b/internal/events/update.go @@ -23,18 +23,37 @@ import ( "github.com/ProtonMail/proton-bridge/v2/internal/updater" ) +// UpdateLatest is published when the latest version of bridge is known. +type UpdateLatest struct { + eventBase + + Version updater.VersionInfo +} + +func (event UpdateLatest) String() string { + return fmt.Sprintf("UpdateLatest: Version: %s", event.Version.Version) +} + +// UpdateAvailable is published when an update is available. +// If the update is compatible (can be installed automatically), Compatible is true. +// If the update will be installed silently (without user interaction), Silent is true. type UpdateAvailable struct { eventBase Version updater.VersionInfo - CanInstall bool + // Compatible is true if the update can be installed automatically. + Compatible bool + + // Silent is true if the update will be installed silently. + Silent bool } func (event UpdateAvailable) String() string { - return fmt.Sprintf("UpdateAvailable: Version %s, CanInstall %t", event.Version.Version, event.CanInstall) + return fmt.Sprintf("UpdateAvailable: Version %s, Compatible: %t, Silent: %t", event.Version.Version, event.Compatible, event.Silent) } +// UpdateNotAvailable is published when no update is available. type UpdateNotAvailable struct { eventBase } @@ -43,20 +62,54 @@ func (event UpdateNotAvailable) String() string { return "UpdateNotAvailable" } +// UpdateInstalling is published when bridge begins installing an update. +type UpdateInstalling struct { + eventBase + + Version updater.VersionInfo + + Silent bool +} + +func (event UpdateInstalling) String() string { + return fmt.Sprintf("UpdateInstalling: Version %s, Silent: %t", event.Version.Version, event.Silent) +} + +// UpdateInstalled is published when an update has been installed. type UpdateInstalled struct { eventBase Version updater.VersionInfo + + Silent bool +} + +func (event UpdateInstalled) String() string { + return fmt.Sprintf("UpdateInstalled: Version %s, Silent: %t", event.Version.Version, event.Silent) +} + +// UpdateFailed is published when an update fails to be installed. +type UpdateFailed struct { + eventBase + + Version updater.VersionInfo + + Silent bool + + Error error +} + +func (event UpdateFailed) String() string { + return fmt.Sprintf("UpdateFailed: Version %s, Silent: %t, Error: %s", event.Version.Version, event.Silent, event.Error) +} + +// UpdateForced is published when the bridge version is too old and must be updated. +type UpdateForced struct { + eventBase + + Version updater.VersionInfo } -func (event UpdateInstalled) String() string { - return fmt.Sprintf("UpdateInstalled: Version %s", event.Version.Version) -} - -type UpdateForced struct { - eventBase -} - func (event UpdateForced) String() string { - return "UpdateForced" + return fmt.Sprintf("UpdateForced: Version %s", event.Version.Version) } diff --git a/internal/frontend/cli/frontend.go b/internal/frontend/cli/frontend.go index 52dff6ba..971b3188 100644 --- a/internal/frontend/cli/frontend.go +++ b/internal/frontend/cli/frontend.go @@ -337,7 +337,17 @@ func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:funle ) case events.UpdateAvailable: - f.Printf("An update is available (version %v)\n", event.Version.Version) + if !event.Compatible { + f.Printf("A new version (%v) is available but it cannot be installed automatically.\n", event.Version.Version) + } else if !event.Silent { + f.Printf("A new version (%v) is available.\n", event.Version.Version) + } + + case events.UpdateInstalled: + f.Printf("A new version (%v) was installed.\n", event.Version.Version) + + case events.UpdateFailed: + f.Printf("A new version (%v) failed to be installed (%v).\n", event.Version.Version, event.Error) case events.UpdateForced: f.notifyNeedUpgrade() diff --git a/internal/frontend/cli/updates.go b/internal/frontend/cli/updates.go index 66206f24..c7beecf8 100644 --- a/internal/frontend/cli/updates.go +++ b/internal/frontend/cli/updates.go @@ -18,12 +18,24 @@ package cli import ( + "github.com/ProtonMail/proton-bridge/v2/internal/events" "github.com/ProtonMail/proton-bridge/v2/internal/updater" "github.com/abiosoft/ishell" ) func (f *frontendCLI) checkUpdates(c *ishell.Context) { + updateCh, done := f.bridge.GetEvents(events.UpdateAvailable{}, events.UpdateNotAvailable{}) + defer done() + f.bridge.CheckForUpdates() + + switch (<-updateCh).(type) { + case events.UpdateAvailable: + // ... this is handled by the main event loop + + case events.UpdateNotAvailable: + f.Println("Bridge is already up to date.") + } } func (f *frontendCLI) enableAutoUpdates(c *ishell.Context) { diff --git a/internal/frontend/grpc/service.go b/internal/frontend/grpc/service.go index 99ca4399..7773c1a0 100644 --- a/internal/frontend/grpc/service.go +++ b/internal/frontend/grpc/service.go @@ -34,6 +34,7 @@ import ( "github.com/ProtonMail/proton-bridge/v2/internal/crash" "github.com/ProtonMail/proton-bridge/v2/internal/events" "github.com/ProtonMail/proton-bridge/v2/internal/locations" + "github.com/ProtonMail/proton-bridge/v2/internal/safe" "github.com/ProtonMail/proton-bridge/v2/internal/updater" "github.com/ProtonMail/proton-bridge/v2/pkg/restarter" "github.com/google/uuid" @@ -63,11 +64,16 @@ type Service struct { // nolint:structcheck eventQueue []*StreamEvent eventQueueMutex sync.Mutex - panicHandler *crash.Handler - restarter *restarter.Restarter - bridge *bridge.Bridge - eventCh <-chan events.Event - newVersionInfo updater.VersionInfo + panicHandler *crash.Handler + restarter *restarter.Restarter + bridge *bridge.Bridge + eventCh <-chan events.Event + + latest updater.VersionInfo + latestLock safe.RWMutex + + target updater.VersionInfo + targetLock safe.RWMutex authClient *liteapi.Client auth liteapi.Auth @@ -82,6 +88,8 @@ type Service struct { // nolint:structcheck } // NewService returns a new instance of the service. +// +// nolint:funlen func NewService( panicHandler *crash.Handler, restarter *restarter.Restarter, @@ -121,6 +129,12 @@ func NewService( bridge: bridge, eventCh: eventCh, + latest: updater.VersionInfo{}, + latestLock: safe.NewRWMutex(), + + target: updater.VersionInfo{}, + targetLock: safe.NewRWMutex(), + log: logrus.WithField("pkg", "grpc"), initializing: sync.WaitGroup{}, initializationDone: sync.Once{}, @@ -178,33 +192,12 @@ func (s *Service) Loop() error { return nil } -func (s *Service) NotifyManualUpdate(version updater.VersionInfo, canInstall bool) { - if canInstall { - _ = s.SendEvent(NewUpdateManualReadyEvent(version.Version.String())) - } else { - _ = s.SendEvent(NewUpdateErrorEvent(UpdateErrorType_UPDATE_MANUAL_ERROR)) - } -} - -func (s *Service) SetVersion(update updater.VersionInfo) { - s.newVersionInfo = update - _ = s.SendEvent(NewUpdateVersionChangedEvent()) -} - -func (s *Service) NotifySilentUpdateInstalled() { - _ = s.SendEvent(NewUpdateSilentRestartNeededEvent()) -} - -func (s *Service) NotifySilentUpdateError(err error) { - s.log.WithError(err).Error("In app update failed, asking for manual.") - _ = s.SendEvent(NewUpdateErrorEvent(UpdateErrorType_UPDATE_SILENT_ERROR)) -} - func (s *Service) WaitUntilFrontendIsReady() { s.initializing.Wait() } -func (s *Service) watchEvents() { //nolint:funlen +// nolint:funlen,gocyclo +func (s *Service) watchEvents() { // GODT-1949 Better error events. for _, err := range s.bridge.GetErrors() { switch { @@ -270,11 +263,43 @@ func (s *Service) watchEvents() { //nolint:funlen _ = s.SendEvent(NewUserDisconnectedEvent(user.Username)) } - case events.TLSIssue: - _ = s.SendEvent(NewMailApiCertIssue()) + case events.UpdateLatest: + safe.RLock(func() { + s.latest = event.Version + }, s.latestLock) + + case events.UpdateAvailable: + switch { + case !event.Compatible: + _ = s.SendEvent(NewUpdateErrorEvent(UpdateErrorType_UPDATE_MANUAL_ERROR)) + + case !event.Silent: + safe.RLock(func() { + s.target = event.Version + }, s.targetLock) + + _ = s.SendEvent(NewUpdateManualReadyEvent(event.Version.Version.String())) + } + + case events.UpdateInstalled: + if event.Silent { + _ = s.SendEvent(NewUpdateSilentRestartNeededEvent()) + } else { + _ = s.SendEvent(NewUpdateManualRestartNeededEvent()) + } + + case events.UpdateFailed: + if event.Silent { + _ = s.SendEvent(NewUpdateErrorEvent(UpdateErrorType_UPDATE_SILENT_ERROR)) + } else { + _ = s.SendEvent(NewUpdateErrorEvent(UpdateErrorType_UPDATE_MANUAL_ERROR)) + } case events.UpdateForced: - _ = s.SendEvent(NewUpdateForceEvent(s.newVersionInfo.Version.String())) + _ = s.SendEvent(NewUpdateForceEvent(event.Version.Version.String())) + + case events.TLSIssue: + _ = s.SendEvent(NewMailApiCertIssue()) } } } diff --git a/internal/frontend/grpc/service_methods.go b/internal/frontend/grpc/service_methods.go index 2244ee45..e2486f20 100644 --- a/internal/frontend/grpc/service_methods.go +++ b/internal/frontend/grpc/service_methods.go @@ -26,7 +26,9 @@ import ( "github.com/Masterminds/semver/v3" "github.com/ProtonMail/proton-bridge/v2/internal/bridge" "github.com/ProtonMail/proton-bridge/v2/internal/constants" + "github.com/ProtonMail/proton-bridge/v2/internal/events" "github.com/ProtonMail/proton-bridge/v2/internal/frontend/theme" + "github.com/ProtonMail/proton-bridge/v2/internal/safe" "github.com/ProtonMail/proton-bridge/v2/internal/updater" "github.com/ProtonMail/proton-bridge/v2/pkg/keychain" "github.com/ProtonMail/proton-bridge/v2/pkg/ports" @@ -257,11 +259,17 @@ func (s *Service) DependencyLicensesLink(_ context.Context, _ *emptypb.Empty) (* } func (s *Service) ReleaseNotesPageLink(ctx context.Context, _ *emptypb.Empty) (*wrapperspb.StringValue, error) { - return wrapperspb.String(s.newVersionInfo.ReleaseNotesPage), nil + s.latestLock.RLock() + defer s.latestLock.RUnlock() + + return wrapperspb.String(s.latest.ReleaseNotesPage), nil } func (s *Service) LandingPageLink(_ context.Context, _ *emptypb.Empty) (*wrapperspb.StringValue, error) { - return wrapperspb.String(s.newVersionInfo.LandingPage), nil + s.latestLock.RLock() + defer s.latestLock.RUnlock() + + return wrapperspb.String(s.latest.LandingPage), nil } func (s *Service) SetColorSchemeName(ctx context.Context, name *wrapperspb.StringValue) (*emptypb.Empty, error) { @@ -486,15 +494,28 @@ func (s *Service) LoginAbort(ctx context.Context, loginAbort *LoginAbortRequest) return &emptypb.Empty{}, nil } -/* func (s *Service) CheckUpdate(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { s.log.Debug("CheckUpdate") go func() { defer s.panicHandler.HandlePanic() - s.checkUpdateAndNotify(true) + updateCh, done := s.bridge.GetEvents(events.UpdateAvailable{}, events.UpdateNotAvailable{}) + defer done() + + s.bridge.CheckForUpdates() + + switch (<-updateCh).(type) { + case events.UpdateAvailable: + // ... this is handled by the main event loop + + case events.UpdateNotAvailable: + _ = s.SendEvent(NewUpdateIsLatestVersionEvent()) + } + + _ = s.SendEvent(NewUpdateCheckFinishedEvent()) }() + return &emptypb.Empty{}, nil } @@ -504,18 +525,18 @@ func (s *Service) InstallUpdate(ctx context.Context, _ *emptypb.Empty) (*emptypb go func() { defer s.panicHandler.HandlePanic() - s.installUpdate() + safe.RLock(func() { + s.bridge.InstallUpdate(s.latest) + }, s.targetLock) }() return &emptypb.Empty{}, nil } -*/ func (s *Service) SetIsAutomaticUpdateOn(ctx context.Context, isOn *wrapperspb.BoolValue) (*emptypb.Empty, error) { s.log.WithField("isOn", isOn.Value).Debug("SetIsAutomaticUpdateOn") - currentlyOn := s.bridge.GetAutoUpdate() - if currentlyOn == isOn.Value { + if currentlyOn := s.bridge.GetAutoUpdate(); currentlyOn == isOn.Value { return &emptypb.Empty{}, nil } @@ -548,6 +569,7 @@ func (s *Service) SetDiskCachePath(ctx context.Context, newPath *wrapperspb.Stri }() path := newPath.Value + //goland:noinspection GoBoolExpressions if (runtime.GOOS == "windows") && (path[0] == '/') { path = path[1:] diff --git a/internal/frontend/grpc/service_updates.go b/internal/frontend/grpc/service_updates.go deleted file mode 100644 index e2e66d6a..00000000 --- a/internal/frontend/grpc/service_updates.go +++ /dev/null @@ -1,85 +0,0 @@ -// 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 . - -package grpc - -/* -func (s *Service) checkUpdate() { - version, err := s.updater.Check() - if err != nil { - s.log.WithError(err).Error("An error occurred while checking for updates") - s.SetVersion(updater.VersionInfo{}) - return - } - s.SetVersion(version) -} - -func (s *Service) updateForce() { - s.updateCheckMutex.Lock() - defer s.updateCheckMutex.Unlock() - s.checkUpdate() - _ = s.SendEvent(NewUpdateForceEvent(s.newVersionInfo.Version.String())) -} - -func (s *Service) checkUpdateAndNotify(isReqFromUser bool) { - s.updateCheckMutex.Lock() - defer func() { - s.updateCheckMutex.Unlock() - _ = s.SendEvent(NewUpdateCheckFinishedEvent()) - }() - - s.checkUpdate() - version := s.newVersionInfo - if version.Version.String() == "" { - if isReqFromUser { - _ = s.SendEvent(NewUpdateErrorEvent(UpdateErrorType_UPDATE_MANUAL_ERROR)) - } - return - } - if !s.updater.IsUpdateApplicable(s.newVersionInfo) { - s.log.Info("No need to update") - if isReqFromUser { - _ = s.SendEvent(NewUpdateIsLatestVersionEvent()) - } - } else if isReqFromUser { - s.NotifyManualUpdate(s.newVersionInfo, s.updater.CanInstall(s.newVersionInfo)) - } -} - -func (s *Service) installUpdate() { - s.updateCheckMutex.Lock() - defer s.updateCheckMutex.Unlock() - - if !s.updater.CanInstall(s.newVersionInfo) { - s.log.Warning("Skipping update installation, current version too old") - _ = s.SendEvent(NewUpdateErrorEvent(UpdateErrorType_UPDATE_MANUAL_ERROR)) - return - } - - if err := s.updater.InstallUpdate(s.newVersionInfo); err != nil { - if errors.Cause(err) == updater.ErrDownloadVerify { - s.log.WithError(err).Warning("Skipping update installation due to temporary error") - } else { - s.log.WithError(err).Error("The update couldn't be installed") - _ = s.SendEvent(NewUpdateErrorEvent(UpdateErrorType_UPDATE_MANUAL_ERROR)) - } - return - } - - _ = s.SendEvent(NewUpdateSilentRestartNeededEvent()) -} -*/ diff --git a/internal/locations/locations.go b/internal/locations/locations.go index 8a495460..18709795 100644 --- a/internal/locations/locations.go +++ b/internal/locations/locations.go @@ -177,16 +177,6 @@ func (l *Locations) ProvideUpdatesPath() (string, error) { return l.getUpdatesPath(), nil } -// GetUpdatesPath returns a new location for update files used for migration scripts only. -func (l *Locations) GetUpdatesPath() string { - return l.getUpdatesPath() -} - -// GetOldUpdatesPath returns a former location for update files used for migration scripts only. -func (l *Locations) GetOldUpdatesPath() string { - return filepath.Join(l.userCache, "updates") -} - func (l *Locations) getGluonPath() string { return filepath.Join(l.userData, "gluon") } @@ -208,17 +198,7 @@ func (l *Locations) getGoIMAPCachePath() string { } func (l *Locations) getUpdatesPath() string { - // In order to properly update Bridge 1.6.X and higher we need to - // change the launcher first. Since this is not part of automatic - // updates the migration must wait until manual update. Until that - // we need to keep old path. - if l.configName == "bridge" { - return l.GetOldUpdatesPath() - } - - // Users might use tools to regularly clear caches, which would mean always - // removing updates, therefore Bridge updates have to be somewhere else. - return filepath.Join(l.userConfig, "updates") + return filepath.Join(l.userData, "updates") } // Clear removes everything except the lock and update files. diff --git a/internal/locations/locations_test.go b/internal/locations/locations_test.go index fabd04e7..99717752 100644 --- a/internal/locations/locations_test.go +++ b/internal/locations/locations_test.go @@ -47,7 +47,6 @@ func TestClearRemovesEverythingExceptLockAndUpdateFiles(t *testing.T) { assert.NoError(t, l.Clear()) - assert.DirExists(t, l.getSettingsPath()) assert.NoFileExists(t, filepath.Join(l.getSettingsPath(), "prefs.json")) assert.NoDirExists(t, l.getLogsPath()) assert.DirExists(t, l.getUpdatesPath()) diff --git a/internal/updater/updater.go b/internal/updater/updater.go index d7c41733..23b410da 100644 --- a/internal/updater/updater.go +++ b/internal/updater/updater.go @@ -58,9 +58,9 @@ func NewUpdater(installer Installer, verifier *crypto.KeyRing, product, platform } } -func (u *Updater) GetVersionInfo(downloader Downloader, channel Channel) (VersionInfo, error) { +func (u *Updater) GetVersionInfo(ctx context.Context, downloader Downloader, channel Channel) (VersionInfo, error) { b, err := downloader.DownloadAndVerify( - context.Background(), + ctx, u.verifier, u.getVersionFileURL(), u.getVersionFileURL()+".sig", @@ -83,9 +83,9 @@ func (u *Updater) GetVersionInfo(downloader Downloader, channel Channel) (Versio return version, nil } -func (u *Updater) InstallUpdate(downloader Downloader, update VersionInfo) error { +func (u *Updater) InstallUpdate(ctx context.Context, downloader Downloader, update VersionInfo) error { b, err := downloader.DownloadAndVerify( - context.Background(), + ctx, u.verifier, update.Package, update.Package+".sig", diff --git a/tests/bridge_test.go b/tests/bridge_test.go index 08b9c83e..3ebec475 100644 --- a/tests/bridge_test.go +++ b/tests/bridge_test.go @@ -214,7 +214,7 @@ func (s *scenario) bridgeSendsAnUpdateAvailableEventForVersion(version string) e return errors.New("expected update available event, got none") } - if !event.CanInstall { + if !event.Compatible { return errors.New("expected update event to be installable") } @@ -231,7 +231,7 @@ func (s *scenario) bridgeSendsAManualUpdateEventForVersion(version string) error return errors.New("expected update available event, got none") } - if event.CanInstall { + if event.Compatible { return errors.New("expected update event to not be installable") }