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:
parent
2f82873a88
commit
b325bf0a35
7 changed files with 132 additions and 18 deletions
|
@ -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.
|
||||
|
|
|
@ -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
97
cli/tools/clean.rs
Normal 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(())
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue