Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow publishing with dev-dependencies without a version. #7333

Merged
merged 2 commits into from
Oct 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/cargo/ops/cargo_package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ fn check_metadata(pkg: &Package, config: &Config) -> CargoResult<()> {
// Checks that the package dependencies are safe to deploy.
fn verify_dependencies(pkg: &Package) -> CargoResult<()> {
for dep in pkg.dependencies() {
if dep.source_id().is_path() && !dep.specified_req() {
if dep.source_id().is_path() && !dep.specified_req() && dep.is_transitive() {
failure::bail!(
"all path dependencies must have a version specified \
when packaging.\ndependency `{}` does not specify \
Expand Down
8 changes: 8 additions & 0 deletions src/cargo/ops/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ fn verify_dependencies(
for dep in pkg.dependencies().iter() {
if dep.source_id().is_path() || dep.source_id().is_git() {
if !dep.specified_req() {
if !dep.is_transitive() {
// dev-dependencies will be stripped in TomlManifest::prepare_for_publish
continue;
}
let which = if dep.source_id().is_path() {
"path"
} else {
Expand Down Expand Up @@ -172,6 +176,10 @@ fn transmit(
let deps = 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.
Expand Down
24 changes: 17 additions & 7 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,7 @@ impl TomlManifest {
.unwrap()
.clone();
package.workspace = None;
let all = |_d: &TomlDependency| true;
return Ok(TomlManifest {
package: Some(package),
project: None,
Expand All @@ -731,19 +732,21 @@ impl TomlManifest {
example: self.example.clone(),
test: self.test.clone(),
bench: self.bench.clone(),
dependencies: map_deps(config, self.dependencies.as_ref())?,
dependencies: map_deps(config, self.dependencies.as_ref(), all)?,
dev_dependencies: map_deps(
config,
self.dev_dependencies
.as_ref()
.or_else(|| self.dev_dependencies2.as_ref()),
TomlDependency::is_version_specified,
)?,
dev_dependencies2: None,
build_dependencies: map_deps(
config,
self.build_dependencies
.as_ref()
.or_else(|| self.build_dependencies2.as_ref()),
all,
)?,
build_dependencies2: None,
features: self.features.clone(),
Expand All @@ -754,19 +757,21 @@ impl TomlManifest {
Ok((
k.clone(),
TomlPlatform {
dependencies: map_deps(config, v.dependencies.as_ref())?,
dependencies: map_deps(config, v.dependencies.as_ref(), all)?,
dev_dependencies: map_deps(
config,
v.dev_dependencies
.as_ref()
.or_else(|| v.dev_dependencies2.as_ref()),
TomlDependency::is_version_specified,
)?,
dev_dependencies2: None,
build_dependencies: map_deps(
config,
v.build_dependencies
.as_ref()
.or_else(|| v.build_dependencies2.as_ref()),
all,
)?,
build_dependencies2: None,
},
Expand All @@ -788,13 +793,15 @@ impl TomlManifest {
fn map_deps(
config: &Config,
deps: Option<&BTreeMap<String, TomlDependency>>,
filter: impl Fn(&TomlDependency) -> bool,
) -> CargoResult<Option<BTreeMap<String, TomlDependency>>> {
let deps = match deps {
Some(deps) => deps,
None => return Ok(None),
};
let deps = deps
.iter()
.filter(|(_k, v)| filter(v))
.map(|(k, v)| Ok((k.clone(), map_dependency(config, v)?)))
.collect::<CargoResult<BTreeMap<_, _>>>()?;
Ok(Some(deps))
Expand Down Expand Up @@ -1221,11 +1228,7 @@ impl TomlManifest {
spec.set_url(CRATES_IO_INDEX.parse().unwrap());
}

let version_specified = match *replacement {
TomlDependency::Detailed(ref d) => d.version.is_some(),
TomlDependency::Simple(..) => true,
};
if version_specified {
if replacement.is_version_specified() {
bail!(
"replacements cannot specify a version \
requirement, but found one for `{}`",
Expand Down Expand Up @@ -1330,6 +1333,13 @@ impl TomlDependency {
TomlDependency::Detailed(ref details) => details.to_dependency(name, cx, kind),
}
}

fn is_version_specified(&self) -> bool {
match self {
TomlDependency::Detailed(d) => d.version.is_some(),
TomlDependency::Simple(..) => true,
}
}
}

impl DetailedTomlDependency {
Expand Down
1 change: 1 addition & 0 deletions src/doc/man/cargo-package.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ steps:
. Load and check the current workspace, performing some basic checks.
- Path dependencies are not allowed unless they have a version key. Cargo
will ignore the path key for dependencies in published packages.
`dev-dependencies` do not have this restriction.
. Create the compressed `.crate` file.
- The original `Cargo.toml` file is rewritten and normalized.
- `[patch]`, `[replace]`, and `[workspace]` sections are removed from the
Expand Down
3 changes: 2 additions & 1 deletion src/doc/man/generated/cargo-package.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ <h2 id="cargo_package_description">DESCRIPTION</h2>
<ul>
<li>
<p>Path dependencies are not allowed unless they have a version key. Cargo
will ignore the path key for dependencies in published packages.</p>
will ignore the path key for dependencies in published packages.
<code>dev-dependencies</code> do not have this restriction.</p>
</li>
</ul>
</div>
Expand Down
7 changes: 4 additions & 3 deletions src/etc/man/cargo-package.1
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
'\" t
.\" Title: cargo-package
.\" Author: [see the "AUTHOR(S)" section]
.\" Generator: Asciidoctor 2.0.8
.\" Date: 2019-07-15
.\" Generator: Asciidoctor 2.0.10
.\" Date: 2019-09-05
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "CARGO\-PACKAGE" "1" "2019-07-15" "\ \&" "\ \&"
.TH "CARGO\-PACKAGE" "1" "2019-09-05" "\ \&" "\ \&"
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.ss \n[.ss] 0
Expand Down Expand Up @@ -59,6 +59,7 @@ Load and check the current workspace, performing some basic checks.
.\}
Path dependencies are not allowed unless they have a version key. Cargo
will ignore the path key for dependencies in published packages.
\fBdev\-dependencies\fP do not have this restriction.
.RE
.RE
.sp
Expand Down
81 changes: 81 additions & 0 deletions tests/testsuite/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1178,3 +1178,84 @@ fn publish_git_with_version() {
],
);
}

#[cargo_test]
fn publish_dev_dep_no_version() {
registry::init();

let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
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 --index")
.arg(registry_url().to_string())
.with_stderr(
"\
[UPDATING] [..]
[PACKAGING] foo v0.1.0 [..]
[UPLOADING] foo v0.1.0 [..]
",
)
.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",
"vers": "0.1.0"
}
"#,
"foo-0.1.0.crate",
&["Cargo.toml", "Cargo.toml.orig", "src/lib.rs"],
&[(
"Cargo.toml",
r#"[..]
[package]
name = "foo"
version = "0.1.0"
authors = []
description = "foo"
homepage = "foo"
documentation = "foo"
license = "MIT"
repository = "foo"

[dev-dependencies]
"#,
)],
);
}