use std::path::{Path, PathBuf};
use semver::Version;
-use core::{
- Dependency,
- Manifest,
- PackageId,
- Registry,
- Target,
- Summary,
-};
+use core::{Dependency, Manifest, PackageId, Registry, Target, Summary, Metadata};
use core::dependency::SerializedDependency;
use util::{CargoResult, graph};
use rustc_serialize::{Encoder,Encodable};
pub fn has_custom_build(&self) -> bool {
self.targets().iter().any(|t| t.is_custom_build())
}
+
+ pub fn generate_metadata(&self) -> Metadata {
+ self.package_id().generate_metadata(self.root())
+ }
}
impl fmt::Display for Package {
impl hash::Hash for Package {
fn hash<H: hash::Hasher>(&self, into: &mut H) {
- self.package_id().hash(into)
+ // We want to be sure that a path-based package showing up at the same
+ // location always has the same hash. To that effect we don't hash the
+ // vanilla package ID if we're a path, but instead feed in our own root
+ // path.
+ if self.package_id().source_id().is_path() {
+ (0, self.root(), self.name(), self.package_id().version()).hash(into)
+ } else {
+ (1, self.package_id()).hash(into)
+ }
}
}
use std::fmt::{self, Formatter};
use std::hash::Hash;
use std::hash;
+use std::path::Path;
use std::sync::Arc;
use regex::Regex;
pub fn version(&self) -> &semver::Version { &self.inner.version }
pub fn source_id(&self) -> &SourceId { &self.inner.source_id }
- pub fn generate_metadata(&self) -> Metadata {
- let metadata = short_hash(
- &(&self.inner.name, self.inner.version.to_string(),
- &self.inner.source_id));
+ pub fn generate_metadata(&self, source_root: &Path) -> Metadata {
+ // See comments in Package::hash for why we have this test
+ let metadata = if self.inner.source_id.is_path() {
+ short_hash(&(0, &self.inner.name, &self.inner.version, source_root))
+ } else {
+ short_hash(&(1, self))
+ };
let extra_filename = format!("-{}", metadata);
Metadata { metadata: metadata, extra_filename: extra_filename }
// Make sure that the name of this test executable doesn't
// conflict with a library that has the same name and is
// being tested
- let mut metadata = pkg.package_id().generate_metadata();
+ let mut metadata = pkg.generate_metadata();
metadata.mix(&format!("bin-{}", target.name()));
Some(metadata)
} else if pkg.package_id() == self.resolve.root() && !profile.test {
}
fn pkg_dir(&self, pkg: &Package) -> String {
- format!("{}-{}", pkg.name(), short_hash(pkg.package_id()))
+ format!("{}-{}", pkg.name(), short_hash(pkg))
}
}
}
let pkgid = try!(project.to_package_id(source_id));
- let metadata = pkgid.generate_metadata();
+ let metadata = pkgid.generate_metadata(&layout.root);
// If we have no lib at all, use the inferred lib if available
// If we have a lib with a path, we're done
for bin in bins.iter() {
if blacklist.iter().find(|&x| *x == bin.name) != None {
- return Err(human(&format!("the binary target name `{}` is forbidden",
- bin.name)));
+ return Err(human(&format!("the binary target name `{}` is \
+ forbidden", bin.name)));
}
}
", COMPILING, p.url(), COMPILING, p.url())));
});
+
+test!(custom_target_no_rebuild {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [project]
+ name = "foo"
+ version = "0.5.0"
+ authors = []
+ [dependencies]
+ a = { path = "a" }
+ "#)
+ .file("src/lib.rs", "")
+ .file("a/Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("a/src/lib.rs", "")
+ .file("b/Cargo.toml", r#"
+ [project]
+ name = "b"
+ version = "0.5.0"
+ authors = []
+ [dependencies]
+ a = { path = "../a" }
+ "#)
+ .file("b/src/lib.rs", "");
+ p.build();
+ assert_that(p.cargo("build"),
+ execs().with_status(0)
+ .with_stdout(&format!("\
+{compiling} a v0.5.0 ([..])
+{compiling} foo v0.5.0 ([..])
+", compiling = COMPILING)));
+
+ assert_that(p.cargo("build")
+ .arg("--manifest-path=b/Cargo.toml")
+ .env("CARGO_TARGET_DIR", "target"),
+ execs().with_status(0)
+ .with_stdout(&format!("\
+{compiling} b v0.5.0 ([..])
+", compiling = COMPILING)));
+});