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 {
}
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))
}
}
}
+impl<'a> ToUrl for &'a Url {
+ fn to_url(self) -> Option<Url> {
+ Some(self.clone())
+ }
+}
+
#[deriving(Clone,PartialEq)]
pub struct PackageId {
name: String,
+use std::fmt::Show;
use std::collections::HashMap;
use core::{
Dependency,
* - 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();
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);
}
};
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);
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));
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()))
}
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");
}
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() {
use ops;
+use url;
use core::source::Source;
use core::{Package,PackageId,Summary};
use util::CargoResult;
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 {
}
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()))
}
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))
}
}
-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)
}
+pub use self::path::PathSource;
+pub use self::git::GitSource;
+
pub mod path;
pub mod git;
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 {
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
}
}
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
}
}
-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()))
+}
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;
pub mod important_paths;
pub mod result;
pub mod toml;
+pub mod paths;
--- /dev/null
+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);
+}
+
match self.desc {
StaticDescription(string) => write!(f, "{}", string),
BoxedDescription(ref string) => write!(f, "{}", string)
- }
+ };
+
+ write!(f, "; kind={}", self.kind)
}
}
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> {
}
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()));
}
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")))
}
/// 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 =====
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
}
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)))
}
}
}
-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() {
}
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());
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");