Skip to content

Commit 9ab86fc

Browse files
committed
Print the bar in verbose mode, keep count of the number of cleaned files
1 parent 4d46ffb commit 9ab86fc

File tree

1 file changed

+131
-47
lines changed

1 file changed

+131
-47
lines changed

src/cargo/ops/cargo_clean.rs

Lines changed: 131 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,8 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
3333

3434
// If the doc option is set, we just want to delete the doc directory.
3535
if opts.doc {
36-
let mut progress = Progress::with_style("Cleaning", ProgressStyle::Percentage, config);
3736
target_dir = target_dir.join("doc");
38-
return rm_rf_with_progress(&target_dir.into_path_unlocked(), &mut progress);
37+
return clean_entire_folder(&target_dir.into_path_unlocked(), &config);
3938
}
4039

4140
let profiles = Profiles::new(ws, opts.requested_profile)?;
@@ -54,8 +53,7 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
5453
// Note that we don't bother grabbing a lock here as we're just going to
5554
// blow it all away anyway.
5655
if opts.spec.is_empty() {
57-
let mut progress = Progress::with_style("Cleaning", ProgressStyle::Percentage, config);
58-
return rm_rf_with_progress(&target_dir.into_path_unlocked(), &mut progress);
56+
return clean_entire_folder(&target_dir.into_path_unlocked(), &config);
5957
}
6058

6159
// Clean specific packages.
@@ -135,23 +133,23 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
135133
}
136134
let packages = pkg_set.get_many(pkg_ids)?;
137135

138-
let mut progress = Progress::with_style("Cleaning", ProgressStyle::Ratio, config);
139-
for (pkg_idx, pkg) in packages.iter().enumerate() {
136+
let mut progress = CleaningPackagesBar::new(config, packages.len());
137+
for pkg in packages {
140138
let pkg_dir = format!("{}-*", pkg.name());
141-
progress.tick_now(pkg_idx + 1, packages.len(), &format!(": {}", pkg.name()))?;
139+
progress.on_cleaning_package(&pkg.name())?;
142140

143141
// Clean fingerprints.
144142
for (_, layout) in &layouts_with_host {
145143
let dir = escape_glob_path(layout.fingerprint())?;
146-
rm_rf_glob(&Path::new(&dir).join(&pkg_dir), config)?;
144+
rm_rf_glob(&Path::new(&dir).join(&pkg_dir), config, &mut progress)?;
147145
}
148146

149147
for target in pkg.targets() {
150148
if target.is_custom_build() {
151149
// Get both the build_script_build and the output directory.
152150
for (_, layout) in &layouts_with_host {
153151
let dir = escape_glob_path(layout.build())?;
154-
rm_rf_glob(&Path::new(&dir).join(&pkg_dir), config)?;
152+
rm_rf_glob(&Path::new(&dir).join(&pkg_dir), config, &mut progress)?;
155153
}
156154
continue;
157155
}
@@ -182,33 +180,33 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
182180
let dir_glob = escape_glob_path(dir)?;
183181
let dir_glob = Path::new(&dir_glob);
184182

185-
rm_rf_glob(&dir_glob.join(&hashed_name), config)?;
186-
rm_rf(&dir.join(&unhashed_name), config)?;
183+
rm_rf_glob(&dir_glob.join(&hashed_name), config, &mut progress)?;
184+
rm_rf(&dir.join(&unhashed_name), config, &mut progress)?;
187185
// Remove dep-info file generated by rustc. It is not tracked in
188186
// file_types. It does not have a prefix.
189187
let hashed_dep_info = dir_glob.join(format!("{}-*.d", crate_name));
190-
rm_rf_glob(&hashed_dep_info, config)?;
188+
rm_rf_glob(&hashed_dep_info, config, &mut progress)?;
191189
let unhashed_dep_info = dir.join(format!("{}.d", crate_name));
192-
rm_rf(&unhashed_dep_info, config)?;
190+
rm_rf(&unhashed_dep_info, config, &mut progress)?;
193191
// Remove split-debuginfo files generated by rustc.
194192
let split_debuginfo_obj = dir_glob.join(format!("{}.*.o", crate_name));
195-
rm_rf_glob(&split_debuginfo_obj, config)?;
193+
rm_rf_glob(&split_debuginfo_obj, config, &mut progress)?;
196194
let split_debuginfo_dwo = dir_glob.join(format!("{}.*.dwo", crate_name));
197-
rm_rf_glob(&split_debuginfo_dwo, config)?;
195+
rm_rf_glob(&split_debuginfo_dwo, config, &mut progress)?;
198196

199197
// Remove the uplifted copy.
200198
if let Some(uplift_dir) = uplift_dir {
201199
let uplifted_path = uplift_dir.join(file_type.uplift_filename(target));
202-
rm_rf(&uplifted_path, config)?;
200+
rm_rf(&uplifted_path, config, &mut progress)?;
203201
// Dep-info generated by Cargo itself.
204202
let dep_info = uplifted_path.with_extension("d");
205-
rm_rf(&dep_info, config)?;
203+
rm_rf(&dep_info, config, &mut progress)?;
206204
}
207205
}
208206
// TODO: what to do about build_script_build?
209207
let dir = escape_glob_path(layout.incremental())?;
210208
let incremental = Path::new(&dir).join(format!("{}-*", crate_name));
211-
rm_rf_glob(&incremental, config)?;
209+
rm_rf_glob(&incremental, config, &mut progress)?;
212210
}
213211
}
214212
}
@@ -224,48 +222,134 @@ fn escape_glob_path(pattern: &Path) -> CargoResult<String> {
224222
Ok(glob::Pattern::escape(pattern))
225223
}
226224

