]> git.proxmox.com Git - cargo.git/commitdiff
Include registry in dependencies in the index.
authorChris Swindle <christopher.swindle@metaswitch.com>
Wed, 1 Nov 2017 22:14:33 +0000 (22:14 +0000)
committerChris Swindle <christopher.swindle@metaswitch.com>
Wed, 1 Nov 2017 22:14:33 +0000 (22:14 +0000)
src/cargo/core/source/source_id.rs
src/cargo/ops/registry.rs
src/crates-io/lib.rs
tests/alt-registry.rs

index 955ecca2107d0dde0808d7da008b8c91cfc1aa52..e7b43089483f415f8b8f9a2d1c3305326d2099fa 100644 (file)
@@ -44,6 +44,8 @@ enum Kind {
     Path,
     /// represents a remote registry
     Registry,
+    /// represents a remote alternative registry
+    AltRegistry,
     /// represents a local filesystem-based registry
     LocalRegistry,
     /// represents a directory-based registry
@@ -148,6 +150,11 @@ impl SourceId {
         SourceId::new(Kind::Registry, url.clone())
     }
 
+    /// Create a SourceId from an alternative registry url
+    pub fn for_alt_registry(url: &Url) -> CargoResult<SourceId> {
+        SourceId::new(Kind::AltRegistry, url.clone())
+    }
+
     /// Create a SourceId from a local registry path
     pub fn for_local_registry(path: &Path) -> CargoResult<SourceId> {
         let url = path.to_url()?;
@@ -186,7 +193,7 @@ impl SourceId {
         let url = config.get_registry_index(key)?;
         Ok(SourceId {
             inner: Arc::new(SourceIdInner {
-                kind: Kind::Registry,
+                kind: Kind::AltRegistry,
                 canonical_url: git::canonicalize_url(&url)?,
                 url: url,
                 precise: None,
@@ -211,11 +218,16 @@ impl SourceId {
     /// Is this source from a registry (either local or not)
     pub fn is_registry(&self) -> bool {
         match self.inner.kind {
-            Kind::Registry | Kind::LocalRegistry    => true,
-            _                                       => false,
+            Kind::Registry | Kind::AltRegistry | Kind::LocalRegistry => true,
+            _                                                        => false,
         }
     }
 
+    /// Is this source from an alternative registry
+    pub fn is_alt_registry(&self) -> bool {
+        self.inner.kind == Kind::AltRegistry
+    }
+
     /// Is this source from a git repository
     pub fn is_git(&self) -> bool {
         match self.inner.kind {
@@ -236,7 +248,7 @@ impl SourceId {
                 };
                 Ok(Box::new(PathSource::new(&path, self, config)))
             }
-            Kind::Registry => Ok(Box::new(RegistrySource::remote(self, config))),
+            Kind::Registry | Kind::AltRegistry => Ok(Box::new(RegistrySource::remote(self, config))),
             Kind::LocalRegistry => {
                 let path = match self.inner.url.to_file_path() {
                     Ok(p) => p,
@@ -361,6 +373,7 @@ impl fmt::Display for SourceId {
                 Ok(())
             }
             SourceIdInner { kind: Kind::Registry, ref url, .. } |
+            SourceIdInner { kind: Kind::AltRegistry, ref url, .. } |
             SourceIdInner { kind: Kind::LocalRegistry, ref url, .. } => {
                 write!(f, "registry `{}`", url)
             }
@@ -458,7 +471,8 @@ impl<'a> fmt::Display for SourceIdToUrl<'a> {
                 }
                 Ok(())
             }
-            SourceIdInner { kind: Kind::Registry, ref url, .. } => {
+            SourceIdInner { kind: Kind::Registry, ref url, .. } |
+            SourceIdInner { kind: Kind::AltRegistry, ref url, .. } => {
                 write!(f, "registry+{}", url)
             }
             SourceIdInner { kind: Kind::LocalRegistry, ref url, .. } => {
index a7e8ef82b72b89ddf5b1a5f28d0eef3257bd6ec1..9b536b21d557fd0835fb39f71c2f595e549d4647 100644 (file)
@@ -74,7 +74,7 @@ pub fn publish(ws: &Workspace, opts: &PublishOpts) -> CargoResult<()> {
 
     // Upload said tarball to the specified destination
     opts.config.shell().status("Uploading", pkg.package_id().to_string())?;
-    transmit(opts.config, pkg, tarball.file(), &mut registry, opts.dry_run)?;
+    transmit(opts.config, pkg, tarball.file(), &mut registry, &reg_id, opts.dry_run)?;
 
     Ok(())
 }
@@ -90,10 +90,14 @@ fn verify_dependencies(pkg: &Package, registry_src: &SourceId)
             }
         } else if dep.source_id() != registry_src {
             if dep.source_id().is_registry() {
-                bail!("crates cannot be published to crates.io with dependencies sourced from other\n\
-                       registries either publish `{}` on crates.io or pull it into this repository\n\
-                       and specify it with a path and version\n\
-                       (crate `{}` is pulled from {}", dep.name(), dep.name(), dep.source_id());
+                // Block requests to send to a registry if it is not an alternative
+                // registry
+                if !registry_src.is_alt_registry() {
+                    bail!("crates cannot be published to crates.io with dependencies sourced from other\n\
+                           registries either publish `{}` on crates.io or pull it into this repository\n\
+                           and specify it with a path and version\n\
+                           (crate `{}` is pulled from {}", dep.name(), dep.name(), dep.source_id());
+                }
             } else {
                 bail!("crates cannot be published to crates.io with dependencies sourced from \
                        a repository\neither publish `{}` as its own crate on crates.io and \
@@ -110,8 +114,19 @@ fn transmit(config: &Config,
             pkg: &Package,
             tarball: &File,
             registry: &mut Registry,
+            registry_id: &SourceId,
             dry_run: bool) -> CargoResult<()> {
+
     let deps = pkg.dependencies().iter().map(|dep| {
+
+        // If the dependency is from a different registry, then include the
+        // registry in the dependency.
+        let dep_registry = if dep.source_id() != registry_id {
+            Some(dep.source_id().url().to_string())
+        } else {
+            None
+        };
+
         NewCrateDependency {
             optional: dep.is_optional(),
             default_features: dep.uses_default_features(),
@@ -124,6 +139,7 @@ fn transmit(config: &Config,
                 Kind::Build => "build",
                 Kind::Development => "dev",
             }.to_string(),
+            registry: dep_registry,
         }
     }).collect::<Vec<NewCrateDependency>>();
     let manifest = pkg.manifest();
@@ -226,9 +242,10 @@ pub fn registry(config: &Config,
         index: index_config,
     } = registry_configuration(config, registry.clone())?;
     let token = token.or(token_config);
-    let sid = match (index_config, index) {
-        (Some(index), _) | (None, Some(index)) => SourceId::for_registry(&index.to_url()?)?,
-        (None, None) => SourceId::crates_io(config)?,
+    let sid = match (index_config, index, registry) {
+        (Some(index), _, Some(_registry)) => SourceId::for_alt_registry(&index.to_url()?)?,
+        (Some(index), _, _) | (None, Some(index), _) => SourceId::for_registry(&index.to_url()?)?,
+        (None, None, _) => SourceId::crates_io(config)?,
     };
     let api_host = {
         let mut src = RegistrySource::remote(&sid, config);
index 4ccfea2d8a9ead3b835af2446d5abb6a8f258deb..9645be81a6f8ca3c5c309a6d63688e311b44dfff 100644 (file)
@@ -100,6 +100,8 @@ pub struct NewCrateDependency {
     pub version_req: String,
     pub target: Option<String>,
     pub kind: String,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub registry: Option<String>,
 }
 
 #[derive(Deserialize)]
index 42770296ea089409a5af83860ed24cf2f366af23..45ef2153529a67dba0a1ec5bad637653bedba8ed 100644 (file)
@@ -65,11 +65,13 @@ fn depend_on_alt_registry() {
     // Don't download a second time
     assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
                 execs().with_status(0).with_stderr(&format!("\
+[UPDATING] registry `{reg}`
 [COMPILING] bar v0.0.1 (registry `file://[..]`)
 [COMPILING] foo v0.0.1 ({dir})
 [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] secs
 ",
-        dir = p.url())));
+        dir = p.url(),
+        reg = registry::alt_registry())));
 }
 
 #[test]
@@ -91,7 +93,7 @@ fn depend_on_alt_registry_depends_on_same_registry() {
         .build();
 
     Package::new("baz", "0.0.1").alternative(true).publish();
-    Package::new("bar", "0.0.1").registry_dep("baz", "0.0.1", registry::alt_registry().as_str()).alternative(true).publish();
+    Package::new("bar", "0.0.1").dep("baz", "0.0.1").alternative(true).publish();
 
     assert_that(p.cargo("build").masquerade_as_nightly_cargo(),
                 execs().with_status(0).with_stderr(&format!("\
@@ -107,7 +109,6 @@ fn depend_on_alt_registry_depends_on_same_registry() {
         reg = registry::alt_registry())));
 }
 
-
 #[test]
 fn depend_on_alt_registry_depends_on_crates_io() {
     let p = project("foo")
@@ -192,7 +193,7 @@ fn registry_incompatible_with_git() {
 }
 
 #[test]
-fn cannot_publish_with_registry_dependency() {
+fn publish_with_registry_dependency() {
     let p = project("foo")
         .file("Cargo.toml", r#"
             cargo-features = ["alternative-registries"]
@@ -211,9 +212,14 @@ fn cannot_publish_with_registry_dependency() {
 
     Package::new("bar", "0.0.1").alternative(true).publish();
 
+    // Login so that we have the token available
+    assert_that(p.cargo("login").masquerade_as_nightly_cargo()
+                 .arg("--registry").arg("alternative").arg("TOKEN").arg("-Zunstable-options"),
+                execs().with_status(0));
+
     assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
-                 .arg("--index").arg(registry::alt_registry().to_string()),
-                execs().with_status(101));
+                 .arg("--registry").arg("alternative").arg("-Zunstable-options"),
+                execs().with_status(0));
 }
 
 #[test]
@@ -288,6 +294,8 @@ fn block_publish_due_to_no_token() {
 fn publish_to_alt_registry() {
     let p = project("foo")
         .file("Cargo.toml", r#"
+            cargo-features = ["alternative-registries"]
+
             [project]
             name = "foo"
             version = "0.0.1"
@@ -301,7 +309,7 @@ fn publish_to_alt_registry() {
 
     // Login so that we have the token available
     assert_that(p.cargo("login").masquerade_as_nightly_cargo()
-                .arg("--registry").arg("alternative").arg("TOKEN").arg("-Zunstable-options"),
+                 .arg("--registry").arg("alternative").arg("TOKEN").arg("-Zunstable-options"),
                 execs().with_status(0));
 
     // Now perform the actual publish
@@ -312,3 +320,34 @@ fn publish_to_alt_registry() {
     // Ensure that the crate is uploaded
     assert!(alt_dl_path().join("api/v1/crates/new").exists());
 }
+
+#[test]
+fn publish_with_crates_io_dep() {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            cargo-features = ["alternative-registries"]
+
+            [project]
+            name = "foo"
+            version = "0.0.1"
+            authors = ["me"]
+            license = "MIT"
+            description = "foo"
+
+            [dependencies.bar]
+            version = "0.0.1"
+        "#)
+        .file("src/main.rs", "fn main() {}")
+        .build();
+
+    Package::new("bar", "0.0.1").publish();
+
+    // Login so that we have the token available
+    assert_that(p.cargo("login").masquerade_as_nightly_cargo()
+                 .arg("--registry").arg("alternative").arg("TOKEN").arg("-Zunstable-options"),
+                execs().with_status(0));
+
+    assert_that(p.cargo("publish").masquerade_as_nightly_cargo()
+                 .arg("--registry").arg("alternative").arg("-Zunstable-options"),
+                execs().with_status(0));
+}