Skip to content

Commit 4c27c96

Browse files
committed
Auto merge of #9612 - Bryysen:master, r=alexcrichton
Error when packaging with git dependencies without version If `cargo package` is run on a package that specifies a git dependency without a version, cargo will error. This should help with clarifying that git dependencies will be stripped when packaging, and that the dependency has to be fetched from a registry. Closes #9442
2 parents a5e7a1d + 4e1910d commit 4c27c96

File tree

4 files changed

+85
-46
lines changed

4 files changed

+85
-46
lines changed

src/cargo/ops/cargo_package.rs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,10 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Option
105105
return Ok(None);
106106
}
107107

108-
verify_dependencies(pkg)?;
108+
// Check that the package dependencies are safe to deploy.
109+
for dep in pkg.dependencies() {
110+
super::check_dep_has_version(dep, false)?;
111+
}
109112

110113
let filename = format!("{}-{}.crate", pkg.name(), pkg.version());
111114
let dir = ws.target_dir().join("package");
@@ -333,21 +336,6 @@ fn check_metadata(pkg: &Package, config: &Config) -> CargoResult<()> {
333336
Ok(())
334337
}
335338

336-
// Checks that the package dependencies are safe to deploy.
337-
fn verify_dependencies(pkg: &Package) -> CargoResult<()> {
338-
for dep in pkg.dependencies() {
339-
if dep.source_id().is_path() && !dep.specified_req() && dep.is_transitive() {
340-
anyhow::bail!(
341-
"all path dependencies must have a version specified \
342-
when packaging.\ndependency `{}` does not specify \
343-
a version.",
344-
dep.name_in_toml()
345-
)
346-
}
347-
}
348-
Ok(())
349-
}
350-
351339
/// Checks if the package source is in a *git* DVCS repository. If *git*, and
352340
/// the source is *dirty* (e.g., has uncommitted changes) then `bail!` with an
353341
/// informative message. Otherwise return the sha1 hash of the current *HEAD*

src/cargo/ops/mod.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,35 @@ mod registry;
5151
mod resolve;
5252
pub mod tree;
5353
mod vendor;
54+
55+
/// Returns true if the dependency is either git or path, false otherwise
56+
/// Error if a git/path dep is transitive, but has no version (registry source).
57+
/// This check is performed on dependencies before publishing or packaging
58+
fn check_dep_has_version(dep: &crate::core::Dependency, publish: bool) -> crate::CargoResult<bool> {
59+
let which = if dep.source_id().is_path() {
60+
"path"
61+
} else if dep.source_id().is_git() {
62+
"git"
63+
} else {
64+
return Ok(false);
65+
};
66+
67+
if !dep.specified_req() && dep.is_transitive() {
68+
let dep_version_source = dep.registry_id().map_or_else(
69+
|| "crates.io".to_string(),
70+
|registry_id| registry_id.display_registry_name(),
71+
);
72+
anyhow::bail!(
73+
"all dependencies must have a version specified when {}.\n\
74+
dependency `{}` does not specify a version\n\
75+
Note: The {} dependency will use the version from {},\n\
76+
the `{}` specification will be removed from the dependency declaration.",
77+
if publish { "publishing" } else { "packaging" },
78+
dep.package_name(),
79+
if publish { "published" } else { "packaged" },
80+
dep_version_source,
81+
which,
82+
)
83+
}
84+
Ok(true)
85+
}

src/cargo/ops/registry.rs

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -138,34 +138,12 @@ fn verify_dependencies(
138138
registry_src: SourceId,
139139
) -> CargoResult<()> {
140140
for dep in pkg.dependencies().iter() {
141-
if dep.source_id().is_path() || dep.source_id().is_git() {
142-
if !dep.specified_req() {
143-
if !dep.is_transitive() {
144-
// dev-dependencies will be stripped in TomlManifest::prepare_for_publish
145-
continue;
146-
}
147-
let which = if dep.source_id().is_path() {
148-
"path"
149-
} else {
150-
"git"
151-
};
152-
let dep_version_source = dep.registry_id().map_or_else(
153-
|| "crates.io".to_string(),
154-
|registry_id| registry_id.display_registry_name(),
155-
);
156-
bail!(
157-
"all dependencies must have a version specified when publishing.\n\
158-
dependency `{}` does not specify a version\n\
159-
Note: The published dependency will use the version from {},\n\
160-
the `{}` specification will be removed from the dependency declaration.",
161-
dep.package_name(),
162-
dep_version_source,
163-
which,
164-
)
165-
}
141+
if super::check_dep_has_version(dep, true)? {
142+
continue;
143+
}
166144
// TomlManifest::prepare_for_publish will rewrite the dependency
167145
// to be just the `version` field.
168-
} else if dep.source_id() != registry_src {
146+
if dep.source_id() != registry_src {
169147
if !dep.source_id().is_registry() {
170148
// Consider making SourceId::kind a public type that we can
171149
// exhaustively match on. Using match can help ensure that

tests/testsuite/package.rs

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,47 @@ fn path_dependency_no_version() {
287287
"\
288288
[WARNING] manifest has no documentation, homepage or repository.
289289
See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
290-
[ERROR] all path dependencies must have a version specified when packaging.
291-
dependency `bar` does not specify a version.
290+
[ERROR] all dependencies must have a version specified when packaging.
291+
dependency `bar` does not specify a version\n\
292+
Note: The packaged dependency will use the version from crates.io,
293+
the `path` specification will be removed from the dependency declaration.
294+
",
295+
)
296+
.run();
297+
}
298+
299+
#[cargo_test]
300+
fn git_dependency_no_version() {
301+
registry::init();
302+
303+
let p = project()
304+
.file(
305+
"Cargo.toml",
306+
r#"
307+
[project]
308+
name = "foo"
309+
version = "0.0.1"
310+
authors = []
311+
license = "MIT"
312+
description = "foo"
313+
314+
[dependencies.foo]
315+
git = "git://path/to/nowhere"
316+
"#,
317+
)
318+
.file("src/main.rs", "fn main() {}")
319+
.build();
320+
321+
p.cargo("package")
322+
.with_status(101)
323+
.with_stderr(
324+
"\
325+
[WARNING] manifest has no documentation, homepage or repository.
326+
See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
327+
[ERROR] all dependencies must have a version specified when packaging.
328+
dependency `foo` does not specify a version
329+
Note: The packaged dependency will use the version from crates.io,
330+
the `git` specification will be removed from the dependency declaration.
292331
",
293332
)
294333
.run();
@@ -1895,8 +1934,10 @@ src/main.rs
18951934
.with_status(101)
18961935
.with_stderr(
18971936
"\
1898-
error: all path dependencies must have a version specified when packaging.
1899-
dependency `bar` does not specify a version.
1937+
[ERROR] all dependencies must have a version specified when packaging.
1938+
dependency `bar` does not specify a version
1939+
Note: The packaged dependency will use the version from crates.io,
1940+
the `path` specification will be removed from the dependency declaration.
19001941
",
19011942
)
19021943
.run();

0 commit comments

Comments
 (0)