227-
fn rm_rf_glob(pattern: &Path, config: &Config) -> CargoResult<()> {
225+
fn rm_rf_glob(
226+
pattern: &Path,
227+
config: &Config,
228+
progress: &mut impl CleaningProgressBar,
229+
) -> CargoResult<()> {
228230
// TODO: Display utf8 warning to user? Or switch to globset?
229231
let pattern = pattern
230232
.to_str()
231233
.ok_or_else(|| anyhow::anyhow!("expected utf-8 path"))?;
232234
for path in glob::glob(pattern)? {
233-
rm_rf(&path?, config)?;
235+
rm_rf(&path?, config, progress)?;
234236
}
235237
Ok(())
236238
}
237239

238-
fn rm_rf_with_progress(path: &Path, progress: &mut Progress<'_>) -> CargoResult<()> {
239-
let num_paths = walkdir::WalkDir::new(path).into_iter().count();
240-
for (idx, entry) in walkdir::WalkDir::new(path)
241-
.contents_first(true)
242-
.into_iter()
243-
.enumerate()
244-
{
245-
progress.tick(std::cmp::min(idx + 1, num_paths), num_paths, "")?;
246-
if let Ok(entry) = entry {
247-
if entry.file_type().is_dir() {
248-
paths::remove_dir(entry.path())?;
249-
} else {
250-
paths::remove_file(entry.path())?;
251-
}
240+
fn rm_rf(path: &Path, config: &Config, progress: &mut impl CleaningProgressBar) -> CargoResult<()> {
241+
if fs::symlink_metadata(path).is_err() {
242+
return Ok(());
243+
}
244+
245+
config
246+
.shell()
247+
.verbose(|shell| shell.status("Removing", path.display()))?;
248+
progress.display_now()?;
249+
250+
for entry in walkdir::WalkDir::new(path).contents_first(true) {
251+
let entry = entry?;
252+
progress.on_clean()?;
253+
if entry.file_type().is_dir() {
254+
paths::remove_dir(entry.path()).with_context(|| "could not remove build directory")?;
255+
} else {
256+
paths::remove_file(entry.path()).with_context(|| "failed to remove build artifact")?;
252257
}
253258
}
259+
254260
Ok(())
255261
}
256262

257-
fn rm_rf(path: &Path, config: &Config) -> CargoResult<()> {
258-
let m = fs::symlink_metadata(path);
259-
if m.as_ref().map(|s| s.is_dir()).unwrap_or(false) {
260-
config
261-
.shell()
262-
.verbose(|shell| shell.status("Removing", path.display()))?;
263-
paths::remove_dir_all(path).with_context(|| "could not remove build directory")?;
264-
} else if m.is_ok() {
265-
config
266-
.shell()
267-
.verbose(|shell| shell.status("Removing", path.display()))?;
268-
paths::remove_file(path).with_context(|| "failed to remove build artifact")?;
263+
fn clean_entire_folder(path: &Path, config: &Config) -> CargoResult<()> {
264+
let num_paths = walkdir::WalkDir::new(path).into_iter().count();
265+
let mut progress = CleaningFolderBar::new(config, num_paths);
266+
rm_rf(path, config, &mut progress)
267+
}
268+
269+
trait CleaningProgressBar {
270+
fn display_now(&mut self) -> CargoResult<()>;
271+
fn on_clean(&mut self) -> CargoResult<()>;
272+
}
273+
274+
struct CleaningFolderBar<'cfg> {
275+
bar: Progress<'cfg>,
276+
max: usize,
277+
cur: usize,
278+
}
279+
280+
impl<'cfg> CleaningFolderBar<'cfg> {
281+
fn new(cfg: &'cfg Config, max: usize) -> Self {
282+
Self {
283+
bar: Progress::with_style("Cleaning", ProgressStyle::Percentage, cfg),
284+
max,
285+
cur: 0,
286+
}
287+
}
288+
289+
fn cur_progress(&self) -> usize {
290+
std::cmp::min(self.cur, self.max)
291+
}
292+
}
293+
294+
impl<'cfg> CleaningProgressBar for CleaningFolderBar<'cfg> {
295+
fn display_now(&mut self) -> CargoResult<()> {
296+
self.bar.tick_now(self.cur_progress(), self.max, "")
297+
}
298+
299+
fn on_clean(&mut self) -> CargoResult<()> {
300+
self.cur += 1;
301+
self.bar.tick(self.cur_progress(), self.max, "")
302+
}
303+
}
304+
305+
struct CleaningPackagesBar<'cfg> {
306+
bar: Progress<'cfg>,
307+
max: usize,
308+
cur: usize,
309+
num_files_folders_cleaned: usize,
310+
package_being_cleaned: String,
311+
}
312+
313+
impl<'cfg> CleaningPackagesBar<'cfg> {
314+
fn new(cfg: &'cfg Config, max: usize) -> Self {
315+
Self {
316+
bar: Progress::with_style("Cleaning", ProgressStyle::Ratio, cfg),
317+
max,
318+
cur: 0,
319+
num_files_folders_cleaned: 0,
320+
package_being_cleaned: String::new(),
321+
}
322+
}
323+
324+
fn on_cleaning_package(&mut self, package: &str) -> CargoResult<()> {
325+
self.cur += 1;
326+
self.package_being_cleaned = String::from(package);
327+
self.bar
328+
.tick(self.cur_progress(), self.max, &self.format_message())
329+
}
330+
331+
fn cur_progress(&self) -> usize {
332+
std::cmp::min(self.cur, self.max)
333+
}
334+
335+
fn format_message(&self) -> String {
336+
format!(
337+
": {}, {} files/folders cleaned",
338+
self.package_being_cleaned, self.num_files_folders_cleaned
339+
)
340+
}
341+
}
342+
343+
impl<'cfg> CleaningProgressBar for CleaningPackagesBar<'cfg> {
344+
fn display_now(&mut self) -> CargoResult<()> {
345+
self.bar
346+
.tick_now(self.cur_progress(), self.max, &self.format_message())
347+
}
348+
349+
fn on_clean(&mut self) -> CargoResult<()> {
350+
self.bar
351+
.tick(self.cur_progress(), self.max, &self.format_message())?;
352+
self.num_files_folders_cleaned += 1;
353+
Ok(())
269354
}
270-
Ok(())
271355
}

0 commit comments

Comments
 (0)