Skip to content

Commit 45c2341

Browse files
authored
feat(manifest): allow git dependency alongside alternate registry (#16810)
### What does this PR try to resolve? Removes the restriction that prevented combining `git` with `registry` (or `registry-index`), bringing alternate registries to parity with crates.io for the [multiple locations feature](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#multiple-locations). Previously, any combination of `git + registry` was rejected. Now: - `git + path` is still always rejected - `registry + registry_index` together is still rejected - `git + registry` is allowed: the git arm `(Some(git), None, _, _)` handles it At publishing time, it already stripped all `git` fields, leaving only `registry`, so it required no changes. Fixes #10875 ### How to test and review this PR? Run tests: - `registry_and_git_dep_works` - `publish_with_git_and_registry_dep` in `alt_registry` test suite, and: - `git_registry` in `cargo_add` test suite.
2 parents 4fc40e1 + d8e9ad4 commit 45c2341

4 files changed

Lines changed: 150 additions & 30 deletions

File tree

src/cargo/util/toml/mod.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2362,21 +2362,17 @@ fn to_dependency_source_id<P: ResolveToPath + Clone>(
23622362
orig.registry.as_deref(),
23632363
orig.registry_index.as_ref(),
23642364
) {
2365-
(Some(_git), _, Some(_registry), _) | (Some(_git), _, _, Some(_registry)) => bail!(
2366-
"dependency ({name_in_toml}) specification is ambiguous. \
2367-
Only one of `git` or `registry` is allowed.",
2368-
),
2369-
(_, _, Some(_registry), Some(_registry_index)) => bail!(
2370-
"dependency ({name_in_toml}) specification is ambiguous. \
2371-
Only one of `registry` or `registry-index` is allowed.",
2372-
),
2373-
(Some(_git), Some(_path), None, None) => {
2365+
(Some(_git), Some(_path), _, _) => {
23742366
bail!(
23752367
"dependency ({name_in_toml}) specification is ambiguous. \
23762368
Only one of `git` or `path` is allowed.",
23772369
);
23782370
}
2379-
(Some(git), None, None, None) => {
2371+
(_, _, Some(_registry), Some(_registry_index)) => bail!(
2372+
"dependency ({name_in_toml}) specification is ambiguous. \
2373+
Only one of `registry` or `registry-index` is allowed.",
2374+
),
2375+
(Some(git), None, _, _) => {
23802376
let n_details = [&orig.branch, &orig.tag, &orig.rev]
23812377
.iter()
23822378
.filter(|d| d.is_some())

tests/testsuite/alt_registry.rs

Lines changed: 139 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::fs;
44

55
use crate::prelude::*;
66
use cargo_test_support::compare::assert_e2e;
7+
use cargo_test_support::git;
78
use cargo_test_support::publish::validate_alt_upload;
89
use cargo_test_support::registry::{self, Package, RegistryBuilder};
910
use cargo_test_support::str;
@@ -227,34 +228,58 @@ fn registry_and_path_dep_works() {
227228
}
228229

229230
#[cargo_test]
230-
fn registry_incompatible_with_git() {
231-
registry::alt_init();
231+
fn registry_and_git_dep_works() {
232+
let _reg = RegistryBuilder::new()
233+
.http_api()
234+
.http_index()
235+
.alternative()
236+
.build();
232237

233-
let p = project()
238+
let bar = git::repo(&paths::root().join("bar"))
234239
.file(
235240
"Cargo.toml",
236241
r#"
242+
[package]
243+
name = "bar"
244+
version = "0.0.1"
245+
edition = "2015"
246+
authors = []
247+
"#,
248+
)
249+
.file("src/lib.rs", "")
250+
.build();
251+
252+
let p = project()
253+
.file(
254+
"Cargo.toml",
255+
&format!(
256+
r#"
237257
[package]
238258
name = "foo"
239259
version = "0.0.1"
240260
authors = []
241261
edition = "2015"
242262
243263
[dependencies.bar]
244-
git = ""
264+
version = "0.0.1"
245265
registry = "alternative"
266+
git="{}"
246267
"#,
268+
bar.url(),
269+
),
247270
)
248271
.file("src/main.rs", "fn main() {}")
249272
.build();
250273

274+
Package::new("bar", "0.0.1").alternative(true).publish();
275+
251276
p.cargo("check")
252-
.with_status(101)
253277
.with_stderr_data(str![[r#"
254-
[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml`
255-
256-
Caused by:
257-
dependency (bar) specification is ambiguous. Only one of `git` or `registry` is allowed.
278+
[UPDATING] git repository `[ROOTURL]/bar`
279+
[LOCKING] 1 package to latest compatible version
280+
[CHECKING] bar v0.0.1 ([ROOTURL]/bar#[..])
281+
[CHECKING] foo v0.0.1 ([ROOT]/foo)
282+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
258283
259284
"#]])
260285
.run();
@@ -648,6 +673,111 @@ fn publish_with_crates_io_dep() {
648673
);
649674
}
650675

676+
#[cargo_test]
677+
fn publish_with_git_and_registry_dep() {
678+
let _reg = RegistryBuilder::new()
679+
.http_api()
680+
.http_index()
681+
.alternative()
682+
.build();
683+
684+
let bar = git::repo(&paths::root().join("bar"))
685+
.file(
686+
"Cargo.toml",
687+
r#"
688+
[package]
689+
name = "bar"
690+
version = "0.0.1"
691+
edition = "2015"
692+
authors = []
693+
"#,
694+
)
695+
.file("src/lib.rs", "")
696+
.build();
697+
698+
let p = project()
699+
.file(
700+
"Cargo.toml",
701+
&format!(
702+
r#"
703+
[package]
704+
name = "foo"
705+
version = "0.0.1"
706+
authors = []
707+
edition = "2015"
708+
709+
[dependencies.bar]
710+
version = "0.0.1"
711+
registry = "alternative"
712+
git="{}"
713+
"#,
714+
bar.url(),
715+
),
716+
)
717+
.file("src/main.rs", "fn main() {}")
718+
.build();
719+
720+
Package::new("bar", "0.0.1").alternative(true).publish();
721+
722+
p.cargo("publish --registry alternative")
723+
.with_stderr_data(str![[r#"
724+
[UPDATING] `alternative` index
725+
[PACKAGING] foo v0.0.1 ([ROOT]/foo)
726+
[UPDATING] `alternative` index
727+
[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)
728+
[VERIFYING] foo v0.0.1 ([ROOT]/foo)
729+
[DOWNLOADING] crates ...
730+
[DOWNLOADED] bar v0.0.1 (registry `alternative`)
731+
[COMPILING] bar v0.0.1 (registry `alternative`)
732+
[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1)
733+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
734+
[UPLOADING] foo v0.0.1 ([ROOT]/foo)
735+
[UPLOADED] foo v0.0.1 to registry `alternative`
736+
[NOTE] waiting for foo v0.0.1 to be available at registry `alternative`
737+
[HELP] you may press ctrl-c to skip waiting; the crate should be available shortly
738+
[PUBLISHED] foo v0.0.1 at registry `alternative`
739+
740+
"#]])
741+
.run();
742+
743+
validate_alt_upload(
744+
r#"{
745+
"authors": [],
746+
"badges": {},
747+
"categories": [],
748+
"deps": [
749+
{
750+
"default_features": true,
751+
"features": [],
752+
"kind": "normal",
753+
"name": "bar",
754+
"optional": false,
755+
"target": null,
756+
"version_req": "^0.0.1"
757+
}
758+
],
759+
"description": null,
760+
"documentation": null,
761+
"features": {},
762+
"homepage": null,
763+
"keywords": [],
764+
"license": null,
765+
"license_file": null,
766+
"links": null,
767+
"name": "foo",
768+
"readme": null,
769+
"readme_file": null,
770+
"repository": null,
771+
"homepage": null,
772+
"documentation": null,
773+
"rust_version": null,
774+
"vers": "0.0.1"
775+
}"#,
776+
"foo-0.0.1.crate",
777+
&["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"],
778+
);
779+
}
780+
651781
#[cargo_test]
652782
fn passwords_in_registries_index_url_forbidden() {
653783
registry::alt_init();

tests/testsuite/cargo_add/git_registry/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ fn case() {
4646
])
4747
.current_dir(cwd)
4848
.assert()
49-
.failure()
5049
.stdout_eq(str![""])
5150
.stderr_eq(file!["stderr.term.svg"]);
5251

tests/testsuite/cargo_add/git_registry/stderr.term.svg

Lines changed: 5 additions & 10 deletions
Loading

0 commit comments

Comments
 (0)