Add namespace to PackageId

This commit is contained in:
Yehuda Katz + Carl Lerche 2014-06-11 14:50:54 -07:00 committed by Tim Carey-Smith
parent 530998b700
commit c57fef459a
15 changed files with 135 additions and 80 deletions

View 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))
}

View 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,

View 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);
}
};

View 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));

View 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()))
}

View 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() {

View 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)
}

View File

@ -1,2 +1,5 @@
pub use self::path::PathSource;
pub use self::git::GitSource;
pub mod path;
pub mod git;

View 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()))
}

View 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;

40
src/cargo/util/paths.rs Normal file
View File

@ -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);
}

View 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)
}
}

View 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")))
}

View 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)))
}
}
}

View 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");