diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index a83df435b2d..459e780f32f 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -288,7 +288,7 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult>(); - let publish_pkg = prepare_for_publish(pkg, ws, &included)?; + let publish_pkg = prepare_for_publish(pkg, ws, Some(&included))?; let mut uncompressed_size = 0; for ar_file in ar_files { @@ -1299,7 +1299,12 @@ impl<'a> TmpRegistry<'a> { self.root.join("index") } - fn add_package(&mut self, package: &Package, tar: &FileLock) -> CargoResult<()> { + fn add_package( + &mut self, + ws: &Workspace<'_>, + package: &Package, + tar: &FileLock, + ) -> CargoResult<()> { debug!( "adding package {}@{} to local overlay at {}", package.name(), @@ -1317,7 +1322,7 @@ impl<'a> TmpRegistry<'a> { tar_copy.flush()?; } - let new_crate = super::registry::prepare_transmit(self.gctx, package, self.upstream)?; + let new_crate = super::registry::prepare_transmit(self.gctx, ws, package, self.upstream)?; tar.file().seek(SeekFrom::Start(0))?; let cksum = cargo_util::Sha256::new() diff --git a/src/cargo/ops/registry/publish.rs b/src/cargo/ops/registry/publish.rs index f0a72bda404..592a1cb0765 100644 --- a/src/cargo/ops/registry/publish.rs +++ b/src/cargo/ops/registry/publish.rs @@ -3,7 +3,6 @@ //! [1]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html#publish use std::collections::BTreeMap; -use std::collections::BTreeSet; use std::collections::HashSet; use std::fs::File; use std::time::Duration; @@ -21,7 +20,6 @@ use crate::core::dependency::DepKind; use crate::core::manifest::ManifestMetadata; use crate::core::resolver::CliFeatures; use crate::core::Dependency; -use crate::core::FeatureValue; use crate::core::Package; use crate::core::PackageIdSpecQuery; use crate::core::SourceId; @@ -35,7 +33,7 @@ use crate::sources::CRATES_IO_REGISTRY; use crate::util::auth; use crate::util::cache_lock::CacheLockMode; use crate::util::context::JobsConfig; -use crate::util::interning::InternedString; +use crate::util::toml::prepare_for_publish; use crate::util::Progress; use crate::util::ProgressStyle; use crate::CargoResult; @@ -185,6 +183,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> { .status("Uploading", pkg.package_id().to_string())?; transmit( opts.gctx, + ws, pkg, tarball.file(), &mut registry, @@ -324,16 +323,16 @@ fn verify_dependencies( pub(crate) fn prepare_transmit( gctx: &GlobalContext, - pkg: &Package, + ws: &Workspace<'_>, + local_pkg: &Package, registry_id: SourceId, ) -> CargoResult { - let deps = pkg + let included = None; // don't filter build-targets + let publish_pkg = prepare_for_publish(local_pkg, ws, included)?; + + let deps = publish_pkg .dependencies() .iter() - .filter(|dep| { - // Skip dev-dependency without version. - dep.is_transitive() || dep.specified_req() - }) .map(|dep| { // If the dependency is from a different registry, then include the // registry in the dependency. @@ -378,7 +377,7 @@ pub(crate) fn prepare_transmit( }) }) .collect::>>()?; - let manifest = pkg.manifest(); + let manifest = publish_pkg.manifest(); let ManifestMetadata { ref authors, ref description, @@ -395,44 +394,30 @@ pub(crate) fn prepare_transmit( ref rust_version, } = *manifest.metadata(); let rust_version = rust_version.as_ref().map(ToString::to_string); - let readme_content = readme + let readme_content = local_pkg + .manifest() + .metadata() + .readme .as_ref() .map(|readme| { - paths::read(&pkg.root().join(readme)) - .with_context(|| format!("failed to read `readme` file for package `{}`", pkg)) + paths::read(&local_pkg.root().join(readme)).with_context(|| { + format!("failed to read `readme` file for package `{}`", local_pkg) + }) }) .transpose()?; - if let Some(ref file) = *license_file { - if !pkg.root().join(file).exists() { + if let Some(ref file) = local_pkg.manifest().metadata().license_file { + if !local_pkg.root().join(file).exists() { bail!("the license file `{}` does not exist", file) } } - let deps_set = deps - .iter() - .map(|dep| dep.name.clone()) - .collect::>(); - let string_features = match manifest.resolved_toml().features() { Some(features) => features .iter() .map(|(feat, values)| { ( feat.to_string(), - values - .iter() - .filter(|fv| { - let feature_value = FeatureValue::new(InternedString::new(fv)); - match feature_value { - FeatureValue::Dep { dep_name } - | FeatureValue::DepFeature { dep_name, .. } => { - deps_set.contains(&dep_name.to_string()) - } - _ => true, - } - }) - .map(|fv| fv.to_string()) - .collect(), + values.iter().map(|fv| fv.to_string()).collect(), ) }) .collect::>>(), @@ -440,8 +425,8 @@ pub(crate) fn prepare_transmit( }; Ok(NewCrate { - name: pkg.name().to_string(), - vers: pkg.version().to_string(), + name: publish_pkg.name().to_string(), + vers: publish_pkg.version().to_string(), deps, features: string_features, authors: authors.clone(), @@ -463,13 +448,14 @@ pub(crate) fn prepare_transmit( fn transmit( gctx: &GlobalContext, + ws: &Workspace<'_>, pkg: &Package, tarball: &File, registry: &mut Registry, registry_id: SourceId, dry_run: bool, ) -> CargoResult<()> { - let new_crate = prepare_transmit(gctx, pkg, registry_id)?; + let new_crate = prepare_transmit(gctx, ws, pkg, registry_id)?; // Do not upload if performing a dry run if dry_run { diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 2fa704a8b87..76892b9d773 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -2551,15 +2551,16 @@ fn unused_dep_keys( } } +/// Make the [`Package`] self-contained so its ready for packaging pub fn prepare_for_publish( me: &Package, ws: &Workspace<'_>, - included: &[PathBuf], + packaged_files: Option<&[PathBuf]>, ) -> CargoResult { let contents = me.manifest().contents(); let document = me.manifest().document(); let original_toml = - prepare_toml_for_publish(me.manifest().resolved_toml(), ws, me.root(), included)?; + prepare_toml_for_publish(me.manifest().resolved_toml(), ws, me.root(), packaged_files)?; let resolved_toml = original_toml.clone(); let features = me.manifest().unstable_features().clone(); let workspace_config = me.manifest().workspace_config().clone(); @@ -2591,7 +2592,7 @@ fn prepare_toml_for_publish( me: &manifest::TomlManifest, ws: &Workspace<'_>, package_root: &Path, - included: &[PathBuf], + packaged_files: Option<&[PathBuf]>, ) -> CargoResult { let gctx = ws.gctx(); @@ -2608,7 +2609,8 @@ fn prepare_toml_for_publish( package.workspace = None; if let Some(StringOrBool::String(path)) = &package.build { let path = paths::normalize_path(Path::new(path)); - let build = if included.contains(&path) { + let included = packaged_files.map(|i| i.contains(&path)).unwrap_or(true); + let build = if included { let path = path .into_os_string() .into_string() @@ -2712,14 +2714,16 @@ fn prepare_toml_for_publish( } let lib = if let Some(target) = &me.lib { - prepare_target_for_publish(target, included, "library", ws.gctx())? + prepare_target_for_publish(target, packaged_files, "library", ws.gctx())? } else { None }; - let bin = prepare_targets_for_publish(me.bin.as_ref(), included, "binary", ws.gctx())?; - let example = prepare_targets_for_publish(me.example.as_ref(), included, "example", ws.gctx())?; - let test = prepare_targets_for_publish(me.test.as_ref(), included, "test", ws.gctx())?; - let bench = prepare_targets_for_publish(me.bench.as_ref(), included, "benchmark", ws.gctx())?; + let bin = prepare_targets_for_publish(me.bin.as_ref(), packaged_files, "binary", ws.gctx())?; + let example = + prepare_targets_for_publish(me.example.as_ref(), packaged_files, "example", ws.gctx())?; + let test = prepare_targets_for_publish(me.test.as_ref(), packaged_files, "test", ws.gctx())?; + let bench = + prepare_targets_for_publish(me.bench.as_ref(), packaged_files, "benchmark", ws.gctx())?; let all = |_d: &manifest::TomlDependency| true; let mut manifest = manifest::TomlManifest { @@ -2877,7 +2881,7 @@ fn prepare_toml_for_publish( fn prepare_targets_for_publish( targets: Option<&Vec>, - included: &[PathBuf], + packaged_files: Option<&[PathBuf]>, context: &str, gctx: &GlobalContext, ) -> CargoResult>> { @@ -2887,7 +2891,8 @@ fn prepare_targets_for_publish( let mut prepared = Vec::with_capacity(targets.len()); for target in targets { - let Some(target) = prepare_target_for_publish(target, included, context, gctx)? else { + let Some(target) = prepare_target_for_publish(target, packaged_files, context, gctx)? + else { continue; }; prepared.push(target); @@ -2902,19 +2907,21 @@ fn prepare_targets_for_publish( fn prepare_target_for_publish( target: &manifest::TomlTarget, - included: &[PathBuf], + packaged_files: Option<&[PathBuf]>, context: &str, gctx: &GlobalContext, ) -> CargoResult> { let path = target.path.as_ref().expect("previously resolved"); let path = normalize_path(&path.0); - if !included.contains(&path) { - let name = target.name.as_ref().expect("previously resolved"); - gctx.shell().warn(format!( - "ignoring {context} `{name}` as `{}` is not included in the published package", - path.display() - ))?; - return Ok(None); + if let Some(packaged_files) = packaged_files { + if !packaged_files.contains(&path) { + let name = target.name.as_ref().expect("previously resolved"); + gctx.shell().warn(format!( + "ignoring {context} `{name}` as `{}` is not included in the published package", + path.display() + ))?; + return Ok(None); + } } let mut target = target.clone(); diff --git a/tests/testsuite/inheritable_workspace_fields.rs b/tests/testsuite/inheritable_workspace_fields.rs index 70fb61197f8..664e25602c1 100644 --- a/tests/testsuite/inheritable_workspace_fields.rs +++ b/tests/testsuite/inheritable_workspace_fields.rs @@ -752,11 +752,11 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. "homepage": "https://www.rust-lang.org", "keywords": ["cli"], "license": "MIT", - "license_file": "../LICENSE", + "license_file": "LICENSE", "links": null, "name": "bar", "readme": "README.md", - "readme_file": "../README.md", + "readme_file": "README.md", "repository": "https://github.com/example/example", "rust_version": "1.60", "vers": "1.2.3" diff --git a/tests/testsuite/publish.rs b/tests/testsuite/publish.rs index c03e726d6da..cb97657040d 100644 --- a/tests/testsuite/publish.rs +++ b/tests/testsuite/publish.rs @@ -1598,112 +1598,20 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. } #[cargo_test] -fn publish_dev_dep_no_version() { - let registry = RegistryBuilder::new().http_api().http_index().build(); - - let p = project() - .file( - "Cargo.toml", - r#" - [package] - name = "foo" - version = "0.1.0" - edition = "2015" - authors = [] - license = "MIT" - description = "foo" - documentation = "foo" - homepage = "foo" - repository = "foo" - - [dev-dependencies] - bar = { path = "bar" } - "#, - ) - .file("src/lib.rs", "") - .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) - .file("bar/src/lib.rs", "") - .build(); - - p.cargo("publish --no-verify") - .replace_crates_io(registry.index_url()) - .with_stderr_data(str![[r#" -[UPDATING] crates.io index -[PACKAGING] foo v0.1.0 ([ROOT]/foo) -[PACKAGED] 3 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) -[UPLOADING] foo v0.1.0 ([ROOT]/foo) -[UPLOADED] foo v0.1.0 to registry `crates-io` -[NOTE] waiting for `foo v0.1.0` to be available at registry `crates-io`. -You may press ctrl-c to skip waiting; the crate should be available shortly. -[PUBLISHED] foo v0.1.0 at registry `crates-io` - -"#]]) - .run(); - - publish::validate_upload_with_contents( - r#" - { - "authors": [], - "badges": {}, - "categories": [], - "deps": [], - "description": "foo", - "documentation": "foo", - "features": {}, - "homepage": "foo", - "keywords": [], - "license": "MIT", - "license_file": null, - "links": null, - "name": "foo", - "readme": null, - "readme_file": null, - "repository": "foo", - "rust_version": null, - "vers": "0.1.0" - } - "#, - "foo-0.1.0.crate", - &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs"], - &[( - "Cargo.toml", - &format!( - r#"{} -[package] -edition = "2015" -name = "foo" -version = "0.1.0" -authors = [] -build = false -autobins = false -autoexamples = false -autotests = false -autobenches = false -description = "foo" -homepage = "foo" -documentation = "foo" -readme = false -license = "MIT" -repository = "foo" - -[lib] -name = "foo" -path = "src/lib.rs" - -[dev-dependencies] -"#, - cargo::core::manifest::MANIFEST_PREAMBLE - ), - )], - ); -} - -#[cargo_test] -fn publish_with_feature_point_diff_kinds_dep() { +fn publish_dev_dep_stripping() { let registry = RegistryBuilder::new().http_api().http_index().build(); Package::new("normal-only", "1.0.0") .feature("cat", &[]) .publish(); + Package::new("optional-dep-feature", "1.0.0") + .feature("cat", &[]) + .publish(); + Package::new("optional-namespaced", "1.0.0") + .feature("cat", &[]) + .publish(); + Package::new("optional-renamed-namespaced", "1.0.0") + .feature("cat", &[]) + .publish(); Package::new("build-only", "1.0.0") .feature("cat", &[]) .publish(); @@ -1745,11 +1653,17 @@ fn publish_with_feature_point_diff_kinds_dep() { "target-build-only/cat", "target-dev-only/cat", "target-normal-and-dev/cat", + "optional-dep-feature/cat", + "dep:optional-namespaced", + "dep:optional-renamed-namespaced10", ] [dependencies] normal-only = { version = "1.0", features = ["cat"] } normal-and-dev = { version = "1.0", features = ["cat"] } + optional-dep-feature = { version = "1.0", features = ["cat"], optional = true } + optional-namespaced = { version = "1.0", features = ["cat"], optional = true } + optional-renamed-namespaced10 = { version = "1.0", features = ["cat"], optional = true, package = "optional-renamed-namespaced" } [build-dependencies] build-only = { version = "1.0", features = ["cat"] } @@ -1839,6 +1753,40 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. "target": null, "version_req": "^1.0" }, + { + "default_features": true, + "features": [ + "cat" + ], + "kind": "normal", + "name": "optional-dep-feature", + "optional": true, + "target": null, + "version_req": "^1.0" + }, + { + "default_features": true, + "features": [ + "cat" + ], + "kind": "normal", + "name": "optional-namespaced", + "optional": true, + "target": null, + "version_req": "^1.0" + }, + { + "default_features": true, + "explicit_name_in_toml": "optional-renamed-namespaced10", + "features": [ + "cat" + ], + "kind": "normal", + "name": "optional-renamed-namespaced", + "optional": true, + "target": null, + "version_req": "^1.0" + }, { "default_features": true, "features": [ @@ -1915,7 +1863,10 @@ You may press ctrl-c to skip waiting; the crate should be available shortly. "normal-and-dev/cat", "target-normal-only/cat", "target-build-only/cat", - "target-normal-and-dev/cat" + "target-normal-and-dev/cat", + "optional-dep-feature/cat", + "dep:optional-namespaced", + "dep:optional-renamed-namespaced10" ] }, "homepage": "foo", @@ -1966,6 +1917,22 @@ features = ["cat"] version = "1.0" features = ["cat"] +[dependencies.optional-dep-feature] +version = "1.0" +features = ["cat"] +optional = true + +[dependencies.optional-namespaced] +version = "1.0" +features = ["cat"] +optional = true + +[dependencies.optional-renamed-namespaced10] +version = "1.0" +features = ["cat"] +optional = true +package = "optional-renamed-namespaced" + [dev-dependencies.normal-and-dev] version = "1.0" features = ["cat"] @@ -1982,6 +1949,9 @@ foo_feature = [ "target-normal-only/cat", "target-build-only/cat", "target-normal-and-dev/cat", + "optional-dep-feature/cat", + "dep:optional-namespaced", + "dep:optional-renamed-namespaced10", ] [target."cfg(unix)".dependencies.target-normal-and-dev] @@ -2005,6 +1975,7 @@ features = ["cat"] )], ); } + #[cargo_test] fn credentials_ambiguous_filename() { // `publish` generally requires a remote registry