diff --git a/Cargo.toml b/Cargo.toml index ed0b32f..3dcc57c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nenv" -version = "0.1.0" +version = "0.2.0" edition = "2021" [lib] @@ -14,6 +14,7 @@ path = "src/main.rs" [dependencies] clap = { version = "4.1.1", features = ["derive"] } +color-eyre = "0.6.2" crossterm = "0.25.0" dialoguer = "0.10.3" dirs = "4.0.0" @@ -22,7 +23,7 @@ futures-util = "0.3.25" indicatif = "0.17.3" lazy_static = "1.4.0" libflate = "1.2.0" -miette = { version = "5.5.0", features = ["fancy"] } +miette = "5.5.0" reqwest = { version = "0.11.14", features = ["json", "stream"] } semver = { version = "1.0.16", features = ["std", "serde"] } serde = { version = "1.0.152", features = ["derive"] } diff --git a/src/args.rs b/src/args.rs index d32112e..5cddefc 100644 --- a/src/args.rs +++ b/src/args.rs @@ -28,6 +28,10 @@ pub enum Command { #[command()] Refresh, + /// Lists all available versions + #[command(name = "list-versions")] + ListVersions, + /// Executes the given version specific node executable #[command()] Exec(ExecArgs), diff --git a/src/lib.rs b/src/lib.rs index 122f868..28dce04 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,8 @@ use dialoguer::Confirm; use error::Result; use tokio::fs; +use crate::error::VersionError; + pub async fn install_version(version: NodeVersion) -> Result<()> { if VERSION_FILE_PATH.exists() { fs::remove_file(&*VERSION_FILE_PATH).await?; @@ -78,6 +80,37 @@ pub async fn refresh() -> Result<()> { Ok(()) } +pub async fn list_versions() -> Result<()> { + let mapper = get_mapper().await?; + let versions = mapper.repository().installed_versions().await?; + let active_version = mapper + .repository() + .lookup_version(mapper.active_version())?; + + println!("{}", "Installed versions:".bold()); + + for version in versions { + let info = mapper + .repository() + .all_versions() + .get(&version) + .ok_or_else(|| VersionError::UnkownVersion(version.to_string()))?; + let lts = info + .lts + .as_ref() + .map(|l| format!(" ({})", l.to_owned().green())) + .unwrap_or_default(); + + if version == active_version.version { + println!(" {}{} [current]", version.to_string().blue().bold(), lts) + } else { + println!(" {}{}", version.to_string().blue(), lts) + } + } + + Ok(()) +} + async fn get_repository() -> Result { Repository::init(Config::load().await?).await } diff --git a/src/main.rs b/src/main.rs index 6906238..fd783ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,7 @@ async fn main() -> miette::Result<()> { process::exit(exit_code); } args::Command::Refresh => nenv::refresh().await, + args::Command::ListVersions => nenv::list_versions().await, }?; Ok(()) diff --git a/src/repository/mod.rs b/src/repository/mod.rs index a685d74..1abbdf0 100644 --- a/src/repository/mod.rs +++ b/src/repository/mod.rs @@ -118,7 +118,7 @@ impl Repository { /// Returns the path for the given node version pub fn get_version_path(&self, version: &NodeVersion) -> LibResult> { - let info = self.parse_req(&version)?; + let info = self.lookup_version(&version)?; let path = build_version_path(&info.version); Ok(if path.exists() { @@ -144,14 +144,37 @@ impl Repository { /// Returns if the given version is installed pub fn is_installed(&self, version: &NodeVersion) -> LibResult { - let info = self.parse_req(version)?; + let info = self.lookup_version(version)?; Ok(build_version_path(&info.version).exists()) } + /// Performs a lookup for the given node version + pub fn lookup_version(&self, version_req: &NodeVersion) -> Result<&VersionInfo, VersionError> { + let version = match version_req { + NodeVersion::Latest => self.versions.latest(), + NodeVersion::LatestLts => self.versions.latest_lts(), + NodeVersion::Lts(lts) => self + .versions + .get_lts(<s) + .ok_or_else(|| VersionError::UnkownVersion(lts.to_owned()))?, + NodeVersion::Req(req) => self + .versions + .get_fulfilling(&req) + .ok_or_else(|| VersionError::Unfulfillable(req.to_owned()))?, + }; + + Ok(version) + } + + /// Returns the reference to all known versions + pub fn all_versions(&self) -> &Versions { + &self.versions + } + /// Installs a specified node version pub async fn install_version(&self, version_req: &NodeVersion) -> LibResult<()> { - let info = self.parse_req(&version_req)?; + let info = self.lookup_version(&version_req)?; let archive_path = self.download_version(&info.version).await?; self.extract_archive(info, &archive_path)?; @@ -178,23 +201,6 @@ impl Repository { Ok(()) } - - fn parse_req(&self, version_req: &NodeVersion) -> Result<&VersionInfo, VersionError> { - let version = match version_req { - NodeVersion::Latest => self.versions.latest(), - NodeVersion::LatestLts => self.versions.latest_lts(), - NodeVersion::Lts(lts) => self - .versions - .get_lts(<s) - .ok_or_else(|| VersionError::UnkownVersion(lts.to_owned()))?, - NodeVersion::Req(req) => self - .versions - .get_fulfilling(&req) - .ok_or_else(|| VersionError::Unfulfillable(req.to_owned()))?, - }; - - Ok(version) - } } #[inline] diff --git a/src/repository/versions.rs b/src/repository/versions.rs index c9568a3..eb6716b 100644 --- a/src/repository/versions.rs +++ b/src/repository/versions.rs @@ -95,4 +95,9 @@ impl Versions { self.versions.get(fulfilling_versions.last()?) } + + /// Returns the info for the given version + pub fn get(&self, version: &Version) -> Option<&VersionInfo> { + self.versions.get(version) + } }