From 32e262d2f7faa407765e97ffb22ef7b466f48ec3 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 29 May 2014 15:07:07 -0700 Subject: [PATCH] Initial GitSource pass --- src/bin/cargo-git-checkout.rs | 2 +- src/cargo/sources/git.rs | 90 ++++++++++++++++++++++++++++++----- 2 files changed, 79 insertions(+), 13 deletions(-) diff --git a/src/bin/cargo-git-checkout.rs b/src/bin/cargo-git-checkout.rs index 7bbf7aabf..a62d1874a 100644 --- a/src/bin/cargo-git-checkout.rs +++ b/src/bin/cargo-git-checkout.rs @@ -35,7 +35,7 @@ fn execute(options: Options) -> CLIResult> { let local = try!(repo.checkout().map_err(|e| CLIError::new(format!("Couldn't check out repository: {}", e), None::<&str>, 1))); - try!(local.copy_to(Path::new(checkout_path)).map_err(|e| + try!(local.copy_to(&Path::new(checkout_path)).map_err(|e| CLIError::new(format!("Couldn't copy repository: {}", e), None::<&str>, 1))); Ok(Some(local)) diff --git a/src/cargo/sources/git.rs b/src/cargo/sources/git.rs index fbfe01f8e..fa2a2c794 100644 --- a/src/cargo/sources/git.rs +++ b/src/cargo/sources/git.rs @@ -2,11 +2,68 @@ use url::Url; use util::{CargoResult,ProcessBuilder,io_error,human_error,process}; -use std::fmt::Show; +use std::fmt; +use std::fmt::{Show,Formatter}; use std::str; use std::io::{UserDir,AllPermissions}; use std::io::fs::{mkdir_recursive,rmdir_recursive,chmod}; use serialize::{Encodable,Encoder}; +use core::source::Source; +use core::{NameVer,Package,Summary}; +use ops; + +pub struct GitSource { + config: GitConfig, + dest: Path +} + +impl GitSource { + pub fn new(config: GitConfig, dest: Path) -> GitSource { + GitSource { config: config, dest: dest } + } +} + +impl Show for GitSource { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + try!(write!(f, "git repo at {}", self.config.url)); + + if self.config.reference.as_slice() != "master" { + try!(write!(f, " ({})", self.config.reference)); + } + + Ok(()) + } +} + +impl Source for GitSource { + fn update(&self) -> CargoResult<()> { + let remote = GitRemoteRepo::from_config(self.config.clone()); + let repo = try!(remote.checkout()); + + try!(repo.copy_to(&self.dest)); + + Ok(()) + } + + fn list(&self) -> CargoResult> { + let pkg = try!(read_manifest(&self.dest)); + Ok(vec!(pkg.get_summary().clone())) + } + + fn download(&self, _: &[NameVer]) -> CargoResult<()> { + Ok(()) + } + + fn get(&self, packages: &[NameVer]) -> CargoResult> { + let pkg = try!(read_manifest(&self.dest)); + + if packages.iter().any(|nv| pkg.is_for_name_ver(nv)) { + Ok(vec!(pkg)) + } else { + Ok(vec!()) + } + } +} macro_rules! git( ($config:expr, $verbose:expr, $str:expr, $($rest:expr),*) => ( @@ -39,9 +96,9 @@ macro_rules! errln( */ #[deriving(Eq,Clone)] -struct GitConfig { +pub struct GitConfig { path: Path, - uri: Url, + url: Url, reference: String, verbose: bool } @@ -49,7 +106,7 @@ struct GitConfig { #[deriving(Eq,Clone,Encodable)] struct EncodableGitConfig { path: String, - uri: String, + url: String, reference: String } @@ -93,15 +150,19 @@ impl> Encodable for GitConfig { fn encode(&self, s: &mut S) -> Result<(), E> { EncodableGitConfig { path: self.path.display().to_str(), - uri: self.uri.to_str(), + url: self.url.to_str(), reference: self.reference.clone() }.encode(s) } } impl GitRemoteRepo { - pub fn new(path: Path, uri: Url, reference: String, verbose: bool) -> GitRemoteRepo { - GitRemoteRepo { config: GitConfig { path: path, uri: uri, reference: reference, verbose: verbose } } + pub fn new(path: Path, url: Url, reference: String, verbose: bool) -> GitRemoteRepo { + GitRemoteRepo { config: GitConfig { path: path, url: url, reference: reference, verbose: verbose } } + } + + pub fn from_config(config: GitConfig) -> GitRemoteRepo { + GitRemoteRepo { config: config } } pub fn get_cwd<'a>(&'a self) -> &'a Path { @@ -120,7 +181,7 @@ impl GitRemoteRepo { } fn fetch(&self) -> CargoResult<()> { - Ok(git!(self.config.path, self.config.verbose, "fetch --force --quiet --tags {} refs/heads/*:refs/heads/*", self.config.uri)) + Ok(git!(self.config.path, self.config.verbose, "fetch --force --quiet --tags {} refs/heads/*:refs/heads/*", self.config.url)) } fn clone(&self) -> CargoResult<()> { @@ -129,7 +190,7 @@ impl GitRemoteRepo { try!(mkdir_recursive(&self.config.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.config.verbose, "clone {} {} --bare --no-hardlinks --quiet", self.config.uri, self.config.path.display())) + Ok(git!(dirname, self.config.verbose, "clone {} {} --bare --no-hardlinks --quiet", self.config.url, self.config.path.display())) } } @@ -138,7 +199,7 @@ impl GitRepo { &self.config.path } - pub fn copy_to<'a>(&'a self, dest: Path) -> CargoResult> { + pub fn copy_to<'a>(&'a self, dest: &Path) -> CargoResult> { let checkout = try!(GitCheckout::clone(dest, self)); try!(checkout.fetch()); @@ -150,8 +211,8 @@ impl GitRepo { } impl<'a> GitCheckout<'a> { - fn clone<'a>(into: Path, repo: &'a GitRepo) -> CargoResult> { - let checkout = GitCheckout { location: into, repo: repo }; + fn clone<'a>(into: &Path, repo: &'a GitRepo) -> CargoResult> { + let checkout = GitCheckout { location: into.clone(), repo: repo }; // If the git checkout already exists, we don't need to clone it again if !checkout.location.join(".git").exists() { @@ -231,3 +292,8 @@ fn git_output(path: &Path, verbose: bool, str: String) -> CargoResult { fn to_str(vec: &[u8]) -> String { str::from_utf8_lossy(vec).to_str() } + +fn read_manifest(path: &Path) -> CargoResult { + let joined = path.join("Cargo.toml"); + ops::read_manifest(joined.as_str().unwrap()) +}