Add namespace to PackageId
authorYehuda Katz + Carl Lerche <engineering@tilde.io>
Wed, 11 Jun 2014 21:50:54 +0000 (14:50 -0700)
committerTim Carey-Smith <tim@spork.in>
Wed, 11 Jun 2014 21:51:13 +0000 (14:51 -0700)
15 files changed:
src/bin/cargo-read-manifest.rs
src/cargo/core/package_id.rs
src/cargo/core/resolver.rs
src/cargo/ops/cargo_compile.rs
src/cargo/ops/cargo_read_manifest.rs
src/cargo/ops/cargo_rustc.rs
src/cargo/sources/git/source.rs
src/cargo/sources/mod.rs
src/cargo/sources/path.rs
src/cargo/util/mod.rs
src/cargo/util/paths.rs [new file with mode: 0644]
src/cargo/util/result.rs
src/cargo/util/toml.rs
tests/support.rs
tests/test_cargo_compile.rs

index 32a3500a597df10fbb33609829e55444b2578ca4..b1a08de0eaf44789782bc777ddf22c84d783c556 100644 (file)
@@ -7,7 +7,7 @@ extern crate hammer;
 use hammer::FlagConfig;
 use cargo::{execute_main_without_stdin,CLIResult,CLIError};
 use cargo::core::Package;
-use cargo::ops;
+use cargo::sources::{PathSource};
 
 #[deriving(PartialEq,Clone,Decodable)]
 struct Options {
@@ -21,6 +21,6 @@ fn main() {
 }
 
 fn execute(options: Options) -> CLIResult<Option<Package>> {
-    ops::read_package(&Path::new(options.manifest_path.as_slice())).map(|m| Some(m))
+    PathSource::read_package(&Path::new(options.manifest_path.as_slice())).map(|m| Some(m))
         .map_err(|err| CLIError::new(err.get_desc(), Some(err.get_detail()), 1))
 }
index ba5594f7a0ae2cd2c536b4122ed53ca94c446436..4b3ea8eb91841fb503e58ffdc0234107605888da 100644 (file)
@@ -42,6 +42,12 @@ impl ToUrl for Url {
     }
 }
 
