@@ -12,6 +12,8 @@ pub mod rustc;
1212pub mod rustdoc;
1313
1414use std:: env;
15+ use std:: fs;
16+ use std:: io;
1517use std:: path:: { Path , PathBuf } ;
1618use std:: process:: { Command , Output } ;
1719
@@ -201,6 +203,70 @@ pub fn set_host_rpath(cmd: &mut Command) {
201203 } ) ;
202204}
203205
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 : & Path , dir2 : & 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+ for entry in fs:: read_dir ( dir1) . unwrap ( ) {
246+ let entry = entry. unwrap ( ) ;
247+ let entry_name = entry. file_name ( ) ;
248+ let path = entry. path ( ) ;
249+
250+ if path. is_dir ( ) {
251+ recursive_diff ( & path, & dir2. join ( entry_name) ) ;
252+ } else {
253+ let path2 = dir2. join ( entry_name) ;
254+ let file1 = read_file ( & path) ;
255+ let file2 = read_file ( & path2) ;
256+
257+ // We don't use `assert_eq!` because they are `Vec<u8>`, so not great for display.
258+ // Why not using String? Because there might be minified files or even potentially
259+ // binary ones, so that would display useless output.
260+ assert ! (
261+ file1 == file2,
262+ "`{}` and `{}` have different content" ,
263+ path. display( ) ,
264+ path2. display( ) ,
265+ ) ;
266+ }
267+ }
268+ }
269+
204270/// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct
205271/// containing a `cmd: Command` field and a `output` function. The provided helpers are:
206272///
0 commit comments