Meta-packages

This commit is contained in:
Yehuda Katz 2014-06-30 18:36:27 -07:00
parent 33b77bb059
commit ea3cb31cec
5 changed files with 167 additions and 22 deletions

View file

@ -29,6 +29,7 @@ impl<'a> PackageRegistry<'a> {
config: &'a mut Config<'a>) -> CargoResult<PackageRegistry<'a>> {
let mut reg = PackageRegistry::empty(config);
let source_ids = dedup(source_ids);
for id in source_ids.iter() {
try!(reg.load(id, false));
@ -90,7 +91,7 @@ impl<'a> PackageRegistry<'a> {
// Get the summaries
for summary in (try!(source.list())).iter() {
assert!(!dst.contains(summary), "duplicate summaries");
assert!(!dst.contains(summary), "duplicate summaries: {}", summary);
dst.push(summary.clone());
// self.summaries.push(summary.clone());
}
@ -106,6 +107,17 @@ impl<'a> PackageRegistry<'a> {
}
}
fn dedup(ids: Vec<SourceId>) -> Vec<SourceId> {
let mut seen = vec!();
for id in ids.move_iter() {
if seen.contains(&id) { continue; }
seen.push(id);
}
seen
}
impl<'a> Registry for PackageRegistry<'a> {
fn query(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
let overrides = try!(self.overrides.query(dep)); // this can never fail in practice

View file

@ -61,7 +61,7 @@ pub enum Location {
Remote(Url),
}
#[deriving(Clone,PartialEq)]
#[deriving(Clone, PartialEq, Eq)]
pub struct SourceId {
pub kind: SourceKind,
pub location: Location,

View file

@ -1,8 +1,9 @@
use std::collections::HashSet;
use std::io::File;
use std::io::{File, fs};
use util;
use core::{Package,Manifest,SourceId};
use util::{CargoResult, human, important_paths};
use util::{CargoResult, human};
use util::important_paths::find_project_manifest_exact;
pub fn read_manifest(contents: &[u8], source_id: &SourceId)
-> CargoResult<(Manifest, Vec<Path>)>
@ -22,26 +23,85 @@ pub fn read_package(path: &Path, source_id: &SourceId)
Ok((Package::new(manifest, path, source_id), nested))
}
pub fn read_packages(path: &Path, source_id: &SourceId)
-> CargoResult<Vec<Package>>
pub fn read_packages(path: &Path,
source_id: &SourceId) -> CargoResult<Vec<Package>>
{
return read_packages(path, source_id, &mut HashSet::new());
let mut all_packages = Vec::new();
let mut visited = HashSet::<Path>::new();
fn read_packages(path: &Path, source_id: &SourceId,
visited: &mut HashSet<Path>) -> CargoResult<Vec<Package>> {
if !visited.insert(path.clone()) { return Ok(Vec::new()) }
log!(5, "looking for root package: {}, source_id={}", path.display(), source_id);
try!(process_possible_package(path, &mut all_packages, source_id, &mut visited));
let manifest = try!(important_paths::find_project_manifest_exact(path,
"Cargo.toml"));
let (pkg, nested) = try!(read_package(&manifest, source_id));
let mut ret = vec![pkg];
try!(walk(path, true, |dir| {
log!(5, "looking for child package: {}", dir.display());
if dir.filename_str() == Some(".git") { return Ok(false); }
if dir.join(".git").is_dir() { return Ok(false); }
try!(process_possible_package(dir, &mut all_packages, source_id, &mut visited));
Ok(true)
}));
for p in nested.iter() {
ret.push_all(try!(read_packages(&path.join(p),
source_id,
visited)).as_slice());
}
Ok(ret)
if all_packages.is_empty() {
Err(human(format!("Could not find Cargo.toml in `{}`", path.display())))
} else {
log!(5, "all packages: {}", all_packages);
Ok(all_packages)
}
}
fn walk(path: &Path, is_root: bool, callback: |&Path| -> CargoResult<bool>) -> CargoResult<()> {
if path.is_dir() {
if !is_root {
let continues = try!(callback(path));
if !continues { log!(5, "Found submodule at {}", path.display()); return Ok(()); }
}
for dir in try!(fs::readdir(path)).iter() {
try!(walk(dir, false, |x| callback(x)))
}
}
Ok(())
}
fn process_possible_package(dir: &Path,
all_packages: &mut Vec<Package>,
source_id: &SourceId,
visited: &mut HashSet<Path>) -> CargoResult<()> {
if !has_manifest(dir) { return Ok(()); }
let packages = try!(read_nested_packages(dir, source_id, visited));
push_all(all_packages, packages);
Ok(())
}
fn has_manifest(path: &Path) -> bool {
find_project_manifest_exact(path, "Cargo.toml").is_ok()
}
fn read_nested_packages(path: &Path, source_id: &SourceId,
visited: &mut HashSet<Path>) -> CargoResult<Vec<Package>> {
if !visited.insert(path.clone()) { return Ok(Vec::new()) }
let manifest = try!(find_project_manifest_exact(path, "Cargo.toml"));
let (pkg, nested) = try!(read_package(&manifest, source_id));
let mut ret = vec![pkg];
for p in nested.iter() {
ret.push_all(try!(read_nested_packages(&path.join(p),
source_id,
visited)).as_slice());
}
Ok(ret)
}
fn push_all(set: &mut Vec<Package>, packages: Vec<Package>) {
for package in packages.move_iter() {
if set.contains(&package) { continue; }
set.push(package)
}
}

View file

@ -203,7 +203,6 @@ fn prepare_rustc(root: &Path, target: &Target, crate_types: Vec<&str>,
build_base_args(&mut args, target, crate_types, cx);
build_deps_args(&mut args, cx);
util::process("rustc")
.cwd(root.clone())
.args(args.as_slice())

View file

@ -227,6 +227,7 @@ test!(cargo_compile_git_dep_tag {
cargo::util::process(project.bin("foo")),
execs().with_stdout("hello world\n"));
})
test!(cargo_compile_with_nested_paths {
let git_project = git_repo("dep1", |project| {
project
@ -302,6 +303,79 @@ test!(cargo_compile_with_nested_paths {
execs().with_stdout("hello world\n"));
})
test!(cargo_compile_with_meta_package {
let git_project = git_repo("meta-dep", |project| {
project
.file("dep1/Cargo.toml", r#"
[project]
name = "dep1"
version = "0.5.0"
authors = ["carlhuda@example.com"]
[[lib]]
name = "dep1"
"#)
.file("dep1/src/dep1.rs", r#"
pub fn hello() -> &'static str {
"this is dep1"
}
"#)
.file("dep2/Cargo.toml", r#"
[project]
name = "dep2"
version = "0.5.0"
authors = ["carlhuda@example.com"]
[[lib]]
name = "dep2"
"#)
.file("dep2/src/dep2.rs", r#"
pub fn hello() -> &'static str {
"this is dep2"
}
"#)
}).assert();
let p = project("parent")
.file("Cargo.toml", format!(r#"
[project]
name = "parent"
version = "0.5.0"
authors = ["wycats@example.com"]
[dependencies.dep1]
version = "0.5.0"
git = "file:{}"
[dependencies.dep2]
version = "0.5.0"
git = "file:{}"
[[bin]]
name = "parent"
"#, escape_path(&git_project.root()), escape_path(&git_project.root())))
.file("src/parent.rs",
main_file(r#""{} {}", dep1::hello(), dep2::hello()"#, ["dep1", "dep2"]).as_slice());
p.cargo_process("cargo-build")
.exec_with_output()
.assert();
assert_that(&p.bin("parent"), existing_file());
assert_that(
cargo::util::process(p.bin("parent")),
execs().with_stdout("this is dep1 this is dep2\n"));
})
test!(cargo_compile_with_short_ssh_git {
let url = "git@github.com:a/dep";