diff --git a/Makefile b/Makefile index 4bba33d9242..2e852de1fa7 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ BINS = cargo \ SRC = $(shell find src -name '*.rs' -not -path 'src/bin*') DEPS = -L libs/hammer.rs/target -L libs/toml-rs/build -TOML = libs/toml-rs/lib/$(shell rustc --crate-file-name libs/toml-rs/src/toml.rs) +TOML = libs/toml-rs/build/$(shell rustc --crate-file-name libs/toml-rs/src/toml.rs) HAMMER = libs/hammer.rs/target/$(shell rustc --crate-type=lib --crate-file-name libs/hammer.rs/src/hammer.rs) HAMCREST = libs/hamcrest-rust/target/libhamcrest.timestamp LIBCARGO = target/libcargo.timestamp diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 1bf19fab624..32284f82f89 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -123,7 +123,7 @@ impl Package { // Sort the sources just to make sure we have a consistent fingerprint. sources.sort_by(|a, b| { cmp::lexical_ordering(a.kind.cmp(&b.kind), - a.url.to_str().cmp(&b.url.to_str())) + a.location.to_str().cmp(&b.location.to_str())) }); let sources = sources.iter().map(|source_id| { source_id.load(config) diff --git a/src/cargo/core/package_id.rs b/src/cargo/core/package_id.rs index d96e21547df..719c709a5db 100644 --- a/src/cargo/core/package_id.rs +++ b/src/cargo/core/package_id.rs @@ -11,6 +11,7 @@ use serialize::{ }; use util::{CargoResult, CargoError}; +use core::source::Location; trait ToVersion { fn to_version(self) -> Result; @@ -57,7 +58,7 @@ impl<'a> ToUrl for &'a Url { pub struct PackageId { name: String, version: semver::Version, - namespace: Url + namespace: Location, } #[deriving(Clone, Show, PartialEq)] @@ -77,14 +78,13 @@ impl CargoError for PackageIdError { } impl PackageId { - pub fn new(name: &str, version: T, - namespace: U) -> CargoResult { + pub fn new(name: &str, version: T, + ns: &Location) -> CargoResult { let v = try!(version.to_version().map_err(InvalidVersion)); - let ns = try!(namespace.to_url().map_err(InvalidNamespace)); Ok(PackageId { name: name.to_str(), version: v, - namespace: ns + namespace: ns.clone() }) } @@ -96,7 +96,7 @@ impl PackageId { &self.version } - pub fn get_namespace<'a>(&'a self) -> &'a Url { + pub fn get_namespace<'a>(&'a self) -> &'a Location { &self.namespace } } @@ -125,7 +125,7 @@ impl>> Decodable> for PackageId { PackageId::new( vector.get(0).as_slice(), vector.get(1).as_slice(), - vector.get(2).as_slice()) + &try!(Location::parse(vector.get(2).as_slice()))) } } @@ -139,12 +139,14 @@ impl> Encodable for PackageId { #[cfg(test)] mod tests { use super::{PackageId, central_repo}; + use core::source::Location; #[test] fn invalid_version_handled_nicely() { - assert!(PackageId::new("foo", "1.0", central_repo).is_err()); - assert!(PackageId::new("foo", "1", central_repo).is_err()); - assert!(PackageId::new("foo", "bar", central_repo).is_err()); - assert!(PackageId::new("foo", "", central_repo).is_err()); + let repo = Location::parse(central_repo).unwrap(); + assert!(PackageId::new("foo", "1.0", &repo).is_err()); + assert!(PackageId::new("foo", "1", &repo).is_err()); + assert!(PackageId::new("foo", "bar", &repo).is_err()); + assert!(PackageId::new("foo", "", &repo).is_err()); } } diff --git a/src/cargo/core/resolver.rs b/src/cargo/core/resolver.rs index da0dcb834bf..dc81e5cb887 100644 --- a/src/cargo/core/resolver.rs +++ b/src/cargo/core/resolver.rs @@ -57,56 +57,43 @@ pub fn resolve(deps: &[Dependency], #[cfg(test)] mod test { use url; + use hamcrest::{assert_that, equal_to, contains}; - use hamcrest::{ - assert_that, - equal_to, - contains - }; - - use core::source::{ - SourceId, - RegistryKind - }; - - use core::{ - Dependency, - PackageId, - Summary - }; - - use super::{ - resolve - }; + use core::source::{SourceId, RegistryKind, Location, Remote}; + use core::{Dependency, PackageId, Summary}; + use super::resolve; macro_rules! pkg( ($name:expr => $($deps:expr),+) => ( { let url = url::from_str("http://example.com").unwrap(); - let source_id = SourceId::new(RegistryKind, url); + let source_id = SourceId::new(RegistryKind, Remote(url)); let d: Vec = vec!($($deps),+).iter().map(|s| { Dependency::parse(*s, Some("1.0.0"), &source_id).unwrap() }).collect(); - Summary::new(&PackageId::new($name, "1.0.0", - "http://www.example.com/").unwrap(), + Summary::new(&PackageId::new($name, "1.0.0", ®istry_loc()).unwrap(), d.as_slice()) } ); ($name:expr) => ( - Summary::new(&PackageId::new($name, "1.0.0", - "http://www.example.com/").unwrap(), []) + Summary::new(&PackageId::new($name, "1.0.0", ®istry_loc()).unwrap(), + []) ) ) + fn registry_loc() -> Location { + Location::parse("http://www.example.com/").unwrap() + } + fn pkg(name: &str) -> Summary { - Summary::new(&PackageId::new(name, "1.0.0", "http://www.example.com/").unwrap(), + Summary::new(&PackageId::new(name, "1.0.0", ®istry_loc()).unwrap(), &[]) } fn dep(name: &str) -> Dependency { let url = url::from_str("http://example.com").unwrap(); - let source_id = SourceId::new(RegistryKind, url); + let source_id = SourceId::new(RegistryKind, Remote(url)); Dependency::parse(name, Some("1.0.0"), &source_id).unwrap() } @@ -116,7 +103,7 @@ mod test { fn names(names: &[&'static str]) -> Vec { names.iter() - .map(|name| PackageId::new(*name, "1.0.0", "http://www.example.com/").unwrap()) + .map(|name| PackageId::new(*name, "1.0.0", ®istry_loc()).unwrap()) .collect() } diff --git a/src/cargo/core/source.rs b/src/cargo/core/source.rs index 8636acf3013..3214a8eb058 100644 --- a/src/cargo/core/source.rs +++ b/src/cargo/core/source.rs @@ -4,9 +4,10 @@ use std::fmt::{Show, Formatter}; use url; use url::Url; -use core::{Summary,Package,PackageId}; -use sources::{PathSource,GitSource}; -use util::{Config,CargoResult}; +use core::{Summary, Package, PackageId}; +use sources::{PathSource, GitSource}; +use util::{Config, CargoResult}; +use util::errors::human; /// A Source finds and downloads remote packages based on names and /// versions. @@ -51,20 +52,47 @@ pub enum SourceKind { RegistryKind } +#[deriving(Clone, PartialEq, Eq)] +pub enum Location { + Local(Path), + Remote(Url), +} + #[deriving(Clone,PartialEq)] pub struct SourceId { pub kind: SourceKind, - pub url: Url + pub location: Location, +} + +impl Show for Location { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match *self { + Local(ref p) => write!(f, "file:{}", p.display()), + Remote(ref u) => write!(f, "{}", u), + } + } +} + +impl Location { + pub fn parse(s: &str) -> CargoResult { + if s.starts_with("file:") { + Ok(Local(Path::new(s.slice_from(5)))) + } else { + url::from_str(s).map(Remote).map_err(|e| { + human(format!("invalid url `{}`: `{}", s, e)) + }) + } + } } impl Show for SourceId { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match *self { - SourceId { kind: PathKind, ref url } => { - try!(write!(f, "{}", url)) + SourceId { kind: PathKind, ref location } => { + try!(write!(f, "{}", location)) }, - SourceId { kind: GitKind(ref reference), ref url } => { - try!(write!(f, "{}", url)); + SourceId { kind: GitKind(ref reference), ref location } => { + try!(write!(f, "{}", location)); if reference.as_slice() != "master" { try!(write!(f, " (ref={})", reference)); } @@ -80,33 +108,26 @@ impl Show for SourceId { } impl SourceId { - pub fn new(kind: SourceKind, url: Url) -> SourceId { - SourceId { kind: kind, url: url } + pub fn new(kind: SourceKind, location: Location) -> SourceId { + SourceId { kind: kind, location: location } } // Pass absolute path pub fn for_path(path: &Path) -> SourceId { - // TODO: use proper path -> URL - let url = if cfg!(windows) { - let path = path.display().to_str(); - format!("file://{}", path.as_slice().replace("\\", "/")) - } else { - format!("file://{}", path.display()) - }; - SourceId::new(PathKind, url::from_str(url.as_slice()).unwrap()) + SourceId::new(PathKind, Local(path.clone())) } pub fn for_git(url: &Url, reference: &str) -> SourceId { - SourceId::new(GitKind(reference.to_str()), url.clone()) + SourceId::new(GitKind(reference.to_str()), Remote(url.clone())) } pub fn for_central() -> SourceId { SourceId::new(RegistryKind, - url::from_str("https://example.com").unwrap()) + Remote(url::from_str("https://example.com").unwrap())) } - pub fn get_url<'a>(&'a self) -> &'a Url { - &self.url + pub fn get_location<'a>(&'a self) -> &'a Location { + &self.location } pub fn is_path(&self) -> bool { @@ -124,12 +145,11 @@ impl SourceId { match self.kind { GitKind(..) => box GitSource::new(self, config) as Box, PathKind => { - let mut path = self.url.path.clone(); - if cfg!(windows) { - path = path.replace("/", "\\"); - } - let path = Path::new(path); - box PathSource::new(&path, self) as Box + let path = match self.location { + Local(ref p) => p, + Remote(..) => fail!("path sources cannot be remote"), + }; + box PathSource::new(path, self) as Box }, RegistryKind => unimplemented!() } diff --git a/src/cargo/sources/git/source.rs b/src/cargo/sources/git/source.rs index aa889f92f80..1868023c04e 100644 --- a/src/cargo/sources/git/source.rs +++ b/src/cargo/sources/git/source.rs @@ -1,13 +1,12 @@ +use std::fmt::{Show,Formatter}; use std::fmt; -use std::hash::sip::SipHasher; use std::hash::Hasher; -use std::fmt::{Show,Formatter}; +use std::hash::sip::SipHasher; use std::io::MemWriter; +use std::str; use serialize::hex::ToHex; -use url; -use url::Url; -use core::source::{Source,SourceId,GitKind}; +use core::source::{Source, SourceId, GitKind, Location, Remote, Local}; use core::{Package,PackageId,Summary}; use util::{CargoResult,Config}; use sources::PathSource; @@ -33,8 +32,8 @@ impl<'a, 'b> GitSource<'a, 'b> { _ => fail!("Not a git source; id={}", source_id) }; - let remote = GitRemote::new(source_id.get_url()); - let ident = ident(&source_id.url); + let remote = GitRemote::new(source_id.get_location()); + let ident = ident(source_id.get_location()); let db_path = config.git_db_path() .join(ident.as_slice()); @@ -54,23 +53,32 @@ impl<'a, 'b> GitSource<'a, 'b> { } } - pub fn get_namespace<'a>(&'a self) -> &'a url::Url { - self.remote.get_url() + pub fn get_namespace<'a>(&'a self) -> &'a Location { + self.remote.get_location() } } -fn ident(url: &Url) -> String { +fn ident(location: &Location) -> String { let hasher = SipHasher::new_with_keys(0,0); - let mut ident = url.path.as_slice().split('/').last().unwrap(); + // FIXME: this really should be able to not use to_str() everywhere, but the + // compiler seems to currently ask for static lifetimes spuriously. + // Perhaps related to rust-lang/rust#15144 + let ident = match *location { + Local(ref path) => { + let last = path.components().last().unwrap(); + str::from_utf8(last).unwrap().to_str() + } + Remote(ref url) => url.path.as_slice().split('/').last().unwrap().to_str() + }; - ident = if ident == "" { - "_empty" + let ident = if ident.as_slice() == "" { + "_empty".to_string() } else { ident }; - format!("{}-{}", ident, to_hex(hasher.hash(&url.to_str()))) + format!("{}-{}", ident, to_hex(hasher.hash(&location.to_str()))) } fn to_hex(num: u64) -> String { @@ -81,7 +89,7 @@ fn to_hex(num: u64) -> String { impl<'a, 'b> Show for GitSource<'a, 'b> { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - try!(write!(f, "git repo at {}", self.remote.get_url())); + try!(write!(f, "git repo at {}", self.remote.get_location())); match self.reference { Master => Ok(()), @@ -98,7 +106,7 @@ impl<'a, 'b> Source for GitSource<'a, 'b> { let repo = if should_update { try!(self.config.shell().status("Updating", - format!("git repository `{}`", self.remote.get_url()))); + format!("git repository `{}`", self.remote.get_location()))); log!(5, "updating git source `{}`", self.remote); try!(self.remote.checkout(&self.db_path)) @@ -135,17 +143,18 @@ impl<'a, 'b> Source for GitSource<'a, 'b> { mod test { use url; use url::Url; + use core::source::Remote; use super::ident; #[test] pub fn test_url_to_path_ident_with_path() { - let ident = ident(&url("https://github.com/carlhuda/cargo")); + let ident = ident(&Remote(url("https://github.com/carlhuda/cargo"))); assert_eq!(ident.as_slice(), "cargo-0eed735c8ffd7c88"); } #[test] pub fn test_url_to_path_ident_without_path() { - let ident = ident(&url("https://github.com")); + let ident = ident(&Remote(url("https://github.com"))); assert_eq!(ident.as_slice(), "_empty-fc065c9b6b16fc00"); } diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs index 5d560a39306..b92fdcb0fd0 100644 --- a/src/cargo/sources/git/utils.rs +++ b/src/cargo/sources/git/utils.rs @@ -1,5 +1,3 @@ -use url::Url; -use util::{CargoResult, ChainError, ProcessBuilder, process, human}; use std::fmt; use std::fmt::{Show,Formatter}; use std::str; @@ -7,6 +5,9 @@ use std::io::{UserDir,AllPermissions}; use std::io::fs::{mkdir_recursive,rmdir_recursive,chmod}; use serialize::{Encodable,Encoder}; +use core::source::{Location, Local, Remote}; +use util::{CargoResult, ChainError, ProcessBuilder, process, human}; + #[deriving(PartialEq,Clone,Encodable)] pub enum GitReference { Master, @@ -67,18 +68,18 @@ macro_rules! errln( /// GitDatabase. #[deriving(PartialEq,Clone,Show)] pub struct GitRemote { - url: Url, + location: Location, } #[deriving(PartialEq,Clone,Encodable)] struct EncodableGitRemote { - url: String, + location: String, } impl> Encodable for GitRemote { fn encode(&self, s: &mut S) -> Result<(), E> { EncodableGitRemote { - url: self.url.to_str() + location: self.location.to_str() }.encode(s) } } @@ -138,12 +139,12 @@ impl> Encodable for GitCheckout { // Implementations impl GitRemote { - pub fn new(url: &Url) -> GitRemote { - GitRemote { url: url.clone() } + pub fn new(location: &Location) -> GitRemote { + GitRemote { location: location.clone() } } - pub fn get_url<'a>(&'a self) -> &'a Url { - &self.url + pub fn get_location<'a>(&'a self) -> &'a Location { + &self.location } pub fn has_ref(&self, path: &Path, reference: S) -> CargoResult<()> { @@ -180,9 +181,9 @@ impl GitRemote { } fn fetch_location(&self) -> String { - match self.url.scheme.as_slice() { - "file" => self.url.path.clone(), - _ => self.url.to_str() + match self.location { + Local(ref p) => p.display().to_str(), + Remote(ref u) => u.to_str(), } } } diff --git a/src/cargo/util/process_builder.rs b/src/cargo/util/process_builder.rs index 1dc3ca4e6fe..1eb7a5f23cc 100644 --- a/src/cargo/util/process_builder.rs +++ b/src/cargo/util/process_builder.rs @@ -1,14 +1,15 @@ use std::fmt; use std::fmt::{Show, Formatter}; use std::os; -use std::path::Path; +use std::c_str::CString; use std::io::process::{Command, ProcessOutput, InheritFd}; -use util::{ProcessError, process_error}; use std::collections::HashMap; +use util::{ProcessError, process_error}; + #[deriving(Clone,PartialEq)] pub struct ProcessBuilder { - program: String, + program: CString, args: Vec, path: Vec, env: HashMap, @@ -17,7 +18,7 @@ pub struct ProcessBuilder { impl Show for ProcessBuilder { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - try!(write!(f, "`{}", self.program)); + try!(write!(f, "`{}", self.program.as_str().unwrap_or(""))); if self.args.len() > 0 { try!(write!(f, " {}", self.args.connect(" "))); @@ -28,7 +29,10 @@ impl Show for ProcessBuilder { } // TODO: Upstream a Windows/Posix branch to Rust proper +#[cfg(unix)] static PATH_SEP : &'static str = ":"; +#[cfg(windows)] +static PATH_SEP : &'static str = ";"; impl ProcessBuilder { pub fn arg(mut self, arg: T) -> ProcessBuilder { @@ -110,16 +114,17 @@ impl ProcessBuilder { } pub fn build_command(&self) -> Command { - let mut command = Command::new(self.program.as_slice()); + let mut command = Command::new(self.program.as_bytes_no_nul()); command.args(self.args.as_slice()).cwd(&self.cwd); command } fn debug_string(&self) -> String { + let program = self.program.as_str().unwrap_or(""); if self.args.len() == 0 { - self.program.to_str() + program.to_string() } else { - format!("{} {}", self.program, self.args.connect(" ")) + format!("{} {}", program, self.args.connect(" ")) } } @@ -163,22 +168,12 @@ impl ProcessBuilder { } } -pub fn process(cmd: &str) -> ProcessBuilder { +pub fn process(cmd: T) -> ProcessBuilder { ProcessBuilder { - program: cmd.to_str(), + program: cmd.to_c_str(), args: vec!(), path: vec!(), cwd: os::getcwd(), - env: system_env() - } -} - -fn system_env() -> HashMap { - let mut ret = HashMap::new(); - - for &(ref key, ref val) in os::env().iter() { - ret.insert(key.to_str(), val.to_str()); + env: os::env().move_iter().collect() } - - ret } diff --git a/src/cargo/util/toml.rs b/src/cargo/util/toml.rs index 8776eac2898..e9352a1400e 100644 --- a/src/cargo/util/toml.rs +++ b/src/cargo/util/toml.rs @@ -2,12 +2,12 @@ use serialize::Decodable; use std::collections::HashMap; use std::str; use toml; -use url::Url; use url; -use core::{SourceId,GitKind}; -use core::manifest::{LibKind,Lib}; -use core::{Summary,Manifest,Target,Dependency,PackageId}; +use core::{SourceId, GitKind}; +use core::manifest::{LibKind, Lib}; +use core::{Summary, Manifest, Target, Dependency, PackageId}; +use core::source::{Location, Local, Remote}; use util::{CargoResult, Require, human}; pub fn to_manifest(contents: &[u8], @@ -95,7 +95,7 @@ pub struct TomlProject { } impl TomlProject { - pub fn to_package_id(&self, namespace: &Url) -> CargoResult { + pub fn to_package_id(&self, namespace: &Location) -> CargoResult { PackageId::new(self.name.as_slice(), self.version.as_slice(), namespace) } } @@ -117,6 +117,15 @@ impl TomlManifest { let mut deps = Vec::new(); + fn to_location(s: &str) -> Location { + if s.starts_with("file:") { + Local(Path::new(s.slice_from(5))) + } else { + // TODO: Don't unwrap here + Remote(url::from_str(s).unwrap()) + } + } + // Collect the deps match self.dependencies { Some(ref dependencies) => { @@ -132,10 +141,9 @@ impl TomlManifest { .unwrap_or_else(|| "master".to_str()); let new_source_id = details.git.as_ref().map(|git| { - // TODO: Don't unwrap here let kind = GitKind(reference.clone()); - let url = url::from_str(git.as_slice()).unwrap(); - let source_id = SourceId::new(kind, url); + let loc = to_location(git.as_slice()); + let source_id = SourceId::new(kind, loc); // TODO: Don't do this for path sources.push(source_id.clone()); source_id @@ -162,7 +170,7 @@ impl TomlManifest { let project = try!(project.require(|| human("No `package` or `project` section found."))); Ok((Manifest::new( - &Summary::new(&try!(project.to_package_id(source_id.get_url())), + &Summary::new(&try!(project.to_package_id(source_id.get_location())), deps.as_slice()), targets.as_slice(), &Path::new("target"), diff --git a/tests/support/mod.rs b/tests/support/mod.rs index 8cac9db37cf..8b3c296e001 100644 --- a/tests/support/mod.rs +++ b/tests/support/mod.rs @@ -66,10 +66,14 @@ impl ProjectBuilder { } pub fn root(&self) -> Path { - self.root.clone() + self.root.clone() } - pub fn process(&self, program: &str) -> ProcessBuilder { + pub fn bin(&self, b: &str) -> Path { + self.root.join("target").join(format!("{}{}", b, os::consts::EXE_SUFFIX)) + } + + pub fn process(&self, program: T) -> ProcessBuilder { process(program) .cwd(self.root()) .env("HOME", Some(paths::home().display().to_str().as_slice())) @@ -78,7 +82,7 @@ impl ProjectBuilder { pub fn cargo_process(&self, program: &str) -> ProcessBuilder { self.build(); - self.process(program) + self.process(cargo_dir().join(program)) } pub fn file(mut self, path: B, @@ -245,7 +249,9 @@ impl Execs { match str::from_utf8(actual) { None => Err(format!("{} was not utf8 encoded", description)), Some(actual) => { - ham::expect(actual == out, + // Let's not deal with \r\n vs \n on windows... + let actual = actual.replace("\r", ""); + ham::expect(actual.as_slice() == out, format!("{} was:\n\ `{}`\n\n\ expected:\n\ @@ -347,3 +353,7 @@ impl Tap for T { self } } + +pub fn escape_path(p: &Path) -> String { + p.display().to_str().as_slice().replace("\\", "\\\\") +} diff --git a/tests/support/paths.rs b/tests/support/paths.rs index b42f5bd69a1..99de20a2280 100644 --- a/tests/support/paths.rs +++ b/tests/support/paths.rs @@ -33,9 +33,23 @@ impl PathExt for Path { */ fn rm_rf(&self) -> IoResult<()> { if self.exists() { + // On windows, apparently git checks out the database with objects + // set to the permission 444, and apparently you can't unlink a file + // with permissions 444 because you don't have write permissions. + // Whow knew! + // + // If the rmdir fails due to a permission denied error, then go back + // and change everything to have write permissions, then remove + // everything. + match fs::rmdir_recursive(self) { + Err(io::IoError { kind: io::PermissionDenied, .. }) => {} + e => return e, + } + for path in try!(fs::walk_dir(self)) { + try!(fs::chmod(&path, io::UserRWX)); + } fs::rmdir_recursive(self) - } - else { + } else { Ok(()) } } diff --git a/tests/test_cargo_compile.rs b/tests/test_cargo_compile.rs index 6354ad4221b..91cb04807d7 100644 --- a/tests/test_cargo_compile.rs +++ b/tests/test_cargo_compile.rs @@ -1,10 +1,11 @@ use std::io::fs; use std::os; +use std::path; -use support::{ResultTest,project,execs,main_file}; -use hamcrest::{assert_that,existing_file}; +use support::{ResultTest, project, execs, main_file, escape_path}; +use hamcrest::{assert_that, existing_file}; use cargo; -use cargo::util::{process,realpath}; +use cargo::util::{process, realpath}; fn setup() { } @@ -31,12 +32,10 @@ test!(cargo_compile_simple { .file("src/foo.rs", main_file(r#""i am foo""#, []).as_slice()); assert_that(p.cargo_process("cargo-build"), execs()); - assert_that(&p.root().join("target/foo"), existing_file()); - - let target = p.root().join("target"); + assert_that(&p.bin("foo"), existing_file()); assert_that( - process("foo").extra_path(target), + process(p.bin("foo")), execs().with_stdout("i am foo\n")); }) @@ -104,14 +103,15 @@ test!(cargo_compile_with_invalid_code { execs() .with_status(101) .with_stderr(format!("\ -src/foo.rs:1:1: 1:8 error: expected item but found `invalid` -src/foo.rs:1 invalid rust code! +{filename}:1:1: 1:8 error: expected item but found `invalid` +{filename}:1 invalid rust code! ^~~~~~~ Could not execute process \ -`rustc src/foo.rs --crate-type bin --out-dir {} -L {} -L {}` (status=101)\n", +`rustc {filename} --crate-type bin --out-dir {} -L {} -L {}` (status=101)\n", target.display(), target.display(), - target.join("deps").display()).as_slice())); + target.join("deps").display(), + filename = format!("src{}foo.rs", path::SEP)).as_slice())); }) test!(cargo_compile_with_warnings_in_the_root_package { @@ -121,12 +121,12 @@ test!(cargo_compile_with_warnings_in_the_root_package { assert_that(p.cargo_process("cargo-build"), execs() - .with_stderr("\ -src/foo.rs:1:14: 1:26 warning: code is never used: `dead`, #[warn(dead_code)] \ + .with_stderr(format!("\ +{filename}:1:14: 1:26 warning: code is never used: `dead`, #[warn(dead_code)] \ on by default -src/foo.rs:1 fn main() {} fn dead() {} +{filename}:1 fn main() {{}} fn dead() {{}} ^~~~~~~~~~~~ -")); +", filename = format!("src{}foo.rs", path::SEP).as_slice()))); }) test!(cargo_compile_with_warnings_in_a_dep_package { @@ -136,7 +136,7 @@ test!(cargo_compile_with_warnings_in_a_dep_package { p = p .file(".cargo/config", format!(r#" paths = ["{}"] - "#, bar.display()).as_slice()) + "#, escape_path(&bar)).as_slice()) .file("Cargo.toml", r#" [project] @@ -184,10 +184,10 @@ test!(cargo_compile_with_warnings_in_a_dep_package { COMPILING, main.display())) .with_stderr("")); - assert_that(&p.root().join("target/foo"), existing_file()); + assert_that(&p.bin("foo"), existing_file()); assert_that( - cargo::util::process("foo").extra_path(p.root().join("target")), + cargo::util::process(p.bin("foo")), execs().with_stdout("test passed\n")); }) @@ -199,7 +199,7 @@ test!(cargo_compile_with_nested_deps_shorthand { p = p .file(".cargo/config", format!(r#" paths = ["{}", "{}"] - "#, bar.display(), baz.display()).as_slice()) + "#, escape_path(&bar), escape_path(&baz)).as_slice()) .file("Cargo.toml", r#" [project] @@ -260,10 +260,10 @@ test!(cargo_compile_with_nested_deps_shorthand { .exec_with_output() .assert(); - assert_that(&p.root().join("target/foo"), existing_file()); + assert_that(&p.bin("foo"), existing_file()); assert_that( - cargo::util::process("foo").extra_path(p.root().join("target")), + cargo::util::process(p.bin("foo")), execs().with_stdout("test passed\n")); }) @@ -275,7 +275,7 @@ test!(cargo_compile_with_nested_deps_longhand { p = p .file(".cargo/config", format!(r#" paths = ["{}", "{}"] - "#, bar.display(), baz.display()).as_slice()) + "#, escape_path(&bar), escape_path(&baz)).as_slice()) .file("Cargo.toml", r#" [project] @@ -334,10 +334,10 @@ test!(cargo_compile_with_nested_deps_longhand { assert_that(p.cargo_process("cargo-build"), execs()); - assert_that(&p.root().join("target/foo"), existing_file()); + assert_that(&p.bin("foo"), existing_file()); assert_that( - cargo::util::process("foo").extra_path(p.root().join("target")), + cargo::util::process(p.bin("foo")), execs().with_stdout("test passed\n")); }) @@ -373,7 +373,7 @@ test!(custom_build { build = "{}" [[bin]] name = "foo" - "#, build.root().join("target/foo").display())) + "#, escape_path(&build.bin("foo")))) .file("src/foo.rs", r#" fn main() {} "#); @@ -394,7 +394,8 @@ test!(custom_build_failure { version = "0.5.0" authors = ["wycats@example.com"] - [[bin]] name = "foo" + [[bin]] + name = "foo" "#) .file("src/foo.rs", r#" fn main() { fail!("nope") } @@ -412,18 +413,19 @@ test!(custom_build_failure { authors = ["wycats@example.com"] build = "{}" - [[bin]] name = "foo" - "#, build.root().join("target/foo").display())) + [[bin]] + name = "foo" + "#, escape_path(&build.bin("foo")))) .file("src/foo.rs", r#" fn main() {} "#); assert_that(p.cargo_process("cargo-build"), execs().with_status(101).with_stderr(format!("\ -Could not execute process `{}` (status=101) ---- stderr -task '
' failed at 'nope', src/foo.rs:2 - -", build.root().join("target/foo").display()))); +Could not execute process `{}` (status=101)\n\ +--- stderr\n\ +task '
' failed at 'nope', {filename}:2\n\ +\n\ +", build.bin("foo").display(), filename = format!("src{}foo.rs", path::SEP)))); }) test!(custom_build_env_vars { @@ -437,7 +439,8 @@ test!(custom_build_env_vars { version = "0.5.0" authors = ["wycats@example.com"] - [[bin]] name = "foo" + [[bin]] + name = "foo" "#) .file("src/foo.rs", format!(r#" use std::os; @@ -446,8 +449,8 @@ test!(custom_build_env_vars { assert_eq!(os::getenv("DEPS_DIR").unwrap(), "{}".to_str()); }} "#, - p.root().join("target").display(), - p.root().join("target/deps").display())); + escape_path(&p.root().join("target")), + escape_path(&p.root().join("target").join("deps")))); assert_that(build.cargo_process("cargo-build"), execs().with_status(0)); @@ -460,8 +463,9 @@ test!(custom_build_env_vars { authors = ["wycats@example.com"] build = "{}" - [[bin]] name = "foo" - "#, build.root().join("target/foo").display())) + [[bin]] + name = "foo" + "#, escape_path(&build.bin("foo")))) .file("src/foo.rs", r#" fn main() {} "#); @@ -480,7 +484,8 @@ test!(custom_build_in_dependency { version = "0.5.0" authors = ["wycats@example.com"] - [[bin]] name = "foo" + [[bin]] + name = "foo" "#) .file("src/foo.rs", format!(r#" use std::os; @@ -489,15 +494,15 @@ test!(custom_build_in_dependency { assert_eq!(os::getenv("DEPS_DIR").unwrap(), "{}".to_str()); }} "#, - p.root().join("target/deps").display(), - p.root().join("target/deps").display())); + escape_path(&p.root().join("target/deps")), + escape_path(&p.root().join("target/deps")))); assert_that(build.cargo_process("cargo-build"), execs().with_status(0)); p = p .file(".cargo/config", format!(r#" paths = ["{}"] - "#, bar.display()).as_slice()) + "#, escape_path(&bar)).as_slice()) .file("Cargo.toml", r#" [project] @@ -505,8 +510,10 @@ test!(custom_build_in_dependency { version = "0.5.0" authors = ["wycats@example.com"] - [[bin]] name = "foo" - [dependencies] bar = "0.5.0" + [[bin]] + name = "foo" + [dependencies] + bar = "0.5.0" "#) .file("src/foo.rs", r#" extern crate bar; @@ -520,8 +527,9 @@ test!(custom_build_in_dependency { authors = ["wycats@example.com"] build = "{}" - [[lib]] name = "bar" - "#, build.root().join("target/foo").display())) + [[lib]] + name = "bar" + "#, escape_path(&build.bin("foo")))) .file("bar/src/bar.rs", r#" pub fn bar() {} "#); @@ -554,7 +562,7 @@ test!(many_crate_types { let mut files: Vec = files.iter().filter_map(|f| { match f.filename_str().unwrap() { "deps" => None, - s if !s.starts_with("lib") => None, + s if s.contains("fingerprint") => None, s => Some(s.to_str()) } }).collect(); diff --git a/tests/test_cargo_compile_git_deps.rs b/tests/test_cargo_compile_git_deps.rs index 9c50a90c23f..052bc7e6e17 100644 --- a/tests/test_cargo_compile_git_deps.rs +++ b/tests/test_cargo_compile_git_deps.rs @@ -1,6 +1,7 @@ use std::io::File; use support::{ProjectBuilder, ResultTest, project, execs, main_file, paths}; +use support::{escape_path, cargo_dir}; use hamcrest::{assert_that,existing_file}; use cargo; use cargo::util::{ProcessError, process}; @@ -73,18 +74,18 @@ test!(cargo_compile_simple_git_dep { [dependencies.dep1] - git = "file://{}" + git = "file:{}" [[bin]] name = "foo" - "#, git_project.root().display())) + "#, escape_path(&git_project.root()))) .file("src/foo.rs", main_file(r#""{}", dep1::hello()"#, ["dep1"])); let root = project.root(); let git_root = git_project.root(); - assert_that(project.cargo_process("cargo-build"), + assert_that(project.cargo_process("cargo-build").arg("--verbose"), execs() .with_stdout(format!("{} git repository `file:{}`\n\ {} dep1 v0.5.0 (file:{})\n\ @@ -94,10 +95,10 @@ test!(cargo_compile_simple_git_dep { COMPILING, root.display())) .with_stderr("")); - assert_that(&project.root().join("target/foo"), existing_file()); + assert_that(&project.bin("foo"), existing_file()); assert_that( - cargo::util::process("foo").extra_path(project.root().join("target")), + cargo::util::process(project.bin("foo")), execs().with_stdout("hello world\n")); }) @@ -136,13 +137,13 @@ test!(cargo_compile_git_dep_branch { [dependencies.dep1] - git = "file://{}" + git = "file:{}" branch = "branchy" [[bin]] name = "foo" - "#, git_project.root().display())) + "#, escape_path(&git_project.root()))) .file("src/foo.rs", main_file(r#""{}", dep1::hello()"#, ["dep1"])); let root = project.root(); @@ -158,10 +159,10 @@ test!(cargo_compile_git_dep_branch { COMPILING, root.display())) .with_stderr("")); - assert_that(&project.root().join("target/foo"), existing_file()); + assert_that(&project.bin("foo"), existing_file()); assert_that( - cargo::util::process("foo").extra_path(project.root().join("target")), + cargo::util::process(project.bin("foo")), execs().with_stdout("hello world\n")); }) @@ -201,13 +202,13 @@ test!(cargo_compile_git_dep_tag { [dependencies.dep1] - git = "file://{}" + git = "file:{}" tag = "v0.1.0" [[bin]] name = "foo" - "#, git_project.root().display())) + "#, escape_path(&git_project.root()))) .file("src/foo.rs", main_file(r#""{}", dep1::hello()"#, ["dep1"])); let root = project.root(); @@ -223,10 +224,10 @@ test!(cargo_compile_git_dep_tag { COMPILING, root.display())) .with_stderr("")); - assert_that(&project.root().join("target/foo"), existing_file()); + assert_that(&project.bin("foo"), existing_file()); assert_that( - cargo::util::process("foo").extra_path(project.root().join("target")), + cargo::util::process(project.bin("foo")), execs().with_stdout("hello world\n")); }) test!(cargo_compile_with_nested_paths { @@ -284,12 +285,12 @@ test!(cargo_compile_with_nested_paths { [dependencies.dep1] version = "0.5.0" - git = "file://{}" + git = "file:{}" [[bin]] name = "parent" - "#, git_project.root().display())) + "#, escape_path(&git_project.root()))) .file("src/parent.rs", main_file(r#""{}", dep1::hello()"#, ["dep1"]).as_slice()); @@ -297,10 +298,10 @@ test!(cargo_compile_with_nested_paths { .exec_with_output() .assert(); - assert_that(&p.root().join("target/parent"), existing_file()); + assert_that(&p.bin("parent"), existing_file()); assert_that( - cargo::util::process("parent").extra_path(p.root().join("target")), + cargo::util::process(p.bin("parent")), execs().with_stdout("hello world\n")); }) @@ -333,12 +334,12 @@ test!(recompilation { [dependencies.bar] version = "0.5.0" - git = "file://{}" + git = "file:{}" [[bin]] name = "foo" - "#, git_project.root().display())) + "#, escape_path(&git_project.root()))) .file("src/foo.rs", main_file(r#""{}", bar::bar()"#, ["bar"]).as_slice()); @@ -352,7 +353,7 @@ test!(recompilation { COMPILING, p.root().display()))); // Don't recompile the second time - assert_that(p.process("cargo-build"), + assert_that(p.process(cargo_dir().join("cargo-build")), execs().with_stdout(format!("{} bar v0.5.0 (file:{})\n\ {} foo v0.5.0 (file:{})\n", FRESH, git_project.root().display(), @@ -363,13 +364,13 @@ test!(recompilation { pub fn bar() { println!("hello!"); } "#).assert(); - assert_that(p.process("cargo-build"), + assert_that(p.process(cargo_dir().join("cargo-build")), execs().with_stdout(format!("{} bar v0.5.0 (file:{})\n\ {} foo v0.5.0 (file:{})\n", FRESH, git_project.root().display(), FRESH, p.root().display()))); - assert_that(p.process("cargo-build").arg("-u"), + assert_that(p.process(cargo_dir().join("cargo-build")).arg("-u"), execs().with_stdout(format!("{} git repository `file:{}`\n\ {} bar v0.5.0 (file:{})\n\ {} foo v0.5.0 (file:{})\n", @@ -385,7 +386,7 @@ test!(recompilation { git_project.process("git").args(["commit", "-m", "test"]).exec_with_output() .assert(); - assert_that(p.process("cargo-build").arg("-u"), + assert_that(p.process(cargo_dir().join("cargo-build")).arg("-u"), execs().with_stdout(format!("{} git repository `file:{}`\n\ {} bar v0.5.0 (file:{})\n\ {} foo v0.5.0 (file:{})\n", diff --git a/tests/test_cargo_compile_path_deps.rs b/tests/test_cargo_compile_path_deps.rs index 412c8174861..f3063d678cb 100644 --- a/tests/test_cargo_compile_path_deps.rs +++ b/tests/test_cargo_compile_path_deps.rs @@ -1,8 +1,8 @@ use std::io::File; use std::io::timer; -use support::{ResultTest,project,execs,main_file}; -use hamcrest::{assert_that,existing_file}; +use support::{ResultTest, project, execs, main_file, escape_path, cargo_dir}; +use hamcrest::{assert_that, existing_file}; use cargo; use cargo::util::{process}; @@ -76,10 +76,10 @@ test!(cargo_compile_with_nested_deps_shorthand { .exec_with_output() .assert(); - assert_that(&p.root().join("target/foo"), existing_file()); + assert_that(&p.bin("foo"), existing_file()); assert_that( - cargo::util::process("foo").extra_path(p.root().join("target")), + cargo::util::process(p.bin("foo")), execs().with_stdout("test passed\n")); }) @@ -89,7 +89,7 @@ test!(no_rebuild_dependency { p = p .file(".cargo/config", format!(r#" paths = ["{}"] - "#, bar.display()).as_slice()) + "#, escape_path(&bar)).as_slice()) .file("Cargo.toml", r#" [project] @@ -123,14 +123,14 @@ test!(no_rebuild_dependency { COMPILING, bar.display(), COMPILING, p.root().display()))); // This time we shouldn't compile bar - assert_that(p.process("cargo-build"), + assert_that(p.process(cargo_dir().join("cargo-build")), execs().with_stdout(format!("{} bar v0.5.0 (file:{})\n\ {} foo v0.5.0 (file:{})\n", FRESH, bar.display(), FRESH, p.root().display()))); p.build(); // rebuild the files (rewriting them in the process) - assert_that(p.process("cargo-build"), + assert_that(p.process(cargo_dir().join("cargo-build")), execs().with_stdout(format!("{} bar v0.5.0 (file:{})\n\ {} foo v0.5.0 (file:{})\n", COMPILING, bar.display(), @@ -144,7 +144,7 @@ test!(deep_dependencies_trigger_rebuild { p = p .file(".cargo/config", format!(r#" paths = ["{}", "{}"] - "#, bar.display(), baz.display()).as_slice()) + "#, escape_path(&bar), escape_path(&baz)).as_slice()) .file("Cargo.toml", r#" [project] @@ -197,7 +197,7 @@ test!(deep_dependencies_trigger_rebuild { COMPILING, baz.display(), COMPILING, bar.display(), COMPILING, p.root().display()))); - assert_that(p.process("cargo-build"), + assert_that(p.process(cargo_dir().join("cargo-build")), execs().with_stdout(format!("{} baz v0.5.0 (file:{})\n\ {} bar v0.5.0 (file:{})\n\ {} foo v0.5.0 (file:{})\n", @@ -213,7 +213,7 @@ test!(deep_dependencies_trigger_rebuild { File::create(&p.root().join("baz/src/baz.rs")).write_str(r#" pub fn baz() { println!("hello!"); } "#).assert(); - assert_that(p.process("cargo-build"), + assert_that(p.process(cargo_dir().join("cargo-build")), execs().with_stdout(format!("{} baz v0.5.0 (file:{})\n\ {} bar v0.5.0 (file:{})\n\ {} foo v0.5.0 (file:{})\n", @@ -226,12 +226,11 @@ test!(deep_dependencies_trigger_rebuild { extern crate baz; pub fn bar() { println!("hello!"); baz::baz(); } "#).assert(); - assert_that(p.process("cargo-build"), + assert_that(p.process(cargo_dir().join("cargo-build")), execs().with_stdout(format!("{} baz v0.5.0 (file:{})\n\ {} bar v0.5.0 (file:{})\n\ {} foo v0.5.0 (file:{})\n", - FRESH, - baz.display(), + FRESH, baz.display(), COMPILING, bar.display(), COMPILING, p.root().display()))); }) @@ -243,7 +242,7 @@ test!(no_rebuild_two_deps { p = p .file(".cargo/config", format!(r#" paths = ["{}", "{}"] - "#, bar.display(), baz.display()).as_slice()) + "#, escape_path(&bar), escape_path(&baz)).as_slice()) .file("Cargo.toml", r#" [project] @@ -296,7 +295,7 @@ test!(no_rebuild_two_deps { COMPILING, baz.display(), COMPILING, bar.display(), COMPILING, p.root().display()))); - assert_that(p.process("cargo-build"), + assert_that(p.process(cargo_dir().join("cargo-build")), execs().with_stdout(format!("{} baz v0.5.0 (file:{})\n\ {} bar v0.5.0 (file:{})\n\ {} foo v0.5.0 (file:{})\n", diff --git a/tests/test_shell.rs b/tests/test_shell.rs index 908ebaf3969..df730a21480 100644 --- a/tests/test_shell.rs +++ b/tests/test_shell.rs @@ -1,3 +1,7 @@ +#![cfg(not(windows))] // getting the actual colored output is a little different + // on windows, so it's tough to get a reference copy of all + // the color + use support::{ResultTest,Tap,shell_writes}; use hamcrest::{assert_that}; use std::io::{MemWriter, BufWriter, IoResult};