mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 04:36:43 +00:00
GODT-1977: fix launcher for v2 to v3 updates.
This commit is contained in:
@ -56,6 +56,7 @@ const (
|
||||
func main() { //nolint:funlen
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
l := logrus.WithField("launcher_version", constants.Version)
|
||||
|
||||
reporter := sentry.NewReporter(appName, constants.Version, useragent.New())
|
||||
|
||||
crashHandler := crash.NewHandler(reporter.ReportException)
|
||||
@ -75,7 +76,7 @@ func main() { //nolint:funlen
|
||||
crashHandler.AddRecoveryAction(logging.DumpStackTrace(logsPath))
|
||||
|
||||
if err := logging.Init(logsPath, os.Getenv("VERBOSITY")); err != nil {
|
||||
logrus.WithError(err).Fatal("Failed to setup logging")
|
||||
l.WithError(err).Fatal("Failed to setup logging")
|
||||
}
|
||||
|
||||
updatesPath, err := locations.ProvideUpdatesPath()
|
||||
@ -240,7 +241,7 @@ func getPathToUpdatedExecutable(
|
||||
}
|
||||
|
||||
// Skip versions that are less or equal to launcher version.
|
||||
if currentVersion != nil && !version.SemVer().GreaterThan(currentVersion) {
|
||||
if currentVersion != nil && !versioner.IsNewerIgnorePrerelease(version.SemVer(), currentVersion) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@ -19,10 +19,12 @@ package bridge
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/safe"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/updater"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/versioner"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -58,7 +60,7 @@ func (bridge *Bridge) handleUpdate(version updater.VersionInfo) {
|
||||
})
|
||||
|
||||
switch {
|
||||
case !version.Version.GreaterThan(bridge.curVersion):
|
||||
case !versioner.IsNewerIgnorePrerelease(version.Version, bridge.curVersion):
|
||||
log.Debug("No update available")
|
||||
|
||||
bridge.publish(events.UpdateNotAvailable{})
|
||||
@ -68,7 +70,7 @@ func (bridge *Bridge) handleUpdate(version updater.VersionInfo) {
|
||||
|
||||
bridge.publish(events.UpdateNotAvailable{})
|
||||
|
||||
case bridge.curVersion.LessThan(version.MinAuto):
|
||||
case versioner.IsNewerIgnorePrerelease(version.MinAuto, bridge.curVersion):
|
||||
log.Info("An update is available but is incompatible with this version")
|
||||
|
||||
bridge.publish(events.UpdateAvailable{
|
||||
@ -88,7 +90,7 @@ func (bridge *Bridge) handleUpdate(version updater.VersionInfo) {
|
||||
|
||||
default:
|
||||
safe.RLock(func() {
|
||||
if version.Version.GreaterThan(bridge.newVersion) {
|
||||
if versioner.IsNewerIgnorePrerelease(version.Version, bridge.newVersion) {
|
||||
log.Info("An update is available")
|
||||
|
||||
select {
|
||||
@ -127,15 +129,21 @@ func (bridge *Bridge) installUpdate(ctx context.Context, job installJob) {
|
||||
Silent: job.silent,
|
||||
})
|
||||
|
||||
if err := bridge.updater.InstallUpdate(ctx, bridge.api, job.version); err != nil {
|
||||
log.Error("The update could not be installed")
|
||||
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,
|
||||
})
|
||||
} else {
|
||||
default:
|
||||
log.Info("The update was installed successfully")
|
||||
|
||||
bridge.publish(events.UpdateInstalled{
|
||||
|
||||
@ -61,3 +61,7 @@ func (i *InstallerDarwin) InstallUpdate(_ *semver.Version, r io.Reader) error {
|
||||
|
||||
return syncFolders(oldBundle, newBundle)
|
||||
}
|
||||
|
||||
func (i *InstallerDarwin) IsAlreadyInstalled(version *semver.Version) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ import (
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/ProtonMail/proton-bridge/v2/internal/versioner"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type InstallerDefault struct {
|
||||
@ -40,3 +41,15 @@ func NewInstaller(versioner *versioner.Versioner) *InstallerDefault {
|
||||
func (i *InstallerDefault) InstallUpdate(version *semver.Version, r io.Reader) error {
|
||||
return i.versioner.InstallNewVersion(version, r)
|
||||
}
|
||||
|
||||
func (i *InstallerDefault) IsAlreadyInstalled(version *semver.Version) bool {
|
||||
versions, err := i.versioner.ListVersions()
|
||||
if err != nil {
|
||||
logrus.WithField("version", version).
|
||||
WithError(err).Error("Failed to determine whether version is installed")
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return versions.HasVersion(version)
|
||||
}
|
||||
|
||||
@ -30,8 +30,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrDownloadVerify = errors.New("failed to download or verify the update")
|
||||
ErrInstall = errors.New("failed to install the update")
|
||||
ErrDownloadVerify = errors.New("failed to download or verify the update")
|
||||
ErrInstall = errors.New("failed to install the update")
|
||||
ErrUpdateAlreadyInstalled = errors.New("update is already installed")
|
||||
)
|
||||
|
||||
type Downloader interface {
|
||||
@ -39,6 +40,7 @@ type Downloader interface {
|
||||
}
|
||||
|
||||
type Installer interface {
|
||||
IsAlreadyInstalled(*semver.Version) bool
|
||||
InstallUpdate(*semver.Version, io.Reader) error
|
||||
}
|
||||
|
||||
@ -84,6 +86,10 @@ func (u *Updater) GetVersionInfo(ctx context.Context, downloader Downloader, cha
|
||||
}
|
||||
|
||||
func (u *Updater) InstallUpdate(ctx context.Context, downloader Downloader, update VersionInfo) error {
|
||||
if u.installer.IsAlreadyInstalled(update.Version) {
|
||||
return ErrUpdateAlreadyInstalled
|
||||
}
|
||||
|
||||
b, err := downloader.DownloadAndVerify(
|
||||
ctx,
|
||||
u.verifier,
|
||||
|
||||
@ -50,6 +50,16 @@ func (v Versions) Swap(i, j int) {
|
||||
v[i], v[j] = v[j], v[i]
|
||||
}
|
||||
|
||||
func (v Versions) HasVersion(want *semver.Version) bool {
|
||||
for i := range v {
|
||||
if v[i].version.Equal(want) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (v *Version) String() string {
|
||||
return fmt.Sprintf("%v", v.version)
|
||||
}
|
||||
@ -101,13 +111,7 @@ func (v *Version) VerifyFiles(kr *crypto.KeyRing) error {
|
||||
// GetExecutable returns the full path to the executable of the given version.
|
||||
// It returns an error if the executable is missing or does not have executable permissions set.
|
||||
func (v *Version) GetExecutable(name string) (string, error) {
|
||||
exe := filepath.Join(v.path, getExeName(name))
|
||||
|
||||
if !fileExists(exe) || !fileIsExecutable(exe) {
|
||||
return "", ErrNoExecutable
|
||||
}
|
||||
|
||||
return exe, nil
|
||||
return getExecutableInDirectory(name, v.path)
|
||||
}
|
||||
|
||||
// Remove removes this version directory.
|
||||
|
||||
@ -72,6 +72,10 @@ func (v *Versioner) ListVersions() (Versions, error) {
|
||||
// GetExecutableInDirectory returns the full path to the executable in the given directory, if present.
|
||||
// It returns an error if the executable is missing or does not have executable permissions set.
|
||||
func (v *Versioner) GetExecutableInDirectory(name, directory string) (string, error) {
|
||||
return getExecutableInDirectory(name, directory)
|
||||
}
|
||||
|
||||
func getExecutableInDirectory(name, directory string) (string, error) {
|
||||
exe := filepath.Join(directory, getExeName(name))
|
||||
|
||||
if !fileExists(exe) || !fileIsExecutable(exe) {
|
||||
@ -80,3 +84,10 @@ func (v *Versioner) GetExecutableInDirectory(name, directory string) (string, er
|
||||
|
||||
return exe, nil
|
||||
}
|
||||
|
||||
func IsNewerIgnorePrerelease(a, b *semver.Version) bool {
|
||||
aN, _ := a.SetPrerelease("")
|
||||
bN, _ := b.SetPrerelease("")
|
||||
|
||||
return aN.GreaterThan(&bN)
|
||||
}
|
||||
|
||||
@ -27,6 +27,21 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestIsNewerIgnorePrelease(t *testing.T) {
|
||||
// older
|
||||
assert.False(t, IsNewerIgnorePrerelease(semver.MustParse("2.5.0"), semver.MustParse("2.5.1")))
|
||||
assert.False(t, IsNewerIgnorePrerelease(semver.MustParse("2.5.0"), semver.MustParse("2.5.0")))
|
||||
assert.False(t, IsNewerIgnorePrerelease(semver.MustParse("2.5.0"), semver.MustParse("2.5.0+qa")))
|
||||
assert.False(t, IsNewerIgnorePrerelease(semver.MustParse("2.5.0"), semver.MustParse("2.5.0-dev")))
|
||||
assert.False(t, IsNewerIgnorePrerelease(semver.MustParse("2.5.0"), semver.MustParse("2.5.0-dev+qa")))
|
||||
assert.False(t, IsNewerIgnorePrerelease(semver.MustParse("2.5.0+qa"), semver.MustParse("2.5.0-dev")))
|
||||
assert.False(t, IsNewerIgnorePrerelease(semver.MustParse("2.5.0-dev"), semver.MustParse("2.5.0+qa")))
|
||||
|
||||
// not older
|
||||
assert.True(t, IsNewerIgnorePrerelease(semver.MustParse("2.5.0"), semver.MustParse("2.4.9-dev+qa")))
|
||||
assert.True(t, IsNewerIgnorePrerelease(semver.MustParse("2.5.0-dev+qa"), semver.MustParse("2.4.9")))
|
||||
}
|
||||
|
||||
func TestListVersions(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user