Skip to content

Commit

Permalink
Auto merge of #4953 - alexcrichton:rename-via-as, r=matklad
Browse files Browse the repository at this point in the history
Implement renaming dependencies in the manifest

This commit implements a new unstable feature for manifests which allows
renaming a crate when depending on it. For example you can do:

```toml
cargo-features = ["dependencies-as"]

...

[dependencies]
foo = "0.1"
bar = { version = "0.1", registry = "custom", package = "foo" }
baz = { git = "https://github.com/foo/bar", package = "foo" }
```

Here three crates will be imported but they'll be made available to the Rust
source code via the names `foo` (crates.io), `bar` (the custom registry), and
`baz` (the git dependency). The *package* name, however, will be `foo` for all
of them. In other words the git repository here would be searched for a crate
called `foo`. For example:

```rust
extern crate foo; // crates.io
extern crate bar; // registry `custom`
extern crate baz; // git repository
```

The intention here is to enable a few use cases:

* Enable depending on the same named crate from different registries
* Allow depending on multiple versions of a crate from one registry
* Removing the need for `extern crate foo as bar` syntactically in Rust source

Currently I don't think we're ready to stabilize this so it's just a nightly
feature, but I'm hoping we can continue to iterate on it!

cc #1311
  • Loading branch information
bors committed Feb 19, 2018
2 parents 0a37d76 + 79942fe commit 4f1c6db
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 40 deletions.
13 changes: 13 additions & 0 deletions src/cargo/core/dependency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct Inner {
specified_req: bool,
kind: Kind,
only_match_name: bool,
rename: Option<String>,

optional: bool,
default_features: bool,
Expand All @@ -49,6 +50,7 @@ struct SerializedDependency<'a> {
source: &'a SourceId,
req: String,
kind: Kind,
rename: Option<&'a str>,

optional: bool,
uses_default_features: bool,
Expand All @@ -69,6 +71,7 @@ impl ser::Serialize for Dependency {
uses_default_features: self.uses_default_features(),
features: self.features(),
target: self.platform(),
rename: self.rename(),
}.serialize(s)
}
}
Expand Down Expand Up @@ -182,6 +185,7 @@ impl Dependency {
default_features: true,
specified_req: false,
platform: None,
rename: None,
}),
}
}
Expand Down Expand Up @@ -221,6 +225,10 @@ impl Dependency {
self.inner.platform.as_ref()
}

pub fn rename(&self) -> Option<&str> {
self.inner.rename.as_ref().map(|s| &**s)
}

pub fn set_kind(&mut self, kind: Kind) -> &mut Dependency {
Rc::make_mut(&mut self.inner).kind = kind;
self
Expand Down Expand Up @@ -261,6 +269,11 @@ impl Dependency {
self
}

pub fn set_rename(&mut self, rename: &str) -> &mut Dependency {
Rc::make_mut(&mut self.inner).rename = Some(rename.to_string());
self
}

/// Lock this dependency to depending on the specified package id
pub fn lock_to(&mut self, id: &PackageId) -> &mut Dependency {
assert_eq!(self.inner.source_id, *id.source_id());
Expand Down
3 changes: 3 additions & 0 deletions src/cargo/core/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ features! {

// Using epochs
[unstable] epoch: bool,

// Renaming a package in the manifest via the `package` key
[unstable] rename_dependency: bool,
}
}

Expand Down
34 changes: 25 additions & 9 deletions src/cargo/ops/cargo_rustc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -947,28 +947,44 @@ Cargo.toml. This warning might turn into a hard error in the future.",
}
}

