Skip to content

Commit d3e84f0

Browse files
committed
Auto merge of #14325 - epage:14321-master, r=weihanglo
fix(publish): Don't strip non-dev features ### What does this PR try to resolve? First, we added support for stripping of local-only dev-dependencies. This was dual-implemented for `Cargo.toml` and `Summary`. This left off stripping of `dep/feature` that reference dev-dependencies (enabling features within dev-dependencies). When we fixed this, we again dual-implemented it. The `Cargo.toml` version was correct but the `Summary` version was instead stripping too many features, particularly features that reference renamed dependencies. We didn't have tests for this case and it wasn't caught earlier because crates.io re-generates the `Summary` from `Cargo.toml`, ignoring what we post. That makes this only show up with custom registries that trust what Cargo posts. Rather than fixing the `Summary` generation, I remove the dual-implementation and instead generate the `Summary` from the published `Cargo.toml`. Fixes #14321 ### How should we test and review this PR? ### Additional information Unfortunately, we don't have access directly to the packaged `Cargo.toml`. It could be passed around and I originally did so, hoping to remove use of the local `Package`. However, the local `Package` is needed for things like reading the `README`. So I scaled back and isolate the change to only what needs it. This also makes it easier for `prepare_transmit` callers. Fully open to someone exploring removing this extra `prepare_for_publish` in the future.
2 parents 257b72b + 7c17862 commit d3e84f0

File tree

5 files changed

+134
-165
lines changed

5 files changed

+134
-165
lines changed