+impl<'a> ToUrl for &'a Url {
+    fn to_url(self) -> Option<Url> {
+        Some(self.clone())
+    }
+}
+
 #[deriving(Clone,PartialEq)]
 pub struct PackageId {
     name: String,
index 724968b716dc81e0b8f829fb3f99fa33fb5a7f6f..a67cbf1d19e9b3408a8ddc1e9e75a75859507a24 100644 (file)
@@ -1,3 +1,4 @@
+use std::fmt::Show;
 use std::collections::HashMap;
 use core::{
     Dependency,
@@ -11,7 +12,9 @@ use util::result::CargoResult;
  * - The correct input here is not a registry. Resolves should be performable
  * on package summaries vs. the packages themselves.
  */
-pub fn resolve(deps: &[Dependency], registry: &Registry) -> CargoResult<Vec<PackageId>> {
+pub fn resolve<R: Registry + Show>(deps: &[Dependency], registry: &R) -> CargoResult<Vec<PackageId>> {
+    log!(5, "resolve; deps={}; registry={}", deps, registry);
+
     let mut remaining = Vec::from_slice(deps);
     let mut resolve = HashMap::<&str, &Summary>::new();
 
@@ -19,7 +22,9 @@ pub fn resolve(deps: &[Dependency], registry: &Registry) -> CargoResult<Vec<Pack
         let curr = match remaining.pop() {
             Some(curr) => curr,
             None => {
-                return Ok(resolve.values().map(|summary| summary.get_package_id().clone()).collect());
+                let ret = resolve.values().map(|summary| summary.get_package_id().clone()).collect();
+                log!(5, "resolve complete; ret={}", ret);
+                return Ok(ret);
             }
         };
 
index bb69aa70011b70c991d5526577eb5828344353db..d68543a1201124fe48b8bcad1fffe059138a7ae6 100644 (file)
@@ -26,7 +26,8 @@ use util::{other_error, CargoResult, Wrap};
 pub fn compile(manifest_path: &Path) -> CargoResult<()> {
     log!(4, "compile; manifest-path={}", manifest_path.display());
 
-    let package = try!(ops::read_package(manifest_path));
+    // TODO: Move this into PathSource
+    let package = try!(PathSource::read_package(manifest_path));
 
     debug!("loaded package; package={}", package);
 
@@ -51,6 +52,8 @@ pub fn compile(manifest_path: &Path) -> CargoResult<()> {
 
     let packages = try!(source.get(resolved.as_slice()).wrap("unable to get packages from source"));
 
+    log!(5, "fetch packages from source; packages={}; ids={}", packages, resolved);
+
     let package_set = PackageSet::new(packages.as_slice());
 
     try!(ops::compile_packages(&package, &package_set));
index 95f1062d00cacbce00bf2815416b40b91530d1cc..97ea1755d057a965988965d57b73a28be549da83 100644 (file)
@@ -1,16 +1,18 @@
 use std::io::File;
 use util;
+use url::Url;
 use core::{Package,Manifest};
 use util::{CargoResult,io_error};
 
-pub fn read_manifest(contents: &[u8]) -> CargoResult<Manifest> {
-    util::toml::to_manifest(contents)
+pub fn read_manifest(contents: &[u8], namespace: &Url) -> CargoResult<Manifest> {
+    util::toml::to_manifest(contents, namespace)
 }
 
-pub fn read_package(path: &Path) -> CargoResult<Package> {
+pub fn read_package(path: &Path, namespace: &Url) -> CargoResult<Package> {
+    log!(5, "read_package; path={}; namespace={}", path.display(), namespace);
     let mut file = try!(File::open(path).map_err(io_error));
     let data = try!(file.read_to_end().map_err(io_error));
-    let manifest = try!(read_manifest(data.as_slice()));
+    let manifest = try!(read_manifest(data.as_slice(), namespace));
 
     Ok(Package::new(&manifest, &path.dir_path()))
 }
index 733e5d91e1a34fff9d93216a4785e4561f074bd5..6e2925cbd7101bbd5e1a85248aaae19bd0c3a2ee 100644 (file)
@@ -10,7 +10,7 @@ use util::result::ProcessError;
 type Args = Vec<String>;
 
 pub fn compile_packages(pkg: &Package, deps: &PackageSet) -> CargoResult<()> {
-    debug!("compiling; pkg={}; deps={}", pkg, deps);
+    debug!("compile_packages; pkg={}; deps={}", pkg, deps);
 
     let target_dir = pkg.get_absolute_target_dir();
     let deps_target_dir = target_dir.join("deps");
@@ -33,7 +33,7 @@ pub fn compile_packages(pkg: &Package, deps: &PackageSet) -> CargoResult<()> {
 }
 
 fn compile_pkg(pkg: &Package, dest: &Path, deps_dir: &Path, primary: bool) -> CargoResult<()> {
-    debug!("compiling; pkg={}; targets={}", pkg, pkg.get_targets());
+    debug!("compile_pkg; pkg={}; targets={}", pkg, pkg.get_targets());
 
     // compile
     for target in pkg.get_targets().iter() {
index 1c88f450f80c73c32087db7be4fe5c579c49401c..ec33b9b0208d72e16f4362acc816154444614af1 100644 (file)
@@ -1,4 +1,5 @@
 use ops;
+use url;
 use core::source::Source;
 use core::{Package,PackageId,Summary};
 use util::CargoResult;
@@ -18,6 +19,10 @@ impl GitSource {
     pub fn new(remote: GitRemote, reference: String, db: Path, checkout: Path, verbose: bool) -> GitSource {
         GitSource { remote: remote, reference: GitReference::for_str(reference), db_path: db, checkout_path: checkout, verbose: verbose }
     }
+
+    pub fn get_namespace<'a>(&'a self) -> &'a url::Url {
+        self.remote.get_url()
+    }
 }
 
 impl Show for GitSource {
@@ -40,7 +45,7 @@ impl Source for GitSource {
     }
 
     fn list(&self) -> CargoResult<Vec<Summary>> {
-        let pkg = try!(read_manifest(&self.checkout_path));
+        let pkg = try!(read_manifest(&self.checkout_path, self.get_namespace()));
         Ok(vec!(pkg.get_summary().clone()))
     }
 
@@ -50,7 +55,7 @@ impl Source for GitSource {
 
     fn get(&self, package_ids: &[PackageId]) -> CargoResult<Vec<Package>> {
         // TODO: Support multiple manifests per repo
-        let pkg = try!(read_manifest(&self.checkout_path));
+        let pkg = try!(read_manifest(&self.checkout_path, self.remote.get_url()));
 
         if package_ids.iter().any(|pkg_id| pkg_id == pkg.get_package_id()) {
             Ok(vec!(pkg))
@@ -60,7 +65,7 @@ impl Source for GitSource {
     }
 }
 
-fn read_manifest(path: &Path) -> CargoResult<Package> {
+fn read_manifest(path: &Path, url: &url::Url) -> CargoResult<Package> {
     let path = path.join("Cargo.toml");
-    ops::read_package(&path)
+    ops::read_package(&path, url)
 }
index dc14a54baa330cd945d720b53dee28cd37692dc5..876c4836e933bd7433cf79b2731cfcccbae44ff1 100644 (file)
@@ -1,2 +1,5 @@
+pub use self::path::PathSource;
+pub use self::git::GitSource;
+
 pub mod path;
 pub mod git;
index dcef3ed29552f3a53cc36812108e76ff36421416..07d9678d3a79b1163adbbe76df81457d64ec9351 100644 (file)
@@ -3,17 +3,31 @@ use std::fmt::{Show,Formatter};
 use core::{Package,PackageId,Summary};
 use core::source::Source;
 use ops;
-use util::{CargoResult};
+use url;
+use util::{CargoResult,simple_human,io_error,realpath};
 
-pub struct PathSource {
-    paths: Vec<Path>
-}
+/* 
+ * TODO: Consider whether it may be more appropriate for a PathSource to only
+ * take in a single path vs. a vec of paths. The pros / cons are unknown at
+ * this point.
+ */
+pub struct PathSource { paths: Vec<Path> }
 
 impl PathSource {
     pub fn new(paths: Vec<Path>) -> PathSource {
-        log!(4, "new; paths={}", display(paths.as_slice()));
+        log!(5, "new; paths={}", display(paths.as_slice()));
         PathSource { paths: paths }
     }
+
+    pub fn read_package(path: &Path) -> CargoResult<Package> {
+        log!(5, "read_package; path={}", path.display());
+
+        // TODO: Use a realpath fn
+        let dir = path.dir_path();
+        let namespace = try!(namespace(&dir));
+
+        ops::read_package(path, &namespace)
+    }
 }
 
 impl Show for PathSource {
@@ -27,10 +41,10 @@ impl Source for PathSource {
 
     fn list(&self) -> CargoResult<Vec<Summary>> {
         Ok(self.paths.iter().filter_map(|path| {
-            match read_manifest(path) {
+            match PathSource::read_package(&path.join("Cargo.toml")) {
                 Ok(ref pkg) => Some(pkg.get_summary().clone()),
                 Err(e) => {
-                    log!(4, "failed to read manifest; path={}; err={}", path.display(), e);
+                    debug!("failed to read manifest; path={}; err={}", path.display(), e);
                     None
                 }
             }
@@ -41,11 +55,15 @@ impl Source for PathSource {
         Ok(())
     }
 
-    fn get(&self, name_vers: &[PackageId]) -> CargoResult<Vec<Package>> {
+    fn get(&self, ids: &[PackageId]) -> CargoResult<Vec<Package>> {
+        log!(5, "getting packages; ids={}", ids);
+
         Ok(self.paths.iter().filter_map(|path| {
-            match read_manifest(path) {
+            match PathSource::read_package(&path.join("Cargo.toml")) {
                 Ok(pkg) => {
-                    if name_vers.iter().any(|pkg_id| pkg.get_package_id() == pkg_id) {
+                    log!(5, "comparing; pkg={}", pkg);
+
+                    if ids.iter().any(|pkg_id| pkg.get_package_id() == pkg_id) {
                         Some(pkg)
                     } else {
                         None
@@ -57,11 +75,12 @@ impl Source for PathSource {
     }
 }
 
-fn read_manifest(path: &Path) -> CargoResult<Package> {
-    let path = path.join("Cargo.toml");
-    ops::read_package(&path)
-}
-
 fn display(paths: &[Path]) -> Vec<String> {
     paths.iter().map(|p| p.display().to_str()).collect()
 }
+
+fn namespace(path: &Path) -> CargoResult<url::Url> {
+    let real = try!(realpath(path).map_err(io_error));
+    url::from_str(format!("file://{}", real.display()).as_slice()).map_err(|err|
+        simple_human(err.as_slice()))
+}
index 2d2229c3c876350b997016b83fe05ecc63ebbcb4..58eaf1829d64a92face918462d4900dab0d0c125 100644 (file)
@@ -1,5 +1,6 @@
 pub use self::process_builder::{process,ProcessBuilder};
 pub use self::result::{CargoError,CargoResult,Wrap,Require,ToCLI,other_error,human_error,simple_human,toml_error,io_error,process_error};
+pub use self::paths::realpath;
 
 pub mod graph;
 pub mod process_builder;
@@ -7,3 +8,4 @@ pub mod config;
 pub mod important_paths;
 pub mod result;
 pub mod toml;
+pub mod paths;
diff --git a/src/cargo/util/paths.rs b/src/cargo/util/paths.rs
new file mode 100644 (file)
index 0000000..bfdf0ca
--- /dev/null
@@ -0,0 +1,40 @@
+use std::{io,os};
+use std::io::fs;
+
+pub fn realpath(original: &Path) -> io::IoResult<Path> {
+    static MAX_LINKS_FOLLOWED: uint = 256;
+    let original = os::make_absolute(original);
+
+    // Right now lstat on windows doesn't work quite well
+    if cfg!(windows) {
+        return Ok(original)
+    }
+
+    let result = original.root_path();
+    let mut result = result.expect("make_absolute has no root_path");
+    let mut followed = 0;
+
+    for part in original.components() {
+        result.push(part);
+
+        loop {
+            if followed == MAX_LINKS_FOLLOWED {
+                return Err(io::standard_error(io::InvalidInput))
+            }
+
+            match fs::lstat(&result) {
+                Err(..) => break,
+                Ok(ref stat) if stat.kind != io::TypeSymlink => break,
+                Ok(..) => {
+                    followed += 1;
+                    let path = try!(fs::readlink(&result));
+                    result.pop();
+                    result.push(path);
+                }
+            }
+        }
+    }
+
+    return Ok(result);
+}
+
index 66489790e2d1bd57ff83e816099e40b9fd09d35e..3f943d1eb66b87b9ab3fb7930101649af4a3140a 100644 (file)
@@ -82,7 +82,9 @@ impl Show for CargoError {
         match self.desc {
             StaticDescription(string) => write!(f, "{}", string),
             BoxedDescription(ref string) => write!(f, "{}", string)
-        }
+        };
+
+        write!(f, "; kind={}", self.kind)
     }
 }
 
index 24aab126905f7d37626ed03972bb12a6d636e3fa..cfbe60147d8f5e78814aa7152aad498479d66cfc 100644 (file)
@@ -1,18 +1,19 @@
 use toml;
+use url::Url;
 use std::collections::HashMap;
 use serialize::Decodable;
 
 use core::{Summary,Manifest,Target,Dependency,PackageId};
 use util::{CargoResult,Require,simple_human,toml_error};
 
-pub fn to_manifest(contents: &[u8]) -> CargoResult<Manifest> {
+pub fn to_manifest(contents: &[u8], namespace: &Url) -> CargoResult<Manifest> {
     let root = try!(toml::parse_from_bytes(contents).map_err(|_|
         simple_human("Cargo.toml is not valid Toml")));
 
     let toml = try!(toml_to_manifest(root).map_err(|_|
         simple_human("Cargo.toml is not a valid Cargo manifest")));
 
-    toml.to_manifest()
+    toml.to_manifest(namespace)
 }
 
 fn toml_to_manifest(root: toml::Value) -> CargoResult<TomlManifest> {
@@ -104,13 +105,13 @@ pub struct TomlProject {
 }
 
 impl TomlProject {
-    pub fn to_package_id(&self, namespace: &str) -> PackageId {
+    pub fn to_package_id(&self, namespace: &Url) -> PackageId {
         PackageId::new(self.name.as_slice(), self.version.as_slice(), namespace)
     }
 }
 
 impl TomlManifest {
-    pub fn to_manifest(&self) -> CargoResult<Manifest> {
+    pub fn to_manifest(&self, namespace: &Url) -> CargoResult<Manifest> {
 
         // Get targets
         let targets = normalize(self.lib.as_ref().map(|l| l.as_slice()), self.bin.as_ref().map(|b| b.as_slice()));
@@ -137,7 +138,7 @@ impl TomlManifest {
         }
 
         Ok(Manifest::new(
-                &Summary::new(&self.project.to_package_id("http://rust-lang.org/central-repo"), deps.as_slice()),
+                &Summary::new(&self.project.to_package_id(namespace), deps.as_slice()),
                 targets.as_slice(),
                 &Path::new("target")))
     }
index efc34259a54b6287514d1294813ea945378cc9f4..ec4f6172dd312d46c74d6289468141f122270ba3 100644 (file)
@@ -152,43 +152,6 @@ pub fn cargo_dir() -> Path {
 
 /// Returns an absolute path in the filesystem that `path` points to. The
 /// returned path does not contain any symlinks in its hierarchy.
-pub fn realpath(original: &Path) -> io::IoResult<Path> {
-    static MAX_LINKS_FOLLOWED: uint = 256;
-    let original = os::make_absolute(original);
-
-    // Right now lstat on windows doesn't work quite well
-    if cfg!(windows) {
-        return Ok(original)
-    }
-
-    let result = original.root_path();
-    let mut result = result.expect("make_absolute has no root_path");
-    let mut followed = 0;
-
-    for part in original.components() {
-        result.push(part);
-
-        loop {
-            if followed == MAX_LINKS_FOLLOWED {
-                return Err(io::standard_error(io::InvalidInput))
-            }
-
-            match fs::lstat(&result) {
-                Err(..) => break,
-                Ok(ref stat) if stat.kind != io::TypeSymlink => break,
-                Ok(..) => {
-                    followed += 1;
-                    let path = try!(fs::readlink(&result));
-                    result.pop();
-                    result.push(path);
-                }
-            }
-        }
-    }
-
-    return Ok(result);
-}
-
 /*
  *
  * ===== Matchers =====
@@ -205,12 +168,12 @@ struct Execs {
 
 impl Execs {
 
-  pub fn with_stdout(mut ~self, expected: &str) -> Box<Execs> {
+  pub fn with_stdout<S: ToStr>(mut ~self, expected: S) -> Box<Execs> {
     self.expect_stdout = Some(expected.to_str());
     self
   }
 
-  pub fn with_stderr(mut ~self, expected: &str) -> Box<Execs> {
+  pub fn with_stderr<S: ToStr>(mut ~self, expected: S) -> Box<Execs> {
       self.expect_stderr = Some(expected.to_str());
       self
   }
@@ -252,7 +215,7 @@ impl Execs {
         match str::from_utf8(actual) {
           None => Err(format!("{} was not utf8 encoded", description)),
           Some(actual) => {
-            ham::expect(actual == out, format!("{} was:\n`{}`\n\nexpected:\n`{}`\n\nother output:\n`{}`", description, actual, out, str::from_utf8(extra)))
+            ham::expect(actual == out, format!("{} was:\n`{}`\n\nexpected:\n`{}`\n\nother output:\n`{}`", description, actual, out, str::from_utf8_lossy(extra)))
           }
         }
       }
index f212d8ef8efb08b9dce3af3de6f73f586a441de4..deeb20fbc38b0d07e084fc2fc62dc3feb2993338 100644 (file)
@@ -1,7 +1,7 @@
-use support::{ResultTest,project,execs,realpath};
+use support::{ResultTest,project,execs};
 use hamcrest::{assert_that,existing_file};
 use cargo;
-use cargo::util::process;
+use cargo::util::{process,realpath};
 
 fn setup() {
 }
@@ -120,9 +120,13 @@ test!(cargo_compile_with_warnings_in_a_dep_package {
             fn dead() {}
         "#);
 
+    let bar = realpath(&p.root().join("bar")).assert();
+    let main = realpath(&p.root()).assert();
+
     assert_that(p.cargo_process("cargo-compile"),
         execs()
-        .with_stdout("Compiling bar v0.5.0\nCompiling foo v0.5.0\n")
+        .with_stdout(format!("Compiling bar v0.5.0 (file:{})\nCompiling foo v0.5.0 (file:{})\n",
+                             bar.display(), main.display()))
         .with_stderr(""));
 
     assert_that(&p.root().join("target/foo"), existing_file());
@@ -132,7 +136,7 @@ test!(cargo_compile_with_warnings_in_a_dep_package {
       execs().with_stdout("test passed\n"));
 })
 
-test!(cargo_compile_with_nested_deps {
+test!(cargo_compile_with_nested_deps_shorthand {
     let mut p = project("foo");
     let bar = p.root().join("bar");
     let baz = p.root().join("baz");