diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2024-08-14 12:04:07 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-14 13:04:07 +0200 |
commit | b325bf0a35baea1275f3be89506e34040bf35b21 (patch) | |
tree | 70708a25471f18b9ce0c2d83d76ca1b1d0fd60e4 /cli/tools/clean.rs | |
parent | 2f82873a88cbaea4ebe8e39b5aa7b57ed867512e (diff) |
feat(clean): add progress bar (#25026)
Closes https://github.com/denoland/deno/issues/25020
Diffstat (limited to 'cli/tools/clean.rs')
-rw-r--r-- | cli/tools/clean.rs | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/cli/tools/clean.rs b/cli/tools/clean.rs new file mode 100644 index 000000000..2a77434f8 --- /dev/null +++ b/cli/tools/clean.rs @@ -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(()) +} |