src/cargo/ops/cargo_package.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Vec<Fi
288288
} else {
289289
let tarball = create_package(ws, &pkg, ar_files, local_reg.as_ref())?;
290290
if let Some(local_reg) = local_reg.as_mut() {
291-
local_reg.add_package(&pkg, &tarball)?;
291+
local_reg.add_package(ws, &pkg, &tarball)?;
292292
}
293293
outputs.push((pkg, opts, tarball));
294294
}
@@ -893,7 +893,7 @@ fn tar(
893893
.iter()
894894
.map(|ar_file| ar_file.rel_path.clone())
895895
.collect::<Vec<_>>();
896-
let publish_pkg = prepare_for_publish(pkg, ws, &included)?;
896+
let publish_pkg = prepare_for_publish(pkg, ws, Some(&included))?;
897897

898898
let mut uncompressed_size = 0;
899899
for ar_file in ar_files {
@@ -1299,7 +1299,12 @@ impl<'a> TmpRegistry<'a> {
12991299
self.root.join("index")
13001300
}
13011301

1302-
fn add_package(&mut self, package: &Package, tar: &FileLock) -> CargoResult<()> {
1302+
fn add_package(
1303+
&mut self,
1304+
ws: &Workspace<'_>,
1305+
package: &Package,
1306+
tar: &FileLock,
1307+
) -> CargoResult<()> {
13031308
debug!(
13041309
"adding package {}@{} to local overlay at {}",
13051310
package.name(),
@@ -1317,7 +1322,7 @@ impl<'a> TmpRegistry<'a> {
13171322
tar_copy.flush()?;
13181323
}
13191324

1320-
let new_crate = super::registry::prepare_transmit(self.gctx, package, self.upstream)?;
1325+
let new_crate = super::registry::prepare_transmit(self.gctx, ws, package, self.upstream)?;
13211326

13221327
tar.file().seek(SeekFrom::Start(0))?;
13231328
let cksum = cargo_util::Sha256::new()

src/cargo/ops/registry/publish.rs

Lines changed: 23 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
//! [1]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html#publish
44
55
use std::collections::BTreeMap;
6-
use std::collections::BTreeSet;
76
use std::collections::HashSet;
87
use std::fs::File;
98
use std::time::Duration;
@@ -21,7 +20,6 @@ use crate::core::dependency::DepKind;
2120
use crate::core::manifest::ManifestMetadata;
2221
use crate::core::resolver::CliFeatures;
2322
use crate::core::Dependency;
24-
use crate::core::FeatureValue;
2523
use crate::core::Package;
2624
use crate::core::PackageIdSpecQuery;
2725
use crate::core::SourceId;
@@ -35,7 +33,7 @@ use crate::sources::CRATES_IO_REGISTRY;
3533
use crate::util::auth;
3634
use crate::util::cache_lock::CacheLockMode;
3735
use crate::util::context::JobsConfig;
38-
use crate::util::interning::InternedString;
36+
use crate::util::toml::prepare_for_publish;
3937
use crate::util::Progress;
4038
use crate::util::ProgressStyle;
4139
use crate::CargoResult;
@@ -185,6 +183,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
185183
.status("Uploading", pkg.package_id().to_string())?;
186184
transmit(
187185
opts.gctx,
186+
ws,
188187
pkg,
189188
tarball.file(),
190189
&mut registry,
@@ -324,16 +323,16 @@ fn verify_dependencies(
324323

325324
pub(crate) fn prepare_transmit(
326325
gctx: &GlobalContext,
327-
pkg: &Package,
326+
ws: &Workspace<'_>,
327+
local_pkg: &Package,
328328
registry_id: SourceId,
329329
) -> CargoResult<NewCrate> {
330-
let deps = pkg
330+
let included = None; // don't filter build-targets
331+
let publish_pkg = prepare_for_publish(local_pkg, ws, included)?;
332+
333+
let deps = publish_pkg
331334
.dependencies()
332335
.iter()
333-
.filter(|dep| {
334-
// Skip dev-dependency without version.
335-
dep.is_transitive() || dep.specified_req()
336-
})
337336
.map(|dep| {
338337
// If the dependency is from a different registry, then include the
339338
// registry in the dependency.
@@ -378,7 +377,7 @@ pub(crate) fn prepare_transmit(
378377
})
379378
})
380379
.collect::<CargoResult<Vec<NewCrateDependency>>>()?;
381-
let manifest = pkg.manifest();
380+
let manifest = publish_pkg.manifest();
382381
let ManifestMetadata {
383382
ref authors,
384383
ref description,
@@ -395,53 +394,39 @@ pub(crate) fn prepare_transmit(
395394
ref rust_version,
396395
} = *manifest.metadata();
397396
let rust_version = rust_version.as_ref().map(ToString::to_string);
398-
let readme_content = readme
397+
let readme_content = local_pkg
398+
.manifest()
399+
.metadata()
400+
.readme
399401
.as_ref()
400402
.map(|readme| {
401-
paths::read(&pkg.root().join(readme))
402-
.with_context(|| format!("failed to read `readme` file for package `{}`", pkg))
403+
paths::read(&local_pkg.root().join(readme)).with_context(|| {
404+
format!("failed to read `readme` file for package `{}`", local_pkg)
405+
})
403406
})
404407
.transpose()?;
405-
if let Some(ref file) = *license_file {
406-
if !pkg.root().join(file).exists() {
408+
if let Some(ref file) = local_pkg.manifest().metadata().license_file {
409+
if !local_pkg.root().join(file).exists() {
407410
bail!("the license file `{}` does not exist", file)
408411
}
409412
}
410413

411-
let deps_set = deps
412-
.iter()
413-
.map(|dep| dep.name.clone())
414-
.collect::<BTreeSet<String>>();
415-
416414
let string_features = match manifest.resolved_toml().features() {
417415
Some(features) => features
418416
.iter()
419417
.map(|(feat, values)| {
420418
(
421419
feat.to_string(),
422-
values
423-
.iter()
424-
.filter(|fv| {
425-
let feature_value = FeatureValue::new(InternedString::new(fv));
426-
match feature_value {
427-
FeatureValue::Dep { dep_name }
428-
| FeatureValue::DepFeature { dep_name, .. } => {
429-
deps_set.contains(&dep_name.to_string())
430-
}
431-
_ => true,
432-
}
433-
})
434-
.map(|fv| fv.to_string())
435-
.collect(),
420+
values.iter().map(|fv| fv.to_string()).collect(),
436421
)
437422
})
438423
.collect::<BTreeMap<String, Vec<String>>>(),
439424
None => BTreeMap::new(),
440425
};
441426

442427
Ok(NewCrate {
443-
name: pkg.name().to_string(),
444-
vers: pkg.version().to_string(),
428+
name: publish_pkg.name().to_string(),
429+
vers: publish_pkg.version().to_string(),
445430
deps,
446431
features: string_features,
447432
authors: authors.clone(),
@@ -463,13 +448,14 @@ pub(crate) fn prepare_transmit(
463448

464449
fn transmit(
465450
gctx: &GlobalContext,
451+
ws: &Workspace<'_>,
466452
pkg: &Package,
467453
tarball: &File,
468454
registry: &mut Registry,
469455
registry_id: SourceId,
470456
dry_run: bool,
471457
) -> CargoResult<()> {
472-
let new_crate = prepare_transmit(gctx, pkg, registry_id)?;
458+
let new_crate = prepare_transmit(gctx, ws, pkg, registry_id)?;
473459

474460
// Do not upload if performing a dry run
475461
if dry_run {

src/cargo/util/toml/mod.rs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2551,15 +2551,16 @@ fn unused_dep_keys(
25512551
}
25522552
}
25532553

2554+
/// Make the [`Package`] self-contained so its ready for packaging
25542555
pub fn prepare_for_publish(
25552556
me: &Package,
25562557
ws: &Workspace<'_>,
2557-
included: &[PathBuf],
2558+
packaged_files: Option<&[PathBuf]>,
25582559
) -> CargoResult<Package> {
25592560
let contents = me.manifest().contents();
25602561
let document = me.manifest().document();
25612562
let original_toml =
2562-
prepare_toml_for_publish(me.manifest().resolved_toml(), ws, me.root(), included)?;
2563+
prepare_toml_for_publish(me.manifest().resolved_toml(), ws, me.root(), packaged_files)?;
25632564
let resolved_toml = original_toml.clone();
25642565
let features = me.manifest().unstable_features().clone();
25652566
let workspace_config = me.manifest().workspace_config().clone();
@@ -2591,7 +2592,7 @@ fn prepare_toml_for_publish(
25912592
me: &manifest::TomlManifest,
25922593
ws: &Workspace<'_>,
25932594
package_root: &Path,
2594-
included: &[PathBuf],
2595+
packaged_files: Option<&[PathBuf]>,
25952596
) -> CargoResult<manifest::TomlManifest> {
25962597
let gctx = ws.gctx();
25972598

@@ -2608,7 +2609,8 @@ fn prepare_toml_for_publish(
26082609
package.workspace = None;
26092610
if let Some(StringOrBool::String(path)) = &package.build {
26102611
let path = paths::normalize_path(Path::new(path));
2611-
let build = if included.contains(&path) {
2612+
let included = packaged_files.map(|i| i.contains(&path)).unwrap_or(true);
2613+
let build = if included {
26122614
let path = path
26132615
.into_os_string()
26142616
.into_string()
@@ -2712,14 +2714,16 @@ fn prepare_toml_for_publish(
27122714
}
27132715

27142716
let lib = if let Some(target) = &me.lib {
2715-
prepare_target_for_publish(target, included, "library", ws.gctx())?
2717+
prepare_target_for_publish(target, packaged_files, "library", ws.gctx())?
27162718
} else {
27172719
None
27182720
};
2719-
let bin = prepare_targets_for_publish(me.bin.as_ref(), included, "binary", ws.gctx())?;
2720-
let example = prepare_targets_for_publish(me.example.as_ref(), included, "example", ws.gctx())?;
2721-
let test = prepare_targets_for_publish(me.test.as_ref(), included, "test", ws.gctx())?;
2722-
let bench = prepare_targets_for_publish(me.bench.as_ref(), included, "benchmark", ws.gctx())?;
2721+
let bin = prepare_targets_for_publish(me.bin.as_ref(), packaged_files, "binary", ws.gctx())?;
2722+
let example =
2723+
prepare_targets_for_publish(me.example.as_ref(), packaged_files, "example", ws.gctx())?;
2724+
let test = prepare_targets_for_publish(me.test.as_ref(), packaged_files, "test", ws.gctx())?;
2725+
let bench =
2726+
prepare_targets_for_publish(me.bench.as_ref(), packaged_files, "benchmark", ws.gctx())?;
27232727

27242728
let all = |_d: &manifest::TomlDependency| true;
27252729
let mut manifest = manifest::TomlManifest {
@@ -2877,7 +2881,7 @@ fn prepare_toml_for_publish(
28772881

28782882
fn prepare_targets_for_publish(
28792883
targets: Option<&Vec<manifest::TomlTarget>>,
2880-
included: &[PathBuf],
2884+
packaged_files: Option<&[PathBuf]>,
28812885
context: &str,
28822886
gctx: &GlobalContext,
28832887
) -> CargoResult<Option<Vec<manifest::TomlTarget>>> {
@@ -2887,7 +2891,8 @@ fn prepare_targets_for_publish(
28872891

28882892
let mut prepared = Vec::with_capacity(targets.len());
28892893
for target in targets {
2890-
let Some(target) = prepare_target_for_publish(target, included, context, gctx)? else {
2894+
let Some(target) = prepare_target_for_publish(target, packaged_files, context, gctx)?
2895+
else {
28912896
continue;
28922897
};
28932898
prepared.push(target);
@@ -2902,19 +2907,21 @@ fn prepare_targets_for_publish(
29022907

29032908
fn prepare_target_for_publish(
29042909
target: &manifest::TomlTarget,
2905-
included: &[PathBuf],
2910+
packaged_files: Option<&[PathBuf]>,
29062911
context: &str,
29072912
gctx: &GlobalContext,
29082913
) -> CargoResult<Option<manifest::TomlTarget>> {
29092914
let path = target.path.as_ref().expect("previously resolved");
29102915
let path = normalize_path(&path.0);
2911-
if !included.contains(&path) {
2912-
let name = target.name.as_ref().expect("previously resolved");
2913-
gctx.shell().warn(format!(
2914-
"ignoring {context} `{name}` as `{}` is not included in the published package",
2915-
path.display()
2916-
))?;
2917-
return Ok(None);
2916+
if let Some(packaged_files) = packaged_files {
2917+
if !packaged_files.contains(&path) {
2918+
let name = target.name.as_ref().expect("previously resolved");
2919+
gctx.shell().warn(format!(
2920+
"ignoring {context} `{name}` as `{}` is not included in the published package",
2921+
path.display()
2922+
))?;
2923+
return Ok(None);
2924+
}
29182925
}
29192926

29202927
let mut target = target.clone();

tests/testsuite/inheritable_workspace_fields.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -752,11 +752,11 @@ You may press ctrl-c to skip waiting; the crate should be available shortly.
752752
"homepage": "https://www.rust-lang.org",
753753
"keywords": ["cli"],
754754
"license": "MIT",
755-
"license_file": "../LICENSE",
755+
"license_file": "LICENSE",
756756
"links": null,
757757
"name": "bar",
758758
"readme": "README.md",
759-
"readme_file": "../README.md",
759+
"readme_file": "README.md",
760760
"repository": "https://github.com/example/example",
761761
"rust_version": "1.60",
762762
"vers": "1.2.3"

0 commit comments

Comments
 (0)