diff --git a/src/bin/cargo-compile.rs b/src/bin/cargo-compile.rs index 818d52ec1..c097f6f2b 100644 --- a/src/bin/cargo-compile.rs +++ b/src/bin/cargo-compile.rs @@ -20,10 +20,13 @@ use cargo::util::important_paths::find_project; #[deriving(PartialEq,Clone,Decodable,Encodable)] pub struct Options { - manifest_path: Option + manifest_path: Option, + update_remotes: bool } -hammer_config!(Options "Compile the current project") +hammer_config!(Options "Compile the current project", |c| { + c.short("update_remotes", 'u') +}) fn main() { execute_main_without_stdin(execute); @@ -43,7 +46,9 @@ fn execute(options: Options, shell: &mut MultiShell) -> CliResult> { })) }; - ops::compile(&root, shell).map(|_| None).map_err(|err| { + let update = options.update_remotes; + + ops::compile(&root, update, shell).map(|_| None).map_err(|err| { CliError::from_boxed(err, 101) }) } diff --git a/src/bin/cargo-git-checkout.rs b/src/bin/cargo-git-checkout.rs index 64fefed8c..699d0a411 100644 --- a/src/bin/cargo-git-checkout.rs +++ b/src/bin/cargo-git-checkout.rs @@ -37,7 +37,7 @@ fn execute(options: Options, shell: &mut MultiShell) -> CliResult> { let source_id = SourceId::for_git(&url, reference.as_slice()); - let mut config = try!(Config::new(shell).map_err(|e| CliError::from_boxed(e, 1))); + let mut config = try!(Config::new(shell, true).map_err(|e| CliError::from_boxed(e, 1))); let mut source = GitSource::new(&source_id, &mut config); try!(source.update().map_err(|e| { diff --git a/src/cargo/core/registry.rs b/src/cargo/core/registry.rs index 169137df5..f150c7880 100644 --- a/src/cargo/core/registry.rs +++ b/src/cargo/core/registry.rs @@ -1,5 +1,5 @@ use std::vec::Vec; -use core::{MultiShell, Source, SourceId, Summary, Dependency, PackageId, Package}; +use core::{Source, SourceId, Summary, Dependency, PackageId, Package}; use util::{CargoResult, ChainError, Config, human}; pub trait Registry { @@ -20,15 +20,15 @@ pub struct PackageRegistry<'a> { overrides: Vec, summaries: Vec, searched: Vec, - shell: &'a mut MultiShell + config: &'a mut Config<'a> } impl<'a> PackageRegistry<'a> { pub fn new<'a>(source_ids: Vec, override_ids: Vec, - shell: &'a mut MultiShell) -> CargoResult> { + config: &'a mut Config<'a>) -> CargoResult> { - let mut reg = PackageRegistry::empty(shell); + let mut reg = PackageRegistry::empty(config); for id in source_ids.iter() { try!(reg.load(id, false)); @@ -41,13 +41,13 @@ impl<'a> PackageRegistry<'a> { Ok(reg) } - fn empty<'a>(shell: &'a mut MultiShell) -> PackageRegistry<'a> { + fn empty<'a>(config: &'a mut Config<'a>) -> PackageRegistry<'a> { PackageRegistry { sources: vec!(), overrides: vec!(), summaries: vec!(), searched: vec!(), - shell: shell + config: config } } @@ -82,7 +82,7 @@ impl<'a> PackageRegistry<'a> { fn load(&mut self, namespace: &SourceId, override: bool) -> CargoResult<()> { (|| { - let mut source = namespace.load(&mut try!(Config::new(self.shell))); + let mut source = namespace.load(self.config); let dst = if override {&mut self.overrides} else {&mut self.summaries}; // Ensure the source has fetched all necessary remote data. diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index ca935f4b4..308a1146a 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -23,14 +23,14 @@ //! use std::os; -use util::config::{ConfigValue}; +use util::config::{Config, ConfigValue}; use core::{MultiShell, Source, SourceId, PackageSet, resolver}; use core::registry::PackageRegistry; use ops; use sources::{PathSource}; use util::{CargoResult, Wrap, config, internal, human}; -pub fn compile(manifest_path: &Path, shell: &mut MultiShell) -> CargoResult<()> { +pub fn compile(manifest_path: &Path, update: bool, shell: &mut MultiShell) -> CargoResult<()> { log!(4, "compile; manifest-path={}", manifest_path.display()); let mut source = PathSource::for_path(&manifest_path.dir_path()); @@ -45,8 +45,10 @@ pub fn compile(manifest_path: &Path, shell: &mut MultiShell) -> CargoResult<()> let source_ids = package.get_source_ids(); let packages = { + let mut config = try!(Config::new(shell, update)); + let mut registry = - try!(PackageRegistry::new(source_ids, override_ids, shell)); + try!(PackageRegistry::new(source_ids, override_ids, &mut config)); let resolved = try!(resolver::resolve(package.get_dependencies(), &mut registry)); @@ -58,7 +60,8 @@ pub fn compile(manifest_path: &Path, shell: &mut MultiShell) -> CargoResult<()> debug!("packages={}", packages); - try!(ops::compile_packages(&package, &PackageSet::new(packages.as_slice()), shell)); + let mut config = try!(Config::new(shell, update)); + try!(ops::compile_packages(&package, &PackageSet::new(packages.as_slice()), &mut config)); Ok(()) } diff --git a/src/cargo/ops/cargo_rustc.rs b/src/cargo/ops/cargo_rustc.rs index 24d171c0b..b28984080 100644 --- a/src/cargo/ops/cargo_rustc.rs +++ b/src/cargo/ops/cargo_rustc.rs @@ -10,20 +10,20 @@ use util::{Config}; type Args = Vec; -struct Context<'a> { +struct Context<'a, 'b> { dest: &'a Path, deps_dir: &'a Path, primary: bool, rustc_version: &'a str, compiled_anything: bool, - config: &'a mut Config<'a> + config: &'b mut Config<'b> } -pub fn compile_packages(pkg: &Package, deps: &PackageSet, - shell: &mut MultiShell) -> CargoResult<()> { +pub fn compile_packages<'a>(pkg: &Package, deps: &PackageSet, + config: &'a mut Config<'a>) -> CargoResult<()> { + debug!("compile_packages; pkg={}; deps={}", pkg, deps); - let mut config = try!(Config::new(shell)); let target_dir = pkg.get_absolute_target_dir(); let deps_target_dir = target_dir.join("deps"); @@ -47,7 +47,7 @@ pub fn compile_packages(pkg: &Package, deps: &PackageSet, primary: false, rustc_version: rustc_version.as_slice(), compiled_anything: false, - config: &mut config + config: config }; // Traverse the dependencies in topological order diff --git a/src/cargo/sources/git/source.rs b/src/cargo/sources/git/source.rs index 3894183b9..aa889f92f 100644 --- a/src/cargo/sources/git/source.rs +++ b/src/cargo/sources/git/source.rs @@ -92,11 +92,20 @@ impl<'a, 'b> Show for GitSource<'a, 'b> { impl<'a, 'b> Source for GitSource<'a, 'b> { fn update(&mut self) -> CargoResult<()> { - try!(self.config.shell().status("Updating", - format!("git repository `{}`", self.remote.get_url()))); + let should_update = self.config.update_remotes() || { + !self.remote.has_ref(&self.db_path, self.reference.as_slice()).is_ok() + }; + + let repo = if should_update { + try!(self.config.shell().status("Updating", + format!("git repository `{}`", self.remote.get_url()))); + + log!(5, "updating git source `{}`", self.remote); + try!(self.remote.checkout(&self.db_path)) + } else { + self.remote.db_at(&self.db_path) + }; - log!(5, "updating git source `{}`", self.remote); - let repo = try!(self.remote.checkout(&self.db_path)); try!(repo.copy_to(self.reference.as_slice(), &self.checkout_path)); self.path_source.update() diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs index 761d9401d..5d560a393 100644 --- a/src/cargo/sources/git/utils.rs +++ b/src/cargo/sources/git/utils.rs @@ -50,13 +50,13 @@ macro_rules! git( ) macro_rules! git_output( - ($config:expr, $str:expr, $($rest:expr),*) => ( + ($config:expr, $str:expr, $($rest:expr),*) => ({ try!(git_output(&$config, format!($str, $($rest),*))) - ); + }); - ($config:expr, $str:expr) => ( + ($config:expr, $str:expr) => ({ try!(git_output(&$config, format!($str))) - ); + }); ) macro_rules! errln( @@ -146,6 +146,11 @@ impl GitRemote { &self.url } + pub fn has_ref(&self, path: &Path, reference: S) -> CargoResult<()> { + git_output!(*path, "rev-parse {}", reference.as_slice()); + Ok(()) + } + pub fn checkout(&self, into: &Path) -> CargoResult { if into.exists() { try!(self.fetch_into(into)); diff --git a/src/cargo/util/config.rs b/src/cargo/util/config.rs index 9dcad1175..7c0ac0a14 100644 --- a/src/cargo/util/config.rs +++ b/src/cargo/util/config.rs @@ -9,16 +9,18 @@ use cargo_toml = util::toml; pub struct Config<'a> { home_path: Path, + update_remotes: bool, shell: &'a mut MultiShell } impl<'a> Config<'a> { - pub fn new<'a>(shell: &'a mut MultiShell) -> CargoResult> { + pub fn new<'a>(shell: &'a mut MultiShell, update_remotes: bool) -> CargoResult> { Ok(Config { home_path: try!(os::homedir().require(|| { human("Cargo couldn't find your home directory. \ This probably means that $HOME was not set.") })), + update_remotes: update_remotes, shell: shell }) } @@ -34,6 +36,10 @@ impl<'a> Config<'a> { pub fn shell<'a>(&'a mut self) -> &'a mut MultiShell { &mut *self.shell } + + pub fn update_remotes(&mut self) -> bool { + self.update_remotes + } } #[deriving(Eq,PartialEq,Clone,Encodable,Decodable)] diff --git a/tests/test_cargo_compile_git_deps.rs b/tests/test_cargo_compile_git_deps.rs index a89fd7135..a5ae21687 100644 --- a/tests/test_cargo_compile_git_deps.rs +++ b/tests/test_cargo_compile_git_deps.rs @@ -222,25 +222,33 @@ test!(recompilation { UPDATING, git_project.root().display(), COMPILING, git_project.root().display(), COMPILING, p.root().display()))); + // Don't recompile the second time assert_that(p.process("cargo-compile"), - execs().with_stdout(format!("{} git repository `file:{}`\n\ - {} bar v0.5.0 (file:{})\n\ + execs().with_stdout(format!("{} bar v0.5.0 (file:{})\n\ {} foo v0.5.0 (file:{})\n", - UPDATING, git_project.root().display(), FRESH, git_project.root().display(), FRESH, p.root().display()))); + // Modify a file manually, shouldn't trigger a recompile File::create(&git_project.root().join("src/bar.rs")).write_str(r#" pub fn bar() { println!("hello!"); } "#).assert(); + assert_that(p.process("cargo-compile"), + 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-compile").arg("-u"), execs().with_stdout(format!("{} git repository `file:{}`\n\ {} bar v0.5.0 (file:{})\n\ {} foo v0.5.0 (file:{})\n", UPDATING, git_project.root().display(), FRESH, git_project.root().display(), FRESH, p.root().display()))); + // Commit the changes and make sure we trigger a recompile File::create(&git_project.root().join("src/bar.rs")).write_str(r#" pub fn bar() { println!("hello!"); } @@ -248,7 +256,8 @@ test!(recompilation { git_project.process("git").args(["add", "."]).exec_with_output().assert(); git_project.process("git").args(["commit", "-m", "test"]).exec_with_output() .assert(); - assert_that(p.process("cargo-compile"), + + assert_that(p.process("cargo-compile").arg("-u"), execs().with_stdout(format!("{} git repository `file:{}`\n\ {} bar v0.5.0 (file:{})\n\ {} foo v0.5.0 (file:{})\n",