-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a progress indicator for cargo clean
#10236
Changes from 1 commit
4d46ffb
9ab86fc
3e1a8ba
9b39df9
60cfe7e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ use crate::ops; | |
use crate::util::errors::CargoResult; | ||
use crate::util::interning::InternedString; | ||
use crate::util::lev_distance; | ||
use crate::util::Config; | ||
use crate::util::{Config, Progress, ProgressStyle}; | ||
|
||
use anyhow::Context as _; | ||
use cargo_util::paths; | ||
|
@@ -33,8 +33,9 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> { | |
|
||
// If the doc option is set, we just want to delete the doc directory. | ||
if opts.doc { | ||
let mut progress = Progress::with_style("Cleaning", ProgressStyle::Percentage, config); | ||
target_dir = target_dir.join("doc"); | ||
return rm_rf(&target_dir.into_path_unlocked(), config); | ||
return rm_rf_with_progress(&target_dir.into_path_unlocked(), &mut progress); | ||
} | ||
|
||
let profiles = Profiles::new(ws, opts.requested_profile)?; | ||
|
@@ -53,7 +54,8 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> { | |
// Note that we don't bother grabbing a lock here as we're just going to | ||
// blow it all away anyway. | ||
if opts.spec.is_empty() { | ||
return rm_rf(&target_dir.into_path_unlocked(), config); | ||
let mut progress = Progress::with_style("Cleaning", ProgressStyle::Percentage, config); | ||
return rm_rf_with_progress(&target_dir.into_path_unlocked(), &mut progress); | ||
} | ||
|
||
// Clean specific packages. | ||
|
@@ -133,8 +135,10 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> { | |
} | ||
let packages = pkg_set.get_many(pkg_ids)?; | ||
|
||
for pkg in packages { | ||
let mut progress = Progress::with_style("Cleaning", ProgressStyle::Ratio, config); | ||
for (pkg_idx, pkg) in packages.iter().enumerate() { | ||
let pkg_dir = format!("{}-*", pkg.name()); | ||
progress.tick_now(pkg_idx + 1, packages.len(), &format!(": {}", pkg.name()))?; | ||
|
||
// Clean fingerprints. | ||
for (_, layout) in &layouts_with_host { | ||
|
@@ -231,6 +235,25 @@ fn rm_rf_glob(pattern: &Path, config: &Config) -> CargoResult<()> { | |
Ok(()) | ||
} | ||
|
||
fn rm_rf_with_progress(path: &Path, progress: &mut Progress<'_>) -> CargoResult<()> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIT: Feel like |
||
let num_paths = walkdir::WalkDir::new(path).into_iter().count(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This naively seems like it would have a large impact and slow things down because we have to walk everything before actually removing everything. I don't have a great sense for the practical impact of this though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An alternative to this I think would be to perform the walk once, collect a list of all paths to remove, then remove them all in a loop. That would mean we only have to walk once and should be similar in performance I think. |
||
for (idx, entry) in walkdir::WalkDir::new(path) | ||
.contents_first(true) | ||
.into_iter() | ||
.enumerate() | ||
{ | ||
progress.tick(std::cmp::min(idx + 1, num_paths), num_paths, "")?; | ||
if let Ok(entry) = entry { | ||
if entry.file_type().is_dir() { | ||
paths::remove_dir(entry.path())?; | ||
} else { | ||
paths::remove_file(entry.path())?; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure but maybe keep the verbose There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops, updated so the verbose |
||
} | ||
} | ||
Ok(()) | ||
} | ||
|
||
fn rm_rf(path: &Path, config: &Config) -> CargoResult<()> { | ||
let m = fs::symlink_metadata(path); | ||
if m.as_ref().map(|s| s.is_dir()).unwrap_or(false) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if there is a package with lots of artifacts? I feel like it would still look like "get stuck"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would. I added a message listing of the # of files/folders cleaned so users can see that it isn't stuck.