diff --git a/crates/plugins/src/manager.rs b/crates/plugins/src/manager.rs index cc7623accb..b9c1bfa2d2 100644 --- a/crates/plugins/src/manager.rs +++ b/crates/plugins/src/manager.rs @@ -12,6 +12,7 @@ use reqwest::{header::HeaderMap, Client}; use serde::Serialize; use spin_common::sha256; use std::{ + cmp::Ordering, fs::{self, File}, io::{copy, Cursor}, path::{Path, PathBuf}, @@ -173,7 +174,9 @@ impl PluginManager { name: plugin_manifest.name(), version: installed.version, }); - } else if installed.version > plugin_manifest.version && !allow_downgrades { + } else if installed.compare_versions(plugin_manifest) == Some(Ordering::Greater) + && !allow_downgrades + { bail!( "Newer version {} of plugin '{}' is already installed. To downgrade to version {}, run `spin plugins upgrade` with the `--downgrade` flag.", installed.version, diff --git a/crates/plugins/src/manifest.rs b/crates/plugins/src/manifest.rs index fdbb1b00bc..b81b5277be 100644 --- a/crates/plugins/src/manifest.rs +++ b/crates/plugins/src/manifest.rs @@ -70,6 +70,16 @@ impl PluginManifest { pub fn try_version(&self) -> Result { semver::Version::parse(&self.version) } + + // Compares the versions. Returns None if either's version string is invalid semver. + pub fn compare_versions(&self, other: &Self) -> Option { + if let Ok(this_version) = self.try_version() { + if let Ok(other_version) = other.try_version() { + return Some(this_version.cmp_precedence(&other_version)); + } + } + None + } } /// Describes compatibility and location of a plugin source.