Skip to content

Commit

Permalink
Add progress bar to install command (#1028)
Browse files Browse the repository at this point in the history
  • Loading branch information
eblocha committed May 25, 2024
1 parent 8f3acbb commit 66efc5b
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .changeset/show-download-progress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"fnm": minor
---

Show a progress bar when downloading and extracting node
74 changes: 72 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ sysinfo = "0.29.3"
thiserror = "1.0.44"
clap_complete = "4.3.1"
anyhow = "1.0.71"
indicatif = "0.17.6"

[dev-dependencies]
pretty_assertions = "1.4.0"
duct = "0.13.6"
test-log = "0.2.12"
http = "0.2.9"

[build-dependencies]
embed-resource = "1.8.0"
Expand Down
3 changes: 3 additions & 0 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ Options:
--latest
Install latest version
--no-progress
Do not display a progress bar
--log-level <LOG_LEVEL>
The log level of fnm commands
Expand Down
13 changes: 13 additions & 0 deletions src/commands/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::alias::create_alias;
use crate::arch::get_safe_arch;
use crate::config::FnmConfig;
use crate::downloader::{install_node_dist, Error as DownloaderError};
use crate::log_level::LogLevel;
use crate::lts::LtsType;
use crate::outln;
use crate::remote_node_index;
Expand All @@ -25,6 +26,10 @@ pub struct Install {
/// Install latest version
#[clap(long, conflicts_with_all = &["version", "lts"])]
pub latest: bool,

/// Do not display a progress bar
#[clap(long)]
pub no_progress: bool,
}

impl Install {
Expand All @@ -34,16 +39,19 @@ impl Install {
version: v,
lts: false,
latest: false,
no_progress: _,
} => Ok(v),
Self {
version: None,
lts: true,
latest: false,
no_progress: _,
} => Ok(Some(UserVersion::Full(Version::Lts(LtsType::Latest)))),
Self {
version: None,
lts: false,
latest: true,
no_progress: _,
} => Ok(Some(UserVersion::Full(Version::Latest))),
_ => Err(Error::TooManyVersionsProvided),
}
Expand All @@ -56,6 +64,8 @@ impl Command for Install {
fn apply(self, config: &FnmConfig) -> Result<(), Self::Error> {
let current_dir = std::env::current_dir().unwrap();

let show_progress = !self.no_progress && config.log_level().is_writable(&LogLevel::Info);

let current_version = self
.version()?
.or_else(|| get_user_version_for_directory(current_dir, config))
Expand Down Expand Up @@ -131,6 +141,7 @@ impl Command for Install {
&config.node_dist_mirror,
config.installations_dir(),
safe_arch,
show_progress,
) {
Err(err @ DownloaderError::VersionAlreadyInstalled { .. }) => {
outln!(config, Error, "{} {}", "warning:".bold().yellow(), err);
Expand Down Expand Up @@ -225,6 +236,7 @@ mod tests {
version: UserVersion::from_str("12.0.0").ok(),
lts: false,
latest: false,
no_progress: true,
}
.apply(&config)
.expect("Can't install");
Expand All @@ -250,6 +262,7 @@ mod tests {
version: None,
lts: false,
latest: true,
no_progress: true,
}
.apply(&config)
.expect("Can't install");
Expand Down
21 changes: 15 additions & 6 deletions src/downloader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ use crate::arch::Arch;
use crate::archive;
use crate::archive::{Error as ExtractError, Extract};
use crate::directory_portal::DirectoryPortal;
use crate::progress::ResponseProgress;
use crate::version::Version;
use indicatif::ProgressDrawTarget;
use log::debug;
use std::io::Read;
use std::path::Path;
use std::path::PathBuf;
use thiserror::Error;
Expand Down Expand Up @@ -63,10 +66,7 @@ fn download_url(base_url: &Url, version: &Version, arch: &Arch) -> Url {
.unwrap()
}

pub fn extract_archive_into<P: AsRef<Path>>(
path: P,
response: crate::http::Response,
) -> Result<(), Error> {
fn extract_archive_into(path: impl AsRef<Path>, response: impl Read) -> Result<(), Error> {
#[cfg(unix)]
let extractor = archive::TarXz::new(response);
#[cfg(windows)]
Expand All @@ -81,6 +81,7 @@ pub fn install_node_dist<P: AsRef<Path>>(
node_dist_mirror: &Url,
installations_dir: P,
arch: &Arch,
show_progress: bool,
) -> Result<(), Error> {
let installation_dir = PathBuf::from(installations_dir.as_ref()).join(version.v_str());

Expand Down Expand Up @@ -109,7 +110,14 @@ pub fn install_node_dist<P: AsRef<Path>>(
}

debug!("Extracting response...");
extract_archive_into(&portal, response)?;
if show_progress {
extract_archive_into(
&portal,
ResponseProgress::new(response, ProgressDrawTarget::stderr()),
)?;
} else {
extract_archive_into(&portal, response)?;
}
debug!("Extraction completed");

let installed_directory = std::fs::read_dir(&portal)?
Expand Down Expand Up @@ -171,7 +179,8 @@ mod tests {
let version = Version::parse("12.0.0").unwrap();
let arch = Arch::X64;
let node_dist_mirror = Url::parse("https://nodejs.org/dist/").unwrap();
install_node_dist(&version, &node_dist_mirror, path, &arch).expect("Can't install Node 12");
install_node_dist(&version, &node_dist_mirror, path, &arch, false)
.expect("Can't install Node 12");

let mut location_path = path.join(version.v_str()).join("installation");

Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ mod installed_versions;
mod lts;
mod package_json;
mod path_ext;
mod progress;
mod remote_node_index;
mod shell;
mod system_info;
Expand Down
Loading

0 comments on commit 66efc5b

Please sign in to comment.