@@ -12,6 +12,8 @@ pub mod rustc;
12
12
pub mod rustdoc;
13
13
14
14
use std:: env;
15
+ use std:: fs;
16
+ use std:: io;
15
17
use std:: path:: { Path , PathBuf } ;
16
18
use std:: process:: { Command , Output } ;
17
19
@@ -201,6 +203,71 @@ pub fn set_host_rpath(cmd: &mut Command) {
201
203
} ) ;
202
204
}
203
205
206
+ /// Copy a directory into another.
207
+ pub fn copy_dir_all ( src : impl AsRef < Path > , dst : impl AsRef < Path > ) {
208
+ fn copy_dir_all_inner ( src : impl AsRef < Path > , dst : impl AsRef < Path > ) -> io:: Result < ( ) > {
209
+ let dst = dst. as_ref ( ) ;
210
+ if !dst. is_dir ( ) {
211
+ fs:: create_dir_all ( & dst) ?;
212
+ }
213
+ for entry in fs:: read_dir ( src) ? {
214
+ let entry = entry?;
215
+ let ty = entry. file_type ( ) ?;
216
+ if ty. is_dir ( ) {
217
+ copy_dir_all_inner ( entry. path ( ) , dst. join ( entry. file_name ( ) ) ) ?;
218
+ } else {
219
+ fs:: copy ( entry. path ( ) , dst. join ( entry. file_name ( ) ) ) ?;
220
+ }
221
+ }
222
+ Ok ( ( ) )
223
+ }
224
+
225
+ if let Err ( e) = copy_dir_all_inner ( & src, & dst) {
226
+ // Trying to give more context about what exactly caused the failure
227
+ panic ! (
228
+ "failed to copy `{}` to `{}`: {:?}" ,
229
+ src. as_ref( ) . display( ) ,
230
+ dst. as_ref( ) . display( ) ,
231
+ e
232
+ ) ;
233
+ }
234
+ }
235
+
236
+ /// Check that all files in `dir1` exist and have the same content in `dir2`. Panic otherwise.
237
+ pub fn recursive_diff ( dir1 : impl AsRef < Path > , dir2 : impl AsRef < Path > ) {
238
+ fn read_file ( path : & Path ) -> Vec < u8 > {
239
+ match fs:: read ( path) {
240
+ Ok ( c) => c,
241
+ Err ( e) => panic ! ( "Failed to read `{}`: {:?}" , path. display( ) , e) ,
242
+ }
243
+ }
244
+
245
+ let dir2 = dir2. as_ref ( ) ;
246
+ for entry in fs:: read_dir ( dir1) . unwrap ( ) {
247
+ let entry = entry. unwrap ( ) ;
248
+ let entry_name = entry. file_name ( ) ;
249
+ let path = entry. path ( ) ;
250
+
251
+ if path. is_dir ( ) {
252
+ recursive_diff ( & path, & dir2. join ( entry_name) ) ;
253
+ } else {
254
+ let path2 = dir2. join ( entry_name) ;
255
+ let file1 = read_file ( & path) ;
256
+ let file2 = read_file ( & path2) ;
257
+
258
+ // We don't use `assert_eq!` because they are `Vec<u8>`, so not great for display.
259
+ // Why not using String? Because there might be minified files or even potentially
260
+ // binary ones, so that would display useless output.
261
+ assert ! (
262
+ file1 == file2,
263
+ "`{}` and `{}` have different content" ,
264
+ path. display( ) ,
265
+ path2. display( ) ,
266
+ ) ;
267
+ }
268
+ }
269
+ }
270
+
204
271
/// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct
205
272
/// containing a `cmd: Command` field and a `output` function. The provided helpers are:
206
273
///
0 commit comments