/// Copies SRC into DST recursively.
///
/// Function is not crash-safe. Caller is responsible to follow guidelines
/// regarding crash-safe I/O.
Copies SRC into DST recursively.
Function is not crash-safe. Caller is responsible to follow guidelines
regarding crash-safe I/O.
Copies SRC into DST recursively . Function is not crash - safe . Caller is responsible to follow guidelines regarding crash - safe I / O .
fn copy_recursively(src: &Path, dst: &Path) -> Result<(), String> {
    enum CanCloneFiles {
        Yes,
        No,
    }
    fn go(src: &Path, dst: &Path, can_clone: &mut CanCloneFiles) -> Result<(), String> {
        let src_metadata = src
            .metadata()
            .map_err(|e| format!("failed to get metadata of path {}: {}", src.display(), e))?;
        if src_metadata.is_dir() {
            let entries = src
                .read_dir()
                .map_err(|e| format!("failed to read directory {}: {}", src.display(), e))?;
            fs::create_dir_all(&dst)
                .map_err(|e| format!("failed to create directory {}: {}", dst.display(), e))?;
            for entry_result in entries {
                let entry = entry_result.map_err(|e| {
                    format!("failed to read entry of directory {}: {}", src.display(), e)
                })?;
                let dst_entry = dst.join(entry.file_name());
                go(&entry.path(), &dst_entry, can_clone)?;
            }
        } else {
            if let CanCloneFiles::Yes = can_clone {
                match clone_file(src, dst) {
                    Ok(_) => return Ok(()),
                    Err(_) => {
                        *can_clone = CanCloneFiles::No;
                    }
                }
            }
            copy_file_sparse(src, dst).map_err(|e| {
                format!(
                    "Failed to copy {} -> {}: {}",
                    src.display(),
                    dst.display(),
                    e
                )
            })?;
        }
        Ok(())
    }
    // We try to clone files first because it's much faster for big files.
    // If cloning fails (most likely, because SRC and DST are on different file
    // systems), we fall back to usual copying.
    let mut can_clone = CanCloneFiles::Yes;
    go(src, dst, &mut can_clone)
}
fn copy_recursively ( src : & Path , dst : & Path ) -> Result < ( ) , String > { enum CanCloneFiles { Yes , No , } fn go ( src : & Path , dst : & Path , can_clone : & mut CanCloneFiles ) -> Result < ( ) , String > { let src_metadata = src . metadata ( ) . map_err ( | e | format ! ( " " src display ( ) e ) ) ? ; if src_metadata . is_dir ( ) { let entries = src . read_dir ( ) . map_err ( | e | format ! ( " " src display ( ) e ) ) ? ; fs :: create_dir_all ( & dst ) . map_err ( | e | format ! ( " " dst display ( ) e ) ) ? ; for entry_result in entries { let entry = entry_result . map_err ( | e | { format ! ( " " src display ( ) e ) } ) ? ; let dst_entry = dst . join ( entry . file_name ( ) ) ; go ( & entry . path ( ) , & dst_entry , can_clone ) ? ; } } else { if let CanCloneFiles :: Yes = can_clone { match clone_file ( src , dst ) { Ok ( _ ) => return Ok ( ( ) ) , Err ( _ ) => { * can_clone = CanCloneFiles :: No ; } } } copy_file_sparse ( src , dst ) . map_err ( | e | { format ! ( " " src display ( ) dst display ( ) e ) } ) ? ; } Ok ( ( ) ) } // We try to clone files first because it's much faster for big files. // If cloning fails (most likely, because SRC and DST are on different file // systems), we fall back to usual copying. let mut can_clone = CanCloneFiles :: Yes ; go ( src , dst , & mut can_clone ) }
Copies SRC into DST recursively.
Copies SRC into DST recursively .
src
&Path
dst
&Path