Skip to content

Commit e3a711f

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 999195c commit e3a711f

File tree

3 files changed

+121
-70
lines changed

3 files changed

+121
-70
lines changed

src/cargo/ops/vendor.rs

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

226226
// Finally, emit the metadata about this package
@@ -316,6 +316,7 @@ fn cp_sources(
316316
dst: &Path,
317317
cksums: &mut BTreeMap<String, String>,
318318
tmp_buf: &mut [u8],
319+
gctx: &GlobalContext,
319320
) -> CargoResult<()> {
320321
for p in paths {
321322
let relative = p.strip_prefix(&src).unwrap();
@@ -359,7 +360,12 @@ fn cp_sources(
359360
let cksum = if dst.file_name() == Some(OsStr::new("Cargo.toml"))
360361
&& pkg.package_id().source_id().is_git()
361362
{
362-
let contents = pkg.manifest().to_resolved_contents()?;
363+
let packaged_files = paths
364+
.iter()
365+
.map(|p| p.strip_prefix(src).unwrap().to_owned())
366+
.collect::<Vec<_>>();
367+
let vendored_pkg = prepare_for_vendor(pkg, &packaged_files, gctx)?;
368+
let contents = vendored_pkg.manifest().to_resolved_contents()?;
363369
copy_and_checksum(
364370
&dst,
365371
&mut dst_opts,
@@ -391,6 +397,111 @@ fn cp_sources(
391397
Ok(())
392398
}
393399

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

src/cargo/util/toml/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,7 @@ fn deprecated_ws_default_features(
10681068
}
10691069

10701070
#[tracing::instrument(skip_all)]
1071-
fn to_real_manifest(
1071+
pub fn to_real_manifest(
10721072
contents: String,
10731073
document: toml_edit::ImDocument<String>,
10741074
original_toml: manifest::TomlManifest,
@@ -2760,7 +2760,7 @@ fn prepare_toml_for_publish(
27602760
}
27612761
}
27622762

2763-
fn prepare_targets_for_publish(
2763+
pub fn prepare_targets_for_publish(
27642764
targets: Option<&Vec<manifest::TomlTarget>>,
27652765
included: &[PathBuf],
27662766
context: &str,
@@ -2785,7 +2785,7 @@ fn prepare_targets_for_publish(
27852785
}
27862786
}
27872787

2788-
fn prepare_target_for_publish(
2788+
pub fn prepare_target_for_publish(
27892789
target: &manifest::TomlTarget,
27902790
included: &[PathBuf],
27912791
context: &str,
@@ -2818,7 +2818,7 @@ fn normalize_path_sep(path: PathBuf, context: &str) -> CargoResult<PathBuf> {
28182818
Ok(path.into())
28192819
}
28202820

2821-
fn normalize_path_string_sep(path: String) -> String {
2821+
pub fn normalize_path_string_sep(path: String) -> String {
28222822
if std::path::MAIN_SEPARATOR != '/' {
28232823
path.replace(std::path::MAIN_SEPARATOR, "/")
28242824
} else {

tests/testsuite/vendor.rs

+4-64
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,6 @@ fn discovery_inferred_build_rs_included() {
283283
# will likely look very different (and much more reasonable).
284284
# See Cargo.toml.orig for the original contents.
285285
286-
bin = []
287-
example = []
288-
test = []
289-
bench = []
290-
291286
[package]
292287
edition = "2015"
293288
name = "dep"
@@ -376,17 +371,12 @@ fn discovery_inferred_build_rs_excluded() {
376371
# will likely look very different (and much more reasonable).
377372
# See Cargo.toml.orig for the original contents.
378373
379-
bin = []
380-
example = []
381-
test = []
382-
bench = []
383-
384374
[package]
385375
edition = "2015"
386376
name = "dep"
387377
version = "0.0.1"
388378
authors = []
389-
build = "build.rs"
379+
build = false
390380
include = ["src/lib.rs"]
391381
autobins = false
392382
autoexamples = false
@@ -404,16 +394,7 @@ path = "src/lib.rs"
404394
"##]],
405395
);
406396

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

419400
#[cargo_test]
@@ -475,10 +456,6 @@ fn discovery_inferred_lib_included() {
475456
# will likely look very different (and much more reasonable).
476457
# See Cargo.toml.orig for the original contents.
477458
478-
example = []
479-
test = []
480-
bench = []
481-
482459
[package]
483460
edition = "2015"
484461
name = "dep"
@@ -571,10 +548,6 @@ fn discovery_inferred_lib_excluded() {
571548
# will likely look very different (and much more reasonable).
572549
# See Cargo.toml.orig for the original contents.
573550
574-
example = []
575-
test = []
576-
bench = []
577-
578551
[package]
579552
edition = "2015"
580553
name = "dep"
@@ -591,27 +564,14 @@ documentation = "docs.rs/foo"
591564
readme = false
592565
license = "MIT"
593566
594-
[lib]
595-
name = "dep"
596-
path = "src/lib.rs"
597-
598567
[[bin]]
599568
name = "dep"
600569
path = "src/main.rs"
601570
602571
"##]],
603572
);
604573

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

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

@@ -1559,10 +1503,6 @@ fn git_deterministic() {
15591503
# will likely look very different (and much more reasonable).
15601504
# See Cargo.toml.orig for the original contents.
15611505
1562-
bin = []
1563-
test = []
1564-
bench = []
1565-
15661506
[package]
15671507
edition = "2021"
15681508
name = "git_dep"
@@ -1580,7 +1520,7 @@ license = "MIT"
15801520
15811521
[lib]
15821522
name = "git_dep"
1583-
path = [..]
1523+
path = "src/lib.rs"
15841524
15851525
[[example]]
15861526
name = "a"

0 commit comments

Comments
 (0)