Implement RFC 3289: source replacement ambiguity

This commit is contained in:
Arlo Siemsen 2022-08-31 00:53:47 -05:00 committed by Arlo Siemsen
parent 8743325fe0
commit dd5134c7a5
32 changed files with 661 additions and 330 deletions

View File

@ -818,6 +818,17 @@ impl Execs {
self
}
/// Overrides the crates.io URL for testing.
///
/// Can be used for testing crates-io functionality where alt registries
/// cannot be used.
pub fn replace_crates_io(&mut self, url: &Url) -> &mut Self {
if let Some(ref mut p) = self.process_builder {
p.env("__CARGO_TEST_CRATES_IO_URL_DO_NOT_USE_THIS", url.as_str());
}
self
}
pub fn enable_mac_dsym(&mut self) -> &mut Self {
if cfg!(target_os = "macos") {
self.env("CARGO_PROFILE_DEV_SPLIT_DEBUGINFO", "packed")

View File

@ -105,7 +105,7 @@ impl RegistryBuilder {
pub fn new() -> RegistryBuilder {
RegistryBuilder {
alternative: None,
token: Some("api-token".to_string()),
token: None,
http_api: false,
http_index: false,
api: true,
@ -197,6 +197,7 @@ impl RegistryBuilder {
let dl_url = generate_url(&format!("{prefix}dl"));
let dl_path = generate_path(&format!("{prefix}dl"));
let api_path = generate_path(&format!("{prefix}api"));
let token = Some(self.token.unwrap_or_else(|| format!("{prefix}sekrit")));
let (server, index_url, api_url, dl_url) = if !self.http_index && !self.http_api {
// No need to start the HTTP server.
@ -205,7 +206,7 @@ impl RegistryBuilder {
let server = HttpServer::new(
registry_path.clone(),
dl_path,
self.token.clone(),
token.clone(),
self.custom_responders,
);
let index_url = if self.http_index {
@ -228,7 +229,7 @@ impl RegistryBuilder {
_server: server,
dl_url,
path: registry_path,
token: self.token,
token,
};
if self.configure_registry {
@ -252,8 +253,8 @@ impl RegistryBuilder {
[source.crates-io]
replace-with = 'dummy-registry'
[source.dummy-registry]
registry = '{}'",
[registries.dummy-registry]
index = '{}'",
registry.index_url
)
.as_bytes(),

View File

@ -1,3 +1,4 @@
use cargo::sources::CRATES_IO_REGISTRY;
use indexmap::IndexMap;
use indexmap::IndexSet;
@ -207,7 +208,10 @@ fn parse_dependencies(config: &Config, matches: &ArgMatches) -> CargoResult<Vec<
let rev = matches.get_one::<String>("rev");
let tag = matches.get_one::<String>("tag");
let rename = matches.get_one::<String>("rename");
let registry = matches.registry(config)?;
let registry = match matches.registry(config)? {
Some(reg) if reg == CRATES_IO_REGISTRY => None,
reg => reg,
};
let default_features = default_features(matches);
let optional = optional(matches);

View File

@ -128,7 +128,7 @@ pub fn add_root_urls(
if !sid.is_registry() {
return false;
}
if sid.is_default_registry() {
if sid.is_crates_io() {
return registry == CRATES_IO_REGISTRY;
}
if let Some(index_url) = name2url.get(registry) {

View File

@ -211,7 +211,7 @@ impl fmt::Display for PackageId {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{} v{}", self.inner.name, self.inner.version)?;
if !self.inner.source_id.is_default_registry() {
if !self.inner.source_id.is_crates_io() {
write!(f, " ({})", self.inner.source_id)?;
}

View File

@ -39,6 +39,10 @@ struct SourceIdInner {
/// WARNING: this is not always set for alt-registries when the name is
/// not known.
name: Option<String>,
/// Name of the alt registry in the `[registries]` table.
/// WARNING: this is not always set for alt-registries when the name is
/// not known.
alt_registry_key: Option<String>,
}
/// The possible kinds of code source. Along with `SourceIdInner`, this fully defines the
@ -81,6 +85,7 @@ impl SourceId {
url,
precise: None,
name: name.map(|n| n.into()),
alt_registry_key: None,
});
Ok(source_id)
}
@ -221,6 +226,9 @@ impl SourceId {
/// Gets the `SourceId` associated with given name of the remote registry.
pub fn alt_registry(config: &Config, key: &str) -> CargoResult<SourceId> {
if key == CRATES_IO_REGISTRY {
return Self::crates_io(config);
}
let url = config.get_registry_index(key)?;
Ok(SourceId::wrap(SourceIdInner {
kind: SourceKind::Registry,
@ -228,6 +236,7 @@ impl SourceId {
url,
precise: None,
name: Some(key.to_string()),
alt_registry_key: Some(key.to_string()),
}))
}
@ -243,7 +252,7 @@ impl SourceId {
}
pub fn display_index(self) -> String {
if self.is_default_registry() {
if self.is_crates_io() {
format!("{} index", CRATES_IO_DOMAIN)
} else {
format!("`{}` index", self.display_registry_name())
@ -251,7 +260,7 @@ impl SourceId {
}
pub fn display_registry_name(self) -> String {
if self.is_default_registry() {
if self.is_crates_io() {
CRATES_IO_REGISTRY.to_string()
} else if let Some(name) = &self.inner.name {
name.clone()
@ -264,6 +273,13 @@ impl SourceId {
}
}
/// Gets the name of the remote registry as defined in the `[registries]` table.
/// WARNING: alt registries that come from Cargo.lock, or --index will
/// not have a name.
pub fn alt_registry_key(&self) -> Option<&str> {
self.inner.alt_registry_key.as_deref()
}
/// Returns `true` if this source is from a filesystem path.
pub fn is_path(self) -> bool {
self.inner.kind == SourceKind::Path
@ -364,13 +380,15 @@ impl SourceId {
}
/// Returns `true` if the remote registry is the standard <https://crates.io>.
pub fn is_default_registry(self) -> bool {
pub fn is_crates_io(self) -> bool {
match self.inner.kind {
SourceKind::Registry => {}
_ => return false,
}
let url = self.inner.url.as_str();
url == CRATES_IO_INDEX || url == CRATES_IO_HTTP_INDEX
url == CRATES_IO_INDEX
|| url == CRATES_IO_HTTP_INDEX
|| std::env::var("__CARGO_TEST_CRATES_IO_URL_DO_NOT_USE_THIS").as_deref() == Ok(url)
}
/// Hashes `self`.

View File

@ -209,7 +209,7 @@ fn verify_dependencies(
// This extra hostname check is mostly to assist with testing,
// but also prevents someone using `--index` to specify
// something that points to crates.io.
if registry_src.is_default_registry() || registry.host_is_crates_io() {
if registry_src.is_crates_io() || registry.host_is_crates_io() {
bail!("crates cannot be published to crates.io with dependencies sourced from other\n\
registries. `{}` needs to be published to crates.io before publishing this crate.\n\
(crate `{}` is pulled from {})",
@ -391,6 +391,22 @@ pub fn registry_configuration(
};
// `registry.default` is handled in command-line parsing.
let (token, process) = match registry {
Some("crates-io") | None => {
// Use crates.io default.
config.check_registry_index_not_set()?;
let token = config.get_string("registry.token")?.map(|p| p.val);
let process = if config.cli_unstable().credential_process {
let process =
config.get::<Option<config::PathAndArgs>>("registry.credential-process")?;
if token.is_some() && process.is_some() {
return err_both("registry.token", "registry.credential-process");
}
process
} else {
None
};
(token, process)
}
Some(registry) => {
let token_key = format!("registries.{registry}.token");
let token = config.get_string(&token_key)?.map(|p| p.val);
@ -411,22 +427,6 @@ pub fn registry_configuration(
};
(token, process)
}
None => {
// Use crates.io default.
config.check_registry_index_not_set()?;
let token = config.get_string("registry.token")?.map(|p| p.val);
let process = if config.cli_unstable().credential_process {
let process =
config.get::<Option<config::PathAndArgs>>("registry.credential-process")?;
if token.is_some() && process.is_some() {
return err_both("registry.token", "registry.credential-process");
}
process
} else {
None
};
(token, process)
}
};
let credential_process =
@ -444,11 +444,9 @@ pub fn registry_configuration(
///
/// * `token`: The token from the command-line. If not set, uses the token
/// from the config.
/// * `index`: The index URL from the command-line. This is ignored if
/// `registry` is set.
/// * `index`: The index URL from the command-line.
/// * `registry`: The registry name from the command-line. If neither
/// `registry`, or `index` are set, then uses `crates-io`, honoring
/// `[source]` replacement if defined.
/// `registry`, or `index` are set, then uses `crates-io`.
/// * `force_update`: If `true`, forces the index to be updated.
/// * `validate_token`: If `true`, the token must be set.
fn registry(
@ -459,24 +457,8 @@ fn registry(
force_update: bool,
validate_token: bool,
) -> CargoResult<(Registry, RegistryConfig, SourceId)> {
if index.is_some() && registry.is_some() {
// Otherwise we would silently ignore one or the other.
bail!("both `--index` and `--registry` should not be set at the same time");
}
// Parse all configuration options
let (sid, sid_no_replacement) = get_source_id(config, index, registry)?;
let reg_cfg = registry_configuration(config, registry)?;
let opt_index = registry
.map(|r| config.get_registry_index(r))
.transpose()?
.map(|u| u.to_string());
let sid = get_source_id(config, opt_index.as_deref().or(index), registry)?;
if !sid.is_remote_registry() {
bail!(
"{} does not support API commands.\n\
Check for a source-replacement in .cargo/config.",
sid
);
}
let api_host = {
let _lock = config.acquire_package_cache_lock()?;
let mut src = RegistrySource::remote(sid, &HashSet::new(), config)?;
@ -503,42 +485,18 @@ fn registry(
}
token
} else {
// Check `is_default_registry` so that the crates.io index can
// change config.json's "api" value, and this won't affect most
// people. It will affect those using source replacement, but
// hopefully that's a relatively small set of users.
if token.is_none()
&& reg_cfg.is_token()
&& registry.is_none()
&& !sid.is_default_registry()
&& !crates_io::is_url_crates_io(&api_host)
{
config.shell().warn(
"using `registry.token` config value with source \
replacement is deprecated\n\
This may become a hard error in the future; \
see <https://github.com/rust-lang/cargo/issues/xxx>.\n\
Use the --token command-line flag to remove this warning.",
)?;
reg_cfg.as_token().map(|t| t.to_owned())
} else {
let token =
auth::auth_token(config, token.as_deref(), &reg_cfg, registry, &api_host)?;
Some(token)
}
let token = auth::auth_token(config, token.as_deref(), &reg_cfg, registry, &api_host)?;
Some(token)
}
} else {
None
};
let handle = http_handle(config)?;
// Workaround for the sparse+https://index.crates.io replacement index. Use the non-replaced
// source_id so that the original (github) url is used when publishing a crate.
let sid = if sid.is_default_registry() {
SourceId::crates_io(config)?
} else {
sid
};
Ok((Registry::new_handle(api_host, token, handle), reg_cfg, sid))
Ok((
Registry::new_handle(api_host, token, handle),
reg_cfg,
sid_no_replacement,
))
}
/// Creates a new HTTP handle with appropriate global configuration for cargo.
@ -947,16 +905,45 @@ pub fn yank(
/// Gets the SourceId for an index or registry setting.
///
/// The `index` and `reg` values are from the command-line or config settings.
/// If both are None, returns the source for crates.io.
fn get_source_id(config: &Config, index: Option<&str>, reg: Option<&str>) -> CargoResult<SourceId> {
match (reg, index) {
(Some(r), _) => SourceId::alt_registry(config, r),
(_, Some(i)) => SourceId::for_registry(&i.into_url()?),
_ => {
let map = SourceConfigMap::new(config)?;
let src = map.load(SourceId::crates_io(config)?, &HashSet::new())?;
Ok(src.replaced_source_id())
/// If both are None, and no source-replacement is configured, returns the source for crates.io.
/// If both are None, and source replacement is configured, returns an error.
///
/// The source for crates.io may be GitHub, index.crates.io, or a test-only registry depending
/// on configuration.
///
/// If `reg` is set, source replacement is not followed.
///
/// The return value is a pair of `SourceId`s: The first may be a built-in replacement of
/// crates.io (such as index.crates.io), while the second is always the original source.
fn get_source_id(
config: &Config,
index: Option<&str>,
reg: Option<&str>,
) -> CargoResult<(SourceId, SourceId)> {
let sid = match (reg, index) {
(None, None) => SourceId::crates_io(config)?,
(Some(r), None) => SourceId::alt_registry(config, r)?,
(None, Some(i)) => SourceId::for_registry(&i.into_url()?)?,
(Some(_), Some(_)) => {
bail!("both `--index` and `--registry` should not be set at the same time")
}
};
// Load source replacements that are built-in to Cargo.
let builtin_replacement_sid = SourceConfigMap::empty(config)?
.load(sid, &HashSet::new())?
.replaced_source_id();
let replacement_sid = SourceConfigMap::new(config)?
.load(sid, &HashSet::new())?
.replaced_source_id();
if reg.is_none() && index.is_none() && replacement_sid != builtin_replacement_sid {
// Neither --registry nor --index was passed and the user has configured source-replacement.
if let Some(replacement_name) = replacement_sid.alt_registry_key() {
bail!("crates-io is replaced with remote registry {replacement_name};\ninclude `--registry {replacement_name}` or `--registry crates-io`");
} else {
bail!("crates-io is replaced with non-remote-registry source {replacement_sid};\ninclude `--registry crates-io` to use crates.io");
}
} else {
Ok((builtin_replacement_sid, sid))
}
}
@ -1024,7 +1011,7 @@ pub fn search(
&ColorSpec::new(),
);
} else if total_crates > limit && limit >= search_max_limit {
let extra = if source_id.is_default_registry() {
let extra = if source_id.is_crates_io() {
format!(
" (go to https://crates.io/search?q={} to see more)",
percent_encode(query.as_bytes(), NON_ALPHANUMERIC)

View File

@ -84,7 +84,7 @@ impl<'a> fmt::Display for Display<'a> {
)?;
let source_id = package.package_id().source_id();
if !source_id.is_default_registry() {
if !source_id.is_crates_io() {
write!(fmt, " ({})", source_id)?;
}
}

View File

@ -252,13 +252,13 @@ fn sync(
// replace original sources with vendor
for source_id in sources {
let name = if source_id.is_default_registry() {
let name = if source_id.is_crates_io() {
CRATES_IO_REGISTRY.to_string()
} else {
source_id.url().to_string()
};
let source = if source_id.is_default_registry() {
let source = if source_id.is_crates_io() {
VendorSource::Registry {
registry: None,
replace_with: merged_source_name.to_string(),

View File

@ -100,6 +100,15 @@ impl<'cfg> SourceConfigMap<'cfg> {
},
)?;
}
if let Ok(url) = std::env::var("__CARGO_TEST_CRATES_IO_URL_DO_NOT_USE_THIS") {
base.add(
CRATES_IO_REGISTRY,
SourceConfig {
id: SourceId::for_alt_registry(&url.parse()?, CRATES_IO_REGISTRY)?,
replace_with: None,
},
)?;
}
Ok(base)
}
@ -121,18 +130,24 @@ impl<'cfg> SourceConfigMap<'cfg> {
};
let mut cfg_loc = "";
let orig_name = name;
let new_id;
loop {
let new_id = loop {
let cfg = match self.cfgs.get(name) {
Some(cfg) => cfg,
None => bail!(
"could not find a configured source with the \
None => {
// Attempt to interpret the source name as an alt registry name
if let Ok(alt_id) = SourceId::alt_registry(self.config, name) {
debug!("following pointer to registry {}", name);
break alt_id.with_precise(id.precise().map(str::to_string));
}
bail!(
"could not find a configured source with the \
name `{}` when attempting to lookup `{}` \
(configuration in `{}`)",
name,
orig_name,
cfg_loc
),
name,
orig_name,
cfg_loc
);
}
};
match &cfg.replace_with {
Some((s, c)) => {
@ -141,8 +156,7 @@ impl<'cfg> SourceConfigMap<'cfg> {
}
None if id == cfg.id => return id.load(self.config, yanked_whitelist),
None => {
new_id = cfg.id.with_precise(id.precise().map(|s| s.to_string()));
break;
break cfg.id.with_precise(id.precise().map(|s| s.to_string()));
}
}
debug!("following pointer to {}", name);
@ -155,7 +169,7 @@ impl<'cfg> SourceConfigMap<'cfg> {
cfg_loc
)
}
}
};
let new_src = new_id.load(
self.config,

View File

@ -402,7 +402,7 @@ impl<'a> RegistryDependency<'a> {
// In index, "registry" is null if it is from the same index.
// In Cargo.toml, "registry" is None if it is from the default
if !id.is_default_registry() {
if !id.is_crates_io() {
dep.set_registry_id(id);
}

View File

@ -2,7 +2,6 @@ use crate::core::compiler::{BuildConfig, MessageFormat, TimingOutput};
use crate::core::resolver::CliFeatures;
use crate::core::{Edition, Workspace};
use crate::ops::{CompileFilter, CompileOptions, NewOptions, Packages, VersionControl};
use crate::sources::CRATES_IO_REGISTRY;
use crate::util::important_paths::find_root_manifest_for_wd;
use crate::util::interning::InternedString;
use crate::util::restricted_names::is_glob_pattern;
@ -669,17 +668,7 @@ pub trait ArgMatchesExt {
match self._value_of("registry") {
Some(registry) => {
validate_package_name(registry, "registry name", "")?;
if registry == CRATES_IO_REGISTRY {
// If "crates.io" is specified, then we just need to return `None`,
// as that will cause cargo to use crates.io. This is required
// for the case where a default alternative registry is used
// but the user wants to switch back to crates.io for a single
// command.
Ok(None)
} else {
Ok(Some(registry.to_string()))
}
Ok(Some(registry.to_string()))
}
None => config.default_registry(),
}

View File

@ -933,7 +933,7 @@ local-registry, or git).
* Default: none
* Environment: not supported
If set, replace this source with the given named source.
If set, replace this source with the given named source or named registry.
##### `source.<name>.directory`
* Type: string (path)

View File

@ -26,6 +26,11 @@ dependencies through the usage of [the `[patch]` key][overriding
dependencies], and private registry support is described in [the Registries
chapter][registries].
When using source replacement, running commands like `cargo publish` that need to
contact the registry require passing the `--registry` option. This helps avoid
any ambiguity about which registry to contact, and will use the authentication
token for the specified registry.
[overriding dependencies]: overriding-dependencies.md
[registries]: registries.md
@ -50,6 +55,9 @@ directory = "vendor"
# The crates.io default source for crates is available under the name
# "crates-io", and here we use the `replace-with` key to indicate that it's
# replaced with our source above.
#
# The `replace-with` key can also reference an alternative registry name
# defined in the `[registries]` table.
[source.crates-io]
replace-with = "my-vendor-source"

View File

@ -1,10 +1,9 @@
//! Tests for alternative registries.
use cargo::util::IntoUrl;
use cargo_test_support::compare::assert_match_exact;
use cargo_test_support::publish::validate_alt_upload;
use cargo_test_support::registry::{self, Package, RegistryBuilder};
use cargo_test_support::{basic_manifest, git, paths, project};
use cargo_test_support::{basic_manifest, paths, project};
use std::fs;
#[cargo_test]
@ -249,9 +248,8 @@ fn registry_incompatible_with_git() {
#[cargo_test]
fn cannot_publish_to_crates_io_with_registry_dependency() {
registry::alt_init();
let fakeio_path = paths::root().join("fake.io");
let fakeio_url = fakeio_path.into_url().unwrap();
let crates_io = registry::init();
let _alternative = RegistryBuilder::new().alternative().build();
let p = project()
.file(
"Cargo.toml",
@ -266,41 +264,22 @@ fn cannot_publish_to_crates_io_with_registry_dependency() {
"#,
)
.file("src/main.rs", "fn main() {}")
.file(
".cargo/config",
&format!(
r#"
[registries.fakeio]
index = "{}"
"#,
fakeio_url
),
)
.build();
Package::new("bar", "0.0.1").alternative(true).publish();
// Since this can't really call plain `publish` without fetching the real
// crates.io index, create a fake one that points to the real crates.io.
git::repo(&fakeio_path)
.file(
"config.json",
r#"
{"dl": "https://crates.io/api/v1/crates", "api": "https://crates.io"}
"#,
)
.build();
// Login so that we have the token available
p.cargo("login --registry fakeio TOKEN").run();
p.cargo("publish --registry fakeio")
p.cargo("publish")
.replace_crates_io(crates_io.index_url())
.with_status(101)
.with_stderr_contains("[ERROR] crates cannot be published to crates.io[..]")
.run();
p.cargo("publish --token sekrit --index")
.arg(fakeio_url.to_string())
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_contains("[ERROR] crates cannot be published to crates.io[..]")
.run();

View File

@ -1872,7 +1872,7 @@ fn env_vars_and_build_products_for_various_build_targets() {
#[cargo_test]
fn publish_artifact_dep() {
registry::init();
let registry = registry::init();
Package::new("bar", "1.0.0").publish();
Package::new("baz", "1.0.0").publish();
@ -1901,7 +1901,8 @@ fn publish_artifact_dep() {
.file("src/lib.rs", "")
.build();
p.cargo("publish -Z bindeps --no-verify --token sekrit")
p.cargo("publish -Z bindeps --no-verify")
.replace_crates_io(registry.index_url())
.masquerade_as_nightly_cargo(&["bindeps"])
.with_stderr(
"\
@ -1924,7 +1925,6 @@ fn publish_artifact_dep() {
"kind": "normal",
"name": "bar",
"optional": false,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^1.0"
},
@ -1934,7 +1934,6 @@ fn publish_artifact_dep() {
"kind": "build",
"name": "baz",
"optional": false,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^1.0"
}

View File

@ -1,6 +1,6 @@
//! Tests for some invalid .cargo/config files.
use cargo_test_support::registry::Package;
use cargo_test_support::registry::{self, Package};
use cargo_test_support::{basic_manifest, project, rustc_host};
#[cargo_test]
@ -62,6 +62,7 @@ Caused by:
#[cargo_test]
fn bad3() {
let registry = registry::init();
let p = project()
.file("src/lib.rs", "")
.file(
@ -75,6 +76,7 @@ fn bad3() {
Package::new("foo", "1.0.0").publish();
p.cargo("publish -v")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(
"\
@ -113,6 +115,7 @@ Caused by:
#[cargo_test]
fn bad6() {
let registry = registry::init();
let p = project()
.file("src/lib.rs", "")
.file(
@ -126,6 +129,7 @@ fn bad6() {
Package::new("foo", "1.0.0").publish();
p.cargo("publish -v")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(
"\

View File

@ -610,7 +610,7 @@ fn z_flags_rejected() {
#[cargo_test]
fn publish_allowed() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -626,7 +626,8 @@ fn publish_allowed() {
)
.file("src/lib.rs", "")
.build();
p.cargo("publish --token sekrit")
p.cargo("publish")
.replace_crates_io(registry.index_url())
.masquerade_as_nightly_cargo(&["test-dummy-unstable"])
.run();
}

View File

@ -15,7 +15,7 @@ fn gated() {
.no_configure_token()
.build();
let _cratesio = registry::RegistryBuilder::new()
let cratesio = registry::RegistryBuilder::new()
.no_configure_token()
.build();
@ -32,6 +32,7 @@ fn gated() {
.build();
p.cargo("publish --no-verify")
.replace_crates_io(cratesio.index_url())
.masquerade_as_nightly_cargo(&["credential-process"])
.with_status(101)
.with_stderr(
@ -147,7 +148,6 @@ fn get_token_test() -> (Project, TestRegistry) {
.alternative()
.http_api()
.build();
// The credential process to use.
let cred_proj = project()
.at("cred_proj")
@ -206,7 +206,7 @@ fn publish() {
#[cargo_test]
fn basic_unsupported() {
// Non-action commands don't support login/logout.
let _server = registry::RegistryBuilder::new()
let registry = registry::RegistryBuilder::new()
.no_configure_token()
.build();
cargo_util::paths::append(
@ -219,6 +219,7 @@ fn basic_unsupported() {
.unwrap();
cargo_process("login -Z credential-process abcdefg")
.replace_crates_io(registry.index_url())
.masquerade_as_nightly_cargo(&["credential-process"])
.with_status(101)
.with_stderr(
@ -232,6 +233,7 @@ the credential-process configuration value must pass the \
.run();
cargo_process("logout -Z credential-process")
.replace_crates_io(registry.index_url())
.masquerade_as_nightly_cargo(&["credential-process", "cargo-logout"])
.with_status(101)
.with_stderr(
@ -288,6 +290,7 @@ fn login() {
cargo_process("login -Z credential-process abcdefg")
.masquerade_as_nightly_cargo(&["credential-process"])
.replace_crates_io(server.index_url())
.with_stderr(
"\
[UPDATING] [..]
@ -303,7 +306,7 @@ fn login() {
#[cargo_test]
fn logout() {
let _server = registry::RegistryBuilder::new()
let server = registry::RegistryBuilder::new()
.no_configure_token()
.build();
// The credential process to use.
@ -342,6 +345,7 @@ fn logout() {
cargo_process("logout -Z credential-process")
.masquerade_as_nightly_cargo(&["credential-process", "cargo-logout"])
.replace_crates_io(server.index_url())
.with_stderr(
"\
[UPDATING] [..]
@ -389,7 +393,7 @@ fn owner() {
#[cargo_test]
fn libexec_path() {
// cargo: prefixed names use the sysroot
let _server = registry::RegistryBuilder::new()
let server = registry::RegistryBuilder::new()
.no_configure_token()
.build();
cargo_util::paths::append(
@ -403,6 +407,7 @@ fn libexec_path() {
cargo_process("login -Z credential-process abcdefg")
.masquerade_as_nightly_cargo(&["credential-process"])
.replace_crates_io(server.index_url())
.with_status(101)
.with_stderr(
// FIXME: Update "Caused by" error message once rust/pull/87704 is merged.

View File

@ -66,7 +66,7 @@ fn publish_with_target() {
return;
}
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -97,12 +97,13 @@ fn publish_with_target() {
let target = cross_compile::alternate();
p.cargo("publish --token sekrit")
p.cargo("publish")
.replace_crates_io(registry.index_url())
.arg("--target")
.arg(&target)
.with_stderr(
"\
[UPDATING] `dummy-registry` index
[UPDATING] crates.io index
[PACKAGING] foo v0.0.0 ([CWD])
[VERIFYING] foo v0.0.0 ([CWD])
[COMPILING] foo v0.0.0 ([CWD]/target/package/foo-0.0.0)

View File

@ -1,7 +1,7 @@
//! Tests for namespaced features.
use super::features2::switch_to_resolver_2;
use cargo_test_support::registry::{Dependency, Package};
use cargo_test_support::registry::{self, Dependency, Package};
use cargo_test_support::{project, publish};
#[cargo_test]
@ -858,6 +858,7 @@ bar v1.0.0
#[cargo_test]
fn publish_no_implicit() {
let registry = registry::init();
// Does not include implicit features or dep: syntax on publish.
Package::new("opt-dep1", "1.0.0").publish();
Package::new("opt-dep2", "1.0.0").publish();
@ -884,7 +885,8 @@ fn publish_no_implicit() {
.file("src/lib.rs", "")
.build();
p.cargo("publish --no-verify --token sekrit")
p.cargo("publish --no-verify")
.replace_crates_io(registry.index_url())
.with_stderr(
"\
[UPDATING] [..]
@ -907,7 +909,6 @@ fn publish_no_implicit() {
"kind": "normal",
"name": "opt-dep1",
"optional": true,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^1.0"
},
@ -917,7 +918,6 @@ fn publish_no_implicit() {
"kind": "normal",
"name": "opt-dep2",
"optional": true,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^1.0"
}
@ -971,6 +971,7 @@ feat = ["opt-dep1"]
#[cargo_test]
fn publish() {
let registry = registry::init();
// Publish behavior with explicit dep: syntax.
Package::new("bar", "1.0.0").publish();
let p = project()
@ -996,7 +997,8 @@ fn publish() {
.file("src/lib.rs", "")
.build();
p.cargo("publish --token sekrit")
p.cargo("publish")
.replace_crates_io(registry.index_url())
.with_stderr(
"\
[UPDATING] [..]
@ -1022,7 +1024,6 @@ fn publish() {
"kind": "normal",
"name": "bar",
"optional": true,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^1.0"
}

View File

@ -107,7 +107,7 @@ Caused by:
#[cargo_test]
fn inherit_own_workspace_fields() {
registry::init();
let registry = registry::init();
let p = project().build();
@ -160,7 +160,9 @@ fn inherit_own_workspace_fields() {
.file("bar.txt", "") // should be included when packaging
.build();
p.cargo("publish --token sekrit").run();
p.cargo("publish")
.replace_crates_io(registry.index_url())
.run();
publish::validate_upload_with_contents(
r#"
{
@ -231,6 +233,7 @@ repository = "https://gitlab.com/rust-lang/rust"
#[cargo_test]
fn inherit_own_dependencies() {
let registry = registry::init();
let p = project()
.file(
"Cargo.toml",
@ -284,7 +287,9 @@ fn inherit_own_dependencies() {
assert!(lockfile.contains("dep"));
assert!(lockfile.contains("dep-dev"));
assert!(lockfile.contains("dep-build"));
p.cargo("publish --token sekrit").run();
p.cargo("publish")
.replace_crates_io(registry.index_url())
.run();
publish::validate_upload_with_contents(
r#"
{
@ -298,7 +303,6 @@ fn inherit_own_dependencies() {
"kind": "normal",
"name": "dep",
"optional": false,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^0.1"
},
@ -308,7 +312,6 @@ fn inherit_own_dependencies() {
"kind": "dev",
"name": "dep-dev",
"optional": false,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^0.5.2"
},
@ -318,7 +321,6 @@ fn inherit_own_dependencies() {
"kind": "build",
"name": "dep-build",
"optional": false,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^0.8"
}
@ -366,6 +368,7 @@ version = "0.8"
#[cargo_test]
fn inherit_own_detailed_dependencies() {
let registry = registry::init();
let p = project()
.file(
"Cargo.toml",
@ -408,7 +411,9 @@ fn inherit_own_detailed_dependencies() {
p.cargo("check").run();
let lockfile = p.read_lockfile();
assert!(lockfile.contains("dep"));
p.cargo("publish --token sekrit").run();
p.cargo("publish")
.replace_crates_io(registry.index_url())
.run();
publish::validate_upload_with_contents(
r#"
{
@ -422,7 +427,6 @@ fn inherit_own_detailed_dependencies() {
"kind": "normal",
"name": "dep",
"optional": false,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^0.1.2"
}
@ -560,7 +564,7 @@ fn inherited_dependencies_union_features() {
#[cargo_test]
fn inherit_workspace_fields() {
registry::init();
let registry = registry::init();
let p = project().build();
@ -624,7 +628,10 @@ fn inherit_workspace_fields() {
.file("bar/bar.txt", "") // should be included when packaging
.build();
p.cargo("publish --token sekrit").cwd("bar").run();
p.cargo("publish")
.replace_crates_io(registry.index_url())
.cwd("bar")
.run();
publish::validate_upload_with_contents(
r#"
{
@ -701,6 +708,7 @@ repository = "https://gitlab.com/rust-lang/rust"
#[cargo_test]
fn inherit_dependencies() {
let registry = registry::init();
let p = project()
.file(
"Cargo.toml",
@ -755,7 +763,10 @@ fn inherit_dependencies() {
assert!(lockfile.contains("dep"));
assert!(lockfile.contains("dep-dev"));
assert!(lockfile.contains("dep-build"));
p.cargo("publish --token sekrit").cwd("bar").run();
p.cargo("publish")
.replace_crates_io(registry.index_url())
.cwd("bar")
.run();
publish::validate_upload_with_contents(
r#"
{
@ -769,7 +780,6 @@ fn inherit_dependencies() {
"kind": "normal",
"name": "dep",
"optional": false,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^0.1"
},
@ -779,7 +789,6 @@ fn inherit_dependencies() {
"kind": "dev",
"name": "dep-dev",
"optional": false,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^0.5.2"
},
@ -789,7 +798,6 @@ fn inherit_dependencies() {
"kind": "build",
"name": "dep-build",
"optional": false,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^0.8"
}

View File

@ -93,15 +93,19 @@ fn registry_credentials() {
#[cargo_test]
fn empty_login_token() {
let _registry = RegistryBuilder::new().build();
let registry = RegistryBuilder::new()
.no_configure_registry()
.no_configure_token()
.build();
setup_new_credentials();
cargo_process("login")
.replace_crates_io(registry.index_url())
.with_stdout("please paste the API Token found on [..]/me below")
.with_stdin("\t\n")
.with_stderr(
"\
[UPDATING] `dummy-registry` index
[UPDATING] crates.io index
[ERROR] please provide a non-empty token
",
)
@ -109,6 +113,7 @@ fn empty_login_token() {
.run();
cargo_process("login")
.replace_crates_io(registry.index_url())
.arg("")
.with_stderr(
"\

View File

@ -1,6 +1,7 @@
//! Tests for the `cargo logout` command.
use cargo_test_support::install::cargo_home;
use cargo_test_support::registry::TestRegistry;
use cargo_test_support::{cargo_process, registry};
use std::fs;
use toml_edit::easy as toml;
@ -44,11 +45,12 @@ fn check_config_token(registry: Option<&str>, should_be_set: bool) {
}
}
fn simple_logout_test(reg: Option<&str>, flag: &str) {
fn simple_logout_test(registry: &TestRegistry, reg: Option<&str>, flag: &str) {
let msg = reg.unwrap_or("crates.io");
check_config_token(reg, true);
cargo_process(&format!("logout -Z unstable-options {}", flag))
.masquerade_as_nightly_cargo(&["cargo-logout"])
.replace_crates_io(registry.index_url())
.with_stderr(&format!(
"\
[UPDATING] [..]
@ -61,6 +63,7 @@ fn simple_logout_test(reg: Option<&str>, flag: &str) {
cargo_process(&format!("logout -Z unstable-options {}", flag))
.masquerade_as_nightly_cargo(&["cargo-logout"])
.replace_crates_io(registry.index_url())
.with_stderr(&format!(
"\
[LOGOUT] not currently logged in to `{}`
@ -73,12 +76,12 @@ fn simple_logout_test(reg: Option<&str>, flag: &str) {
#[cargo_test]
fn default_registry() {
registry::init();
simple_logout_test(None, "");
let registry = registry::init();
simple_logout_test(&registry, None, "");
}
#[cargo_test]
fn other_registry() {
registry::alt_init();
simple_logout_test(Some("alternative"), "--registry alternative");
let registry = registry::alt_init();
simple_logout_test(&registry, Some("alternative"), "--registry alternative");
}

View File

@ -118,6 +118,7 @@ mod rustdocflags;
mod rustflags;
mod search;
mod shell_quoting;
mod source_replacement;
mod standard_lib;
mod test;
mod timings;

View File

@ -16,7 +16,7 @@ fn setup(name: &str, content: Option<&str>) {
#[cargo_test]
fn simple_list() {
registry::init();
let registry = registry::init();
let content = r#"{
"users": [
{
@ -47,7 +47,8 @@ fn simple_list() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("owner -l --token sekrit")
p.cargo("owner -l")
.replace_crates_io(registry.index_url())
.with_stdout(
"\
github:rust-lang:core (Core)
@ -59,7 +60,7 @@ octocat
#[cargo_test]
fn simple_add() {
registry::init();
let registry = registry::init();
setup("foo", None);
let p = project()
@ -77,10 +78,11 @@ fn simple_add() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("owner -a username --token sekrit")
p.cargo("owner -a username")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(
" Updating `[..]` index
" Updating crates.io index
error: failed to invite owners to crate `foo` on registry at file://[..]
Caused by:
@ -91,7 +93,7 @@ Caused by:
#[cargo_test]
fn simple_remove() {
registry::init();
let registry = registry::init();
setup("foo", None);
let p = project()
@ -109,10 +111,11 @@ fn simple_remove() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("owner -r username --token sekrit")
p.cargo("owner -r username")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(
" Updating `[..]` index
" Updating crates.io index
Owner removing [\"username\"] from crate foo
error: failed to remove owners from crate `foo` on registry at file://[..]

View File

@ -100,7 +100,7 @@ fn validate_upload_foo_clean() {
#[cargo_test]
fn simple() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -117,10 +117,11 @@ fn simple() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("publish --no-verify --token sekrit")
p.cargo("publish --no-verify")
.replace_crates_io(registry.index_url())
.with_stderr(
"\
[UPDATING] `dummy-registry` index
[UPDATING] crates.io index
[WARNING] manifest has no documentation, [..]
See [..]
[PACKAGING] foo v0.0.1 ([CWD])
@ -136,7 +137,7 @@ See [..]
fn old_token_location() {
// Check that the `token` key works at the root instead of under a
// `[registry]` table.
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -158,6 +159,7 @@ fn old_token_location() {
// Verify can't publish without a token.
p.cargo("publish --no-verify")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr_contains(
"[ERROR] no upload token found, \
@ -165,15 +167,13 @@ fn old_token_location() {
)
.run();
fs::write(&credentials, r#"token = "api-token""#).unwrap();
fs::write(&credentials, format!(r#"token = "{}""#, registry.token())).unwrap();
p.cargo("publish --no-verify")
.replace_crates_io(registry.index_url())
.with_stderr(
"\
[UPDATING] `dummy-registry` index
[WARNING] using `registry.token` config value with source replacement is deprecated
This may become a hard error in the future[..]
Use the --token command-line flag to remove this warning.
[UPDATING] crates.io index
[WARNING] manifest has no documentation, [..]
See [..]
[PACKAGING] foo v0.0.1 ([CWD])
@ -204,7 +204,10 @@ fn simple_with_index() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("publish --no-verify --token sekrit --index")
p.cargo("publish --no-verify")
.arg("--token")
.arg(registry.token())
.arg("--index")
.arg(registry.index_url().as_str())
.run();
@ -213,7 +216,7 @@ fn simple_with_index() {
#[cargo_test]
fn git_deps() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -233,7 +236,8 @@ fn git_deps() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("publish -v --no-verify --token sekrit")
p.cargo("publish -v --no-verify")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(
"\
@ -249,7 +253,7 @@ the `git` specification will be removed from the dependency declaration.
#[cargo_test]
fn path_dependency_no_version() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -271,7 +275,8 @@ fn path_dependency_no_version() {
.file("bar/src/lib.rs", "")
.build();
p.cargo("publish --token sekrit")
p.cargo("publish")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(
"\
@ -319,7 +324,7 @@ The registry `crates-io` is not listed in the `publish` value in Cargo.toml.
#[cargo_test]
fn dont_publish_dirty() {
registry::init();
let registry = registry::init();
let p = project().file("bar", "").build();
let _ = git::repo(&paths::root().join("foo"))
@ -340,11 +345,12 @@ fn dont_publish_dirty() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("publish --token sekrit")
p.cargo("publish")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(
"\
[UPDATING] `[..]` index
[UPDATING] crates.io index
error: 1 files in the working directory contain changes that were not yet \
committed into git:
@ -358,7 +364,7 @@ to proceed despite this and include the uncommitted changes, pass the `--allow-d
#[cargo_test]
fn publish_clean() {
registry::init();
let registry = registry::init();
let p = project().build();
@ -380,14 +386,16 @@ fn publish_clean() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("publish --token sekrit").run();
p.cargo("publish")
.replace_crates_io(registry.index_url())
.run();
validate_upload_foo_clean();
}
#[cargo_test]
fn publish_in_sub_repo() {
registry::init();
let registry = registry::init();
let p = project().no_manifest().file("baz", "").build();
@ -409,14 +417,17 @@ fn publish_in_sub_repo() {
.file("bar/src/main.rs", "fn main() {}")
.build();
p.cargo("publish --token sekrit").cwd("bar").run();
p.cargo("publish")
.replace_crates_io(registry.index_url())
.cwd("bar")
.run();
validate_upload_foo_clean();
}
#[cargo_test]
fn publish_when_ignored() {
registry::init();
let registry = registry::init();
let p = project().file("baz", "").build();
@ -439,7 +450,9 @@ fn publish_when_ignored() {
.file(".gitignore", "baz")
.build();
p.cargo("publish --token sekrit").run();
p.cargo("publish")
.replace_crates_io(registry.index_url())
.run();
publish::validate_upload(
CLEAN_FOO_JSON,
@ -457,7 +470,7 @@ fn publish_when_ignored() {
#[cargo_test]
fn ignore_when_crate_ignored() {
registry::init();
let registry = registry::init();
let p = project().no_manifest().file("bar/baz", "").build();
@ -478,7 +491,10 @@ fn ignore_when_crate_ignored() {
"#,
)
.nocommit_file("bar/src/main.rs", "fn main() {}");
p.cargo("publish --token sekrit").cwd("bar").run();
p.cargo("publish")
.replace_crates_io(registry.index_url())
.cwd("bar")
.run();
publish::validate_upload(
CLEAN_FOO_JSON,
@ -495,7 +511,7 @@ fn ignore_when_crate_ignored() {
#[cargo_test]
fn new_crate_rejected() {
registry::init();
let registry = registry::init();
let p = project().file("baz", "").build();
@ -515,7 +531,8 @@ fn new_crate_rejected() {
"#,
)
.nocommit_file("src/main.rs", "fn main() {}");
p.cargo("publish --token sekrit")
p.cargo("publish")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr_contains(
"[ERROR] 3 files in the working directory contain \
@ -567,8 +584,6 @@ See [..]
#[cargo_test]
fn registry_not_in_publish_list() {
registry::init();
let p = project()
.file(
"Cargo.toml",
@ -602,8 +617,6 @@ The registry `alternative` is not listed in the `publish` value in Cargo.toml.
#[cargo_test]
fn publish_empty_list() {
registry::init();
let p = project()
.file(
"Cargo.toml",
@ -713,8 +726,6 @@ fn publish_implicitly_to_only_allowed_registry() {
#[cargo_test]
fn publish_fail_with_no_registry_specified() {
registry::init();
let p = project().build();
let _ = repo(&paths::root().join("foo"))
@ -749,8 +760,6 @@ The registry `crates-io` is not listed in the `publish` value in Cargo.toml.
#[cargo_test]
fn block_publish_no_registry() {
registry::init();
let p = project()
.file(
"Cargo.toml",
@ -781,7 +790,7 @@ The registry `alternative` is not listed in the `publish` value in Cargo.toml.
#[cargo_test]
fn publish_with_crates_io_explicit() {
// Explicitly setting `crates-io` in the publish list.
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -809,12 +818,14 @@ The registry `alternative` is not listed in the `publish` value in Cargo.toml.
)
.run();
p.cargo("publish").run();
p.cargo("publish")
.replace_crates_io(registry.index_url())
.run();
}
#[cargo_test]
fn publish_with_select_features() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -840,14 +851,15 @@ fn publish_with_select_features() {
)
.build();
p.cargo("publish --features required --token sekrit")
p.cargo("publish --features required")
.replace_crates_io(registry.index_url())
.with_stderr_contains("[UPLOADING] foo v0.0.1 ([CWD])")
.run();
}
#[cargo_test]
fn publish_with_all_features() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -873,14 +885,15 @@ fn publish_with_all_features() {
)
.build();
p.cargo("publish --all-features --token sekrit")
p.cargo("publish --all-features")
.replace_crates_io(registry.index_url())
.with_stderr_contains("[UPLOADING] foo v0.0.1 ([CWD])")
.run();
}
#[cargo_test]
fn publish_with_no_default_features() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -906,7 +919,8 @@ fn publish_with_no_default_features() {
)
.build();
p.cargo("publish --no-default-features --token sekrit")
p.cargo("publish --no-default-features")
.replace_crates_io(registry.index_url())
.with_stderr_contains("error: This crate requires `required` feature!")
.with_status(101)
.run();
@ -914,6 +928,7 @@ fn publish_with_no_default_features() {
#[cargo_test]
fn publish_with_patch() {
let registry = registry::init();
Package::new("bar", "1.0.0").publish();
let p = project()
@ -947,7 +962,8 @@ fn publish_with_patch() {
p.cargo("build").run();
// Check that verify fails with patched crate which has new functionality.
p.cargo("publish --token sekrit")
p.cargo("publish")
.replace_crates_io(registry.index_url())
.with_stderr_contains("[..]newfunc[..]")
.with_status(101)
.run();
@ -955,11 +971,10 @@ fn publish_with_patch() {
// Remove the usage of new functionality and try again.
p.change_file("src/main.rs", "extern crate bar; pub fn main() {}");
p.cargo("publish --token sekrit").run();
p.cargo("publish")
.replace_crates_io(registry.index_url())
.run();
// Note, use of `registry` in the deps here is an artifact that this
// publishes to a fake, local registry that is pretending to be crates.io.
// Normal publishes would set it to null.
publish::validate_upload(
r#"
{
@ -973,7 +988,6 @@ fn publish_with_patch() {
"kind": "normal",
"name": "bar",
"optional": false,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^1.0"
}
@ -1000,7 +1014,9 @@ fn publish_with_patch() {
#[cargo_test]
fn publish_checks_for_token_before_verify() {
registry::init();
let registry = registry::RegistryBuilder::new()
.no_configure_token()
.build();
let p = project()
.file(
@ -1017,11 +1033,9 @@ fn publish_checks_for_token_before_verify() {
.file("src/main.rs", "fn main() {}")
.build();
let credentials = paths::home().join(".cargo/credentials");
fs::remove_file(&credentials).unwrap();
// Assert upload token error before the package is verified
p.cargo("publish")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr_contains(
"[ERROR] no upload token found, \
@ -1032,6 +1046,7 @@ fn publish_checks_for_token_before_verify() {
// Assert package verified successfully on dry run
p.cargo("publish --dry-run")
.replace_crates_io(registry.index_url())
.with_status(0)
.with_stderr_contains("[VERIFYING] foo v0.0.1 ([CWD])")
.run();
@ -1053,12 +1068,12 @@ fn publish_with_bad_source() {
.file("src/lib.rs", "")
.build();
p.cargo("publish --token sekrit")
p.cargo("publish")
.with_status(101)
.with_stderr(
"\
[ERROR] registry `[..]/foo/registry` does not support API commands.
Check for a source-replacement in .cargo/config.
[ERROR] crates-io is replaced with non-remote-registry source registry `[..]/foo/registry`;
include `--registry crates-io` to use crates.io
",
)
.run();
@ -1074,12 +1089,12 @@ Check for a source-replacement in .cargo/config.
"#,
);
p.cargo("publish --token sekrit")
p.cargo("publish")
.with_status(101)
.with_stderr(
"\
[ERROR] dir [..]/foo/vendor does not support API commands.
Check for a source-replacement in .cargo/config.
[ERROR] crates-io is replaced with non-remote-registry source dir [..]/foo/vendor;
include `--registry crates-io` to use crates.io
",
)
.run();
@ -1087,6 +1102,7 @@ Check for a source-replacement in .cargo/config.
#[cargo_test]
fn publish_git_with_version() {
let registry = registry::init();
// A dependency with both `git` and `version`.
Package::new("dep1", "1.0.1")
.file("src/lib.rs", "pub fn f() -> i32 {1}")
@ -1128,7 +1144,9 @@ fn publish_git_with_version() {
.build();
p.cargo("run").with_stdout("2").run();
p.cargo("publish --no-verify --token sekrit").run();
p.cargo("publish --no-verify")
.replace_crates_io(registry.index_url())
.run();
publish::validate_upload_with_contents(
r#"
@ -1143,7 +1161,6 @@ fn publish_git_with_version() {
"kind": "normal",
"name": "dep1",
"optional": false,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^1.0"
}
@ -1212,7 +1229,7 @@ fn publish_git_with_version() {
#[cargo_test]
fn publish_dev_dep_no_version() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -1237,7 +1254,8 @@ fn publish_dev_dep_no_version() {
.file("bar/src/lib.rs", "")
.build();
p.cargo("publish --no-verify --token sekrit")
p.cargo("publish --no-verify")
.replace_crates_io(registry.index_url())
.with_stderr(
"\
[UPDATING] [..]
@ -1295,7 +1313,7 @@ repository = "foo"
#[cargo_test]
fn credentials_ambiguous_filename() {
registry::init();
let registry = registry::init();
let credentials_toml = paths::home().join(".cargo/credentials.toml");
fs::write(credentials_toml, r#"token = "api-token""#).unwrap();
@ -1315,7 +1333,8 @@ fn credentials_ambiguous_filename() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("publish --no-verify --token sekrit")
p.cargo("publish --no-verify")
.replace_crates_io(registry.index_url())
.with_stderr_contains(
"\
[WARNING] Both `[..]/credentials` and `[..]/credentials.toml` exist. Using `[..]/credentials`
@ -1362,10 +1381,9 @@ fn index_requires_token() {
}
#[cargo_test]
fn registry_token_with_source_replacement() {
// publish with source replacement without --token
fn cratesio_source_replacement() {
// publish with source replacement without --registry
registry::init();
let p = project()
.file(
"Cargo.toml",
@ -1382,16 +1400,11 @@ fn registry_token_with_source_replacement() {
.build();
p.cargo("publish --no-verify")
.with_status(101)
.with_stderr(
"\
[UPDATING] [..]
[WARNING] using `registry.token` config value with source replacement is deprecated
This may become a hard error in the future[..]
Use the --token command-line flag to remove this warning.
[WARNING] manifest has no documentation, [..]
See [..]
[PACKAGING] foo v0.0.1 ([CWD])
[UPLOADING] foo v0.0.1 ([CWD])
[ERROR] crates-io is replaced with remote registry dummy-registry;
include `--registry dummy-registry` or `--registry crates-io`
",
)
.run();
@ -1399,7 +1412,7 @@ See [..]
#[cargo_test]
fn publish_with_missing_readme() {
registry::init();
let registry = registry::init();
let p = project()
.file(
"Cargo.toml",
@ -1417,7 +1430,8 @@ fn publish_with_missing_readme() {
.file("src/lib.rs", "")
.build();
p.cargo("publish --no-verify --token sekrit")
p.cargo("publish --no-verify")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(&format!(
"\
@ -1685,7 +1699,7 @@ Caused by:
#[cargo_test]
fn in_package_workspace() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -1713,7 +1727,8 @@ fn in_package_workspace() {
.file("li/src/main.rs", "fn main() {}")
.build();
p.cargo("publish -p li --no-verify --token sekrit")
p.cargo("publish -p li --no-verify")
.replace_crates_io(registry.index_url())
.with_stderr(
"\
[UPDATING] [..]
@ -1730,7 +1745,7 @@ See [..]
#[cargo_test]
fn with_duplicate_spec_in_members() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -1770,7 +1785,8 @@ fn with_duplicate_spec_in_members() {
.file("bar/src/main.rs", "fn main() {}")
.build();
p.cargo("publish --no-verify --token sekrit")
p.cargo("publish --no-verify")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(
"error: the `-p` argument must be specified to select a single package to publish",
@ -1780,7 +1796,7 @@ fn with_duplicate_spec_in_members() {
#[cargo_test]
fn in_package_workspace_with_members_with_features_old() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -1807,7 +1823,8 @@ fn in_package_workspace_with_members_with_features_old() {
.file("li/src/main.rs", "fn main() {}")
.build();
p.cargo("publish -p li --no-verify --token sekrit")
p.cargo("publish -p li --no-verify")
.replace_crates_io(registry.index_url())
.with_stderr(
"\
[UPDATING] [..]
@ -1824,7 +1841,7 @@ See [..]
#[cargo_test]
fn in_virtual_workspace() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -1848,7 +1865,8 @@ fn in_virtual_workspace() {
.file("foo/src/main.rs", "fn main() {}")
.build();
p.cargo("publish --no-verify --token sekrit")
p.cargo("publish --no-verify")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(
"error: the `-p` argument must be specified in the root of a virtual workspace",
@ -1858,7 +1876,7 @@ fn in_virtual_workspace() {
#[cargo_test]
fn in_virtual_workspace_with_p() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -1893,7 +1911,8 @@ fn in_virtual_workspace_with_p() {
.file("li/src/main.rs", "fn main() {}")
.build();
p.cargo("publish -p li --no-verify --token sekrit")
p.cargo("publish -p li --no-verify")
.replace_crates_io(registry.index_url())
.with_stderr(
"\
[UPDATING] [..]
@ -1908,7 +1927,7 @@ See [..]
#[cargo_test]
fn in_package_workspace_not_found() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -1937,7 +1956,8 @@ fn in_package_workspace_not_found() {
.file("li/src/main.rs", "fn main() {}")
.build();
p.cargo("publish -p li --no-verify --token sekrit ")
p.cargo("publish -p li --no-verify")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(
"\
@ -1951,7 +1971,7 @@ error: package ID specification `li` did not match any packages
#[cargo_test]
fn in_package_workspace_found_multiple() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -1994,7 +2014,8 @@ fn in_package_workspace_found_multiple() {
.file("lii/src/main.rs", "fn main() {}")
.build();
p.cargo("publish -p li* --no-verify --token sekrit ")
p.cargo("publish -p li* --no-verify")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(
"\
@ -2007,7 +2028,7 @@ error: the `-p` argument must be specified to select a single package to publish
#[cargo_test]
// https://github.com/rust-lang/cargo/issues/10536
fn publish_path_dependency_without_workspace() {
registry::init();
let registry = registry::init();
let p = project()
.file(
@ -2037,7 +2058,8 @@ fn publish_path_dependency_without_workspace() {
.file("bar/src/main.rs", "fn main() {}")
.build();
p.cargo("publish -p bar --no-verify --token sekrit ")
p.cargo("publish -p bar --no-verify")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(
"\
@ -2051,7 +2073,7 @@ error: package ID specification `bar` did not match any packages
#[cargo_test]
fn http_api_not_noop() {
let _registry = registry::RegistryBuilder::new().http_api().build();
let registry = registry::RegistryBuilder::new().http_api().build();
let p = project()
.file(
@ -2068,7 +2090,9 @@ fn http_api_not_noop() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("publish --token api-token").run();
p.cargo("publish")
.replace_crates_io(registry.index_url())
.run();
let p = project()
.file(

View File

@ -1074,10 +1074,12 @@ fn dev_dependency_not_used(cargo: fn(&Project, &str) -> Execs) {
fn login_with_no_cargo_dir() {
// Create a config in the root directory because `login` requires the
// index to be updated, and we don't want to hit crates.io.
registry::init();
let registry = registry::init();
fs::rename(paths::home().join(".cargo"), paths::root().join(".cargo")).unwrap();
paths::home().rm_rf();
cargo_process("login foo -v").run();
cargo_process("login foo -v")
.replace_crates_io(registry.index_url())
.run();
let credentials = fs::read_to_string(paths::home().join(".cargo/credentials")).unwrap();
assert_eq!(credentials, "[registry]\ntoken = \"foo\"\n");
}
@ -1085,23 +1087,32 @@ fn login_with_no_cargo_dir() {
#[cargo_test]
fn login_with_differently_sized_token() {
// Verify that the configuration file gets properly truncated.
registry::init();
let registry = registry::init();
let credentials = paths::home().join(".cargo/credentials");
fs::remove_file(&credentials).unwrap();
cargo_process("login lmaolmaolmao -v").run();
cargo_process("login lmao -v").run();
cargo_process("login lmaolmaolmao -v").run();
cargo_process("login lmaolmaolmao -v")
.replace_crates_io(registry.index_url())
.run();
cargo_process("login lmao -v")
.replace_crates_io(registry.index_url())
.run();
cargo_process("login lmaolmaolmao -v")
.replace_crates_io(registry.index_url())
.run();
let credentials = fs::read_to_string(&credentials).unwrap();
assert_eq!(credentials, "[registry]\ntoken = \"lmaolmaolmao\"\n");
}
#[cargo_test]
fn login_with_token_on_stdin() {
registry::init();
let registry = registry::init();
let credentials = paths::home().join(".cargo/credentials");
fs::remove_file(&credentials).unwrap();
cargo_process("login lmao -v").run();
cargo_process("login lmao -v")
.replace_crates_io(registry.index_url())
.run();
cargo_process("login")
.replace_crates_io(registry.index_url())
.with_stdout("please paste the API Token found on [..]/me below")
.with_stdin("some token")
.run();
@ -1111,16 +1122,17 @@ fn login_with_token_on_stdin() {
#[cargo_test]
fn bad_license_file_http() {
let _server = setup_http();
bad_license_file(cargo_http);
let registry = setup_http();
bad_license_file(cargo_http, &registry);
}
#[cargo_test]
fn bad_license_file_git() {
bad_license_file(cargo_stable);
let registry = registry::init();
bad_license_file(cargo_stable, &registry);
}
fn bad_license_file(cargo: fn(&Project, &str) -> Execs) {
fn bad_license_file(cargo: fn(&Project, &str) -> Execs, registry: &TestRegistry) {
Package::new("foo", "1.0.0").publish();
let p = project()
.file(
@ -1137,7 +1149,8 @@ fn bad_license_file(cargo: fn(&Project, &str) -> Execs) {
)
.file("src/main.rs", "fn main() {}")
.build();
cargo(&p, "publish -v --token sekrit")
cargo(&p, "publish -v")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr_contains("[ERROR] the license file `foo` does not exist")
.run();

View File

@ -106,6 +106,7 @@ fn not_update() {
drop(lock);
cargo_process("search postgres")
.replace_crates_io(registry.index_url())
.with_stdout_contains(SEARCH_RESULTS)
.with_stderr("") // without "Updating ... index"
.run();
@ -113,9 +114,10 @@ fn not_update() {
#[cargo_test]
fn replace_default() {
let _server = setup().build();
let registry = setup().build();
cargo_process("search postgres")
.replace_crates_io(registry.index_url())
.with_stdout_contains(SEARCH_RESULTS)
.with_stderr_contains("[..]Updating [..] index")
.run();
@ -143,22 +145,25 @@ fn multiple_query_params() {
#[cargo_test]
fn ignore_quiet() {
let _server = setup().build();
let registry = setup().build();
cargo_process("search -q postgres")
.replace_crates_io(registry.index_url())
.with_stdout_contains(SEARCH_RESULTS)
.run();
}
#[cargo_test]
fn colored_results() {
let _server = setup().build();
let registry = setup().build();
cargo_process("search --color=never postgres")
.replace_crates_io(registry.index_url())
.with_stdout_does_not_contain("[..]\x1b[[..]")
.run();
cargo_process("search --color=always postgres")
.replace_crates_io(registry.index_url())
.with_stdout_contains("[..]\x1b[[..]")
.run();
}

View File

@ -0,0 +1,243 @@
//! Tests for `[source]` table (source replacement).
use std::fs;
use cargo_test_support::registry::{Package, RegistryBuilder, TestRegistry};
use cargo_test_support::{cargo_process, paths, project, t};
fn setup_replacement(config: &str) -> TestRegistry {
let crates_io = RegistryBuilder::new()
.no_configure_registry()
.http_api()
.build();
let root = paths::root();
t!(fs::create_dir(&root.join(".cargo")));
t!(fs::write(root.join(".cargo/config"), config,));
crates_io
}
#[cargo_test]
fn crates_io_token_not_sent_to_replacement() {
// verifies that the crates.io token is not sent to a replacement registry during publish.
let crates_io = setup_replacement(
r#"
[source.crates-io]
replace-with = 'alternative'
"#,
);
let _alternative = RegistryBuilder::new()
.alternative()
.http_api()
.no_configure_token()
.build();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
license = "MIT"
description = "foo"
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("publish --no-verify --registry crates-io")
.replace_crates_io(crates_io.index_url())
.with_stderr_contains("[UPDATING] crates.io index")
.run();
}
#[cargo_test]
fn token_sent_to_correct_registry() {
// verifies that the crates.io token is not sent to a replacement registry during yank.
let crates_io = setup_replacement(
r#"
[source.crates-io]
replace-with = 'alternative'
"#,
);
let _alternative = RegistryBuilder::new().alternative().http_api().build();
cargo_process("yank foo@0.0.1 --registry crates-io")
.replace_crates_io(crates_io.index_url())
.with_stderr(
"\
[UPDATING] crates.io index
[YANK] foo@0.0.1
",
)
.run();
cargo_process("yank foo@0.0.1 --registry alternative")
.replace_crates_io(crates_io.index_url())
.with_stderr(
"\
[UPDATING] `alternative` index
[YANK] foo@0.0.1
",
)
.run();
}
#[cargo_test]
fn ambiguous_registry() {
// verifies that an error is issued when a source-replacement is configured
// and no --registry argument is given.
let crates_io = setup_replacement(
r#"
[source.crates-io]
replace-with = 'alternative'
"#,
);
let _alternative = RegistryBuilder::new()
.alternative()
.http_api()
.no_configure_token()
.build();
cargo_process("yank foo@0.0.1")
.replace_crates_io(crates_io.index_url())
.with_status(101)
.with_stderr(
"\
error: crates-io is replaced with remote registry alternative;
include `--registry alternative` or `--registry crates-io`
",
)
.run();
}
#[cargo_test]
fn yank_with_default_crates_io() {
// verifies that no error is given when registry.default is used.
let crates_io = setup_replacement(
r#"
[source.crates-io]
replace-with = 'alternative'
[registry]
default = 'crates-io'
"#,
);
let _alternative = RegistryBuilder::new().alternative().http_api().build();
cargo_process("yank foo@0.0.1")
.replace_crates_io(crates_io.index_url())
.with_stderr(
"\
[UPDATING] crates.io index
[YANK] foo@0.0.1
",
)
.run();
}
#[cargo_test]
fn yank_with_default_alternative() {
// verifies that no error is given when registry.default is an alt registry.
let crates_io = setup_replacement(
r#"
[source.crates-io]
replace-with = 'alternative'
[registry]
default = 'alternative'
"#,
);
let _alternative = RegistryBuilder::new().alternative().http_api().build();
cargo_process("yank foo@0.0.1")
.replace_crates_io(crates_io.index_url())
.with_stderr(
"\
[UPDATING] `alternative` index
[YANK] foo@0.0.1
",
)
.run();
}
#[cargo_test]
fn publish_with_replacement() {
// verifies that the crates.io token is not sent to a replacement registry during publish.
let crates_io = setup_replacement(
r#"
[source.crates-io]
replace-with = 'alternative'
"#,
);
let _alternative = RegistryBuilder::new()
.alternative()
.http_api()
.no_configure_token()
.build();
// Publish bar only to alternative. This tests that the publish verification build
// does uses the source replacement.
Package::new("bar", "1.0.0").alternative(true).publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
license = "MIT"
description = "foo"
[dependencies]
bar = "1.0"
"#,
)
.file("src/lib.rs", "")
.build();
// Verifies that the crates.io index is used to find the publishing endpoint
// and that the crate is sent to crates.io. The source replacement is only used
// for the verification step.
p.cargo("publish --registry crates-io")
.replace_crates_io(crates_io.index_url())
.with_stderr(
"[UPDATING] crates.io 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 ([..])
[VERIFYING] foo v0.0.1 ([..])
[UPDATING] `alternative` index
[DOWNLOADING] crates ...
[DOWNLOADED] bar v1.0.0 (registry `alternative`)
[COMPILING] bar v1.0.0
[COMPILING] foo v0.0.1 ([..]foo-0.0.1)
[FINISHED] dev [..]
[UPLOADING] foo v0.0.1 ([..])",
)
.run();
}
#[cargo_test]
fn undefined_default() {
// verifies that no error is given when registry.default is used.
let crates_io = setup_replacement(
r#"
[registry]
default = 'undefined'
"#,
);
cargo_process("yank foo@0.0.1")
.replace_crates_io(crates_io.index_url())
.with_status(101)
.with_stderr(
"[ERROR] no index found for registry: `undefined`
",
)
.run();
}

View File

@ -2,7 +2,7 @@
use super::features2::switch_to_resolver_2;
use cargo_test_support::paths::CargoPathExt;
use cargo_test_support::registry::{Dependency, Package};
use cargo_test_support::registry::{self, Dependency, Package};
use cargo_test_support::{project, publish};
use std::fmt::Write;
@ -523,6 +523,7 @@ bar v1.0.0
#[cargo_test]
fn publish() {
let registry = registry::init();
// Publish behavior with /? syntax.
Package::new("bar", "1.0.0").feature("feat", &[]).publish();
let p = project()
@ -547,7 +548,8 @@ fn publish() {
.file("src/lib.rs", "")
.build();
p.cargo("publish --token sekrit")
p.cargo("publish")
.replace_crates_io(registry.index_url())
.with_stderr(
"\
[UPDATING] [..]
@ -573,7 +575,6 @@ fn publish() {
"kind": "normal",
"name": "bar",
"optional": true,
"registry": "https://github.com/rust-lang/crates.io-index",
"target": null,
"version_req": "^1.0"
}

View File

@ -14,7 +14,7 @@ fn setup(name: &str, version: &str) {
#[cargo_test]
fn explicit_version() {
registry::init();
let registry = registry::init();
setup("foo", "0.0.1");
let p = project()
@ -32,12 +32,15 @@ fn explicit_version() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("yank --version 0.0.1 --token sekrit").run();
p.cargo("yank --version 0.0.1")
.replace_crates_io(registry.index_url())
.run();
p.cargo("yank --undo --version 0.0.1 --token sekrit")
p.cargo("yank --undo --version 0.0.1")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(
" Updating `[..]` index
" Updating crates.io index
Unyank foo@0.0.1
error: failed to undo a yank from the registry at file:///[..]
@ -49,7 +52,7 @@ Caused by:
#[cargo_test]
fn inline_version() {
registry::init();
let registry = registry::init();
setup("foo", "0.0.1");
let p = project()
@ -67,12 +70,15 @@ fn inline_version() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("yank foo@0.0.1 --token sekrit").run();
p.cargo("yank foo@0.0.1")
.replace_crates_io(registry.index_url())
.run();
p.cargo("yank --undo foo@0.0.1 --token sekrit")
p.cargo("yank --undo foo@0.0.1")
.replace_crates_io(registry.index_url())
.with_status(101)
.with_stderr(
" Updating `[..]` index
" Updating crates.io index
Unyank foo@0.0.1
error: failed to undo a yank from the registry at file:///[..]
@ -84,7 +90,6 @@ Caused by:
#[cargo_test]
fn version_required() {
registry::init();
setup("foo", "0.0.1");
let p = project()
@ -102,7 +107,7 @@ fn version_required() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("yank foo --token sekrit")
p.cargo("yank foo")
.with_status(101)
.with_stderr("error: `--version` is required")
.run();
@ -110,7 +115,6 @@ fn version_required() {
#[cargo_test]
fn inline_version_without_name() {
registry::init();
setup("foo", "0.0.1");
let p = project()
@ -128,7 +132,7 @@ fn inline_version_without_name() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("yank @0.0.1 --token sekrit")
p.cargo("yank @0.0.1")
.with_status(101)
.with_stderr("error: missing crate name for `@0.0.1`")
.run();
@ -136,7 +140,6 @@ fn inline_version_without_name() {
#[cargo_test]
fn inline_and_explicit_version() {
registry::init();
setup("foo", "0.0.1");
let p = project()
@ -154,7 +157,7 @@ fn inline_and_explicit_version() {
.file("src/main.rs", "fn main() {}")
.build();
p.cargo("yank foo@0.0.1 --version 0.0.1 --token sekrit")
p.cargo("yank foo@0.0.1 --version 0.0.1")
.with_status(101)
.with_stderr("error: cannot specify both `@0.0.1` and `--version`")
.run();