Skip to content

Commit

Permalink
Auto merge of #6500 - ehuss:metadata-reg, r=alexcrichton
Browse files Browse the repository at this point in the history
Add dependency `registry` to `cargo metadata`.

This adds the `registry` field for dependencies for alternate registries in
`cargo metadata`.
  • Loading branch information
bors committed Jan 2, 2019
2 parents 9bfaf2e + 64042d8 commit 21fe000
Show file tree
Hide file tree
Showing 15 changed files with 930 additions and 341 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Expand Up @@ -19,6 +19,7 @@ path = "src/cargo/lib.rs"

[dependencies]
atty = "0.2"
byteorder = "1.2"
bytesize = "1.0"
crates-io = { path = "src/crates-io", version = "0.22" }
crossbeam-utils = "0.6"
Expand Down Expand Up @@ -57,6 +58,7 @@ tempfile = "3.0"
termcolor = "1.0"
toml = "0.4.2"
url = "1.1"
url_serde = "0.2.0"
clap = "2.31.2"
unicode-width = "0.1.5"
openssl = { version = '0.10.11', optional = true }
Expand Down
12 changes: 12 additions & 0 deletions src/cargo/core/dependency.rs
Expand Up @@ -7,6 +7,7 @@ use semver::ReqParseError;
use semver::VersionReq;
use serde::ser;
use serde::Serialize;
use url::Url;

