Improve performance

feature/lookup-installed
trivernis 2 years ago
parent 8d304a7169
commit 1a3811d81b
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -19,7 +19,7 @@ pub async fn install_version(version: NodeVersion) -> Result<()> {
fs::remove_file(&*VERSION_FILE_PATH).await?; fs::remove_file(&*VERSION_FILE_PATH).await?;
let repo = get_repository().await?; let repo = get_repository().await?;
if repo.is_installed(&version).await? { if repo.is_installed(&version) {
if !Confirm::new() if !Confirm::new()
.with_prompt("The version {version} is already installed. Reinstall?") .with_prompt("The version {version} is already installed. Reinstall?")
.default(false) .default(false)
@ -38,7 +38,7 @@ pub async fn install_version(version: NodeVersion) -> Result<()> {
pub async fn set_default_version(version: NodeVersion) -> Result<()> { pub async fn set_default_version(version: NodeVersion) -> Result<()> {
let mut mapper = get_mapper().await?; let mut mapper = get_mapper().await?;
if !mapper.repository().is_installed(&version).await? if !mapper.repository().is_installed(&version)
&& Confirm::new() && Confirm::new()
.with_prompt(format!( .with_prompt(format!(
"The version {version} is not installed. Do you want to install it?" "The version {version} is not installed. Do you want to install it?"
@ -56,11 +56,12 @@ pub async fn set_default_version(version: NodeVersion) -> Result<()> {
Ok(()) Ok(())
} }
#[inline]
pub async fn exec(command: String, args: Vec<OsString>) -> Result<i32> { pub async fn exec(command: String, args: Vec<OsString>) -> Result<i32> {
let mapper = get_mapper().await?; let mapper = get_mapper().await?;
let active_version = mapper.active_version(); let active_version = mapper.active_version();
if !mapper.repository().is_installed(active_version).await? { if !mapper.repository().is_installed(active_version) {
mapper.repository().install_version(&active_version).await?; mapper.repository().install_version(&active_version).await?;
} }
let exit_status = mapper.exec(command, args).await?; let exit_status = mapper.exec(command, args).await?;

@ -9,6 +9,7 @@ mod args;
async fn main() -> nenv::error::Result<()> { async fn main() -> nenv::error::Result<()> {
color_eyre::install().unwrap(); color_eyre::install().unwrap();
let args: Args = Args::parse(); let args: Args = Args::parse();
match args.commmand { match args.commmand {
args::Command::Version => Ok(print_version()), args::Command::Version => Ok(print_version()),
args::Command::Install(v) => nenv::install_version(v.version).await, args::Command::Install(v) => nenv::install_version(v.version).await,

@ -58,11 +58,9 @@ impl Mapper {
/// Executes a mapped command with the given node environment /// Executes a mapped command with the given node environment
pub async fn exec(&self, command: String, args: Vec<OsString>) -> LibResult<ExitStatus> { pub async fn exec(&self, command: String, args: Vec<OsString>) -> LibResult<ExitStatus> {
self.map_active_version().await?;
let node_path = self let node_path = self
.repo .repo
.get_version_path(&self.active_version) .get_version_path(&self.active_version)
.await?
.expect("version not installed"); .expect("version not installed");
let executable = node_path.bin().join(command); let executable = node_path.bin().join(command);
let exit_status = MappedCommand::new(executable, args) let exit_status = MappedCommand::new(executable, args)
@ -104,7 +102,6 @@ impl Mapper {
let dir = self let dir = self
.repo .repo
.get_version_path(&self.active_version) .get_version_path(&self.active_version)
.await?
.expect("missing version"); .expect("missing version");
map_node_bin(dir).await?; map_node_bin(dir).await?;

@ -90,15 +90,7 @@ impl Repository {
pub async fn init(config: Config) -> LibResult<Self> { pub async fn init(config: Config) -> LibResult<Self> {
Self::create_folders().await?; Self::create_folders().await?;
let web_api = WebApi::new(&config.dist_base_url); let web_api = WebApi::new(&config.dist_base_url);
let versions = load_versions(&web_api).await?;
let versions = if let Some(v) = Versions::load().await {
v
} else {
let all_versions = web_api.get_versions().await?;
let v = Versions::new(all_versions);
v.save().await?;
v
};
Ok(Self { Ok(Self {
config, config,
@ -125,24 +117,15 @@ impl Repository {
} }
/// Returns the path for the given node version /// Returns the path for the given node version
pub async fn get_version_path(&self, version: &NodeVersion) -> LibResult<Option<NodePath>> { pub fn get_version_path(&self, version: &NodeVersion) -> Option<NodePath> {
let info = self.parse_req(&version); let info = self.parse_req(&version);
let mut iter = fs::read_dir(&*NODE_VERSIONS_DIR).await?; let path = build_version_path(&info.version);
let mut path = None;
while let Some(entry) = iter.next_entry().await? { if path.exists() {
if let Ok(version) = Version::parse(entry.file_name().to_string_lossy().as_ref()) { Some(NodePath::new(path))
if version == info.version { } else {
path = Some(entry.path()); None
}
};
} }
let Some(path) = path else {
return Ok(None);
};
let path = path.join(format!("node-v{}-{}-{}", info.version, OS, ARCH));
Ok(Some(NodePath::new(path)))
} }
/// Returns a list of installed versions /// Returns a list of installed versions
@ -160,10 +143,10 @@ impl Repository {
} }
/// Returns if the given version is installed /// Returns if the given version is installed
pub async fn is_installed(&self, version: &NodeVersion) -> LibResult<bool> { pub fn is_installed(&self, version: &NodeVersion) -> bool {
let info = self.parse_req(version); let info = self.parse_req(version);
Ok(self.installed_versions().await?.contains(&info.version)) build_version_path(&info.version).exists()
} }
/// Installs a specified node version /// Installs a specified node version
@ -208,3 +191,22 @@ impl Repository {
} }
} }
} }
#[inline]
async fn load_versions(web_api: &WebApi) -> Result<Versions, crate::error::Error> {
let versions = if let Some(v) = Versions::load().await {
v
} else {
let all_versions = web_api.get_versions().await?;
let v = Versions::new(all_versions);
v.save().await?;
v
};
Ok(versions)
}
fn build_version_path(version: &Version) -> PathBuf {
NODE_VERSIONS_DIR
.join(version.to_string())
.join(format!("node-v{}-{}-{}", version, OS, ARCH))
}

@ -10,6 +10,7 @@ use crate::{consts::VERSION_FILE_PATH, error::LibResult, web_api::VersionInfo};
pub struct Versions { pub struct Versions {
lts_versions: HashMap<String, VersionReq>, lts_versions: HashMap<String, VersionReq>,
versions: HashMap<Version, VersionInfo>, versions: HashMap<Version, VersionInfo>,
sorted_versions: Vec<Version>,
} }
impl Versions { impl Versions {
@ -35,6 +36,12 @@ impl Versions {
)) ))
}) })
.collect::<HashMap<_, _>>(); .collect::<HashMap<_, _>>();
let mut sorted_versions = all_versions
.iter()
.map(|v| v.version.to_owned())
.collect::<Vec<_>>();
sorted_versions.sort();
let versions = all_versions let versions = all_versions
.into_iter() .into_iter()
.map(|v| (v.version.to_owned(), v)) .map(|v| (v.version.to_owned(), v))
@ -43,6 +50,7 @@ impl Versions {
Self { Self {
lts_versions, lts_versions,
versions, versions,
sorted_versions,
} }
} }
@ -55,11 +63,8 @@ impl Versions {
/// Returns the latest known node version /// Returns the latest known node version
pub fn latest(&self) -> &VersionInfo { pub fn latest(&self) -> &VersionInfo {
let mut versions = self.versions.keys().collect::<Vec<_>>();
versions.sort();
self.versions self.versions
.get(versions.last().expect("No known node versions")) .get(self.sorted_versions.last().expect("No known node versions"))
.unwrap() .unwrap()
} }
@ -82,13 +87,12 @@ impl Versions {
/// Returns any version that fulfills the given requirement /// Returns any version that fulfills the given requirement
pub fn get_fulfilling(&self, req: &VersionReq) -> Option<&VersionInfo> { pub fn get_fulfilling(&self, req: &VersionReq) -> Option<&VersionInfo> {
let mut versions = self let fulfilling_versions = self
.versions .sorted_versions
.keys() .iter()
.filter(|v| req.matches(v)) .filter(|v| req.matches(v))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
versions.sort();
self.versions.get(versions.last()?) self.versions.get(fulfilling_versions.last()?)
} }
} }

@ -3,7 +3,10 @@ use std::{
fmt::{Debug, Display}, fmt::{Debug, Display},
}; };
use crate::{consts::NODE_ARCHIVE_SUFFIX, utils::progress_bar}; use crate::{
consts::{NODE_ARCHIVE_SUFFIX, NODE_DIST_URL},
utils::progress_bar,
};
use self::error::{ApiError, ApiResult}; use self::error::{ApiError, ApiResult};
@ -26,7 +29,7 @@ pub struct WebApi {
impl Default for WebApi { impl Default for WebApi {
fn default() -> Self { fn default() -> Self {
Self::new("https://nodejs.org/dist") Self::new(NODE_DIST_URL)
} }
} }

Loading…
Cancel
Save