Skip to content

Commit f50c592

Browse files
committed
Auto merge of #14367 - epage:vendor, r=weihanglo
fix(vendor): Strip excluded build targets ### What does this PR try to resolve? Fixes #14348 ### How should we test and review this PR? The commits are setup to be able to show, through the tests, how the `cargo package` and `cargo vendor` behavior diverge and then how `cargo vendor`s behavior changes over time. This is a **very** hacky solution, duplicating the minimum of what `prepare_for_publish` does to fix this one issue and in the least intrusive way to the vendor code. The intention is to keep this low risk for backporting to beta and stable. We need to revisit this, refactoring the `cargo package` code so that we can call into that for each vendored dependency. ### Additional information
2 parents 495d02c + 1ae77f5 commit f50c592

File tree

3 files changed

+697
-17
lines changed

3 files changed

+697
-17
lines changed

src/cargo/ops/vendor.rs

+121-2
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ fn sync(
221221
let pathsource = PathSource::new(src, id.source_id(), gctx);
222222
let paths = pathsource.list_files(pkg)?;
223223
let mut map = BTreeMap::new();
224-
cp_sources(pkg, src, &paths, &dst, &mut map, &mut tmp_buf)
224+
cp_sources(pkg, src, &paths, &dst, &mut map, &mut tmp_buf, gctx)
225225
.with_context(|| format!("failed to copy over vendored sources for: {}", id))?;
226226

227227
// Finally, emit the metadata about this package
@@ -317,6 +317,7 @@ fn cp_sources(
317317
dst: &Path,
318318
cksums: &mut BTreeMap<String, String>,
319319
tmp_buf: &mut [u8],
320+
gctx: &GlobalContext,
320321
) -> CargoResult<()> {
321322
for p in paths {
322323
let relative = p.strip_prefix(&src).unwrap();
@@ -360,7 +361,12 @@ fn cp_sources(
360361
let cksum = if dst.file_name() == Some(OsStr::new("Cargo.toml"))
361362
&& pkg.package_id().source_id().is_git()
362363
{
363-
let contents = pkg.manifest().to_normalized_contents()?;
364+
let packaged_files = paths
365+
.iter()
366+
.map(|p| p.strip_prefix(src).unwrap().to_owned())
367+
.collect::<Vec<_>>();
368+
let vendored_pkg = prepare_for_vendor(pkg, &packaged_files, gctx)?;
369+
let contents = vendored_pkg.manifest().to_normalized_contents()?;
364370
copy_and_checksum(
365371
&dst,
366372
&mut dst_opts,
@@ -392,6 +398,119 @@ fn cp_sources(
392398
Ok(())
393399
}
394400

401+
/// HACK: Perform the bare minimum of `prepare_for_publish` needed for #14348.
402+
///
403+
/// There are parts of `prepare_for_publish` that could be directly useful (e.g. stripping
404+
/// `[workspace]`) while other parts that require other filesystem operations (moving the README
405+
/// file) and ideally we'd reuse `cargo package` code to take care of all of this for us.
406+
fn prepare_for_vendor(
407+
me: &Package,
408+
packaged_files: &[PathBuf],
409+
gctx: &GlobalContext,
410+
) -> CargoResult<Package> {
411+
let contents = me.manifest().contents();
412+
let document = me.manifest().document();
413+
let original_toml = prepare_toml_for_vendor(
414+
me.manifest().normalized_toml().clone(),
415+
packaged_files,
416+
gctx,
417+
)?;
418+
let normalized_toml = original_toml.clone();
419+
let features = me.manifest().unstable_features().clone();
420+
let workspace_config = me.manifest().workspace_config().clone();
421+
let source_id = me.package_id().source_id();
422+
let mut warnings = Default::default();
423+
let mut errors = Default::default();
424+
let manifest = crate::util::toml::to_real_manifest(
425+
contents.to_owned(),
426+
document.clone(),
427+
original_toml,
428+
normalized_toml,
429+
features,
430+
workspace_config,
431+
source_id,
432+
me.manifest_path(),
433+
gctx,
434+
&mut warnings,
435+
&mut errors,
436+
)?;
437+
let new_pkg = Package::new(manifest, me.manifest_path());
438+
Ok(new_pkg)
439+
}
440+
441+
fn prepare_toml_for_vendor(
442+
mut me: cargo_util_schemas::manifest::TomlManifest,
443+
packaged_files: &[PathBuf],
444+
gctx: &GlobalContext,
445+
) -> CargoResult<cargo_util_schemas::manifest::TomlManifest> {
446+
let package = me
447+
.package
448+
.as_mut()
449+
.expect("venedored manifests must have packages");
450+
if let Some(cargo_util_schemas::manifest::StringOrBool::String(path)) = &package.build {
451+
let path = paths::normalize_path(Path::new(path));
452+
let included = packaged_files.contains(&path);
453+
let build = if included {
454+
let path = path
455+
.into_os_string()
456+
.into_string()
457+
.map_err(|_err| anyhow::format_err!("non-UTF8 `package.build`"))?;
458+
let path = crate::util::toml::normalize_path_string_sep(path);
459+
cargo_util_schemas::manifest::StringOrBool::String(path)
460+
} else {
461+
gctx.shell().warn(format!(
462+
"ignoring `package.build` as `{}` is not included in the published package",
463+
path.display()
464+
))?;
465+
cargo_util_schemas::manifest::StringOrBool::Bool(false)
466+
};
467+
package.build = Some(build);
468+
}
469+
470+
let lib = if let Some(target) = &me.lib {
471+
crate::util::toml::prepare_target_for_publish(
472+
target,
473+
Some(packaged_files),
474+
"library",
475+
gctx,
476+
)?
477+
} else {
478+
None
479+
};
480+
let bin = crate::util::toml::prepare_targets_for_publish(
481+
me.bin.as_ref(),
482+
Some(packaged_files),
483+
"binary",
484+
gctx,
485+
)?;
486+
let example = crate::util::toml::prepare_targets_for_publish(
487+
me.example.as_ref(),
488+
Some(packaged_files),
489+
"example",
490+
gctx,
491+
)?;
492+
let test = crate::util::toml::prepare_targets_for_publish(
493+
me.test.as_ref(),
494+
Some(packaged_files),
495+
"test",
496+
gctx,
497+
)?;
498+
let bench = crate::util::toml::prepare_targets_for_publish(
499+
me.bench.as_ref(),
500+
Some(packaged_files),
501+
"benchmark",
502+
gctx,
503+
)?;
504+
505+
me.lib = lib;
506+
me.bin = bin;
507+
me.example = example;
508+
me.test = test;
509+
me.bench = bench;
510+
511+
Ok(me)
512+
}
513+
395514
fn copy_and_checksum<T: Read>(
396515
dst_path: &Path,
397516
dst_opts: &mut OpenOptions,

src/cargo/util/toml/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,7 @@ fn deprecated_ws_default_features(
10861086
}
10871087

10881088
#[tracing::instrument(skip_all)]
1089-
fn to_real_manifest(
1089+
pub fn to_real_manifest(
10901090
contents: String,
10911091
document: toml_edit::ImDocument<String>,
10921092
original_toml: manifest::TomlManifest,
@@ -2889,7 +2889,7 @@ fn prepare_toml_for_publish(
28892889
}
28902890
}
28912891

2892-
fn prepare_targets_for_publish(
2892+
pub fn prepare_targets_for_publish(
28932893
targets: Option<&Vec<manifest::TomlTarget>>,
28942894
packaged_files: Option<&[PathBuf]>,
28952895
context: &str,
@@ -2915,7 +2915,7 @@ fn prepare_targets_for_publish(
29152915
}
29162916
}
29172917

2918-
fn prepare_target_for_publish(
2918+
pub fn prepare_target_for_publish(
29192919
target: &manifest::TomlTarget,
29202920
packaged_files: Option<&[PathBuf]>,
29212921
context: &str,
@@ -2950,7 +2950,7 @@ fn normalize_path_sep(path: PathBuf, context: &str) -> CargoResult<PathBuf> {
29502950
Ok(path.into())
29512951
}
29522952

2953-
fn normalize_path_string_sep(path: String) -> String {
2953+
pub fn normalize_path_string_sep(path: String) -> String {
29542954
if std::path::MAIN_SEPARATOR != '/' {
29552955
path.replace(std::path::MAIN_SEPARATOR, "/")
29562956
} else {

0 commit comments

Comments
 (0)