1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-23 15:16:54 -05:00

feat(clean): add progress bar (#25026)

Closes https://github.com/denoland/deno/issues/25020
This commit is contained in:
Bartek Iwańczuk 2024-08-14 12:04:07 +01:00 committed by GitHub
parent 2f82873a88
commit b325bf0a35
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 132 additions and 18 deletions

View file

@ -157,6 +157,7 @@ tower-lsp.workspace = true
twox-hash.workspace = true
typed-arena = "=2.0.2"
uuid = { workspace = true, features = ["serde"] }
walkdir = "=2.3.2"
which.workspace = true
zeromq.workspace = true
zip = { version = "2.1.6", default-features = false, features = ["deflate-flate2"] }
@ -173,7 +174,6 @@ nix.workspace = true
deno_bench_util.workspace = true
pretty_assertions.workspace = true
test_util.workspace = true
walkdir = "=2.3.2"
[package.metadata.winres]
# This section defines the metadata that appears in the deno.exe PE header.

View file

@ -32,7 +32,6 @@ use crate::args::flags_from_vec;
use crate::args::DenoSubcommand;
use crate::args::Flags;
use crate::args::DENO_FUTURE;
use crate::cache::DenoDir;
use crate::graph_container::ModuleGraphContainer;
use crate::util::display;
use crate::util::v8::get_v8_flags_from_env;
@ -138,12 +137,7 @@ async fn run_subcommand(flags: Arc<Flags>) -> Result<i32, AnyError> {
.await
}),
DenoSubcommand::Clean => spawn_subcommand(async move {
let deno_dir = DenoDir::new(None)?;
if deno_dir.root.exists() {
std::fs::remove_dir_all(&deno_dir.root)?;
log::info!("{} {}", colors::green("Removed"), deno_dir.root.display());
}
Ok::<(), std::io::Error>(())
tools::clean::clean()
}),
DenoSubcommand::Compile(compile_flags) => spawn_subcommand(async {
tools::compile::compile(flags, compile_flags).await

97
cli/tools/clean.rs Normal file
View file

@ -0,0 +1,97 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::anyhow::Context;
use deno_core::error::AnyError;
use std::path::Path;
use crate::cache::DenoDir;
use crate::colors;
use crate::display;
use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
use crate::util::progress_bar::ProgressMessagePrompt;
use crate::util::progress_bar::UpdateGuard;
struct CleanState {
files_removed: u64,
dirs_removed: u64,
bytes_removed: u64,
progress_guard: UpdateGuard,
}
impl CleanState {
fn update_progress(&self) {
self
.progress_guard
.set_position(self.files_removed + self.dirs_removed);
}
}
pub fn clean() -> Result<(), AnyError> {
let deno_dir = DenoDir::new(None)?;
if deno_dir.root.exists() {
let no_of_files = walkdir::WalkDir::new(&deno_dir.root).into_iter().count();
let progress_bar = ProgressBar::new(ProgressBarStyle::ProgressBars);
let progress_guard =
progress_bar.update_with_prompt(ProgressMessagePrompt::Cleaning, "");
let mut state = CleanState {
files_removed: 0,
dirs_removed: 0,
bytes_removed: 0,
progress_guard,
};
state
.progress_guard
.set_total_size(no_of_files.try_into().unwrap());
rm_rf(&mut state, &deno_dir.root)?;
// Drop the guard so that progress bar disappears.
drop(state.progress_guard);
log::info!(
"{} {} {}",
colors::green("Removed"),
deno_dir.root.display(),
colors::gray(&format!(
"({} files, {})",
state.files_removed + state.dirs_removed,
display::human_size(state.bytes_removed as f64)
))
);
}
Ok(())
}
fn rm_rf(state: &mut CleanState, path: &Path) -> Result<(), AnyError> {
for entry in walkdir::WalkDir::new(path).contents_first(true) {
let entry = entry?;
if entry.file_type().is_dir() {
state.dirs_removed += 1;
state.update_progress();
std::fs::remove_dir_all(entry.path())?;
} else {
remove_file(state, entry.path(), entry.metadata().ok())?;
}
}
Ok(())
}
fn remove_file(
state: &mut CleanState,
path: &Path,
meta: Option<std::fs::Metadata>,
) -> Result<(), AnyError> {
if let Some(meta) = meta {
state.bytes_removed += meta.len();
}
state.files_removed += 1;
state.update_progress();
std::fs::remove_file(path)
.with_context(|| format!("Failed to remove file: {}", path.display()))?;
Ok(())
}

View file

@ -3,6 +3,7 @@
pub mod bench;
pub mod bundle;
pub mod check;
pub mod clean;
pub mod compile;
pub mod coverage;
pub mod doc;

View file

@ -28,6 +28,7 @@ pub enum ProgressMessagePrompt {
Download,
Blocking,
Initialize,
Cleaning,
}
impl ProgressMessagePrompt {
@ -38,6 +39,7 @@ impl ProgressMessagePrompt {
ProgressMessagePrompt::Initialize => {
colors::green("Initialize").to_string()
}
ProgressMessagePrompt::Cleaning => colors::green("Cleaning").to_string(),
}
}
}
@ -71,7 +73,13 @@ impl UpdateGuard {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProgressBarStyle {
/// Shows a progress bar with human readable download size
DownloadBars,
/// Shows a progress bar with numeric progres count
ProgressBars,
/// Shows a list of currently downloaded files.
TextOnly,
}
@ -270,7 +278,14 @@ impl ProgressBar {
Self {
inner: ProgressBarInner::new(match style {
ProgressBarStyle::DownloadBars => {
Arc::new(renderer::BarProgressBarRenderer)
Arc::new(renderer::BarProgressBarRenderer {
display_human_download_size: true,
})
}
ProgressBarStyle::ProgressBars => {
Arc::new(renderer::BarProgressBarRenderer {
display_human_download_size: false,
})
}
ProgressBarStyle::TextOnly => {
Arc::new(renderer::TextOnlyProgressBarRenderer::default())

View file

@ -34,7 +34,9 @@ pub trait ProgressBarRenderer: Send + Sync + std::fmt::Debug {
/// Indicatif style progress bar.
#[derive(Debug)]
pub struct BarProgressBarRenderer;
pub struct BarProgressBarRenderer {
pub display_human_download_size: bool,
}
impl ProgressBarRenderer for BarProgressBarRenderer {
fn render(&self, data: ProgressData) -> String {
@ -48,13 +50,16 @@ impl ProgressBarRenderer for BarProgressBarRenderer {
if total_size == 0 {
(String::new(), 0)
} else {
let total_size_str = human_download_size(total_size, total_size);
(
format!(
" {}/{}",
let (pos_str, total_size_str) = if self.display_human_download_size {
(
human_download_size(pos, total_size),
total_size_str,
),
human_download_size(total_size, total_size),
)
} else {
(pos.to_string(), total_size.to_string())
};
(
format!(" {}/{}", pos_str, total_size_str,),
2 + total_size_str.len() * 2,
)
}
@ -244,7 +249,9 @@ mod test {
#[test]
fn should_render_bar_progress() {
let renderer = BarProgressBarRenderer;
let renderer = BarProgressBarRenderer {
display_human_download_size: true,
};
let mut data = ProgressData {
display_entries: vec![ProgressDataDisplayEntry {
prompt: ProgressMessagePrompt::Download,

View file

@ -15,7 +15,7 @@
"output": "true\n"
}, {
"args": "clean",
"output": "Removed [WILDLINE]/deno_dir\n"
"output": "Removed [WILDLINE]/deno_dir ([WILDCARD]files, [WILDCARD])\n"
}, {
"envs": {
// use a new dir to avoid creating the old one