for unit in dep_targets {
if unit.profile.run_custom_build {
cmd.env("OUT_DIR", &cx.build_script_out_dir(&unit));
for dep in dep_targets {
if dep.profile.run_custom_build {
cmd.env("OUT_DIR", &cx.build_script_out_dir(&dep));
}
if unit.target.linkable() && !unit.profile.doc {
link_to(cmd, cx, &unit)?;
if dep.target.linkable() && !dep.profile.doc {
link_to(cmd, cx, &unit, &dep)?;
}
}

return Ok(());

fn link_to<'a, 'cfg>(cmd: &mut ProcessBuilder,
cx: &mut Context<'a, 'cfg>,
unit: &Unit<'a>) -> CargoResult<()> {
for &(ref dst, _, file_type) in cx.target_filenames(unit)?.iter() {
current: &Unit<'a>,
dep: &Unit<'a>) -> CargoResult<()> {
for &(ref dst, _, file_type) in cx.target_filenames(dep)?.iter() {
if file_type != TargetFileType::Linkable {
continue
}
let mut v = OsString::new();
v.push(&unit.target.crate_name());

// Unfortunately right now Cargo doesn't have a great way to get a
// 1:1 mapping of entries in `dependencies()` to the actual crate
// we're depending on. Instead we're left to do some guesswork here
// to figure out what `Dependency` the `dep` unit corresponds to in
// `current` to see if we're renaming it.
//
// This I believe mostly works out for now, but we'll likely want
// to tighten up this in the future.
let name = current.pkg.dependencies()
.iter()
.filter(|d| d.matches_ignoring_source(dep.pkg.summary()))
.filter_map(|d| d.rename())
.next();

v.push(name.unwrap_or(&dep.target.crate_name()));
v.push("=");
v.push(cx.out_dir(unit));
v.push(cx.out_dir(dep));
v.push(&path::MAIN_SEPARATOR.to_string());
v.push(&dst.file_name().unwrap());
cmd.arg("--extern").arg(&v);
Expand Down
80 changes: 51 additions & 29 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ type TomlBenchTarget = TomlTarget;
#[serde(untagged)]
pub enum TomlDependency {
Simple(String),
Detailed(DetailedTomlDependency)
Detailed(DetailedTomlDependency),
}

impl<'de> de::Deserialize<'de> for TomlDependency {
Expand Down Expand Up @@ -193,6 +193,7 @@ pub struct DetailedTomlDependency {
default_features: Option<bool>,
#[serde(rename = "default_features")]
default_features2: Option<bool>,
package: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
Expand Down Expand Up @@ -917,28 +918,40 @@ impl TomlDependency {
cx: &mut Context,
kind: Option<Kind>)
-> CargoResult<Dependency> {
let details = match *self {
TomlDependency::Simple(ref version) => DetailedTomlDependency {
version: Some(version.clone()),
.. Default::default()
},
TomlDependency::Detailed(ref details) => details.clone(),
};
match *self {
TomlDependency::Simple(ref version) => {
DetailedTomlDependency {
version: Some(version.clone()),
..Default::default()
}.to_dependency(name, cx, kind)
}
TomlDependency::Detailed(ref details) => {
details.to_dependency(name, cx, kind)
}
}
}
}

if details.version.is_none() && details.path.is_none() &&
details.git.is_none() {
impl DetailedTomlDependency {
fn to_dependency(&self,
name: &str,
cx: &mut Context,
kind: Option<Kind>)
-> CargoResult<Dependency> {
if self.version.is_none() && self.path.is_none() &&
self.git.is_none() {
let msg = format!("dependency ({}) specified without \
providing a local path, Git repository, or \
version to use. This will be considered an \
error in future versions", name);
cx.warnings.push(msg);
}

if details.git.is_none() {
if self.git.is_none() {
let git_only_keys = [
(&details.branch, "branch"),
(&details.tag, "tag"),
(&details.rev, "rev")
(&self.branch, "branch"),
(&self.tag, "tag"),
(&self.rev, "rev")
];

for &(key, key_name) in &git_only_keys {
Expand All @@ -951,7 +964,7 @@ impl TomlDependency {
}
}

let registry_id = match details.registry {
let registry_id = match self.registry {
Some(ref registry) => {
cx.features.require(Feature::alternative_registries())?;
SourceId::alt_registry(cx.config, registry)?
Expand All @@ -960,10 +973,10 @@ impl TomlDependency {
};

let new_source_id = match (
details.git.as_ref(),
details.path.as_ref(),
details.registry.as_ref(),
details.registry_index.as_ref(),
self.git.as_ref(),
self.path.as_ref(),
self.registry.as_ref(),
self.registry_index.as_ref(),
) {
(Some(_), _, Some(_), _) |
(Some(_), _, _, Some(_))=> bail!("dependency ({}) specification is ambiguous. \
Expand All @@ -978,7 +991,7 @@ impl TomlDependency {
cx.warnings.push(msg)
}

let n_details = [&details.branch, &details.tag, &details.rev]
let n_details = [&self.branch, &self.tag, &self.rev]
.iter()
.filter(|d| d.is_some())
.count();
Expand All @@ -990,9 +1003,9 @@ impl TomlDependency {
cx.warnings.push(msg)
}

let reference = details.branch.clone().map(GitReference::Branch)
.or_else(|| details.tag.clone().map(GitReference::Tag))
.or_else(|| details.rev.clone().map(GitReference::Rev))
let reference = self.branch.clone().map(GitReference::Branch)
.or_else(|| self.tag.clone().map(GitReference::Tag))
.or_else(|| self.rev.clone().map(GitReference::Rev))
.unwrap_or_else(|| GitReference::Branch("master".to_string()));
let loc = git.to_url()?;
SourceId::for_git(&loc, reference)?
Expand Down Expand Up @@ -1023,24 +1036,33 @@ impl TomlDependency {
(None, None, None, None) => SourceId::crates_io(cx.config)?,
};

let version = details.version.as_ref().map(|v| &v[..]);
let (pkg_name, rename) = match self.package {
Some(ref s) => (&s[..], Some(name)),
None => (name, None),
};

let version = self.version.as_ref().map(|v| &v[..]);
let mut dep = match cx.pkgid {
Some(id) => {
Dependency::parse(name, version, &new_source_id,
Dependency::parse(pkg_name, version, &new_source_id,
id, cx.config)?
}
None => Dependency::parse_no_deprecated(name, version, &new_source_id)?,
};
dep.set_features(details.features.unwrap_or_default())
.set_default_features(details.default_features
.or(details.default_features2)
dep.set_features(self.features.clone().unwrap_or_default())
.set_default_features(self.default_features
.or(self.default_features2)
.unwrap_or(true))
.set_optional(details.optional.unwrap_or(false))
.set_optional(self.optional.unwrap_or(false))
.set_platform(cx.platform.clone())
.set_registry_id(&registry_id);
if let Some(kind) = kind {
dep.set_kind(kind);
}
if let Some(rename) = rename {
cx.features.require(Feature::rename_dependency())?;
dep.set_rename(rename);
}
Ok(dep)
}
}
Expand Down
6 changes: 4 additions & 2 deletions tests/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ fn cargo_metadata_with_deps_and_version() {
"req": "^0.0.1",
"source": "registry+[..]",
"target": null,
"uses_default_features": true
"uses_default_features": true,
"rename": null
}
],
"features": {},
Expand Down Expand Up @@ -228,7 +229,8 @@ fn cargo_metadata_with_deps_and_version() {
"req": "*",
"source": "registry+[..]",
"target": null,
"uses_default_features": true
"uses_default_features": true,
"rename": null
}
],
"features": {},
Expand Down
Loading

0 comments on commit 4f1c6db

Please sign in to comment.