Initial work to enable cross-source transitive dependencies.
cargo-verify-project \
cargo-git-checkout \
-SRC = $(shell find src -name '*.rs')
+SRC = $(shell find src -name '*.rs' -not -path 'src/bin*')
DEPS = -L libs/hammer.rs/target -L libs/rust-toml/lib
TOML = libs/rust-toml/lib/$(shell rustc --crate-file-name libs/rust-toml/src/toml/lib.rs)
use cargo::{execute_main_without_stdin,CLIResult,CLIError,ToResult};
use cargo::ops;
use cargo::util::important_paths::find_project;
-use cargo::util::{ToCLI,simple_human};
+use cargo::util::{ToCLI};
#[deriving(PartialEq,Clone,Decodable,Encodable)]
pub struct Options {
use hammer::FlagConfig;
use cargo::{execute_main_without_stdin,CLIResult,CLIError,ToResult};
use cargo::core::source::Source;
-use cargo::sources::git::{GitSource,GitRemote};
+use cargo::sources::git::{GitSource};
+use cargo::util::{Config,ToCLI};
use url::Url;
#[deriving(PartialEq,Clone,Decodable)]
struct Options {
- database_path: String,
- checkout_path: String,
url: String,
reference: String,
verbose: bool
}
fn execute(options: Options) -> CLIResult<Option<()>> {
- let Options { database_path, checkout_path, url, reference, verbose } = options;
+ let Options { url, reference, .. } = options;
let url: Url = try!(from_str(url.as_slice()).to_result(|_|
CLIError::new(format!("The URL `{}` you passed was not a valid URL", url), None::<&str>, 1)));
- let remote = GitRemote::new(url, verbose);
- let source = GitSource::new(remote, reference, Path::new(database_path), Path::new(checkout_path));
+ let source = GitSource::new(&url, reference.as_slice(), &try!(Config::new().to_cli(1)));
+
try!(source.update().map_err(|e| {
CLIError::new(format!("Couldn't update {}: {}", source, e), None::<&str>, 1)
}));
use cargo::{NoFlags,execute_main_without_stdin,handle_error};
use cargo::core::errors::{CLIError,CLIResult,ToResult};
use cargo::util::important_paths::find_project;
-use cargo::util::{ToCLI,Wrap,config,io_error,simple_human};
+use cargo::util::{ToCLI,config,simple_human};
fn main() {
execute();
&self.target_dir
}
- pub fn get_sources<'a>(&'a self) -> &'a [SourceId] {
+ pub fn get_source_ids<'a>(&'a self) -> &'a [SourceId] {
self.sources.as_slice()
}
}
self.get_root().join(self.get_target_dir())
}
- pub fn get_sources<'a>(&'a self) -> &'a [SourceId] {
- self.manifest.get_sources()
+ pub fn get_source_ids(&self) -> Vec<SourceId> {
+ let mut ret = vec!(SourceId::for_path(&self.get_root()));
+ ret.push_all(self.manifest.get_source_ids());
+ ret
}
}
use std::vec::Vec;
-use core::{Source, SourceId, SourceSet, Summary, Dependency, PackageSet};
-use util::CargoResult;
+use core::{Source, SourceId, Summary, Dependency, PackageId, Package};
+use util::{CargoResult,Config};
pub trait Registry {
fn query(&mut self, name: &Dependency) -> CargoResult<Vec<Summary>>;
}
impl PackageRegistry {
- pub fn new(sources: Vec<Box<Source>>, overrides: SourceSet) -> CargoResult<PackageRegistry> {
- Ok(PackageRegistry {
- sources: sources,
- overrides: try!(overrides.list()),
+ pub fn new(source_ids: Vec<SourceId>, override_ids: Vec<SourceId>) -> CargoResult<PackageRegistry> {
+ let mut reg = PackageRegistry::empty();
+
+ for id in source_ids.iter() {
+ try!(reg.load(id, false));
+ }
+
+ for id in override_ids.iter() {
+ try!(reg.load(id, true));
+ }
+
+ Ok(reg)
+ }
+
+ fn empty() -> PackageRegistry {
+ PackageRegistry {
+ sources: vec!(),
+ overrides: vec!(),
summaries: vec!(),
searched: vec!()
- })
+ }
+ }
+
+ pub fn get(&self, package_ids: &[PackageId]) -> CargoResult<Vec<Package>> {
+ log!(5, "getting packags; sources={}; ids={}", self.sources.len(), package_ids);
+
+ // TODO: Only call source with package ID if the package came from the source
+ let mut ret = Vec::new();
+
+ for source in self.sources.iter() {
+ try!(source.download(package_ids));
+ let packages = try!(source.get(package_ids));
+
+ ret.push_all_move(packages);
+ }
+
+ // TODO: Return earlier if fail
+ assert!(package_ids.len() == ret.len(), "could not get packages from registry; ids={}", package_ids);
+
+ Ok(ret)
}
fn ensure_loaded(&mut self, namespace: &SourceId) -> CargoResult<()> {
if self.searched.contains(namespace) { return Ok(()); }
- self.load(namespace);
+ try!(self.load(namespace, false));
Ok(())
}
- fn load(&mut self, namespace: &SourceId) -> CargoResult<()> {
- let source = namespace.load();
+ fn load(&mut self, namespace: &SourceId, override: bool) -> CargoResult<()> {
+ let source = namespace.load(&try!(Config::new()));
+ let dst = if override { &mut self.overrides } else { &mut self.summaries };
// Ensure the source has fetched all necessary remote data.
try!(source.update());
// Get the summaries
for summary in (try!(source.list())).iter() {
- assert!(!self.summaries.contains(summary), "duplicate summaries");
- self.summaries.push(summary.clone());
+ assert!(!dst.contains(summary), "duplicate summaries");
+ dst.push(summary.clone());
+ // self.summaries.push(summary.clone());
}
+ // Save off the source
+ self.sources.push(source);
+
// Track that the source has been searched
self.searched.push(namespace.clone());
-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<R: Registry + Show>(deps: &[Dependency], registry: &mut R) -> CargoResult<Vec<PackageId>> {
- log!(5, "resolve; deps={}; registry={}", deps, registry);
+pub fn resolve<R: Registry>(deps: &[Dependency], registry: &mut R) -> CargoResult<Vec<PackageId>> {
+ log!(5, "resolve; deps={}", deps);
let mut remaining = Vec::from_slice(deps);
let mut resolve = HashMap::<String, Summary>::new();
+use url;
use url::Url;
use core::{Summary,Package,PackageId};
-use util::CargoResult;
+use sources::{PathSource,GitSource};
+use util::{Config,CargoResult};
/**
* A Source finds and downloads remote packages based on names and
SourceId { kind: kind, url: url }
}
- pub fn load(&self) -> Box<Source> {
+ // Pass absolute path
+ pub fn for_path(path: &Path) -> SourceId {
+ // TODO: use proper path -> URL
+ SourceId::new(PathKind, url::from_str(format!("file://{}", path.display()).as_slice()).unwrap())
+ }
+
+ pub fn for_central() -> SourceId {
+ SourceId::new(RegistryKind, url::from_str(format!("https://example.com").as_slice()).unwrap())
+ }
+
+ /*
+ let git_sources: Vec<Box<Source>> = try!(result::collect(package.get_sources().iter().map(|source_id: &SourceId| {
+ match source_id.kind {
+ GitKind(ref reference) => {
+ let remote = GitRemote::new(source_id.url.clone(), false);
+ let home = try!(os::homedir().require(simple_human("Cargo couldn't find a home directory")));
+ let git = home.join(".cargo").join("git");
+ let ident = url_to_path_ident(&source_id.url);
+
+ // .cargo/git/db
+ // .cargo/git/checkouts
+ let db_path = git.join("db").join(ident.as_slice());
+ let checkout_path = git.join("checkouts").join(ident.as_slice()).join(reference.as_slice());
+ Ok(box GitSource::new(remote, reference.clone(), db_path, checkout_path) as Box<Source>)
+ },
+ ref PathKind => fail!("Cannot occur")
+ }
+ })));
+ */
+
+ pub fn load(&self, config: &Config) -> Box<Source> {
match self.kind {
- GitKind(ref reference) => unimplemented!(),
- _ => unimplemented!()
+ GitKind(ref reference) => {
+ box GitSource::new(&self.url, reference.as_slice(), config) as Box<Source>
+ },
+ PathKind => box PathSource::new(&Path::new(self.url.path.as_slice())) as Box<Source>,
+ RegistryKind => unimplemented!()
}
}
}
PackageId
};
+/**
+ * Summaries are cloned, and should not be mutated after creation
+ */
+
#[deriving(Show,Clone,PartialEq)]
pub struct Summary {
package_id: PackageId,
* b. Compile each dependency in order, passing in the -L's pointing at each previously compiled dependency
*/
-use std::io::MemWriter;
use std::os;
-use std::result;
-use std::hash::sip::SipHasher;
-use std::hash::Hasher;
-use serialize::hex::ToHex;
-use url::Url;
-use util::config;
use util::config::{ConfigValue};
-use core::{Package,PackageSet,Source,SourceSet};
-use core::resolver::resolve;
-use core::source::{GitKind,SourceId};
+use core::{SourceId,PackageSet,resolver};
use core::registry::PackageRegistry;
-use sources::{PathSource,GitSource};
-use sources::git::GitRemote;
use ops;
-use util::{CargoResult, Wrap, Require, simple_human, other_error};
+use sources::{PathSource};
+use util::{CargoResult,Wrap,config,other_error};
pub fn compile(manifest_path: &Path) -> CargoResult<()> {
log!(4, "compile; manifest-path={}", manifest_path.display());
let package = try!(PathSource::read_package(manifest_path));
debug!("loaded package; package={}", package);
- let overrides = try!(sources_from_config());
- let sources = try!(sources_for(&package));
+ let override_ids = try!(source_ids_from_config());
+ let source_ids = package.get_source_ids();
- let registry = PackageRegistry::new(sources, overrides);
+ let mut registry = try!(PackageRegistry::new(source_ids, override_ids));
+ let resolved = try!(resolver::resolve(package.get_dependencies(), &mut registry).wrap("unable to resolve dependencies"));
- //try!(sources.update().wrap("unable to update sources"));
- //let summaries = try!(sources.list().wrap("unable to list packages from source"));
+ let packages = try!(registry.get(resolved.as_slice()).wrap("unable to get packages from source"));
- //let registry = PackageRegistry::new(&summaries, &overrides);
+ debug!("packages={}", packages);
- //let resolved = try!(resolve(package.get_dependencies(), &summaries).wrap("unable to resolve dependencies"));
-
- //try!(sources.download(resolved.as_slice()).wrap("unable to download packages"));
-
- //let packages = try!(sources.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));
+ try!(ops::compile_packages(&package, &PackageSet::new(packages.as_slice())));
Ok(())
}
-fn sources_for(package: &Package) -> CargoResult<Vec<Box<Source>>> {
- let mut sources = vec!(box PathSource::new(vec!(package.get_manifest_path().dir_path())) as Box<Source>);
-
- let git_sources: Vec<Box<Source>> = try!(result::collect(package.get_sources().iter().map(|source_id: &SourceId| {
- match source_id.kind {
- GitKind(ref reference) => {
- let remote = GitRemote::new(source_id.url.clone(), false);
- let home = try!(os::homedir().require(simple_human("Cargo couldn't find a home directory")));
- let git = home.join(".cargo").join("git");
- let ident = url_to_path_ident(&source_id.url);
-
- // .cargo/git/db
- // .cargo/git/checkouts
- let db_path = git.join("db").join(ident.as_slice());
- let checkout_path = git.join("checkouts").join(ident.as_slice()).join(reference.as_slice());
- Ok(box GitSource::new(remote, reference.clone(), db_path, checkout_path) as Box<Source>)
- },
- ref PathKind => fail!("Cannot occur")
- }
- })));
-
- sources.push_all_move(git_sources);
-
- Ok(sources)
-}
-
-fn sources_from_config() -> CargoResult<SourceSet> {
+fn source_ids_from_config() -> CargoResult<Vec<SourceId>> {
let configs = try!(config::all_configs(os::getcwd()));
debug!("loaded config; configs={}", configs);
let config_paths = configs.find_equiv(&"paths").map(|v| v.clone()).unwrap_or_else(|| ConfigValue::new());
- let mut paths: Vec<Path> = match config_paths.get_value() {
+ let paths: Vec<Path> = match config_paths.get_value() {
&config::String(_) => return Err(other_error("The path was configured as a String instead of a List")),
&config::List(ref list) => list.iter().map(|path| Path::new(path.as_slice())).collect()
};
- Ok(SourceSet::new(vec!(box PathSource::new(paths) as Box<Source>)))
-}
-
-fn url_to_path_ident(url: &Url) -> String {
- let hasher = SipHasher::new_with_keys(0,0);
-
- let mut ident = url.path.as_slice().split('/').last().unwrap();
-
- ident = if ident == "" {
- "_empty"
- } else {
- ident
- };
-
- format!("{}-{}", ident, to_hex(hasher.hash(&url.to_str())))
-}
-
-fn to_hex(num: u64) -> String {
- let mut writer = MemWriter::with_capacity(8);
- writer.write_le_u64(num).unwrap(); // this should never fail
- writer.get_ref().to_hex()
-}
-
-#[cfg(test)]
-mod test {
- use url;
- use url::Url;
- use super::url_to_path_ident;
-
- #[test]
- pub fn test_url_to_path_ident_with_path() {
- let ident = url_to_path_ident(&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 = url_to_path_ident(&url("https://github.com"));
- assert_eq!(ident.as_slice(), "_empty-fc065c9b6b16fc00");
- }
-
-
- fn url(s: &str) -> Url {
- url::from_str(s).unwrap()
- }
+ Ok(paths.iter().map(|p| SourceId::for_path(p)).collect())
}
-use ops;
+use std::fmt;
+use std::hash::sip::SipHasher;
+use std::hash::Hasher;
+use std::fmt::{Show,Formatter};
+use std::io::MemWriter;
+use serialize::hex::ToHex;
use url;
+use url::Url;
+
+use ops;
use core::source::Source;
use core::{Package,PackageId,Summary};
-use util::CargoResult;
+use util::{CargoResult,Config};
use sources::git::utils::{GitReference,GitRemote,Master,Other};
-use std::fmt;
-use std::fmt::{Show,Formatter};
pub struct GitSource {
remote: GitRemote,
}
impl GitSource {
- pub fn new(remote: GitRemote, reference: String, db: Path, checkout: Path) -> GitSource {
- GitSource { remote: remote, reference: GitReference::for_str(reference), db_path: db, checkout_path: checkout }
+ pub fn new(url: &Url, reference: &str, config: &Config) -> GitSource {
+ let remote = GitRemote::new(url);
+ let ident = ident(url);
+
+ let db_path = config.git_db_path()
+ .join(ident.as_slice());
+
+ let checkout_path = config.git_checkout_path()
+ .join(ident.as_slice()).join(reference);
+
+ GitSource {
+ remote: remote,
+ reference: GitReference::for_str(reference),
+ db_path: db_path,
+ checkout_path: checkout_path
+ }
}
pub fn get_namespace<'a>(&'a self) -> &'a url::Url {
self.remote.get_url()
}
+
+}
+
+fn ident(url: &Url) -> String {
+ let hasher = SipHasher::new_with_keys(0,0);
+
+ let mut ident = url.path.as_slice().split('/').last().unwrap();
+
+ ident = if ident == "" {
+ "_empty"
+ } else {
+ ident
+ };
+
+ format!("{}-{}", ident, to_hex(hasher.hash(&url.to_str())))
+}
+
+fn to_hex(num: u64) -> String {
+ let mut writer = MemWriter::with_capacity(8);
+ writer.write_le_u64(num).unwrap(); // this should never fail
+ writer.get_ref().to_hex()
}
impl Show for GitSource {
let path = path.join("Cargo.toml");
ops::read_package(&path, url)
}
+
+#[cfg(test)]
+mod test {
+ use url;
+ use url::Url;
+ use super::ident;
+
+ #[test]
+ pub fn test_url_to_path_ident_with_path() {
+ let ident = ident(&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"));
+ assert_eq!(ident.as_slice(), "_empty-fc065c9b6b16fc00");
+ }
+
+
+ fn url(s: &str) -> Url {
+ url::from_str(s).unwrap()
+ }
+}
macro_rules! git(
- ($config:expr, $verbose:expr, $str:expr, $($rest:expr),*) => (
- try!(git_inherit(&$config, $verbose, format!($str, $($rest),*)))
+ ($config:expr, $str:expr, $($rest:expr),*) => (
+ try!(git_inherit(&$config, format!($str, $($rest),*)))
);
- ($config:expr, $verbose:expr, $str:expr) => (
- try!(git_inherit(&$config, $verbose, format!($str)))
+ ($config:expr, $str:expr) => (
+ try!(git_inherit(&$config, format!($str)))
);
)
macro_rules! git_output(
- ($config:expr, $verbose:expr, $str:expr, $($rest:expr),*) => (
- try!(git_output(&$config, $verbose, format!($str, $($rest),*)))
+ ($config:expr, $str:expr, $($rest:expr),*) => (
+ try!(git_output(&$config, format!($str, $($rest),*)))
);
- ($config:expr, $verbose:expr, $str:expr) => (
- try!(git_output(&$config, $verbose, format!($str)))
+ ($config:expr, $str:expr) => (
+ try!(git_output(&$config, format!($str)))
);
)
#[deriving(PartialEq,Clone,Show)]
pub struct GitRemote {
url: Url,
- verbose: bool
}
#[deriving(PartialEq,Clone,Encodable)]
pub struct GitDatabase {
remote: GitRemote,
path: Path,
- verbose: bool
}
#[deriving(Encodable)]
location: Path,
reference: GitReference,
revision: String,
- verbose: bool
}
#[deriving(Encodable)]
*/
impl GitRemote {
- pub fn new(url: Url, verbose: bool) -> GitRemote {
- GitRemote { url: url, verbose: verbose }
+ pub fn new(url: &Url) -> GitRemote {
+ GitRemote { url: url.clone() }
}
pub fn get_url<'a>(&'a self) -> &'a Url {
try!(self.clone_into(into));
}
- Ok(GitDatabase { remote: self.clone(), path: into.clone(), verbose: self.verbose })
+ Ok(GitDatabase { remote: self.clone(), path: into.clone() })
}
fn fetch_into(&self, path: &Path) -> CargoResult<()> {
- Ok(git!(*path, self.verbose, "fetch --force --quiet --tags {} refs/heads/*:refs/heads/*", self.fetch_location()))
+ Ok(git!(*path, "fetch --force --quiet --tags {} refs/heads/*:refs/heads/*", self.fetch_location()))
}
fn clone_into(&self, path: &Path) -> CargoResult<()> {
try!(mkdir_recursive(path, UserDir).map_err(|err|
human_error(format!("Couldn't recursively create `{}`", dirname.display()), format!("path={}", dirname.display()), io_error(err))));
- Ok(git!(dirname, self.verbose, "clone {} {} --bare --no-hardlinks --quiet", self.fetch_location(), path.display()))
+ Ok(git!(dirname, "clone {} {} --bare --no-hardlinks --quiet", self.fetch_location(), path.display()))
}
fn fetch_location(&self) -> String {
}
pub fn copy_to<S: Str>(&self, reference: S, dest: &Path) -> CargoResult<GitCheckout> {
- let verbose = self.verbose;
- let checkout = try!(GitCheckout::clone_into(dest, self.clone(), GitReference::for_str(reference.as_slice()), verbose));
+ let checkout = try!(GitCheckout::clone_into(dest, self.clone(), GitReference::for_str(reference.as_slice())));
try!(checkout.fetch());
try!(checkout.update_submodules());
}
pub fn rev_for<S: Str>(&self, reference: S) -> CargoResult<String> {
- Ok(git_output!(self.path, self.verbose, "rev-parse {}", reference.as_slice()))
+ Ok(git_output!(self.path, "rev-parse {}", reference.as_slice()))
}
}
impl GitCheckout {
- fn clone_into(into: &Path, database: GitDatabase, reference: GitReference, verbose: bool) -> CargoResult<GitCheckout> {
+ fn clone_into(into: &Path, database: GitDatabase, reference: GitReference) -> CargoResult<GitCheckout> {
let revision = try!(database.rev_for(reference.as_slice()));
- let checkout = GitCheckout { location: into.clone(), database: database, reference: reference, revision: revision, verbose: verbose };
+ let checkout = GitCheckout { location: into.clone(), database: database, reference: reference, revision: revision };
// If the git checkout already exists, we don't need to clone it again
if !checkout.location.join(".git").exists() {
human_error(format!("Couldn't rmdir {}", Path::new(&self.location).display()), None::<&str>, io_error(e))));
}
- git!(dirname, self.verbose, "clone --no-checkout --quiet {} {}", self.get_source().display(), self.location.display());
+ git!(dirname, "clone --no-checkout --quiet {} {}", self.get_source().display(), self.location.display());
try!(chmod(&self.location, AllPermissions).map_err(io_error));
Ok(())
}
fn fetch(&self) -> CargoResult<()> {
- git!(self.location, self.verbose, "fetch --force --quiet --tags {}", self.get_source().display());
+ git!(self.location, "fetch --force --quiet --tags {}", self.get_source().display());
try!(self.reset(self.revision.as_slice()));
Ok(())
}
fn reset<T: Show>(&self, revision: T) -> CargoResult<()> {
- Ok(git!(self.location, self.verbose, "reset -q --hard {}", revision))
+ Ok(git!(self.location, "reset -q --hard {}", revision))
}
fn update_submodules(&self) -> CargoResult<()> {
- Ok(git!(self.location, self.verbose, "submodule update --init --recursive --quiet"))
+ Ok(git!(self.location, "submodule update --init --recursive --quiet"))
}
}
-fn git(path: &Path, verbose: bool, str: &str) -> ProcessBuilder {
+fn git(path: &Path, str: &str) -> ProcessBuilder {
debug!("Executing git {} @ {}", str, path.display());
process("git").args(str.split(' ').collect::<Vec<&str>>().as_slice()).cwd(path.clone())
}
-fn git_inherit(path: &Path, verbose: bool, str: String) -> CargoResult<()> {
- git(path, verbose, str.as_slice()).exec().map_err(|err|
+fn git_inherit(path: &Path, str: String) -> CargoResult<()> {
+ git(path, str.as_slice()).exec().map_err(|err|
human_error(format!("Executing `git {}` failed: {}", str, err), None::<&str>, err))
}
-fn git_output(path: &Path, verbose: bool, str: String) -> CargoResult<String> {
- let output = try!(git(path, verbose, str.as_slice()).exec_with_output().map_err(|err|
+fn git_output(path: &Path, str: String) -> CargoResult<String> {
+ let output = try!(git(path, str.as_slice()).exec_with_output().map_err(|err|
human_error(format!("Executing `git {}` failed", str), None::<&str>, err)));
Ok(to_str(output.output.as_slice()).as_slice().trim_right().to_str())
* take in a single path vs. a vec of paths. The pros / cons are unknown at
* this point.
*/
-pub struct PathSource { paths: Vec<Path> }
+pub struct PathSource {
+ path: Path
+}
impl PathSource {
- pub fn new(paths: Vec<Path>) -> PathSource {
- log!(5, "new; paths={}", display(paths.as_slice()));
- PathSource { paths: paths }
+
+ /**
+ * Invoked with an absolute path to a directory that contains a Cargo.toml.
+ * The source will read the manifest and find any other packages contained
+ * in the directory structure reachable by the root manifest.
+ */
+ pub fn new(path: &Path) -> PathSource {
+ log!(5, "new; path={}", path.display());
+ PathSource { path: path.clone() }
}
pub fn read_package(path: &Path) -> CargoResult<Package> {
}
impl Source for PathSource {
- fn update(&self) -> CargoResult<()> { Ok(()) }
+ fn update(&self) -> CargoResult<()> {
+ Ok(())
+ }
fn list(&self) -> CargoResult<Vec<Summary>> {
- Ok(self.paths.iter().filter_map(|path| {
- match PathSource::read_package(&path.join("Cargo.toml")) {
- Ok(ref pkg) => Some(pkg.get_summary().clone()),
- Err(e) => {
- debug!("failed to read manifest; path={}; err={}", path.display(), e);
- None
- }
+ // TODO: Recursively find manifests
+
+ match PathSource::read_package(&self.path.join("Cargo.toml")) {
+ Ok(ref pkg) => Ok(vec!(pkg.get_summary().clone())),
+ Err(e) => {
+ debug!("failed to read manifest; path={}; err={}", self.path.display(), e);
+ Err(e)
}
- }).collect())
+ }
}
fn download(&self, _: &[PackageId]) -> CargoResult<()>{
+ // TODO: assert! that the PackageId is contained by the source
Ok(())
}
fn get(&self, ids: &[PackageId]) -> CargoResult<Vec<Package>> {
log!(5, "getting packages; ids={}", ids);
- Ok(self.paths.iter().filter_map(|path| {
- match PathSource::read_package(&path.join("Cargo.toml")) {
- Ok(pkg) => {
- log!(5, "comparing; pkg={}", pkg);
+ PathSource::read_package(&self.path.join("Cargo.toml")).and_then(|pkg| {
+ log!(5, "comparing; pkg={}", pkg);
- if ids.iter().any(|pkg_id| pkg.get_package_id() == pkg_id) {
- Some(pkg)
- } else {
- None
- }
- }
- Err(_) => None
+ if ids.iter().any(|pkg_id| pkg.get_package_id() == pkg_id) {
+ Ok(vec!(pkg))
+ } else {
+ // TODO: Be smarter
+ // Err(simple_human(format!("Couldn't find `{}` in path source", ids)))
+ Ok(vec!())
}
- }).collect())
+ })
}
}
-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|
-use std::{io,fmt};
+use std::{io,fmt,os};
use std::collections::HashMap;
use serialize::{Encodable,Encoder};
use toml;
-use util::{other_error,CargoResult,Require};
+use util::{CargoResult,Require,other_error,simple_human};
+
+pub struct Config {
+ home_path: Path
+}
+
+impl Config {
+ pub fn new() -> CargoResult<Config> {
+ Ok(Config {
+ home_path: try!(os::homedir()
+ .require(simple_human("Couldn't find the home directory")))
+ })
+ }
+
+ pub fn git_db_path(&self) -> Path {
+ self.home_path.join(".cargo").join("git").join("db")
+ }
+
+ pub fn git_checkout_path(&self) -> Path {
+ self.home_path.join(".cargo").join("git").join("checkouts")
+ }
+}
#[deriving(Eq,PartialEq,Clone,Encodable,Decodable)]
pub enum Location {
+pub use self::config::Config;
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;
use std::collections::HashMap;
use serialize::Decodable;
-use core::{SourceId,GitKind,RegistryKind};
+use core::{SourceId,GitKind};
use core::manifest::{LibKind,Lib};
use core::{Summary,Manifest,Target,Dependency,PackageId};
use util::{CargoResult,Require,simple_human,toml_error};
for (n, v) in dependencies.iter() {
let (version, source_id) = match *v {
SimpleDep(ref string) => {
- let source_id = SourceId::new(RegistryKind, url::from_str("http://example.com").unwrap());
- (string.clone(), source_id)
+ (string.clone(), SourceId::for_central())
},
DetailedDep(ref details) => {
let source_id = details.other.find_equiv(&"git").map(|git| {
let kind = GitKind("master".to_str());
let url = url::from_str(git.as_slice()).unwrap();
let source_id = SourceId::new(kind, url);
+ // TODO: Don't do this for path
sources.push(source_id.clone());
source_id
});
- (details.version.clone(), try!(source_id.require(simple_human("Dependencies must supply a git location"))))
+ // TODO: Convert relative path dependencies to namespace
+
+ match source_id {
+ Some(source_id) => (details.version.clone(), source_id),
+ None => (details.version.clone(), SourceId::for_central())
+ }
}
};