Skip to content

Commit 78651cd

Browse files
committed
fix(vendor): Strip excluded build targets
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. Fixes #14348
1 parent 567f66d commit 78651cd

File tree

3 files changed

+126
-70
lines changed

3 files changed

+126
-70
lines changed

src/cargo/ops/vendor.rs

Lines changed: 118 additions & 2 deletions
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_resolved_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_resolved_contents()?;
364370
copy_and_checksum(
365371
&dst,
366372
&mut dst_opts,
@@ -392,6 +398,116 @@ 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 =
414+
prepare_toml_for_vendor(me.manifest().resolved_toml().clone(), packaged_files, gctx)?;
415+
let normalized_toml = original_toml.clone();
416+
let features = me.manifest().unstable_features().clone();
417+
let workspace_config = me.manifest().workspace_config().clone();
418+
let source_id = me.package_id().source_id();
419+
let mut warnings = Default::default();
420+
let mut errors = Default::default();
421+
let manifest = crate::util::toml::to_real_manifest(
422+
contents.to_owned(),
423+
document.clone(),
424+
original_toml,
425+
normalized_toml,
426+
features,
427+
workspace_config,
428+
source_id,
429+
me.manifest_path(),
430+
gctx,
431+
&mut warnings,
432+
&mut errors,
433+
)?;
434+
let new_pkg = Package::new(manifest, me.manifest_path());
435+
Ok(new_pkg)
436+
}
437+
438+
fn prepare_toml_for_vendor(
439+
mut me: cargo_util_schemas::manifest::TomlManifest,
440+
packaged_files: &[PathBuf],
441+
gctx: &GlobalContext,
442+
) -> CargoResult<cargo_util_schemas::manifest::TomlManifest> {
443+
let package = me
444+
.package
445+
.as_mut()
446+
.expect("venedored manifests must have packages");
447+
if let Some(cargo_util_schemas::manifest::StringOrBool::String(path)) = &package.build {
448+
let path = paths::normalize_path(Path::new(path));
449+
let included = packaged_files.contains(&path);
450+
let build = if included {
451+
let path = path
452+
.into_os_string()
453+
.into_string()
454+
.map_err(|_err| anyhow::format_err!("non-UTF8 `package.build`"))?;
455+
let path = crate::util::toml::normalize_path_string_sep(path);
456+
cargo_util_schemas::manifest::StringOrBool::String(path)
457+
} else {
458+
gctx.shell().warn(format!(
459+
"ignoring `package.build` as `{}` is not included in the published package",
460+
path.display()
461+
))?;
462+
cargo_util_schemas::manifest::StringOrBool::Bool(false)
463+
};
464+
package.build = Some(build);
465+
}
466+
467+
let lib = if let Some(target) = &me.lib {
468+
crate::util::toml::prepare_target_for_publish(
469+
target,
470+
Some(packaged_files),
471+
"library",
472+
gctx,
473+
)?
474+
} else {
475+
None
476+
};
477+
let bin = crate::util::toml::prepare_targets_for_publish(
478+
me.bin.as_ref(),
479+
Some(packaged_files),
480+
"binary",
481+
gctx,
482+
)?;
483+
let example = crate::util::toml::prepare_targets_for_publish(
484+
me.example.as_ref(),
485+
Some(packaged_files),
486+
"example",
487+
gctx,
488+
)?;
489+
let test = crate::util::toml::prepare_targets_for_publish(
490+
me.test.as_ref(),
491+
Some(packaged_files),
492+
"test",
493+
gctx,
494+
)?;
495+
let bench = crate::util::toml::prepare_targets_for_publish(
496+
me.bench.as_ref(),
497+
Some(packaged_files),
498+
"benchmark",
499+
gctx,
500+
)?;
501+
502+
me.lib = lib;
503+
me.bin = bin;
504+
me.example = example;
505+
me.test = test;
506+
me.bench = bench;
507+
508+
Ok(me)
509+
}
510+
395511
fn copy_and_checksum<T: Read>(
396512
dst_path: &Path,
397513
dst_opts: &mut OpenOptions,

src/cargo/util/toml/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,7 +1107,7 @@ fn deprecated_ws_default_features(
11071107
}
11081108

11091109
#[tracing::instrument(skip_all)]
1110-
fn to_real_manifest(
1110+
pub fn to_real_manifest(
11111111
contents: String,
11121112
document: toml_edit::ImDocument<String>,
11131113
original_toml: manifest::TomlManifest,
@@ -2897,7 +2897,7 @@ fn prepare_toml_for_publish(
28972897
}
28982898
}
28992899

2900-
fn prepare_targets_for_publish(
2900+
pub fn prepare_targets_for_publish(
29012901
targets: Option<&Vec<manifest::TomlTarget>>,
29022902
included: Option<&[PathBuf]>,
29032903
context: &str,
@@ -2922,7 +2922,7 @@ fn prepare_targets_for_publish(
29222922
}
29232923
}
29242924

2925-
fn prepare_target_for_publish(
2925+
pub fn prepare_target_for_publish(
29262926
target: &manifest::TomlTarget,
29272927
included: Option<&[PathBuf]>,
29282928
context: &str,
@@ -2957,7 +2957,7 @@ fn normalize_path_sep(path: PathBuf, context: &str) -> CargoResult<PathBuf> {
29572957
Ok(path.into())
29582958
}
29592959

2960-
fn normalize_path_string_sep(path: String) -> String {
2960+
pub fn normalize_path_string_sep(path: String) -> String {
29612961
if std::path::MAIN_SEPARATOR != '/' {
29622962
path.replace(std::path::MAIN_SEPARATOR, "/")
29632963
} else {

tests/testsuite/vendor.rs

Lines changed: 4 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,6 @@ fn discovery_inferred_build_rs_included() {
284284
# will likely look very different (and much more reasonable).
285285
# See Cargo.toml.orig for the original contents.
286286
287-
bin = []
288-
example = []
289-
test = []
290-
bench = []
291-
292287
[package]
293288
edition = "2015"
294289
name = "dep"
@@ -377,17 +372,12 @@ fn discovery_inferred_build_rs_excluded() {
377372
# will likely look very different (and much more reasonable).
378373
# See Cargo.toml.orig for the original contents.
379374
380-
bin = []
381-
example = []
382-
test = []
383-
bench = []
384-
385375
[package]
386376
edition = "2015"
387377
name = "dep"
388378
version = "0.0.1"
389379
authors = []
390-
build = "build.rs"
380+
build = false
391381
include = ["src/lib.rs"]
392382
autobins = false
393383
autoexamples = false
@@ -405,16 +395,7 @@ path = "src/lib.rs"
405395
"##]],
406396
);
407397

408-
p.cargo("check")
409-
.with_status(101)
410-
.with_stderr_data(str![[r#"
411-
[COMPILING] dep v0.0.1 ([ROOTURL]/dep#[..])
412-
[ERROR] couldn't read [ROOT]/foo/vendor/dep/build.rs: [NOT_FOUND]
413-
414-
[ERROR] could not compile `dep` (build script) due to 1 previous error
415-
416-
"#]])
417-
.run();
398+
p.cargo("check").run();
418399
}
419400

420401
#[cargo_test]
@@ -476,10 +457,6 @@ fn discovery_inferred_lib_included() {
476457
# will likely look very different (and much more reasonable).
477458
# See Cargo.toml.orig for the original contents.
478459
479-
example = []
480-
test = []
481-
bench = []
482-
483460
[package]
484461
edition = "2015"
485462
name = "dep"
@@ -572,10 +549,6 @@ fn discovery_inferred_lib_excluded() {
572549
# will likely look very different (and much more reasonable).
573550
# See Cargo.toml.orig for the original contents.
574551
575-
example = []
576-
test = []
577-
bench = []
578-
579552
[package]
580553
edition = "2015"
581554
name = "dep"
@@ -592,27 +565,14 @@ documentation = "docs.rs/foo"
592565
readme = false
593566
license = "MIT"
594567
595-
[lib]
596-
name = "dep"
597-
path = "src/lib.rs"
598-
599568
[[bin]]
600569
name = "dep"
601570
path = "src/main.rs"
602571
603572
"##]],
604573
);
605574

606-
p.cargo("check")
607-
.with_status(101)
608-
.with_stderr_data(str![[r#"
609-
[CHECKING] dep v0.0.1 ([ROOTURL]/dep#[..])
610-
[ERROR] couldn't read [ROOT]/foo/vendor/dep/src/lib.rs: [NOT_FOUND]
611-
612-
[ERROR] could not compile `dep` (lib) due to 1 previous error
613-
614-
"#]])
615-
.run();
575+
p.cargo("check").run();
616576
}
617577

618578
#[cargo_test]
@@ -807,22 +767,6 @@ license = "MIT"
807767
name = "dep"
808768
path = "src/lib.rs"
809769
810-
[[bin]]
811-
name = "foo"
812-
path = "src/bin/foo/main.rs"
813-
814-
[[example]]
815-
name = "example_foo"
816-
path = "examples/example_foo.rs"
817-
818-
[[test]]
819-
name = "test_foo"
820-
path = "tests/test_foo.rs"
821-
822-
[[bench]]
823-
name = "bench_foo"
824-
path = "benches/bench_foo.rs"
825-
826770
"##]],
827771
);
828772

@@ -1577,10 +1521,6 @@ fn git_deterministic() {
15771521
# will likely look very different (and much more reasonable).
15781522
# See Cargo.toml.orig for the original contents.
15791523
1580-
bin = []
1581-
test = []
1582-
bench = []
1583-
15841524
[package]
15851525
edition = "2021"
15861526
name = "git_dep"
@@ -1598,7 +1538,7 @@ license = "MIT"
15981538
15991539
[lib]
16001540
name = "git_dep"
1601-
path = [..]
1541+
path = "src/lib.rs"
16021542
16031543
[[example]]
16041544
name = "a"

0 commit comments

Comments
 (0)