use crate::core::interning::InternedString;
use crate::core::{PackageId, SourceId, Summary};
Expand All @@ -25,6 +26,12 @@ pub struct Dependency {
struct Inner {
name: InternedString,
source_id: SourceId,
/// Source ID for the registry as specified in the manifest.
///
/// This will be None if it is not specified (crates.io dependency).
/// This is different from `source_id` for example when both a `path` and
/// `registry` is specified. Or in the case of a crates.io dependency,
/// `source_id` will be crates.io and this will be None.
registry_id: Option<SourceId>,
req: VersionReq,
specified_req: bool,
Expand Down Expand Up @@ -59,6 +66,10 @@ struct SerializedDependency<'a> {
uses_default_features: bool,
features: &'a [InternedString],
target: Option<&'a Platform>,
/// The registry URL this dependency is from.
/// If None, then it comes from the default registry (crates.io).
#[serde(with = "url_serde")]
registry: Option<Url>,
}

impl ser::Serialize for Dependency {
Expand All @@ -76,6 +87,7 @@ impl ser::Serialize for Dependency {
features: self.features(),
target: self.platform(),
rename: self.explicit_name_in_toml().map(|s| s.as_str()),
registry: self.registry_id().map(|sid| sid.url().clone()),
}
.serialize(s)
}
Expand Down
4 changes: 4 additions & 0 deletions src/cargo/core/source/source_id.rs
Expand Up @@ -40,6 +40,8 @@ struct SourceIdInner {
// e.g. the exact git revision of the specified branch for a Git Source
precise: Option<String>,
/// Name of the registry source for alternative registries
/// WARNING: This is not always set for alt-registries when the name is
/// not known.
name: Option<String>,
}

Expand Down Expand Up @@ -247,6 +249,8 @@ impl SourceId {
}

/// Is this source from an alternative registry
/// DEPRECATED: This is not correct if the registry name is not known
/// (for example when loaded from an index).
pub fn is_alt_registry(self) -> bool {
self.is_registry() && self.inner.name.is_some()
}
Expand Down
4 changes: 3 additions & 1 deletion src/cargo/ops/registry.rs
Expand Up @@ -159,8 +159,10 @@ fn transmit(
// registry in the dependency.
let dep_registry_id = match dep.registry_id() {
Some(id) => id,
None => failure::bail!("dependency missing registry ID"),
None => SourceId::crates_io(config)?,
};
// In the index and Web API, None means "from the same registry"
// whereas in Cargo.toml, it means "from crates.io".
let dep_registry = if dep_registry_id != registry_id {
Some(dep_registry_id.url().to_string())
} else {
Expand Down
25 changes: 8 additions & 17 deletions src/cargo/sources/registry/mod.rs
Expand Up @@ -299,7 +299,7 @@ impl<'a> RegistryDependency<'a> {
package,
} = self;

let id = if let Some(registry) = registry {
let id = if let Some(registry) = &registry {
SourceId::for_registry(&registry.to_url()?)?
} else {
default
Expand Down Expand Up @@ -328,6 +328,12 @@ impl<'a> RegistryDependency<'a> {
// out here.
features.retain(|s| !s.is_empty());

// 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() {
dep.set_registry_id(id);
}

dep.set_optional(optional)
.set_default_features(default_features)
.set_features(features)
Expand Down Expand Up @@ -486,22 +492,7 @@ impl<'cfg> RegistrySource<'cfg> {
MaybePackage::Ready(pkg) => pkg,
MaybePackage::Download { .. } => unreachable!(),
};

// Unfortunately the index and the actual Cargo.toml in the index can
// differ due to historical Cargo bugs. To paper over these we trash the
// *summary* loaded from the Cargo.toml we just downloaded with the one
// we loaded from the index.
let summaries = self
.index
.summaries(package.name().as_str(), &mut *self.ops)?;
let summary = summaries
.iter()
.map(|s| &s.0)
.find(|s| s.package_id() == package)
.expect("summary not found");
let mut manifest = pkg.manifest().clone();
manifest.set_summary(summary.clone());
Ok(Package::new(manifest, pkg.manifest_path()))
Ok(pkg)
}
}

Expand Down
29 changes: 19 additions & 10 deletions src/cargo/util/toml/mod.rs
Expand Up @@ -201,6 +201,12 @@ impl<'de> de::Deserialize<'de> for TomlDependency {
pub struct DetailedTomlDependency {
version: Option<String>,
registry: Option<String>,
/// The URL of the `registry` field.
/// This is an internal implementation detail. When Cargo creates a
/// package, it replaces `registry` with `registry-index` so that the
/// manifest contains the correct URL. All users won't have the same
/// registry names configured, so Cargo can't rely on just the name for
/// crates published by other users.
registry_index: Option<String>,
path: Option<String>,
git: Option<String>,
Expand Down Expand Up @@ -1307,14 +1313,6 @@ impl DetailedTomlDependency {
}
}

let registry_id = match self.registry {
Some(ref registry) => {
cx.features.require(Feature::alternative_registries())?;
SourceId::alt_registry(cx.config, registry)?
}
None => SourceId::crates_io(cx.config)?,
};

let new_source_id = match (
self.git.as_ref(),
self.path.as_ref(),
Expand Down Expand Up @@ -1410,8 +1408,19 @@ impl DetailedTomlDependency {
.unwrap_or(true),
)
.set_optional(self.optional.unwrap_or(false))
.set_platform(cx.platform.clone())
.set_registry_id(registry_id);
.set_platform(cx.platform.clone());
if let Some(registry) = &self.registry {
cx.features.require(Feature::alternative_registries())?;
let registry_id = SourceId::alt_registry(cx.config, registry)?;
dep.set_registry_id(registry_id);
}
if let Some(registry_index) = &self.registry_index {
cx.features.require(Feature::alternative_registries())?;
let url = registry_index.to_url()?;
let registry_id = SourceId::for_registry(&url)?;
dep.set_registry_id(registry_id);
}

if let Some(kind) = kind {
dep.set_kind(kind);
}
Expand Down
11 changes: 9 additions & 2 deletions src/doc/man/cargo-metadata.adoc
Expand Up @@ -61,7 +61,9 @@ The output has the following format:
{
/* The name of the dependency. */
"name": "bitflags",
/* The source ID of the dependency. */
/* The source ID of the dependency. May be null, see
description for the package source.
*/
"source": "registry+https://github.com/rust-lang/crates.io-index",
/* The version requirement for the dependency.
Dependencies without a version requirement have a value of "*".
Expand All @@ -84,7 +86,12 @@ The output has the following format:
/* The target platform for the dependency.
null if not a target dependency.
*/
"target": "cfg(windows)"
"target": "cfg(windows)",
/* A string of the URL of the registry this dependency is from.
If not specified or null, the dependency is from the default
registry (crates.io).
*/
"registry": null
}
],
/* Array of Cargo targets. */
Expand Down

0 comments on commit 21fe000

Please sign in to comment.