diff --git a/src/commands/install.rs b/src/commands/install.rs index 7b37d1c..4a8f253 100644 --- a/src/commands/install.rs +++ b/src/commands/install.rs @@ -18,25 +18,33 @@ pub struct Install { pub version: Option, /// Install latest LTS - #[clap(long, conflicts_with = "version")] + #[clap(long, conflicts_with_all = &["version", "latest"])] pub lts: bool, + + /// Install latest version + #[clap(long, conflicts_with_all = &["version", "lts"])] + pub latest: bool, } impl Install { fn version(self) -> Result, Error> { match self { - Self { - version: Some(_), - lts: true, - } => Err(Error::TooManyVersionsProvided), Self { version: v, lts: false, + latest: false, } => Ok(v), Self { version: None, lts: true, + latest: false, } => Ok(Some(UserVersion::Full(Version::Lts(LtsType::Latest)))), + Self { + version: None, + lts: false, + latest: true, + } => Ok(Some(UserVersion::Full(Version::Latest))), + _ => Err(Error::TooManyVersionsProvided), } } } @@ -74,6 +82,20 @@ impl super::command::Command for Install { ); picked_version } + UserVersion::Full(Version::Latest) => { + let available_versions: Vec<_> = remote_node_index::list(&config.node_dist_mirror) + .map_err(|source| Error::CantListRemoteVersions { source })?; + let picked_version = available_versions.last() + .ok_or_else(|| Error::CantFindLatest)? + .version + .clone(); + debug!( + "Resolved {} into Node version {}", + Version::Latest.v_str().cyan(), + picked_version.v_str().cyan() + ); + picked_version + } current_version => { let available_versions: Vec<_> = remote_node_index::list(&config.node_dist_mirror) .map_err(|source| Error::CantListRemoteVersions { source })? @@ -153,6 +175,8 @@ pub enum Error { CantFindNodeVersion { requested_version: UserVersion }, #[error("Can't find relevant LTS named {}", lts_type)] CantFindRelevantLts { lts_type: crate::lts::LtsType }, + #[error("Can't find latest version")] + CantFindLatest, #[error("The requested version is not installable: {}", version.v_str())] UninstallableVersion { version: Version }, #[error("Too many versions provided. Please don't use --lts with a version string.")] @@ -175,6 +199,7 @@ mod tests { Install { version: UserVersion::from_str("12.0.0").ok(), lts: false, + latest: false, } .apply(&config) .expect("Can't install"); diff --git a/src/user_version.rs b/src/user_version.rs index 1e08618..bf1897e 100644 --- a/src/user_version.rs +++ b/src/user_version.rs @@ -41,7 +41,7 @@ impl UserVersion { } } } - (_, Version::Bypassed | Version::Lts(_) | Version::Alias(_)) => false, + (_, Version::Bypassed | Version::Lts(_) | Version::Alias(_) | Version::Latest) => false, (Self::OnlyMajor(major), Version::Semver(other)) => *major == other.major, (Self::MajorMinor(major, minor), Version::Semver(other)) => { *major == other.major && *minor == other.minor diff --git a/src/version.rs b/src/version.rs index b6c4a13..89d792f 100644 --- a/src/version.rs +++ b/src/version.rs @@ -9,6 +9,7 @@ pub enum Version { Semver(semver::Version), Lts(LtsType), Alias(String), + Latest, Bypassed, } @@ -58,7 +59,7 @@ impl Version { pub fn installation_path(&self, config: &config::FnmConfig) -> std::path::PathBuf { match self { Self::Bypassed => system_version::path(), - v @ (Self::Lts(_) | Self::Alias(_)) => { + v @ (Self::Lts(_) | Self::Alias(_) | Self::Latest) => { config.aliases_dir().join(v.alias_name().unwrap()) } v @ Self::Semver(_) => config @@ -93,6 +94,7 @@ impl std::fmt::Display for Version { Self::Lts(lts) => write!(f, "lts-{}", lts), Self::Semver(semver) => write!(f, "v{}", semver), Self::Alias(alias) => write!(f, "{}", alias), + Self::Latest => write!(f, "latest"), } } } @@ -107,7 +109,7 @@ impl FromStr for Version { impl PartialEq for Version { fn eq(&self, other: &semver::Version) -> bool { match self { - Self::Bypassed | Self::Lts(_) | Self::Alias(_) => false, + Self::Bypassed | Self::Lts(_) | Self::Alias(_) | Self::Latest => false, Self::Semver(v) => v == other, } }