diff --git a/Cargo.lock b/Cargo.lock index 69fd99c1418..a1dc3dfcccd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,6 +9,7 @@ dependencies = [ "curl 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.6.74 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "file-lock 0.0.16 (git+https://github.com/Byron/file-lock?branch=cargo-adjustments)", "filetime 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -123,6 +124,26 @@ dependencies = [ "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "errno" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "file-lock" +version = "0.0.16" +source = "git+https://github.com/Byron/file-lock?branch=cargo-adjustments#0d28d6cff55e1a7f9bcd469d9dae1543cc236d78" +dependencies = [ + "errno 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "filetime" version = "0.1.6" @@ -407,6 +428,14 @@ dependencies = [ "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "winapi" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi" version = "0.2.4" diff --git a/Cargo.toml b/Cargo.toml index 7422dbad88d..d9ee01aa9e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,10 @@ toml = "0.1" url = "0.2" winapi = "0.2" +[dependencies.file-lock] +git = "https://github.com/Byron/file-lock" +branch = "cargo-adjustments" + [dev-dependencies] tempdir = "0.3" hamcrest = "0.1" diff --git a/src/bin/cargo.rs b/src/bin/cargo.rs index f21ffb1d5c5..80291848c24 100644 --- a/src/bin/cargo.rs +++ b/src/bin/cargo.rs @@ -14,7 +14,8 @@ use std::process::Command; use cargo::{execute_main_without_stdin, handle_error, shell}; use cargo::core::MultiShell; -use cargo::util::{CliError, CliResult, lev_distance, Config}; +use cargo::util::{CliError, CliResult, lev_distance, Config, CargoLock, LockKind, human, + ChainError}; #[derive(RustcDecodable)] struct Flags { @@ -95,6 +96,12 @@ macro_rules! each_subcommand{ ($mac:ident) => ({ on this top-level information. */ fn execute(flags: Flags, config: &Config) -> CliResult> { + let mut fl = CargoLock::new(config.home().join(".global-lock")); + + try!(fl.lock(LockKind::Blocking).chain_error(|| { + human("Failed to obtain global cargo lock") + })); + try!(config.shell().set_verbosity(flags.flag_verbose, flags.flag_quiet)); try!(config.shell().set_color_config(flags.flag_color.as_ref().map(|s| &s[..]))); diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs index 949e3c0e6fa..fb8b8a3a77e 100644 --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -22,6 +22,7 @@ extern crate term; extern crate time; extern crate toml; extern crate url; +extern crate file_lock; use std::env; use std::error::Error; diff --git a/src/cargo/util/errors.rs b/src/cargo/util/errors.rs index 1d53d6fc84d..8d5a437618d 100644 --- a/src/cargo/util/errors.rs +++ b/src/cargo/util/errors.rs @@ -12,6 +12,7 @@ use curl; use git2; use toml; use url; +use file_lock; pub type CargoResult = Result>; @@ -307,12 +308,18 @@ from_error! { url::ParseError, toml::DecodeError, ffi::NulError, + file_lock::filename::Error, + file_lock::filename::ParseError, } impl From> for Box { fn from(t: Human) -> Box { Box::new(t) } } +impl CargoError for file_lock::filename::Error { + fn is_human(&self) -> bool { true } +} + impl CargoError for semver::ReqParseError {} impl CargoError for io::Error {} impl CargoError for git2::Error {} @@ -325,6 +332,7 @@ impl CargoError for toml::Error {} impl CargoError for toml::DecodeError {} impl CargoError for url::ParseError {} impl CargoError for ffi::NulError {} +impl CargoError for file_lock::filename::ParseError {} // ============================================================================= // Construction helpers diff --git a/src/cargo/util/lock.rs b/src/cargo/util/lock.rs new file mode 100644 index 00000000000..a15c2859160 --- /dev/null +++ b/src/cargo/util/lock.rs @@ -0,0 +1,33 @@ +use file_lock::filename::Mode; +use file_lock::filename::Lock as FileLock; + +use std::path::PathBuf; +use std::fs; + +use util::{CargoResult, ChainError, human}; + +pub use file_lock::filename::Kind as LockKind; + +pub struct CargoLock { + inner: FileLock, +} + +impl CargoLock { + pub fn new(path: PathBuf) -> CargoLock { + CargoLock { + inner: FileLock::new(path, Mode::Write) + } + } + + pub fn lock(&mut self, kind: LockKind) -> CargoResult<()> { + { + let lock_dir = self.inner.path().parent().unwrap(); + try!(fs::create_dir_all(lock_dir).chain_error(|| { + human(format!("Failed to create parent directory of lock-file at '{}'", + lock_dir.display())) + })); + } + debug!("About to acquire file lock: '{}'", self.inner.path().display()); + Ok(try!(self.inner.any_lock(kind))) + } +} diff --git a/src/cargo/util/mod.rs b/src/cargo/util/mod.rs index 49963201d92..461210cb4c1 100644 --- a/src/cargo/util/mod.rs +++ b/src/cargo/util/mod.rs @@ -16,6 +16,7 @@ pub use self::sha256::Sha256; pub use self::to_semver::ToSemver; pub use self::to_url::ToUrl; pub use self::vcs::{GitRepo, HgRepo}; +pub use self::lock::{CargoLock, LockKind}; pub mod config; pub mod errors; @@ -33,4 +34,5 @@ mod dependency_queue; mod sha256; mod shell_escape; mod vcs; +mod lock; mod rustc; diff --git a/tests/test_cargo_build_lib.rs b/tests/test_cargo_build_lib.rs index 476d2f14bdf..6cebca3963e 100644 --- a/tests/test_cargo_build_lib.rs +++ b/tests/test_cargo_build_lib.rs @@ -53,6 +53,32 @@ test!(build_with_no_lib { .with_stderr("no library targets found")); }); +test!(build_global_lock { + + let p = project("foo") + .file("Cargo.toml", r#" + [package] + + name = "foo" + version = "0.0.1" + authors = ["wycats@example.com"] + "#) + .file("src/main.rs", r#" + fn main() {} + "#) + .file("src/lib.rs", r#" "#); + + p.build(); + + let bg_process = p.cargo("build"); + let fg_process = bg_process.clone(); + let mut bg_process_handle = bg_process.build_command().spawn().unwrap(); + + assert_eq!(fg_process.build_command().output().unwrap().status.code().unwrap(), 101); + assert!(bg_process_handle.wait().unwrap().success()); +}); + + test!(build_with_relative_cargo_home_path { let p = project("foo") .file("Cargo.toml", r#"