|
1 | 1 | use crate::core::shell::Verbosity;
|
2 |
| -use crate::core::{GitReference, Workspace}; |
| 2 | +use crate::core::{GitReference, Package, Workspace}; |
3 | 3 | use crate::ops;
|
| 4 | +use crate::ops::cargo_package::{build_ar_list, build_lock, FileContents, GeneratedFile}; |
4 | 5 | use crate::sources::path::PathSource;
|
5 | 6 | use crate::sources::CRATES_IO_REGISTRY;
|
6 | 7 | use crate::util::{CargoResult, Config};
|
@@ -160,10 +161,13 @@ fn sync(
|
160 | 161 | }
|
161 | 162 | ids.insert(
|
162 | 163 | pkg,
|
163 |
| - packages |
164 |
| - .get_one(pkg) |
165 |
| - .with_context(|| "failed to fetch package")? |
166 |
| - .clone(), |
| 164 | + ( |
| 165 | + ws, |
| 166 | + packages |
| 167 | + .get_one(pkg) |
| 168 | + .with_context(|| "failed to fetch package")? |
| 169 | + .clone(), |
| 170 | + ), |
167 | 171 | );
|
168 | 172 |
|
169 | 173 | checksums.insert(pkg, resolve.checksums().get(&pkg).cloned());
|
@@ -191,7 +195,7 @@ fn sync(
|
191 | 195 |
|
192 | 196 | let mut sources = BTreeSet::new();
|
193 | 197 | let mut tmp_buf = [0; 64 * 1024];
|
194 |
| - for (id, pkg) in ids.iter() { |
| 198 | + for (id, (ws, pkg)) in ids.iter() { |
195 | 199 | // Next up, copy it to the vendor directory
|
196 | 200 | let src = pkg
|
197 | 201 | .manifest_path()
|
@@ -225,7 +229,7 @@ fn sync(
|
225 | 229 | let pathsource = PathSource::new(src, id.source_id(), config);
|
226 | 230 | let paths = pathsource.list_files(pkg)?;
|
227 | 231 | let mut map = BTreeMap::new();
|
228 |
| - cp_sources(src, &paths, &dst, &mut map, &mut tmp_buf) |
| 232 | + cp_sources(ws, pkg, &paths, &dst, &mut map, &mut tmp_buf) |
229 | 233 | .with_context(|| format!("failed to copy over vendored sources for: {}", id))?;
|
230 | 234 |
|
231 | 235 | // Finally, emit the metadata about this package
|
@@ -313,74 +317,105 @@ fn sync(
|
313 | 317 | }
|
314 | 318 |
|
315 | 319 | fn cp_sources(
|
316 |
| - src: &Path, |
| 320 | + ws: &Workspace<'_>, |
| 321 | + pkg: &Package, |
317 | 322 | paths: &[PathBuf],
|
318 | 323 | dst: &Path,
|
319 | 324 | cksums: &mut BTreeMap<String, String>,
|
320 | 325 | tmp_buf: &mut [u8],
|
321 | 326 | ) -> CargoResult<()> {
|
322 |
| - for p in paths { |
323 |
| - let relative = p.strip_prefix(&src).unwrap(); |
324 |
| - |
325 |
| - match relative.to_str() { |
| 327 | + let ar_files = build_ar_list(ws, pkg, paths.to_vec(), None)?; |
| 328 | + for file in ar_files { |
| 329 | + match file.rel_str.as_str() { |
326 | 330 | // Skip git config files as they're not relevant to builds most of
|
327 | 331 | // the time and if we respect them (e.g. in git) then it'll
|
328 | 332 | // probably mess with the checksums when a vendor dir is checked
|
329 | 333 | // into someone else's source control
|
330 |
| - Some(".gitattributes") | Some(".gitignore") | Some(".git") => continue, |
| 334 | + ".gitattributes" | ".gitignore" | ".git" => continue, |
331 | 335 |
|
332 | 336 | // Temporary Cargo files
|
333 |
| - Some(".cargo-ok") => continue, |
| 337 | + ".cargo-ok" => continue, |
334 | 338 |
|
335 | 339 | // Skip patch-style orig/rej files. Published crates on crates.io
|
336 | 340 | // have `Cargo.toml.orig` which we don't want to use here and
|
337 | 341 | // otherwise these are rarely used as part of the build process.
|
338 |
| - Some(filename) => { |
| 342 | + filename => { |
339 | 343 | if filename.ends_with(".orig") || filename.ends_with(".rej") {
|
340 | 344 | continue;
|
341 | 345 | }
|
342 | 346 | }
|
343 |
| - _ => {} |
344 | 347 | };
|
345 | 348 |
|
346 | 349 | // Join pathname components individually to make sure that the joined
|
347 | 350 | // path uses the correct directory separators everywhere, since
|
348 | 351 | // `relative` may use Unix-style and `dst` may require Windows-style
|
349 | 352 | // backslashes.
|
350 |
| - let dst = relative |
| 353 | + let dst = file |
| 354 | + .rel_path |
351 | 355 | .iter()
|
352 | 356 | .fold(dst.to_owned(), |acc, component| acc.join(&component));
|
353 | 357 |
|
354 | 358 | paths::create_dir_all(dst.parent().unwrap())?;
|
355 | 359 |
|
356 |
| - let cksum = copy_and_checksum(p, &dst, tmp_buf)?; |
357 |
| - cksums.insert(relative.to_str().unwrap().replace("\\", "/"), cksum); |
| 360 | + let mut dst_opts = OpenOptions::new(); |
| 361 | + dst_opts.write(true).create(true).truncate(true); |
| 362 | + let cksum = match file.contents { |
| 363 | + FileContents::OnDisk(disk_path) => { |
| 364 | + let mut src = File::open(&disk_path) |
| 365 | + .with_context(|| format!("failed to open {:?}", &disk_path))?; |
| 366 | + #[cfg(unix)] |
| 367 | + { |
| 368 | + use std::os::unix::fs::{MetadataExt, OpenOptionsExt}; |
| 369 | + let src_metadata = src |
| 370 | + .metadata() |
| 371 | + .with_context(|| format!("failed to stat {:?}", disk_path))?; |
| 372 | + dst_opts.mode(src_metadata.mode()); |
| 373 | + } |
| 374 | + copy_and_checksum( |
| 375 | + &dst, |
| 376 | + &mut dst_opts, |
| 377 | + &mut src, |
| 378 | + disk_path.to_str().unwrap(), |
| 379 | + tmp_buf, |
| 380 | + )? |
| 381 | + } |
| 382 | + FileContents::Generated(generated_kind) => { |
| 383 | + let contents = match generated_kind { |
| 384 | + GeneratedFile::Manifest => pkg.to_registry_toml(ws)?, |
| 385 | + GeneratedFile::Lockfile => build_lock(ws, pkg)?, |
| 386 | + GeneratedFile::VcsInfo(ref s) => serde_json::to_string_pretty(s)?, |
| 387 | + }; |
| 388 | + copy_and_checksum( |
| 389 | + &dst, |
| 390 | + &mut dst_opts, |
| 391 | + &mut contents.as_bytes(), |
| 392 | + "Generated File", |
| 393 | + tmp_buf, |
| 394 | + )? |
| 395 | + } |
| 396 | + }; |
| 397 | + cksums.insert(file.rel_str.replace("\\", "/"), cksum); |
358 | 398 | }
|
359 | 399 | Ok(())
|
360 | 400 | }
|
361 | 401 |
|
362 |
| -fn copy_and_checksum(src_path: &Path, dst_path: &Path, buf: &mut [u8]) -> CargoResult<String> { |
363 |
| - let mut src = File::open(src_path).with_context(|| format!("failed to open {:?}", src_path))?; |
364 |
| - let mut dst_opts = OpenOptions::new(); |
365 |
| - dst_opts.write(true).create(true).truncate(true); |
366 |
| - #[cfg(unix)] |
367 |
| - { |
368 |
| - use std::os::unix::fs::{MetadataExt, OpenOptionsExt}; |
369 |
| - let src_metadata = src |
370 |
| - .metadata() |
371 |
| - .with_context(|| format!("failed to stat {:?}", src_path))?; |
372 |
| - dst_opts.mode(src_metadata.mode()); |
373 |
| - } |
| 402 | +fn copy_and_checksum<T: Read>( |
| 403 | + dst_path: &Path, |
| 404 | + dst_opts: &mut OpenOptions, |
| 405 | + contents: &mut T, |
| 406 | + contents_path: &str, |
| 407 | + buf: &mut [u8], |
| 408 | +) -> CargoResult<String> { |
374 | 409 | let mut dst = dst_opts
|
375 | 410 | .open(dst_path)
|
376 | 411 | .with_context(|| format!("failed to create {:?}", dst_path))?;
|
377 | 412 | // Not going to bother setting mode on pre-existing files, since there
|
378 | 413 | // shouldn't be any under normal conditions.
|
379 | 414 | let mut cksum = Sha256::new();
|
380 | 415 | loop {
|
381 |
| - let n = src |
| 416 | + let n = contents |
382 | 417 | .read(buf)
|
383 |
| - .with_context(|| format!("failed to read from {:?}", src_path))?; |
| 418 | + .with_context(|| format!("failed to read from {:?}", contents_path))?; |
384 | 419 | if n == 0 {
|
385 | 420 | break Ok(cksum.finish_hex());
|
386 | 421 | }
|
|
0 commit comments