diff --git a/src/cargo/ops/vendor.rs b/src/cargo/ops/vendor.rs index 5e1c0568ee0..05bbb22523e 100644 --- a/src/cargo/ops/vendor.rs +++ b/src/cargo/ops/vendor.rs @@ -9,6 +9,8 @@ use serde::Serialize; use std::collections::HashSet; use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::fs; +use std::fs::File; +use std::io::{Read, Write}; use std::path::{Path, PathBuf}; pub struct VendorOptions<'a> { @@ -182,6 +184,7 @@ fn sync( } let mut sources = BTreeSet::new(); + let mut tmp_buf = [0; 64 * 1024]; for (id, pkg) in ids.iter() { // Next up, copy it to the vendor directory let src = pkg @@ -216,7 +219,7 @@ fn sync( let pathsource = PathSource::new(src, id.source_id(), config); let paths = pathsource.list_files(pkg)?; let mut map = BTreeMap::new(); - cp_sources(src, &paths, &dst, &mut map) + cp_sources(src, &paths, &dst, &mut map, &mut tmp_buf) .chain_err(|| format!("failed to copy over vendored sources for: {}", id))?; // Finally, emit the metadata about this package @@ -299,6 +302,7 @@ fn cp_sources( paths: &[PathBuf], dst: &Path, cksums: &mut BTreeMap, + tmp_buf: &mut [u8], ) -> CargoResult<()> { for p in paths { let relative = p.strip_prefix(&src).unwrap(); @@ -334,9 +338,27 @@ fn cp_sources( paths::create_dir_all(dst.parent().unwrap())?; - paths::copy(&p, &dst)?; - let cksum = Sha256::new().update_path(dst)?.finish_hex(); + let cksum = copy_and_checksum(&p, &dst, tmp_buf)?; cksums.insert(relative.to_str().unwrap().replace("\\", "/"), cksum); } Ok(()) } + +fn copy_and_checksum(src_path: &Path, dst_path: &Path, buf: &mut [u8]) -> CargoResult { + let mut src = File::open(src_path).chain_err(|| format!("failed to open {:?}", src_path))?; + let mut dst = + File::create(dst_path).chain_err(|| format!("failed to create {:?}", dst_path))?; + let mut cksum = Sha256::new(); + loop { + let n = src + .read(buf) + .chain_err(|| format!("failed to read from {:?}", src_path))?; + if n == 0 { + break Ok(cksum.finish_hex()); + } + let data = &buf[..n]; + cksum.update(data); + dst.write_all(data) + .chain_err(|| format!("failed to write to {:?}", dst_path))?; + } +}