//! Tests for alternative registries. use std::fs; use cargo_test_support::compare::assert_e2e; use cargo_test_support::prelude::*; use cargo_test_support::publish::validate_alt_upload; use cargo_test_support::registry::{self, Package, RegistryBuilder}; use cargo_test_support::str; use cargo_test_support::{basic_manifest, paths, project}; #[cargo_test] fn depend_on_alt_registry() { registry::alt_init(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] edition = "2015" [dependencies.bar] version = "0.0.1" registry = "alternative" "#, ) .file("src/main.rs", "fn main() {}") .build(); Package::new("bar", "0.0.1").alternative(true).publish(); p.cargo("check") .with_stderr_data(str![[r#" [UPDATING] `alternative` index [LOCKING] 2 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] bar v0.0.1 (registry `alternative`) [CHECKING] bar v0.0.1 (registry `alternative`) [CHECKING] foo v0.0.1 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); p.cargo("clean").run(); // Don't download a second time p.cargo("check") .with_stderr_data(str![[r#" [CHECKING] bar v0.0.1 (registry `alternative`) [CHECKING] foo v0.0.1 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); } #[cargo_test] fn depend_on_alt_registry_depends_on_same_registry_no_index() { registry::alt_init(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] edition = "2015" [dependencies.bar] version = "0.0.1" registry = "alternative" "#, ) .file("src/main.rs", "fn main() {}") .build(); Package::new("baz", "0.0.1").alternative(true).publish(); Package::new("bar", "0.0.1") .registry_dep("baz", "0.0.1") .alternative(true) .publish(); p.cargo("check") .with_stderr_data(str![[r#" [UPDATING] `alternative` index [LOCKING] 3 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] baz v0.0.1 (registry `alternative`) [DOWNLOADED] bar v0.0.1 (registry `alternative`) [CHECKING] baz v0.0.1 (registry `alternative`) [CHECKING] bar v0.0.1 (registry `alternative`) [CHECKING] foo v0.0.1 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); } #[cargo_test] fn depend_on_alt_registry_depends_on_same_registry() { registry::alt_init(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] edition = "2015" [dependencies.bar] version = "0.0.1" registry = "alternative" "#, ) .file("src/main.rs", "fn main() {}") .build(); Package::new("baz", "0.0.1").alternative(true).publish(); Package::new("bar", "0.0.1") .registry_dep("baz", "0.0.1") .alternative(true) .publish(); p.cargo("check") .with_stderr_data(str![[r#" [UPDATING] `alternative` index [LOCKING] 3 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] baz v0.0.1 (registry `alternative`) [DOWNLOADED] bar v0.0.1 (registry `alternative`) [CHECKING] baz v0.0.1 (registry `alternative`) [CHECKING] bar v0.0.1 (registry `alternative`) [CHECKING] foo v0.0.1 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); } #[cargo_test] fn depend_on_alt_registry_depends_on_crates_io() { registry::alt_init(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] edition = "2015" [dependencies.bar] version = "0.0.1" registry = "alternative" "#, ) .file("src/main.rs", "fn main() {}") .build(); Package::new("baz", "0.0.1").publish(); Package::new("bar", "0.0.1") .dep("baz", "0.0.1") .alternative(true) .publish(); p.cargo("check") .with_stderr_data( str![[r#" [UPDATING] `alternative` index [UPDATING] `dummy-registry` index [LOCKING] 3 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] baz v0.0.1 (registry `dummy-registry`) [DOWNLOADED] bar v0.0.1 (registry `alternative`) [CHECKING] baz v0.0.1 [CHECKING] bar v0.0.1 (registry `alternative`) [CHECKING] foo v0.0.1 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]] .unordered(), ) .run(); } #[cargo_test] fn registry_and_path_dep_works() { registry::alt_init(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] edition = "2015" [dependencies.bar] path = "bar" registry = "alternative" "#, ) .file("src/main.rs", "fn main() {}") .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) .file("bar/src/lib.rs", "") .build(); p.cargo("check") .with_stderr_data(str![[r#" [LOCKING] 2 packages to latest compatible versions [CHECKING] bar v0.0.1 ([ROOT]/foo/bar) [CHECKING] foo v0.0.1 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); } #[cargo_test] fn registry_incompatible_with_git() { registry::alt_init(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] edition = "2015" [dependencies.bar] git = "" registry = "alternative" "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("check") .with_status(101) .with_stderr_data(str![[r#" [ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` Caused by: dependency (bar) specification is ambiguous. Only one of `git` or `registry` is allowed. "#]]) .run(); } #[cargo_test] fn cannot_publish_to_crates_io_with_registry_dependency() { let crates_io = registry::init(); let _alternative = RegistryBuilder::new().alternative().build(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] edition = "2015" [dependencies.bar] version = "0.0.1" registry = "alternative" "#, ) .file("src/main.rs", "fn main() {}") .build(); Package::new("bar", "0.0.1").alternative(true).publish(); p.cargo("publish") .replace_crates_io(crates_io.index_url()) .with_status(101) .with_stderr_data(str![[r#" [UPDATING] crates.io index [ERROR] crates cannot be published to crates.io with dependencies sourced from other registries. `bar` needs to be published to crates.io before publishing this crate. (crate `bar` is pulled from registry `alternative`) "#]]) .run(); p.cargo("publish") .replace_crates_io(crates_io.index_url()) .arg("--token") .arg(crates_io.token()) .arg("--index") .arg(crates_io.index_url().as_str()) .with_status(101) .with_stderr_data(str![[r#" [UPDATING] crates.io index [ERROR] crates cannot be published to crates.io with dependencies sourced from other registries. `bar` needs to be published to crates.io before publishing this crate. (crate `bar` is pulled from registry `alternative`) "#]]) .run(); } #[cargo_test] fn publish_with_registry_dependency() { let _reg = RegistryBuilder::new() .http_api() .http_index() .alternative() .build(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] edition = "2015" [dependencies.bar] version = "0.0.1" registry = "alternative" "#, ) .file("src/main.rs", "fn main() {}") .build(); Package::new("bar", "0.0.1").alternative(true).publish(); p.cargo("publish --registry alternative") .with_stderr_data(str![[r#" [UPDATING] `alternative` index [WARNING] manifest has no description, license, license-file, documentation, homepage or repository. See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. [PACKAGING] foo v0.0.1 ([ROOT]/foo) [UPDATING] `alternative` index [PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) [VERIFYING] foo v0.0.1 ([ROOT]/foo) [DOWNLOADING] crates ... [DOWNLOADED] bar v0.0.1 (registry `alternative`) [COMPILING] bar v0.0.1 (registry `alternative`) [COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s [UPLOADING] foo v0.0.1 ([ROOT]/foo) [UPLOADED] foo v0.0.1 to registry `alternative` [NOTE] waiting for `foo v0.0.1` to be available at registry `alternative`. You may press ctrl-c to skip waiting; the crate should be available shortly. [PUBLISHED] foo v0.0.1 at registry `alternative` "#]]) .run(); validate_alt_upload( r#"{ "authors": [], "badges": {}, "categories": [], "deps": [ { "default_features": true, "features": [], "kind": "normal", "name": "bar", "optional": false, "target": null, "version_req": "^0.0.1" } ], "description": null, "documentation": null, "features": {}, "homepage": null, "keywords": [], "license": null, "license_file": null, "links": null, "name": "foo", "readme": null, "readme_file": null, "repository": null, "homepage": null, "documentation": null, "rust_version": null, "vers": "0.0.1" }"#, "foo-0.0.1.crate", &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], ); } #[cargo_test] fn alt_registry_and_crates_io_deps() { registry::alt_init(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] edition = "2015" [dependencies] crates_io_dep = "0.0.1" [dependencies.alt_reg_dep] version = "0.1.0" registry = "alternative" "#, ) .file("src/main.rs", "fn main() {}") .build(); Package::new("crates_io_dep", "0.0.1").publish(); Package::new("alt_reg_dep", "0.1.0") .alternative(true) .publish(); p.cargo("check") .with_stderr_data( str![[r#" [UPDATING] `alternative` index [UPDATING] `dummy-registry` index [LOCKING] 3 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] crates_io_dep v0.0.1 (registry `dummy-registry`) [DOWNLOADED] alt_reg_dep v0.1.0 (registry `alternative`) [CHECKING] crates_io_dep v0.0.1 [CHECKING] alt_reg_dep v0.1.0 (registry `alternative`) [CHECKING] foo v0.0.1 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]] .unordered(), ) .run(); } #[cargo_test] fn block_publish_due_to_no_token() { registry::alt_init(); let p = project().file("src/lib.rs", "").build(); fs::remove_file(paths::home().join(".cargo/credentials.toml")).unwrap(); // Now perform the actual publish p.cargo("publish --registry alternative") .with_status(101) .with_stderr_data(str![[r#" [UPDATING] `alternative` index [ERROR] no token found for `alternative`, please run `cargo login --registry alternative` or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN "#]]) .run(); } #[cargo_test] fn cargo_registries_crates_io_protocol() { let _ = RegistryBuilder::new() .no_configure_token() .alternative() .build(); // Should not produce a warning due to the registries.crates-io.protocol = 'sparse' configuration let p = project() .file("src/lib.rs", "") .file( ".cargo/config.toml", "[registries.crates-io] protocol = 'sparse'", ) .build(); p.cargo("publish --registry alternative") .with_status(101) .with_stderr_data(str![[r#" [UPDATING] `alternative` index [ERROR] no token found for `alternative`, please run `cargo login --registry alternative` or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN "#]]) .run(); } #[cargo_test] fn publish_to_alt_registry() { let _reg = RegistryBuilder::new() .http_api() .http_index() .alternative() .build(); let p = project().file("src/main.rs", "fn main() {}").build(); // Now perform the actual publish p.cargo("publish --registry alternative") .with_stderr_data(str![[r#" [UPDATING] `alternative` index [WARNING] manifest has no description, license, license-file, documentation, homepage or repository. See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. [PACKAGING] foo v0.0.1 ([ROOT]/foo) [PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) [VERIFYING] foo v0.0.1 ([ROOT]/foo) [COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s [UPLOADING] foo v0.0.1 ([ROOT]/foo) [UPLOADED] foo v0.0.1 to registry `alternative` [NOTE] waiting for `foo v0.0.1` to be available at registry `alternative`. You may press ctrl-c to skip waiting; the crate should be available shortly. [PUBLISHED] foo v0.0.1 at registry `alternative` "#]]) .run(); validate_alt_upload( r#"{ "authors": [], "badges": {}, "categories": [], "deps": [], "description": null, "documentation": null, "features": {}, "homepage": null, "keywords": [], "license": null, "license_file": null, "links": null, "name": "foo", "readme": null, "readme_file": null, "repository": null, "homepage": null, "documentation": null, "rust_version": null, "vers": "0.0.1" }"#, "foo-0.0.1.crate", &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], ); } #[cargo_test] fn publish_with_crates_io_dep() { // crates.io registry. let _dummy_reg = registry::init(); // Alternative registry. let _alt_reg = RegistryBuilder::new() .http_api() .http_index() .alternative() .build(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = ["me"] edition = "2015" license = "MIT" description = "foo" [dependencies.bar] version = "0.0.1" "#, ) .file("src/main.rs", "fn main() {}") .build(); Package::new("bar", "0.0.1").publish(); p.cargo("publish --registry alternative") .with_stderr_data(str![[r#" [UPDATING] `alternative` index [WARNING] manifest has no documentation, homepage or repository. See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. [PACKAGING] foo v0.0.1 ([ROOT]/foo) [UPDATING] `dummy-registry` index [PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) [VERIFYING] foo v0.0.1 ([ROOT]/foo) [DOWNLOADING] crates ... [DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) [COMPILING] bar v0.0.1 [COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s [UPLOADING] foo v0.0.1 ([ROOT]/foo) [UPLOADED] foo v0.0.1 to registry `alternative` [NOTE] waiting for `foo v0.0.1` to be available at registry `alternative`. You may press ctrl-c to skip waiting; the crate should be available shortly. [PUBLISHED] foo v0.0.1 at registry `alternative` "#]]) .run(); validate_alt_upload( r#"{ "authors": ["me"], "badges": {}, "categories": [], "deps": [ { "default_features": true, "features": [], "kind": "normal", "name": "bar", "optional": false, "registry": "https://github.com/rust-lang/crates.io-index", "target": null, "version_req": "^0.0.1" } ], "description": "foo", "documentation": null, "features": {}, "homepage": null, "keywords": [], "license": "MIT", "license_file": null, "links": null, "name": "foo", "readme": null, "readme_file": null, "repository": null, "homepage": null, "documentation": null, "rust_version": null, "vers": "0.0.1" }"#, "foo-0.0.1.crate", &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], ); } #[cargo_test] fn passwords_in_registries_index_url_forbidden() { registry::alt_init(); let config = paths::home().join(".cargo/config.toml"); fs::write( config, r#" [registries.alternative] index = "ssh://git:secret@foobar.com" "#, ) .unwrap(); let p = project().file("src/main.rs", "fn main() {}").build(); p.cargo("publish --registry alternative") .with_status(101) .with_stderr_data(str![[r#" [ERROR] invalid index URL for registry `alternative` defined in [ROOT]/home/.cargo/config.toml Caused by: registry URLs may not contain passwords "#]]) .run(); } #[cargo_test] fn patch_alt_reg() { registry::alt_init(); Package::new("bar", "0.1.0").publish(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" edition = "2015" [dependencies] bar = { version = "0.1.0", registry = "alternative" } [patch.alternative] bar = { path = "bar" } "#, ) .file( "src/lib.rs", " extern crate bar; pub fn f() { bar::bar(); } ", ) .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) .file("bar/src/lib.rs", "pub fn bar() {}") .build(); p.cargo("check") .with_stderr_data(str![[r#" [UPDATING] `alternative` index [LOCKING] 2 packages to latest compatible versions [CHECKING] bar v0.1.0 ([ROOT]/foo/bar) [CHECKING] foo v0.0.1 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); } #[cargo_test] fn bad_registry_name() { let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] edition = "2015" [dependencies.bar] version = "0.0.1" registry = "bad name" "#, ) .file("src/main.rs", "fn main() {}") .build(); p.cargo("build") .with_status(101) .with_stderr_data(str![[r#" [ERROR] invalid character ` ` in registry name: `bad name`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters) --> Cargo.toml:8:17 | 8 | [dependencies.bar] | _________________^ 9 | | version = "0.0.1" 10 | | registry = "bad name" | |_____________________________________^ | "#]]) .run(); for cmd in &[ "init", "install foo", "login", "owner", "publish", "search", "yank --version 0.0.1", ] { p.cargo(cmd) .arg("--registry") .arg("bad name") .with_status(101) .with_stderr_data(str![[r#" [ERROR] invalid character ` ` in registry name: `bad name`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters) "#]]) .run(); } } #[cargo_test] fn no_api() { let _registry = RegistryBuilder::new().alternative().no_api().build(); Package::new("bar", "0.0.1").alternative(true).publish(); // First check that a dependency works. let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" edition = "2015" [dependencies.bar] version = "0.0.1" registry = "alternative" "#, ) .file("src/lib.rs", "") .build(); p.cargo("check") .with_stderr_data(str![[r#" [UPDATING] `alternative` index [LOCKING] 2 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] bar v0.0.1 (registry `alternative`) [CHECKING] bar v0.0.1 (registry `alternative`) [CHECKING] foo v0.0.1 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); p.cargo("login --registry alternative TOKEN") .with_status(101) .with_stderr_data(str![[r#" [ERROR] registry `alternative` does not support API commands "#]]) .run(); p.cargo("publish --registry alternative") .with_status(101) .with_stderr_data(str![[r#" [UPDATING] `alternative` index [ERROR] registry `alternative` does not support API commands "#]]) .run(); p.cargo("search --registry alternative") .with_status(101) .with_stderr_data(str![[r#" [ERROR] registry `alternative` does not support API commands "#]]) .run(); p.cargo("owner --registry alternative --list") .with_status(101) .with_stderr_data(str![[r#" [UPDATING] `alternative` index [ERROR] registry `alternative` does not support API commands "#]]) .run(); p.cargo("yank --registry alternative --version=0.0.1 bar") .with_status(101) .with_stderr_data(str![[r#" [UPDATING] `alternative` index [ERROR] registry `alternative` does not support API commands "#]]) .run(); p.cargo("yank --registry alternative --version=0.0.1 bar") .with_status(101) .with_stderr_data(str![[r#" [UPDATING] `alternative` index [ERROR] registry `alternative` does not support API commands "#]]) .run(); } #[cargo_test] fn alt_reg_metadata() { // Check for "registry" entries in `cargo metadata` with alternative registries. registry::alt_init(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" edition = "2015" [dependencies] altdep = { version = "0.0.1", registry = "alternative" } iodep = { version = "0.0.1" } "#, ) .file("src/lib.rs", "") .build(); Package::new("bar", "0.0.1").publish(); Package::new("altdep", "0.0.1") .dep("bar", "0.0.1") .alternative(true) .publish(); Package::new("altdep2", "0.0.1").alternative(true).publish(); Package::new("iodep", "0.0.1") .registry_dep("altdep2", "0.0.1") .publish(); // The important thing to check here is the "registry" value in `deps`. // They should be: // foo -> altdep: alternative-registry // foo -> iodep: null (because it is in crates.io) // altdep -> bar: null (because it is in crates.io) // iodep -> altdep2: alternative-registry p.cargo("metadata --format-version=1 --no-deps") .with_stdout_data( str![[r#" { "metadata": null, "packages": [ { "authors": [], "categories": [], "default_run": null, "dependencies": [ { "features": [], "kind": null, "name": "altdep", "optional": false, "registry": "[ROOTURL]/alternative-registry", "rename": null, "req": "^0.0.1", "source": "registry+[ROOTURL]/alternative-registry", "target": null, "uses_default_features": true }, { "features": [], "kind": null, "name": "iodep", "optional": false, "registry": null, "rename": null, "req": "^0.0.1", "source": "registry+https://github.com/rust-lang/crates.io-index", "target": null, "uses_default_features": true } ], "description": null, "documentation": null, "edition": "2015", "features": {}, "homepage": null, "id": "path+[ROOTURL]/foo#0.0.1", "keywords": [], "license": null, "license_file": null, "links": null, "manifest_path": "[ROOT]/foo/Cargo.toml", "metadata": null, "name": "foo", "publish": null, "readme": null, "repository": null, "rust_version": null, "source": null, "targets": [ { "crate_types": [ "lib" ], "doc": true, "doctest": true, "edition": "2015", "kind": [ "lib" ], "name": "foo", "src_path": "[ROOT]/foo/src/lib.rs", "test": true } ], "version": "0.0.1" } ], "resolve": null, "target_directory": "[ROOT]/foo/target", "version": 1, "workspace_default_members": [ "path+[ROOTURL]/foo#0.0.1" ], "workspace_members": [ "path+[ROOTURL]/foo#0.0.1" ], "workspace_root": "[ROOT]/foo" } "#]] .json(), ) .run(); // --no-deps uses a different code path, make sure both work. p.cargo("metadata --format-version=1") .with_stdout_data( str![[r#" { "metadata": null, "packages": [ { "authors": [], "categories": [], "default_run": null, "dependencies": [ { "features": [], "kind": null, "name": "bar", "optional": false, "registry": null, "rename": null, "req": "^0.0.1", "source": "registry+https://github.com/rust-lang/crates.io-index", "target": null, "uses_default_features": true } ], "description": null, "documentation": null, "edition": "2015", "features": {}, "homepage": null, "id": "registry+[ROOTURL]/alternative-registry#altdep@0.0.1", "keywords": [], "license": null, "license_file": null, "links": null, "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/altdep-0.0.1/Cargo.toml", "metadata": null, "name": "altdep", "publish": null, "readme": null, "repository": null, "rust_version": null, "source": "registry+[ROOTURL]/alternative-registry", "targets": [ { "crate_types": [ "lib" ], "doc": true, "doctest": true, "edition": "2015", "kind": [ "lib" ], "name": "altdep", "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/altdep-0.0.1/src/lib.rs", "test": true } ], "version": "0.0.1" }, { "authors": [], "categories": [], "default_run": null, "dependencies": [], "description": null, "documentation": null, "edition": "2015", "features": {}, "homepage": null, "id": "registry+[ROOTURL]/alternative-registry#altdep2@0.0.1", "keywords": [], "license": null, "license_file": null, "links": null, "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/altdep2-0.0.1/Cargo.toml", "metadata": null, "name": "altdep2", "publish": null, "readme": null, "repository": null, "rust_version": null, "source": "registry+[ROOTURL]/alternative-registry", "targets": [ { "crate_types": [ "lib" ], "doc": true, "doctest": true, "edition": "2015", "kind": [ "lib" ], "name": "altdep2", "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/altdep2-0.0.1/src/lib.rs", "test": true } ], "version": "0.0.1" }, { "authors": [], "categories": [], "default_run": null, "dependencies": [], "description": null, "documentation": null, "edition": "2015", "features": {}, "homepage": null, "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1", "keywords": [], "license": null, "license_file": null, "links": null, "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/Cargo.toml", "metadata": null, "name": "bar", "publish": null, "readme": null, "repository": null, "rust_version": null, "source": "registry+https://github.com/rust-lang/crates.io-index", "targets": [ { "crate_types": [ "lib" ], "doc": true, "doctest": true, "edition": "2015", "kind": [ "lib" ], "name": "bar", "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/src/lib.rs", "test": true } ], "version": "0.0.1" }, { "authors": [], "categories": [], "default_run": null, "dependencies": [ { "features": [], "kind": null, "name": "altdep", "optional": false, "registry": "[ROOTURL]/alternative-registry", "rename": null, "req": "^0.0.1", "source": "registry+[ROOTURL]/alternative-registry", "target": null, "uses_default_features": true }, { "features": [], "kind": null, "name": "iodep", "optional": false, "registry": null, "rename": null, "req": "^0.0.1", "source": "registry+https://github.com/rust-lang/crates.io-index", "target": null, "uses_default_features": true } ], "description": null, "documentation": null, "edition": "2015", "features": {}, "homepage": null, "id": "path+[ROOTURL]/foo#0.0.1", "keywords": [], "license": null, "license_file": null, "links": null, "manifest_path": "[ROOT]/foo/Cargo.toml", "metadata": null, "name": "foo", "publish": null, "readme": null, "repository": null, "rust_version": null, "source": null, "targets": [ { "crate_types": [ "lib" ], "doc": true, "doctest": true, "edition": "2015", "kind": [ "lib" ], "name": "foo", "src_path": "[ROOT]/foo/src/lib.rs", "test": true } ], "version": "0.0.1" }, { "authors": [], "categories": [], "default_run": null, "dependencies": [ { "features": [], "kind": null, "name": "altdep2", "optional": false, "registry": "[ROOTURL]/alternative-registry", "rename": null, "req": "^0.0.1", "source": "registry+[ROOTURL]/alternative-registry", "target": null, "uses_default_features": true } ], "description": null, "documentation": null, "edition": "2015", "features": {}, "homepage": null, "id": "registry+https://github.com/rust-lang/crates.io-index#iodep@0.0.1", "keywords": [], "license": null, "license_file": null, "links": null, "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/iodep-0.0.1/Cargo.toml", "metadata": null, "name": "iodep", "publish": null, "readme": null, "repository": null, "rust_version": null, "source": "registry+https://github.com/rust-lang/crates.io-index", "targets": [ { "crate_types": [ "lib" ], "doc": true, "doctest": true, "edition": "2015", "kind": [ "lib" ], "name": "iodep", "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/iodep-0.0.1/src/lib.rs", "test": true } ], "version": "0.0.1" } ], "resolve": { "nodes": [ { "dependencies": [ "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1" ], "deps": [ { "dep_kinds": [ { "kind": null, "target": null } ], "name": "bar", "pkg": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1" } ], "features": [], "id": "registry+[ROOTURL]/alternative-registry#altdep@0.0.1" }, { "dependencies": [], "deps": [], "features": [], "id": "registry+[ROOTURL]/alternative-registry#altdep2@0.0.1" }, { "dependencies": [], "deps": [], "features": [], "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1" }, { "dependencies": [ "registry+[ROOTURL]/alternative-registry#altdep@0.0.1", "registry+https://github.com/rust-lang/crates.io-index#iodep@0.0.1" ], "deps": [ { "dep_kinds": [ { "kind": null, "target": null } ], "name": "altdep", "pkg": "registry+[ROOTURL]/alternative-registry#altdep@0.0.1" }, { "dep_kinds": [ { "kind": null, "target": null } ], "name": "iodep", "pkg": "registry+https://github.com/rust-lang/crates.io-index#iodep@0.0.1" } ], "features": [], "id": "path+[ROOTURL]/foo#0.0.1" }, { "dependencies": [ "registry+[ROOTURL]/alternative-registry#altdep2@0.0.1" ], "deps": [ { "dep_kinds": [ { "kind": null, "target": null } ], "name": "altdep2", "pkg": "registry+[ROOTURL]/alternative-registry#altdep2@0.0.1" } ], "features": [], "id": "registry+https://github.com/rust-lang/crates.io-index#iodep@0.0.1" } ], "root": "path+[ROOTURL]/foo#0.0.1" }, "target_directory": "[ROOT]/foo/target", "version": 1, "workspace_default_members": [ "path+[ROOTURL]/foo#0.0.1" ], "workspace_members": [ "path+[ROOTURL]/foo#0.0.1" ], "workspace_root": "[ROOT]/foo" } "#]] .json(), ) .run(); } #[cargo_test] fn unknown_registry() { // A known registry refers to an unknown registry. // foo -> bar(crates.io) -> baz(alt) registry::alt_init(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] edition = "2015" [dependencies.bar] version = "0.0.1" "#, ) .file("src/main.rs", "fn main() {}") .build(); Package::new("baz", "0.0.1").alternative(true).publish(); Package::new("bar", "0.0.1") .registry_dep("baz", "0.0.1") .publish(); // Remove "alternative" from config. let cfg_path = paths::home().join(".cargo/config.toml"); let mut config = fs::read_to_string(&cfg_path).unwrap(); let start = config.find("[registries.alternative]").unwrap(); config.insert(start, '#'); let start_index = &config[start..].find("index =").unwrap(); config.insert(start + start_index, '#'); fs::write(&cfg_path, config).unwrap(); p.cargo("check").run(); // Important parts: // foo -> bar registry = null // bar -> baz registry = alternate p.cargo("metadata --format-version=1") .with_stdout_data( str![[r#" { "metadata": null, "packages": [ { "authors": [], "categories": [], "default_run": null, "dependencies": [ { "features": [], "kind": null, "name": "baz", "optional": false, "registry": "[ROOTURL]/alternative-registry", "rename": null, "req": "^0.0.1", "source": "registry+[ROOTURL]/alternative-registry", "target": null, "uses_default_features": true } ], "description": null, "documentation": null, "edition": "2015", "features": {}, "homepage": null, "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1", "keywords": [], "license": null, "license_file": null, "links": null, "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/Cargo.toml", "metadata": null, "name": "bar", "publish": null, "readme": null, "repository": null, "rust_version": null, "source": "registry+https://github.com/rust-lang/crates.io-index", "targets": [ { "crate_types": [ "lib" ], "doc": true, "doctest": true, "edition": "2015", "kind": [ "lib" ], "name": "bar", "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/src/lib.rs", "test": true } ], "version": "0.0.1" }, { "authors": [], "categories": [], "default_run": null, "dependencies": [], "description": null, "documentation": null, "edition": "2015", "features": {}, "homepage": null, "id": "registry+[ROOTURL]/alternative-registry#baz@0.0.1", "keywords": [], "license": null, "license_file": null, "links": null, "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/baz-0.0.1/Cargo.toml", "metadata": null, "name": "baz", "publish": null, "readme": null, "repository": null, "rust_version": null, "source": "registry+[ROOTURL]/alternative-registry", "targets": [ { "crate_types": [ "lib" ], "doc": true, "doctest": true, "edition": "2015", "kind": [ "lib" ], "name": "baz", "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/baz-0.0.1/src/lib.rs", "test": true } ], "version": "0.0.1" }, { "authors": [], "categories": [], "default_run": null, "dependencies": [ { "features": [], "kind": null, "name": "bar", "optional": false, "registry": null, "rename": null, "req": "^0.0.1", "source": "registry+https://github.com/rust-lang/crates.io-index", "target": null, "uses_default_features": true } ], "description": null, "documentation": null, "edition": "2015", "features": {}, "homepage": null, "id": "path+[ROOTURL]/foo#0.0.1", "keywords": [], "license": null, "license_file": null, "links": null, "manifest_path": "[ROOT]/foo/Cargo.toml", "metadata": null, "name": "foo", "publish": null, "readme": null, "repository": null, "rust_version": null, "source": null, "targets": [ { "crate_types": [ "bin" ], "doc": true, "doctest": false, "edition": "2015", "kind": [ "bin" ], "name": "foo", "src_path": "[ROOT]/foo/src/main.rs", "test": true } ], "version": "0.0.1" } ], "resolve": { "nodes": [ { "dependencies": [ "registry+[ROOTURL]/alternative-registry#baz@0.0.1" ], "deps": [ { "dep_kinds": [ { "kind": null, "target": null } ], "name": "baz", "pkg": "registry+[ROOTURL]/alternative-registry#baz@0.0.1" } ], "features": [], "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1" }, { "dependencies": [], "deps": [], "features": [], "id": "registry+[ROOTURL]/alternative-registry#baz@0.0.1" }, { "dependencies": [ "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1" ], "deps": [ { "dep_kinds": [ { "kind": null, "target": null } ], "name": "bar", "pkg": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1" } ], "features": [], "id": "path+[ROOTURL]/foo#0.0.1" } ], "root": "path+[ROOTURL]/foo#0.0.1" }, "target_directory": "[ROOT]/foo/target", "version": 1, "workspace_default_members": [ "path+[ROOTURL]/foo#0.0.1" ], "workspace_members": [ "path+[ROOTURL]/foo#0.0.1" ], "workspace_root": "[ROOT]/foo" } "#]] .json(), ) .run(); } #[cargo_test] fn registries_index_relative_url() { registry::alt_init(); let config = paths::root().join(".cargo/config.toml"); fs::create_dir_all(config.parent().unwrap()).unwrap(); fs::write( &config, r#" [registries.relative] index = "file:alternative-registry" "#, ) .unwrap(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] edition = "2015" [dependencies.bar] version = "0.0.1" registry = "relative" "#, ) .file("src/main.rs", "fn main() {}") .build(); Package::new("bar", "0.0.1").alternative(true).publish(); p.cargo("check") .with_stderr_data(str![[r#" [UPDATING] `relative` index [LOCKING] 2 packages to latest compatible versions [DOWNLOADING] crates ... [DOWNLOADED] bar v0.0.1 (registry `relative`) [CHECKING] bar v0.0.1 (registry `relative`) [CHECKING] foo v0.0.1 ([ROOT]/foo) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s "#]]) .run(); } #[cargo_test] fn registries_index_relative_path_not_allowed() { registry::alt_init(); let config = paths::root().join(".cargo/config.toml"); fs::create_dir_all(config.parent().unwrap()).unwrap(); fs::write( &config, r#" [registries.relative] index = "alternative-registry" "#, ) .unwrap(); let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" authors = [] edition = "2015" [dependencies.bar] version = "0.0.1" registry = "relative" "#, ) .file("src/main.rs", "fn main() {}") .build(); Package::new("bar", "0.0.1").alternative(true).publish(); p.cargo("check") .with_stderr_data(str![[r#" [ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` Caused by: invalid index URL for registry `relative` defined in [ROOT]/.cargo/config.toml Caused by: invalid url `alternative-registry`: relative URL without a base "#]]) .with_status(101) .run(); } #[cargo_test] fn both_index_and_registry() { let p = project().file("src/lib.rs", "").build(); for cmd in &["publish", "owner", "search", "yank --version 1.0.0"] { p.cargo(cmd) .arg("--registry=foo") .arg("--index=foo") .with_status(1) .with_stderr_data(str![[r#" [ERROR] the argument '--registry ' cannot be used with '--index ' Usage: [..] For more information, try '--help'. "#]]) .run(); } } #[cargo_test] fn both_index_and_default() { let p = project().file("src/lib.rs", "").build(); for cmd in &[ "publish", "owner", "search", "yank --version 1.0.0", "install foo", ] { p.cargo(cmd) .env("CARGO_REGISTRY_DEFAULT", "undefined") .arg(format!("--index=index_url")) .with_status(101) .with_stderr_data(str![[r#" [ERROR] invalid url `index_url`: relative URL without a base "#]]) .run(); } } #[cargo_test] fn sparse_lockfile() { let _registry = registry::RegistryBuilder::new() .http_index() .alternative() .build(); Package::new("foo", "0.1.0").alternative(true).publish(); let p = project() .file( "Cargo.toml", r#" [project] name = "a" version = "0.5.0" authors = [] edition = "2015" [dependencies] foo = { registry = 'alternative', version = '0.1.0'} "#, ) .file("src/lib.rs", "") .build(); p.cargo("generate-lockfile").run(); assert_e2e().eq( &p.read_lockfile(), str![[r##" # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "a" version = "0.5.0" dependencies = [ "foo", ] [[package]] name = "foo" version = "0.1.0" source = "sparse+http://127.0.0.1:[..]/index/" checksum = "458c1addb23fde7dfbca0410afdbcc0086f96197281ec304d9e0e10def3cb899" "##]], ); } #[cargo_test] fn publish_with_transitive_dep() { let _alt1 = RegistryBuilder::new() .http_api() .http_index() .alternative_named("Alt-1") .build(); let _alt2 = RegistryBuilder::new() .http_api() .http_index() .alternative_named("Alt-2") .build(); let p1 = project() .file( "Cargo.toml", r#" [package] name = "a" version = "0.5.0" edition = "2015" "#, ) .file("src/lib.rs", "") .build(); p1.cargo("publish --registry Alt-1").run(); let p2 = project() .file( "Cargo.toml", r#" [package] name = "b" version = "0.6.0" publish = ["Alt-2"] edition = "2015" [dependencies] a = { version = "0.5.0", registry = "Alt-1" } "#, ) .file("src/lib.rs", "") .build(); p2.cargo("publish").run(); } #[cargo_test] fn warn_for_unused_fields() { let _ = RegistryBuilder::new() .no_configure_token() .alternative() .build(); let p = project() .file("src/lib.rs", "") .file( ".cargo/config.toml", "[registry] unexpected-field = 'foo' [registries.alternative] unexpected-field = 'foo' ", ) .build(); p.cargo("publish --registry alternative") .with_status(101) .with_stderr_data(str![[r#" [UPDATING] `alternative` index [WARNING] unused config key `registries.alternative.unexpected-field` in `[ROOT]/foo/.cargo/config.toml` [ERROR] no token found for `alternative`, please run `cargo login --registry alternative` or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN "#]]) .run(); let crates_io = registry::RegistryBuilder::new() .no_configure_token() .build(); p.cargo("publish --registry crates-io") .replace_crates_io(crates_io.index_url()) .with_status(101) .with_stderr_data(str![[r#" [UPDATING] crates.io index [WARNING] unused config key `registry.unexpected-field` in `[ROOT]/foo/.cargo/config.toml` [ERROR] no token found, please run `cargo login` or use environment variable CARGO_REGISTRY_TOKEN "#]]) .run(); } #[cargo_test] fn config_empty_registry_name() { let _ = RegistryBuilder::new() .no_configure_token() .alternative() .build(); let p = project() .file("src/lib.rs", "") .file( ".cargo/config.toml", "[registry.''] ", ) .build(); p.cargo("publish") .arg("--registry") .arg("") .with_status(101) .with_stderr_data(str![[r#" [ERROR] registry name cannot be empty "#]]) .run(); } #[cargo_test] fn empty_registry_flag() { let p = project().file("src/lib.rs", "").build(); p.cargo("publish") .arg("--registry") .arg("") .with_status(101) .with_stderr_data(str![[r#" [ERROR] registry name cannot be empty "#]]) .run(); } #[cargo_test] fn empty_dependency_registry() { let p = project() .file( "Cargo.toml", r#" [package] name = "foo" version = "0.0.1" edition = "2015" [dependencies] bar = { version = "0.1.0", registry = "" } "#, ) .file( "src/lib.rs", " extern crate bar; pub fn f() { bar::bar(); } ", ) .build(); p.cargo("check") .with_status(101) .with_stderr_data(str![[r#" [ERROR] registry name cannot be empty --> Cargo.toml:8:23 | 8 | bar = { version = "0.1.0", registry = "" } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | "#]]) .run(); }