@@ -33,9 +33,8 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
33
33
34
34
// If the doc option is set, we just want to delete the doc directory.
35
35
if opts. doc {
36
- let mut progress = Progress :: with_style ( "Cleaning" , ProgressStyle :: Percentage , config) ;
37
36
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 ) ;
39
38
}
40
39
41
40
let profiles = Profiles :: new ( ws, opts. requested_profile ) ?;
@@ -54,8 +53,7 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
54
53
// Note that we don't bother grabbing a lock here as we're just going to
55
54
// blow it all away anyway.
56
55
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) ;
59
57
}
60
58
61
59
// Clean specific packages.
@@ -135,23 +133,23 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
135
133
}
136
134
let packages = pkg_set. get_many ( pkg_ids) ?;
137
135
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 {
140
138
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 ( ) ) ?;
142
140
143
141
// Clean fingerprints.
144
142
for ( _, layout) in & layouts_with_host {
145
143
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 ) ?;
147
145
}
148
146
149
147
for target in pkg. targets ( ) {
150
148
if target. is_custom_build ( ) {
151
149
// Get both the build_script_build and the output directory.
152
150
for ( _, layout) in & layouts_with_host {
153
151
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 ) ?;
155
153
}
156
154
continue ;
157
155
}
@@ -182,33 +180,33 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
182
180
let dir_glob = escape_glob_path ( dir) ?;
183
181
let dir_glob = Path :: new ( & dir_glob) ;
184
182
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 ) ?;
187
185
// Remove dep-info file generated by rustc. It is not tracked in
188
186
// file_types. It does not have a prefix.
189
187
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 ) ?;
191
189
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 ) ?;
193
191
// Remove split-debuginfo files generated by rustc.
194
192
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 ) ?;
196
194
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 ) ?;
198
196
199
197
// Remove the uplifted copy.
200
198
if let Some ( uplift_dir) = uplift_dir {
201
199
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 ) ?;
203
201
// Dep-info generated by Cargo itself.
204
202
let dep_info = uplifted_path. with_extension ( "d" ) ;
205
- rm_rf ( & dep_info, config) ?;
203
+ rm_rf ( & dep_info, config, & mut progress ) ?;
206
204
}
207
205
}
208
206
// TODO: what to do about build_script_build?
209
207
let dir = escape_glob_path ( layout. incremental ( ) ) ?;
210
208
let incremental = Path :: new ( & dir) . join ( format ! ( "{}-*" , crate_name) ) ;
211
- rm_rf_glob ( & incremental, config) ?;
209
+ rm_rf_glob ( & incremental, config, & mut progress ) ?;
212
210
}
213
211
}
214
212
}
@@ -224,48 +222,134 @@ fn escape_glob_path(pattern: &Path) -> CargoResult<String> {
224
222
Ok ( glob:: Pattern :: escape ( pattern) )
225
223
}
226
224
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 < ( ) > {
228
230
// TODO: Display utf8 warning to user? Or switch to globset?
229
231
let pattern = pattern
230
232
. to_str ( )
231
233
. ok_or_else ( || anyhow:: anyhow!( "expected utf-8 path" ) ) ?;
232
234
for path in glob:: glob ( pattern) ? {
233
- rm_rf ( & path?, config) ?;
235
+ rm_rf ( & path?, config, progress ) ?;
234
236
}
235
237
Ok ( ( ) )
236
238
}
237
239
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" ) ?;
252
257
}
253
258
}
259
+
254
260
Ok ( ( ) )
255
261
}
256
262
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 ( ( ) )
269
354
}
270
- Ok ( ( ) )
271
355
}
0 commit comments