Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
5 changes: 5 additions & 0 deletions .changeset/warm-rice-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"fnm": minor
---

support `fnm install --latest` to install the latest Node.js version
2 changes: 1 addition & 1 deletion .ci/prepare-version.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const command = cmd.command({
async handler({}) {
updateCargoToml(await getPackageVersion())
exec("cargo build --release")
exec("yarn generate-command-docs --binary-path=./target/release/fnm")
exec("pnpm generate-command-docs --binary-path=./target/release/fnm")
exec("./.ci/record_screen.sh")
},
})
Expand Down
4 changes: 2 additions & 2 deletions .ci/print-command-docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const command = cmd.command({
if (gitStatus.state === "dirty") {
process.exitCode = 1
console.error(
"The file has changed. Please re-run `yarn generate-command-docs`."
"The file has changed. Please re-run `pnpm generate-command-docs`."
)
console.error(`hint: The following diff was found:`)
console.error()
Expand Down Expand Up @@ -76,7 +76,7 @@ async function main(targetFile, fnmPath) {

stream.close()

await execa(`yarn`, ["prettier", "--write", targetFile])
await execa(`pnpm`, ["prettier", "--write", targetFile])
}

/**
Expand Down
3 changes: 3 additions & 0 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,9 @@ OPTIONS:
-h, --help
Print help information

--latest
Install latest version

--log-level <LOG_LEVEL>
The log level of fnm commands

Expand Down
63 changes: 58 additions & 5 deletions src/commands/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,33 @@ pub struct Install {
pub version: Option<UserVersion>,

/// 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<Option<UserVersion>, 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),
}
}
}
Expand Down Expand Up @@ -74,6 +82,21 @@ 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(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 })?
Expand Down Expand Up @@ -153,6 +176,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 any versions in the upstream version index.")]
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.")]
Expand All @@ -175,6 +200,7 @@ mod tests {
Install {
version: UserVersion::from_str("12.0.0").ok(),
lts: false,
latest: false,
}
.apply(&config)
.expect("Can't install");
Expand All @@ -190,4 +216,31 @@ mod tests {
.ok()
);
}

#[test]
fn test_install_latest() {
let base_dir = tempfile::tempdir().unwrap();
let config = FnmConfig::default().with_base_dir(Some(base_dir.path().to_path_buf()));

Install {
version: None,
lts: false,
latest: true,
}
.apply(&config)
.expect("Can't install");

let available_versions: Vec<_> =
remote_node_index::list(&config.node_dist_mirror).expect("Can't get node version list");
let latest_version = available_versions.last().unwrap().version.clone();

assert!(config.installations_dir().exists());
assert!(config
.installations_dir()
.join(latest_version.to_string())
.join("installation")
.canonicalize()
.unwrap()
.exists());
}
}
2 changes: 1 addition & 1 deletion src/user_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions src/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub enum Version {
Semver(semver::Version),
Lts(LtsType),
Alias(String),
Latest,
Bypassed,
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"),
}
}
}
Expand All @@ -107,7 +109,7 @@ impl FromStr for Version {
impl PartialEq<semver::Version> 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,
}
}
Expand Down