From 03b3e83d948d9802a59bc03b970099da6b442289 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 3 Oct 2018 11:23:40 -0700 Subject: [PATCH 001/128] Use `Multi::get_timeout` instead of our own This is what curl recommends we use so let's be sure to not mess up any timers by accident! --- src/cargo/core/package.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 25243b83d0e..0a879b5d7ee 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -619,7 +619,9 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { break Ok(pair) } assert!(self.pending.len() > 0); - self.set.multi.wait(&mut [], Duration::new(60, 0)) + let timeout = self.set.multi.get_timeout()? + .unwrap_or(Duration::new(5, 0)); + self.set.multi.wait(&mut [], timeout) .chain_err(|| "failed to wait on curl `Multi`")?; } } From c14839b56e494d17a34465c5b4cc2d2c278aa3f6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 3 Oct 2018 11:25:14 -0700 Subject: [PATCH 002/128] Scope retries per download Prevoiusly retries were tracked per-session, which meant that if you were downloading 100 packages and they all failed spuriously for the same reason you'd immediately abort. Instead though let's keep track of retries per package so if they're all coupled on one connection a failure of one will end up retrying all of them. We want to make sure that we actually retry again! --- src/cargo/core/package.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 0a879b5d7ee..8824ee75b1a 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -255,11 +255,10 @@ pub struct PackageSet<'cfg> { pub struct Downloads<'a, 'cfg: 'a> { set: &'a PackageSet<'cfg>, - pending: HashMap, + pending: HashMap, EasyHandle)>, pending_ids: HashSet, results: Vec<(usize, CargoResult<()>)>, next: usize, - retry: Retry<'cfg>, progress: RefCell>>, downloads_finished: usize, downloaded_bytes: u64, @@ -268,7 +267,7 @@ pub struct Downloads<'a, 'cfg: 'a> { success: bool, } -struct Download { +struct Download<'cfg> { token: usize, id: PackageId, data: RefCell>, @@ -277,6 +276,7 @@ struct Download { total: Cell, current: Cell, start: Instant, + retry: Retry<'cfg>, } impl<'cfg> PackageSet<'cfg> { @@ -329,7 +329,6 @@ impl<'cfg> PackageSet<'cfg> { pending: HashMap::new(), pending_ids: HashSet::new(), results: Vec::new(), - retry: Retry::new(self.config)?, progress: RefCell::new(Some(Progress::with_style( "Downloading", ProgressStyle::Ratio, @@ -478,6 +477,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { total: Cell::new(0), current: Cell::new(0), start: Instant::now(), + retry: Retry::new(self.set.config)?, }; self.enqueue(dl, handle)?; self.tick(WhyTick::DownloadStarted)?; @@ -514,12 +514,13 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { // then we want to re-enqueue our request for another attempt and // then we wait for another request to finish. let ret = { - self.retry.try(|| { + let url = &dl.url; + dl.retry.try(|| { result?; let code = handle.response_code()?; if code != 200 && code != 0 { - let url = handle.effective_url()?.unwrap_or(&dl.url); + let url = handle.effective_url()?.unwrap_or(&url); return Err(HttpNot200 { code, url: url.to_string(), @@ -574,7 +575,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { Ok(slot.borrow().unwrap()) } - fn enqueue(&mut self, dl: Download, handle: Easy) -> CargoResult<()> { + fn enqueue(&mut self, dl: Download<'cfg>, handle: Easy) -> CargoResult<()> { let mut handle = self.set.multi.add(handle)?; handle.set_token(dl.token)?; self.pending.insert(dl.token, (dl, handle)); From 0b0f089d3d27f4dd322ae8393c70ad7a9733b4e1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 3 Oct 2018 16:16:24 -0700 Subject: [PATCH 003/128] Fix timeouts firing while tarballs are extracted This commit fixes #6125 by ensuring that while we're extracting tarballs or doing other synchronous work like grabbing file locks we're not letting the timeout timers of each HTTP transfer keep ticking. This is curl's default behavior (which we don't want in this scenario). Instead the timeout logic is inlined directly and we manually account for the synchronous work happening not counting towards timeout limits. Closes #6125 --- Cargo.toml | 1 + src/cargo/core/package.rs | 154 ++++++++++++++++++++++++++++++++++---- src/cargo/lib.rs | 1 + src/cargo/ops/mod.rs | 3 +- src/cargo/ops/registry.rs | 75 ++++++++++++------- src/cargo/util/config.rs | 3 +- src/cargo/util/network.rs | 6 +- 7 files changed, 196 insertions(+), 47 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8d2c62b6fbd..5dbff3eacf8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ crates-io = { path = "src/crates-io", version = "0.20" } crossbeam-utils = "0.5" crypto-hash = "0.3.1" curl = { version = "0.4.17", features = ['http2'] } +curl-sys = "0.4.12" env_logger = "0.5.11" failure = "0.1.2" filetime = "0.2" diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 8824ee75b1a..5770311e350 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -7,6 +7,8 @@ use std::path::{Path, PathBuf}; use std::time::{Instant, Duration}; use bytesize::ByteSize; +use curl; +use curl_sys; use curl::easy::{Easy, HttpVersion}; use curl::multi::{Multi, EasyHandle}; use lazycell::LazyCell; @@ -257,7 +259,7 @@ pub struct Downloads<'a, 'cfg: 'a> { set: &'a PackageSet<'cfg>, pending: HashMap, EasyHandle)>, pending_ids: HashSet, - results: Vec<(usize, CargoResult<()>)>, + results: Vec<(usize, Result<(), curl::Error>)>, next: usize, progress: RefCell>>, downloads_finished: usize, @@ -268,14 +270,49 @@ pub struct Downloads<'a, 'cfg: 'a> { } struct Download<'cfg> { + /// Token for this download, used as the key of the `Downloads::pending` map + /// and stored in `EasyHandle` as well. token: usize, + + /// Package that we're downloading id: PackageId, + + /// Actual downloaded data, updated throughout the lifetime of this download data: RefCell>, + + /// The URL that we're downloading from, cached here for error messages and + /// reenqueuing. url: String, + + /// A descriptive string to print when we've finished downloading this crate descriptor: String, + + /// Statistics updated from the progress callback in libcurl total: Cell, current: Cell, + + /// The moment we started this transfer at start: Instant, + + /// Last time we noticed that we got some more data from libcurl + updated_at: Cell, + + /// Timeout management, both of timeout thresholds as well as whether or not + /// our connection has timed out (and accompanying message if it has). + /// + /// Note that timeout management is done manually here because we have a + /// `Multi` with a lot of active transfers but between transfers finishing + /// we perform some possibly slow synchronous work (like grabbing file + /// locks, extracting tarballs, etc). The default timers on our `Multi` keep + /// running during this work, but we don't want them to count towards timing + /// everythig out. As a result, we manage this manually and take the time + /// for synchronous work into account manually. + timeout: ops::HttpTimeout, + timed_out: Cell>, + next_speed_check: Cell, + next_speed_check_bytes_threshold: Cell, + + /// Logic used to track retrying this download if it's a spurious failure. retry: Retry<'cfg>, } @@ -409,7 +446,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { debug!("downloading {} as {}", id, token); assert!(self.pending_ids.insert(id.clone())); - let mut handle = ops::http_handle(self.set.config)?; + let (mut handle, timeout) = ops::http_handle_and_timeout(self.set.config)?; handle.get(true)?; handle.url(&url)?; handle.follow_location(true)?; // follow redirects @@ -447,14 +484,10 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { handle.progress(true)?; handle.progress_function(move |dl_total, dl_cur, _, _| { tls::with(|downloads| { - let downloads = match downloads { - Some(d) => d, - None => return false, - }; - let dl = &downloads.pending[&token].0; - dl.total.set(dl_total as u64); - dl.current.set(dl_cur as u64); - downloads.tick(WhyTick::DownloadUpdate).is_ok() + match downloads { + Some(d) => d.progress(token, dl_total as u64, dl_cur as u64), + None => false, + } }) })?; @@ -468,6 +501,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { self.set.config.shell().status("Downloading", "crates ...")?; } + let now = Instant::now(); let dl = Download { token, data: RefCell::new(Vec::new()), @@ -477,6 +511,11 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { total: Cell::new(0), current: Cell::new(0), start: Instant::now(), + updated_at: Cell::new(now), + timeout, + timed_out: Cell::new(None), + next_speed_check: Cell::new(now), + next_speed_check_bytes_threshold: Cell::new(0), retry: Retry::new(self.set.config)?, }; self.enqueue(dl, handle)?; @@ -514,13 +553,35 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { // then we want to re-enqueue our request for another attempt and // then we wait for another request to finish. let ret = { + let timed_out = &dl.timed_out; let url = &dl.url; dl.retry.try(|| { - result?; + if let Err(e) = result { + // If this error is "aborted by callback" then that's + // probably because our progress callback aborted due to + // a timeout. We'll find out by looking at the + // `timed_out` field, looking for a descriptive message. + // If one is found we switch the error code (to ensure + // it's flagged as spurious) and then attach our extra + // information to the error. + if !e.is_aborted_by_callback() { + return Err(e.into()) + } + + return Err(match timed_out.replace(None) { + Some(msg) => { + let code = curl_sys::CURLE_OPERATION_TIMEDOUT; + let mut err = curl::Error::new(code); + err.set_extra(msg); + err + } + None => e, + }.into()) + } let code = handle.response_code()?; if code != 200 && code != 0 { - let url = handle.effective_url()?.unwrap_or(&url); + let url = handle.effective_url()?.unwrap_or(url); return Err(HttpNot200 { code, url: url.to_string(), @@ -569,7 +630,19 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { let source = sources .get_mut(dl.id.source_id()) .ok_or_else(|| internal(format!("couldn't find source for `{}`", dl.id)))?; + let start = Instant::now(); let pkg = source.finish_download(&dl.id, data)?; + + // Assume that no time has passed while we were calling + // `finish_download`, update all speed checks and timeout limits of all + // active downloads to make sure they don't fire because of a slowly + // extracted tarball. + let finish_dur = start.elapsed(); + for (dl, _) in self.pending.values_mut() { + dl.updated_at.set(dl.updated_at.get() + finish_dur); + dl.next_speed_check.set(dl.next_speed_check.get() + finish_dur); + } + let slot = &self.set.packages[&dl.id]; assert!(slot.fill(pkg).is_ok()); Ok(slot.borrow().unwrap()) @@ -577,12 +650,19 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { fn enqueue(&mut self, dl: Download<'cfg>, handle: Easy) -> CargoResult<()> { let mut handle = self.set.multi.add(handle)?; + let now = Instant::now(); handle.set_token(dl.token)?; + dl.timed_out.set(None); + dl.updated_at.set(now); + dl.current.set(0); + dl.total.set(0); + dl.next_speed_check.set(now + dl.timeout.dur); + dl.next_speed_check_bytes_threshold.set(dl.timeout.low_speed_limit as u64); self.pending.insert(dl.token, (dl, handle)); Ok(()) } - fn wait_for_curl(&mut self) -> CargoResult<(usize, CargoResult<()>)> { + fn wait_for_curl(&mut self) -> CargoResult<(usize, Result<(), curl::Error>)> { // This is the main workhorse loop. We use libcurl's portable `wait` // method to actually perform blocking. This isn't necessarily too // efficient in terms of fd management, but we should only be juggling @@ -610,7 +690,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { let token = msg.token().expect("failed to read token"); let handle = &pending[&token].1; if let Some(result) = msg.result_for(&handle) { - results.push((token, result.map_err(|e| e.into()))); + results.push((token, result)); } else { debug!("message without a result (?)"); } @@ -627,6 +707,52 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { } } + fn progress(&self, token: usize, total: u64, cur: u64) -> bool { + let dl = &self.pending[&token].0; + dl.total.set(total); + let now = Instant::now(); + if cur != dl.current.get() { + dl.current.set(cur); + dl.updated_at.set(now); + + if dl.current.get() >= dl.next_speed_check_bytes_threshold.get() { + dl.next_speed_check.set(now + dl.timeout.dur); + dl.next_speed_check_bytes_threshold.set( + dl.current.get() + dl.timeout.low_speed_limit as u64, + ); + } + } + if !self.tick(WhyTick::DownloadUpdate).is_ok() { + return false + } + + // If we've spent too long not actually receiving any data we time out. + if now - dl.updated_at.get() > dl.timeout.dur { + let msg = format!("failed to download any data for `{}` within {}s", + dl.id, + dl.timeout.dur.as_secs()); + dl.timed_out.set(Some(msg)); + return false + } + + // If we reached the point in time that we need to check our speed + // limit, see if we've transferred enough data during this threshold. If + // it fails this check then we fail because the download is going too + // slowly. + if now >= dl.next_speed_check.get() { + assert!(dl.current.get() < dl.next_speed_check_bytes_threshold.get()); + let msg = format!("download of `{}` failed to transfer more \ + than {} bytes in {}s", + dl.id, + dl.timeout.low_speed_limit, + dl.timeout.dur.as_secs()); + dl.timed_out.set(Some(msg)); + return false + } + + true + } + fn tick(&self, why: WhyTick) -> CargoResult<()> { let mut progress = self.progress.borrow_mut(); let progress = progress.as_mut().unwrap(); diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs index fa54ebbfe9b..e7fcac41d24 100644 --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -22,6 +22,7 @@ extern crate core_foundation; extern crate crates_io as registry; extern crate crossbeam_utils; extern crate curl; +extern crate curl_sys; #[macro_use] extern crate failure; extern crate filetime; diff --git a/src/cargo/ops/mod.rs b/src/cargo/ops/mod.rs index 9c09f14f5ed..3b653b00158 100644 --- a/src/cargo/ops/mod.rs +++ b/src/cargo/ops/mod.rs @@ -15,7 +15,8 @@ pub use self::cargo_package::{package, PackageOpts}; pub use self::registry::{publish, registry_configuration, RegistryConfig}; pub use self::registry::{http_handle, needs_custom_http_transport, registry_login, search}; pub use self::registry::{modify_owners, yank, OwnersOptions, PublishOpts}; -pub use self::registry::configure_http_handle; +pub use self::registry::{configure_http_handle, http_handle_and_timeout}; +pub use self::registry::HttpTimeout; pub use self::cargo_fetch::{fetch, FetchOptions}; pub use self::cargo_pkgid::pkgid; pub use self::resolve::{add_overrides, get_resolved_packages, resolve_with_previous, resolve_ws, diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index 21d70acb485..3932abdbece 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -330,6 +330,12 @@ pub fn registry( /// Create a new HTTP handle with appropriate global configuration for cargo. pub fn http_handle(config: &Config) -> CargoResult { + let (mut handle, timeout) = http_handle_and_timeout(config)?; + timeout.configure(&mut handle)?; + Ok(handle) +} + +pub fn http_handle_and_timeout(config: &Config) -> CargoResult<(Easy, HttpTimeout)> { if config.frozen() { bail!( "attempting to make an HTTP request, but --frozen was \ @@ -345,33 +351,26 @@ pub fn http_handle(config: &Config) -> CargoResult { // connect phase as well as a "low speed" timeout so if we don't receive // many bytes in a large-ish period of time then we time out. let mut handle = Easy::new(); - configure_http_handle(config, &mut handle)?; - Ok(handle) + let timeout = configure_http_handle(config, &mut handle)?; + Ok((handle, timeout)) } pub fn needs_custom_http_transport(config: &Config) -> CargoResult { let proxy_exists = http_proxy_exists(config)?; - let timeout = http_timeout(config)?; + let timeout = HttpTimeout::new(config)?.is_non_default(); let cainfo = config.get_path("http.cainfo")?; let check_revoke = config.get_bool("http.check-revoke")?; let user_agent = config.get_string("http.user-agent")?; Ok(proxy_exists - || timeout.is_some() + || timeout || cainfo.is_some() || check_revoke.is_some() || user_agent.is_some()) } /// Configure a libcurl http handle with the defaults options for Cargo -pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult<()> { - // The timeout option for libcurl by default times out the entire transfer, - // but we probably don't want this. Instead we only set timeouts for the - // connect phase as well as a "low speed" timeout so if we don't receive - // many bytes in a large-ish period of time then we time out. - handle.connect_timeout(Duration::new(30, 0))?; - handle.low_speed_time(Duration::new(30, 0))?; - handle.low_speed_limit(http_low_speed_limit(config)?)?; +pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult { if let Some(proxy) = http_proxy(config)? { handle.proxy(&proxy)?; } @@ -381,10 +380,6 @@ pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult< if let Some(check) = config.get_bool("http.check-revoke")? { handle.ssl_options(SslOpt::new().no_revoke(!check.val))?; } - if let Some(timeout) = http_timeout(config)? { - handle.connect_timeout(Duration::new(timeout as u64, 0))?; - handle.low_speed_time(Duration::new(timeout as u64, 0))?; - } if let Some(user_agent) = config.get_string("http.user-agent")? { handle.useragent(&user_agent.val)?; } else { @@ -416,15 +411,44 @@ pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult< } })?; } - Ok(()) + + HttpTimeout::new(config) } -/// Find an override from config for curl low-speed-limit option, otherwise use default value -fn http_low_speed_limit(config: &Config) -> CargoResult { - if let Some(s) = config.get::>("http.low-speed-limit")? { - return Ok(s); +#[must_use] +pub struct HttpTimeout { + pub dur: Duration, + pub low_speed_limit: u32, +} + +impl HttpTimeout { + pub fn new(config: &Config) -> CargoResult { + let low_speed_limit = config.get::>("http.low-speed-limit")? + .unwrap_or(10); + let seconds = config.get::>("http.timeout")? + .or_else(|| env::var("HTTP_TIMEOUT").ok().and_then(|s| s.parse().ok())) + .unwrap_or(30); + Ok(HttpTimeout { + dur: Duration::new(seconds, 0), + low_speed_limit, + }) + } + + fn is_non_default(&self) -> bool { + self.dur != Duration::new(30, 0) || self.low_speed_limit != 10 + } + + pub fn configure(&self, handle: &mut Easy) -> CargoResult<()> { + // The timeout option for libcurl by default times out the entire + // transfer, but we probably don't want this. Instead we only set + // timeouts for the connect phase as well as a "low speed" timeout so + // if we don't receive many bytes in a large-ish period of time then we + // time out. + handle.connect_timeout(self.dur)?; + handle.low_speed_time(self.dur)?; + handle.low_speed_limit(self.low_speed_limit)?; + Ok(()) } - Ok(10) } /// Find an explicit HTTP proxy if one is available. @@ -463,13 +487,6 @@ fn http_proxy_exists(config: &Config) -> CargoResult { } } -fn http_timeout(config: &Config) -> CargoResult> { - if let Some(s) = config.get_i64("http.timeout")? { - return Ok(Some(s.val)); - } - Ok(env::var("HTTP_TIMEOUT").ok().and_then(|s| s.parse().ok())) -} - pub fn registry_login(config: &Config, token: String, registry: Option) -> CargoResult<()> { let RegistryConfig { token: old_token, .. diff --git a/src/cargo/util/config.rs b/src/cargo/util/config.rs index 99689e40cf4..cf5b22a0dda 100644 --- a/src/cargo/util/config.rs +++ b/src/cargo/util/config.rs @@ -780,7 +780,8 @@ impl Config { { let mut http = http.borrow_mut(); http.reset(); - ops::configure_http_handle(self, &mut http)?; + let timeout = ops::configure_http_handle(self, &mut http)?; + timeout.configure(&mut http)?; } Ok(http) } diff --git a/src/cargo/util/network.rs b/src/cargo/util/network.rs index 60a629ea4dc..4c3fcace3f2 100644 --- a/src/cargo/util/network.rs +++ b/src/cargo/util/network.rs @@ -47,9 +47,11 @@ fn maybe_spurious(err: &Error) -> bool { } } if let Some(curl_err) = e.downcast_ref::() { - if curl_err.is_couldnt_connect() || curl_err.is_couldnt_resolve_proxy() + if curl_err.is_couldnt_connect() + || curl_err.is_couldnt_resolve_proxy() || curl_err.is_couldnt_resolve_host() - || curl_err.is_operation_timedout() || curl_err.is_recv_error() + || curl_err.is_operation_timedout() + || curl_err.is_recv_error() { return true; } From c9a367c3e8ad06a8054aebf08c29b072bfe85dfe Mon Sep 17 00:00:00 2001 From: Paul Woolcock Date: Sun, 28 Oct 2018 13:50:03 -0400 Subject: [PATCH 004/128] Update docs to be more like a regular local crates.io setup --- src/doc/src/reference/unstable.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index e7c6461165e..d273a91b5ba 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -21,14 +21,14 @@ table: ```toml [registries] -my-registry = { index = "https://my-intranet:8080/index" } +my-registry = { index = "https://my-intranet:8080/git/index" } ``` Authentication information for alternate registries can be added to `.cargo/credentials`: ```toml -[my-registry] +[registries.my-registry] token = "api-token" ``` From d534875fa31fa9cec758e3c4daca5e9de0e70a93 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 28 Oct 2018 11:39:37 -0700 Subject: [PATCH 005/128] Use ANSI escape code to clear line This eliminates the trailing spaces that Cargo used to use for clearing a line of output. Trailing spaces are problematic because they take up space on the next line when reducing the width of a terminal. --- src/cargo/core/shell.rs | 31 +++++++++++++++++++++++++++++++ src/cargo/util/progress.rs | 4 +--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/cargo/core/shell.rs b/src/cargo/core/shell.rs index 77f897d6073..023a87e6562 100644 --- a/src/cargo/core/shell.rs +++ b/src/cargo/core/shell.rs @@ -120,6 +120,13 @@ impl Shell { self.err.as_write() } + /// Erase from cursor to end of line. + pub fn err_erase_line(&mut self) { + if let ShellOut::Stream { tty: true, .. } = self.err { + imp::err_erase_line(self); + } + } + /// Shortcut to right-align and color green a status message. pub fn status(&mut self, status: T, message: U) -> CargoResult<()> where @@ -332,6 +339,8 @@ mod imp { use libc; + use super::Shell; + pub fn stderr_width() -> Option { unsafe { let mut winsize: libc::winsize = mem::zeroed(); @@ -345,10 +354,19 @@ mod imp { } } } + + pub fn err_erase_line(shell: &mut Shell) { + // This is the "EL - Erase in Line" sequence. It clears from the cursor + // to the end of line. + // https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences + let _ = shell.err().write_all(b"\x1B[K"); + } } #[cfg(all(unix, not(any(target_os = "linux", target_os = "macos"))))] mod imp { + pub(super) use super::default_err_erase_line as err_erase_line; + pub fn stderr_width() -> Option { None } @@ -366,6 +384,8 @@ mod imp { use self::winapi::um::wincon::*; use self::winapi::um::winnt::*; + pub(super) use super::default_err_erase_line as err_erase_line; + pub fn stderr_width() -> Option { unsafe { let stdout = GetStdHandle(STD_ERROR_HANDLE); @@ -408,3 +428,14 @@ mod imp { } } } + +#[cfg(any( + all(unix, not(any(target_os = "linux", target_os = "macos"))), + windows, +))] +fn default_err_erase_line(shell: &mut Shell) { + if let Some(max_width) = imp::stderr_width() { + let blank = " ".repeat(max_width); + drop(write!(shell.err(), "{}\r", blank)); + } +} diff --git a/src/cargo/util/progress.rs b/src/cargo/util/progress.rs index c6cedf62191..15347690cd2 100644 --- a/src/cargo/util/progress.rs +++ b/src/cargo/util/progress.rs @@ -196,9 +196,7 @@ impl<'cfg> State<'cfg> { } fn clear(&mut self) { - self.try_update_max_width(); - let blank = " ".repeat(self.format.max_width); - drop(write!(self.config.shell().err(), "{}\r", blank)); + self.config.shell().err_erase_line(); } fn try_update_max_width(&mut self) { From d2acfb66269d542d745c6b3b84480b452dc803f3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 29 Oct 2018 09:14:07 -0700 Subject: [PATCH 006/128] Bump to 0.33.0 --- Cargo.toml | 4 ++-- src/crates-io/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8d2c62b6fbd..0866ce233d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cargo" -version = "0.32.0" +version = "0.33.0" authors = ["Yehuda Katz ", "Carl Lerche ", "Alex Crichton "] @@ -19,7 +19,7 @@ path = "src/cargo/lib.rs" [dependencies] atty = "0.2" bytesize = "1.0" -crates-io = { path = "src/crates-io", version = "0.20" } +crates-io = { path = "src/crates-io", version = "0.21" } crossbeam-utils = "0.5" crypto-hash = "0.3.1" curl = { version = "0.4.17", features = ['http2'] } diff --git a/src/crates-io/Cargo.toml b/src/crates-io/Cargo.toml index 8b0bd9c5207..dc47dedabf0 100644 --- a/src/crates-io/Cargo.toml +++ b/src/crates-io/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "crates-io" -version = "0.20.0" +version = "0.21.0" authors = ["Alex Crichton "] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/cargo" From d4b5038d0615b136fc01dc0c1d844043a936a630 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 29 Oct 2018 11:10:42 -0700 Subject: [PATCH 007/128] Fix `globs` link. --- src/doc/src/reference/manifest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/src/reference/manifest.md b/src/doc/src/reference/manifest.md index 8bc522d1ded..9ff1bce7b22 100644 --- a/src/doc/src/reference/manifest.md +++ b/src/doc/src/reference/manifest.md @@ -125,7 +125,7 @@ The options are mutually exclusive: setting `include` will override an `exclude`. Note that `include` must be an exhaustive list of files as otherwise necessary source files may not be included. -[globs]: http://doc.rust-lang.org/glob/glob/struct.Pattern.html +[globs]: https://docs.rs/glob/0.2.11/glob/struct.Pattern.html #### Migrating to `gitignore`-like pattern matching From 52f45b539754c206a19de5417211cec872f9f52b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 29 Oct 2018 14:55:21 -0700 Subject: [PATCH 008/128] Fix fix_path_deps test error. --- src/cargo/core/compiler/job_queue.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/cargo/core/compiler/job_queue.rs b/src/cargo/core/compiler/job_queue.rs index 1bb654d1f2d..5ee957d7f31 100644 --- a/src/cargo/core/compiler/job_queue.rs +++ b/src/cargo/core/compiler/job_queue.rs @@ -400,6 +400,12 @@ impl<'a> JobQueue<'a> { let res = job.run(fresh, &JobState { tx: my_tx.clone() }); my_tx.send(Message::Finish(key, res)).unwrap(); }; + + if !build_plan { + // Print out some nice progress information + self.note_working_on(config, &key, fresh)?; + } + match fresh { Freshness::Fresh => doit(), Freshness::Dirty => { @@ -407,11 +413,6 @@ impl<'a> JobQueue<'a> { } } - if !build_plan { - // Print out some nice progress information - self.note_working_on(config, &key, fresh)?; - } - Ok(()) } From 6e90641759ef6102c2a696653675ee024116e128 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 30 Oct 2018 18:01:44 -0700 Subject: [PATCH 009/128] Allow usernames in alt registry URLs We want to forbid secrets since they'll commonly end up checked into source control, but usernames are fine (and are commonly going to be `git`). Closes #6241 --- src/cargo/util/config.rs | 4 ++-- tests/testsuite/alt_registry.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cargo/util/config.rs b/src/cargo/util/config.rs index 99689e40cf4..1170176135b 100644 --- a/src/cargo/util/config.rs +++ b/src/cargo/util/config.rs @@ -669,8 +669,8 @@ impl Config { match self.get_string(&format!("registries.{}.index", registry))? { Some(index) => { let url = index.val.to_url()?; - if url.username() != "" || url.password().is_some() { - bail!("Registry URLs may not contain credentials"); + if url.password().is_some() { + bail!("Registry URLs may not contain passwords"); } url } diff --git a/tests/testsuite/alt_registry.rs b/tests/testsuite/alt_registry.rs index b1669fff4db..0893e52cf0f 100644 --- a/tests/testsuite/alt_registry.rs +++ b/tests/testsuite/alt_registry.rs @@ -458,7 +458,7 @@ fn publish_with_crates_io_dep() { } #[test] -fn credentials_in_url_forbidden() { +fn passwords_in_url_forbidden() { registry::init(); let config = paths::home().join(".cargo/config"); @@ -489,6 +489,6 @@ fn credentials_in_url_forbidden() { p.cargo("publish --registry alternative -Zunstable-options") .masquerade_as_nightly_cargo() .with_status(101) - .with_stderr_contains("error: Registry URLs may not contain credentials") + .with_stderr_contains("error: Registry URLs may not contain passwords") .run(); } From 4f784a10d1d1814c271fc8c0ef7798b402435c8d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 1 Nov 2018 08:13:11 -0700 Subject: [PATCH 010/128] Don't turn on edition lints for unfixed crates Currently Cargo runs the risk of turning on the edition lints for crates which `cargo fix` isn't actually fixing, which means you'll get a huge deluge of lints that would otherwise be automatically fixable! Fix this situation by only enabling lints in the same cases that we're actually applying fixes. Closes rust-lang-nursery/rustfix#150 --- src/cargo/ops/fix.rs | 12 ++++++++---- tests/testsuite/fix.rs | 44 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/cargo/ops/fix.rs b/src/cargo/ops/fix.rs index 1dd4ee8ca80..2e09303a1ac 100644 --- a/src/cargo/ops/fix.rs +++ b/src/cargo/ops/fix.rs @@ -165,7 +165,7 @@ pub fn fix_maybe_exec_rustc() -> CargoResult { // not the best heuristic but matches what Cargo does today at least. let mut fixes = FixedCrate::default(); if let Some(path) = &args.file { - if env::var("CARGO_PRIMARY_PACKAGE").is_ok() { + if args.primary_package { trace!("start rustfixing {:?}", path); fixes = rustfix_crate(&lock_addr, rustc.as_ref(), path, &args)?; } @@ -503,6 +503,7 @@ struct FixArgs { idioms: bool, enabled_edition: Option, other: Vec, + primary_package: bool, } enum PrepareFor { @@ -543,6 +544,7 @@ impl FixArgs { ret.prepare_for_edition = PrepareFor::Next; } ret.idioms = env::var(IDIOMS_ENV).is_ok(); + ret.primary_package = env::var("CARGO_PRIMARY_PACKAGE").is_ok(); ret } @@ -554,12 +556,14 @@ impl FixArgs { .arg("--cap-lints=warn"); if let Some(edition) = &self.enabled_edition { cmd.arg("--edition").arg(edition); - if self.idioms { + if self.idioms && self.primary_package { if edition == "2018" { cmd.arg("-Wrust-2018-idioms"); } } } - if let Some(edition) = self.prepare_for_edition_resolve() { - cmd.arg("-W").arg(format!("rust-{}-compatibility", edition)); + if self.primary_package { + if let Some(edition) = self.prepare_for_edition_resolve() { + cmd.arg("-W").arg(format!("rust-{}-compatibility", edition)); + } } } diff --git a/tests/testsuite/fix.rs b/tests/testsuite/fix.rs index dbf1035d8db..d37688368f0 100644 --- a/tests/testsuite/fix.rs +++ b/tests/testsuite/fix.rs @@ -1072,3 +1072,47 @@ fn does_not_crash_with_rustc_wrapper() { .env("RUSTC_WRAPPER", "/usr/bin/env") .run(); } + +#[test] +fn only_warn_for_relevant_crates() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + a = { path = 'a' } + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + "#, + ) + .file( + "a/src/lib.rs", + " + pub fn foo() {} + pub mod bar { + use foo; + pub fn baz() { foo() } + } + ", + ) + .build(); + + p.cargo("fix --allow-no-vcs --edition") + .with_stderr("\ +[CHECKING] a v0.1.0 ([..]) +[CHECKING] foo v0.1.0 ([..]) +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +") + .run(); +} From 7d579483c6141b47dd619d09908941e7b2d1416c Mon Sep 17 00:00:00 2001 From: Brennan Ashton Date: Wed, 31 Oct 2018 13:07:02 -0700 Subject: [PATCH 011/128] Strip angle brackets from author email before passing to template. Some people already have angle brackets around their email in git settings or other author sources. Right now if you create a new project the Cargo.toml would render something like: authors = ["bar <>"] instead of authors = ["bar "] This detects the emails that start and end with <> and removes them. --- src/cargo/ops/cargo_new.rs | 12 +++++++++++- tests/testsuite/new.rs | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/cargo/ops/cargo_new.rs b/src/cargo/ops/cargo_new.rs index bd2bc4073cc..4be3af40a05 100644 --- a/src/cargo/ops/cargo_new.rs +++ b/src/cargo/ops/cargo_new.rs @@ -660,7 +660,17 @@ fn discover_author() -> CargoResult<(String, Option)> { .or_else(|| get_environment_variable(&email_variables[3..])); let name = name.trim().to_string(); - let email = email.map(|s| s.trim().to_string()); + let email = email.map(|s| { + let mut s = s.trim(); + + // In some cases emails will already have <> remove them since they + // are already added when needed. + if s.starts_with("<") && s.ends_with(">") { + s = &s[1..s.len() - 1]; + } + + s.to_string() + }); Ok((name, email)) } diff --git a/tests/testsuite/new.rs b/tests/testsuite/new.rs index 1cdabf7b93d..52e327e36c2 100644 --- a/tests/testsuite/new.rs +++ b/tests/testsuite/new.rs @@ -337,6 +337,23 @@ fn author_prefers_cargo() { assert!(!root.join("foo/.gitignore").exists()); } +#[test] +fn strip_angle_bracket_author_email() { + create_empty_gitconfig(); + cargo_process("new foo") + .env("USER", "bar") + .env("EMAIL", "") + .run(); + + let toml = paths::root().join("foo/Cargo.toml"); + let mut contents = String::new(); + File::open(&toml) + .unwrap() + .read_to_string(&mut contents) + .unwrap(); + assert!(contents.contains(r#"authors = ["bar "]"#)); +} + #[test] fn git_prefers_command_line() { let root = paths::root(); From 3a6788b378d5736bc19335cf5cdf06c7be91741c Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Thu, 18 Oct 2018 10:04:57 -0400 Subject: [PATCH 012/128] move the `ActivateError` to the `errors.rs` and fmt --- src/cargo/core/resolver/context.rs | 19 ++++++++++--------- src/cargo/core/resolver/encode.rs | 3 ++- src/cargo/core/resolver/errors.rs | 21 ++++++++++++++++++++- src/cargo/core/resolver/mod.rs | 21 +++++++++++++-------- src/cargo/core/resolver/types.rs | 22 ++-------------------- 5 files changed, 47 insertions(+), 39 deletions(-) diff --git a/src/cargo/core/resolver/context.rs b/src/cargo/core/resolver/context.rs index b39bbd18f39..d3c5d545e9a 100644 --- a/src/cargo/core/resolver/context.rs +++ b/src/cargo/core/resolver/context.rs @@ -6,8 +6,8 @@ use core::{Dependency, FeatureValue, PackageId, SourceId, Summary}; use util::CargoResult; use util::Graph; -use super::types::RegistryQueryer; -use super::types::{ActivateResult, ConflictReason, DepInfo, GraphNode, Method, RcList}; +use super::types::{ConflictReason, DepInfo, GraphNode, Method, RcList, RegistryQueryer}; +use super::errors::ActivateResult; pub use super::encode::{EncodableDependency, EncodablePackageId, EncodableResolve}; pub use super::encode::{Metadata, WorkspaceResolve}; @@ -186,11 +186,10 @@ impl Context { // name. let base = reqs.deps.get(&dep.name_in_toml()).unwrap_or(&default_dep); used_features.insert(dep.name_in_toml()); - let always_required = !dep.is_optional() - && !s - .dependencies() - .iter() - .any(|d| d.is_optional() && d.name_in_toml() == dep.name_in_toml()); + let always_required = !dep.is_optional() && !s + .dependencies() + .iter() + .any(|d| d.is_optional() && d.name_in_toml() == dep.name_in_toml()); if always_required && base.0 { self.warnings.push(format!( "Package `{}` does not have feature `{}`. It has a required dependency \ @@ -230,11 +229,13 @@ impl Context { "Package `{}` does not have these features: `{}`", s.package_id(), features - ).into(), + ) + .into(), Some(p) => ( p.package_id().clone(), ConflictReason::MissingFeatures(features), - ).into(), + ) + .into(), }); } diff --git a/src/cargo/core/resolver/encode.rs b/src/cargo/core/resolver/encode.rs index 33704ba16a1..c80ce59dfee 100644 --- a/src/cargo/core/resolver/encode.rs +++ b/src/cargo/core/resolver/encode.rs @@ -377,7 +377,8 @@ impl<'a, 'cfg> ser::Serialize for WorkspaceResolve<'a, 'cfg> { root: None, metadata, patch, - }.serialize(s) + } + .serialize(s) } } diff --git a/src/cargo/core/resolver/errors.rs b/src/cargo/core/resolver/errors.rs index 74979c6df09..fbfe5e79e8c 100644 --- a/src/cargo/core/resolver/errors.rs +++ b/src/cargo/core/resolver/errors.rs @@ -4,8 +4,8 @@ use std::fmt; use core::{Dependency, PackageId, Registry, Summary}; use failure::{Error, Fail}; use semver; -use util::config::Config; use util::lev_distance::lev_distance; +use util::{CargoError, Config}; use super::context::Context; use super::types::{Candidate, ConflictReason}; @@ -49,6 +49,25 @@ impl fmt::Display for ResolveError { } } +pub type ActivateResult = Result; + +pub enum ActivateError { + Fatal(CargoError), + Conflict(PackageId, ConflictReason), +} + +impl From<::failure::Error> for ActivateError { + fn from(t: ::failure::Error) -> Self { + ActivateError::Fatal(t) + } +} + +impl From<(PackageId, ConflictReason)> for ActivateError { + fn from(t: (PackageId, ConflictReason)) -> Self { + ActivateError::Conflict(t.0, t.1) + } +} + pub(super) fn activation_error( cx: &Context, registry: &mut Registry, diff --git a/src/cargo/core/resolver/mod.rs b/src/cargo/core/resolver/mod.rs index 196c25016fb..851dcd85b8f 100644 --- a/src/cargo/core/resolver/mod.rs +++ b/src/cargo/core/resolver/mod.rs @@ -62,21 +62,21 @@ use util::errors::CargoResult; use util::profile; use self::context::{Activations, Context}; -use self::types::{ActivateError, ActivateResult, Candidate, ConflictReason, DepsFrame, GraphNode}; +use self::types::{Candidate, ConflictReason, DepsFrame, GraphNode}; use self::types::{RcVecIter, RegistryQueryer, RemainingDeps, ResolverProgress}; pub use self::encode::{EncodableDependency, EncodablePackageId, EncodableResolve}; pub use self::encode::{Metadata, WorkspaceResolve}; +pub use self::errors::{ActivateError, ActivateResult, ResolveError}; pub use self::resolve::Resolve; pub use self::types::Method; -pub use self::errors::ResolveError; mod conflict_cache; mod context; mod encode; +mod errors; mod resolve; mod types; -mod errors; /// Builds the list of all packages required to build the first argument. /// @@ -403,7 +403,8 @@ fn activate_deps_loop( .clone() .filter_map(|(_, (ref new_dep, _, _))| { past_conflicting_activations.conflicting(&cx, new_dep) - }).next() + }) + .next() { // If one of our deps is known unresolvable // then we will not succeed. @@ -438,12 +439,15 @@ fn activate_deps_loop( // for deps related to us .filter(|&(_, ref other_dep)| { known_related_bad_deps.contains(other_dep) - }).filter_map(|(other_parent, other_dep)| { + }) + .filter_map(|(other_parent, other_dep)| { past_conflicting_activations .find_conflicting(&cx, &other_dep, |con| { con.contains_key(&pid) - }).map(|con| (other_parent, con)) - }).next() + }) + .map(|con| (other_parent, con)) + }) + .next() { let rel = conflict.get(&pid).unwrap().clone(); @@ -485,7 +489,8 @@ fn activate_deps_loop( &parent, backtracked, &conflicting_activations, - ).is_none() + ) + .is_none() } }; diff --git a/src/cargo/core/resolver/types.rs b/src/cargo/core/resolver/types.rs index b9494546db7..0f39783a99e 100644 --- a/src/cargo/core/resolver/types.rs +++ b/src/cargo/core/resolver/types.rs @@ -6,7 +6,8 @@ use std::time::{Duration, Instant}; use core::interning::InternedString; use core::{Dependency, PackageId, PackageIdSpec, Registry, Summary}; -use util::{CargoError, CargoResult, Config}; +use util::errors::CargoResult; +use util::Config; pub struct ResolverProgress { ticks: u16, @@ -348,25 +349,6 @@ impl RemainingDeps { // (dependency info, candidates, features activated) pub type DepInfo = (Dependency, Rc>, Rc>); -pub type ActivateResult = Result; - -pub enum ActivateError { - Fatal(CargoError), - Conflict(PackageId, ConflictReason), -} - -impl From<::failure::Error> for ActivateError { - fn from(t: ::failure::Error) -> Self { - ActivateError::Fatal(t) - } -} - -impl From<(PackageId, ConflictReason)> for ActivateError { - fn from(t: (PackageId, ConflictReason)) -> Self { - ActivateError::Conflict(t.0, t.1) - } -} - /// All possible reasons that a package might fail to activate. /// /// We maintain a list of conflicts for error reporting as well as backtracking From cccf8170f85cbf34bfaffbdda2c50283b136187d Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Sun, 7 Oct 2018 21:02:36 -0400 Subject: [PATCH 013/128] generate Build deps, don't bother with Development deps. --- tests/testsuite/support/resolver.rs | 50 +++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/tests/testsuite/support/resolver.rs b/tests/testsuite/support/resolver.rs index 9b97daf0b0e..43f8bf65b77 100644 --- a/tests/testsuite/support/resolver.rs +++ b/tests/testsuite/support/resolver.rs @@ -235,6 +235,11 @@ pub fn dep(name: &str) -> Dependency { pub fn dep_req(name: &str, req: &str) -> Dependency { Dependency::parse_no_deprecated(name, Some(req), ®istry_loc()).unwrap() } +pub fn dep_req_kind(name: &str, req: &str, kind: Kind) -> Dependency { + let mut dep = dep_req(name, req); + dep.set_kind(kind); + dep +} pub fn dep_loc(name: &str, location: &str) -> Dependency { let url = location.to_url().unwrap(); @@ -277,12 +282,26 @@ impl fmt::Debug for PrettyPrintRegistry { } else { write!(f, "pkg!((\"{}\", \"{}\") => [", s.name(), s.version())?; for d in s.dependencies() { - write!( - f, - "dep_req(\"{}\", \"{}\"),", - d.name_in_toml(), - d.version_req() - )?; + if d.kind() == Kind::Normal { + write!( + f, + "dep_req(\"{}\", \"{}\"),", + d.name_in_toml(), + d.version_req() + )?; + } else { + write!( + f, + "dep_req_kind(\"{}\", \"{}\", {}),", + d.name_in_toml(), + d.version_req(), + match d.kind() { + Kind::Development => "Kind::Development", + Kind::Build => "Kind::Build", + Kind::Normal => "Kind::Normal", + } + )?; + } } write!(f, "]),")?; } @@ -304,6 +323,8 @@ fn meta_test_deep_pretty_print_registry() { pkg!(("bar", "2.0.0") => [dep_req("baz", "=1.0.1")]), pkg!(("baz", "1.0.2") => [dep_req("other", "2")]), pkg!(("baz", "1.0.1")), + pkg!(("cat", "1.0.2") => [dep_req_kind("other", "2", Kind::Build)]), + pkg!(("cat", "1.0.2") => [dep_req_kind("other", "2", Kind::Development)]), pkg!(("dep_req", "1.0.0")), pkg!(("dep_req", "2.0.0")), ]) @@ -313,7 +334,10 @@ fn meta_test_deep_pretty_print_registry() { pkg!((\"bar\", \"1.0.0\") => [dep_req(\"baz\", \"= 1.0.2\"),dep_req(\"other\", \"^1\"),]),\ pkg!((\"bar\", \"2.0.0\") => [dep_req(\"baz\", \"= 1.0.1\"),]),\ pkg!((\"baz\", \"1.0.2\") => [dep_req(\"other\", \"^2\"),]),\ - pkg!((\"baz\", \"1.0.1\")),pkg!((\"dep_req\", \"1.0.0\")),\ + pkg!((\"baz\", \"1.0.1\")),\ + pkg!((\"cat\", \"1.0.2\") => [dep_req_kind(\"other\", \"^2\", Kind::Build),]),\ + pkg!((\"cat\", \"1.0.2\") => [dep_req_kind(\"other\", \"^2\", Kind::Development),]),\ + pkg!((\"dep_req\", \"1.0.0\")),\ pkg!((\"dep_req\", \"2.0.0\")),]" ) } @@ -357,7 +381,7 @@ pub fn registry_strategy( let max_deps = max_versions * (max_crates * (max_crates - 1)) / shrinkage; let raw_version_range = (any::(), any::()); - let raw_dependency = (any::(), any::(), raw_version_range); + let raw_dependency = (any::(), any::(), raw_version_range, 0..=1); fn order_index(a: Index, b: Index, size: usize) -> (usize, usize) { let (a, b) = (a.index(size), b.index(size)); @@ -374,7 +398,7 @@ pub fn registry_strategy( .collect(); let len_all_pkgid = list_of_pkgid.len(); let mut dependency_by_pkgid = vec![vec![]; len_all_pkgid]; - for (a, b, (c, d)) in raw_dependencies { + for (a, b, (c, d), k) in raw_dependencies { let (a, b) = order_index(a, b, len_all_pkgid); let ((dep_name, _), _) = list_of_pkgid[a]; if (list_of_pkgid[b].0).0 == dep_name { @@ -383,13 +407,19 @@ pub fn registry_strategy( let s = &crate_vers_by_name[dep_name]; let (c, d) = order_index(c, d, s.len()); - dependency_by_pkgid[b].push(dep_req( + dependency_by_pkgid[b].push(dep_req_kind( &dep_name, &if c == d { format!("={}", s[c].0) } else { format!(">={}, <={}", s[c].0, s[d].0) }, + match k { + 0 => Kind::Normal, + 1 => Kind::Build, + // => Kind::Development, + _ => panic!("bad index for Kind"), + }, )) } From 71bb4619849a6c424751c934160361e62e8f2e3b Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Sun, 14 Oct 2018 21:39:30 -0400 Subject: [PATCH 014/128] Bring back `Graph::sort` so we can use it in tests This reverts commit a26676a --- src/cargo/core/resolver/resolve.rs | 4 ++++ src/cargo/util/graph.rs | 26 +++++++++++++++++++++++++- tests/testsuite/support/resolver.rs | 5 ++--- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/cargo/core/resolver/resolve.rs b/src/cargo/core/resolver/resolve.rs index dff80107f07..14e37c54447 100644 --- a/src/cargo/core/resolver/resolve.rs +++ b/src/cargo/core/resolver/resolve.rs @@ -171,6 +171,10 @@ unable to verify that `{0}` is the same as when the lockfile was generated self.graph.contains(k) } + pub fn sort(&self) -> Vec { + self.graph.sort() + } + pub fn iter(&self) -> impl Iterator { self.graph.iter() } diff --git a/src/cargo/util/graph.rs b/src/cargo/util/graph.rs index 78aa2b93f16..50df74f873e 100644 --- a/src/cargo/util/graph.rs +++ b/src/cargo/util/graph.rs @@ -1,5 +1,5 @@ use std::borrow::Borrow; -use std::collections::hash_map::HashMap; +use std::collections::{HashMap, HashSet}; use std::fmt; use std::hash::Hash; @@ -42,6 +42,30 @@ impl Graph { self.nodes.get(from).into_iter().flat_map(|x| x.iter()) } + /// A topological sort of the `Graph` + pub fn sort(&self) -> Vec { + let mut ret = Vec::new(); + let mut marks = HashSet::new(); + + for node in self.nodes.keys() { + self.sort_inner_visit(node, &mut ret, &mut marks); + } + + ret + } + + fn sort_inner_visit(&self, node: &N, dst: &mut Vec, marks: &mut HashSet) { + if !marks.insert(node.clone()) { + return; + } + + for child in self.nodes[node].keys() { + self.sort_inner_visit(child, dst, marks); + } + + dst.push(node.clone()); + } + pub fn iter(&self) -> impl Iterator { self.nodes.keys() } diff --git a/tests/testsuite/support/resolver.rs b/tests/testsuite/support/resolver.rs index 43f8bf65b77..7aa3cebca71 100644 --- a/tests/testsuite/support/resolver.rs +++ b/tests/testsuite/support/resolver.rs @@ -50,7 +50,7 @@ pub fn resolve_and_validated( })); } } - let out: Vec = resolve.iter().cloned().collect(); + let out = resolve.sort(); assert_eq!(out.len(), used.len()); Ok(out) } @@ -62,8 +62,7 @@ pub fn resolve_with_config( config: Option<&Config>, ) -> CargoResult> { let resolve = resolve_with_config_raw(pkg, deps, registry, config)?; - let out: Vec = resolve.iter().cloned().collect(); - Ok(out) + Ok(resolve.sort()) } pub fn resolve_with_config_raw( From 9955f8216248255717ed3488e3cf5cdfd6a24121 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Thu, 18 Oct 2018 14:50:46 -0400 Subject: [PATCH 015/128] the simplest kind of dep is a "*", so change the default --- tests/testsuite/resolve.rs | 58 ++++++++++++++--------------- tests/testsuite/support/resolver.rs | 21 +++++++++-- 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/tests/testsuite/resolve.rs b/tests/testsuite/resolve.rs index afe06f5fe58..7afd1f4cac8 100644 --- a/tests/testsuite/resolve.rs +++ b/tests/testsuite/resolve.rs @@ -1,14 +1,14 @@ use std::env; -use cargo::core::dependency::Kind::Development; +use cargo::core::dependency::Kind; use cargo::core::{enable_nightly_features, Dependency}; use cargo::util::Config; use support::project; use support::registry::Package; use support::resolver::{ - assert_contains, assert_same, dep, dep_kind, dep_loc, dep_req, loc_names, names, pkg, pkg_dep, - pkg_id, pkg_loc, registry, registry_strategy, resolve, resolve_and_validated, + assert_contains, assert_same, dep, dep_kind, dep_loc, dep_req, loc_names, names, + pkg, pkg_dep, pkg_id, pkg_loc, registry, registry_strategy, resolve, resolve_and_validated, resolve_with_config, PrettyPrintRegistry, ToDep, ToPkgId, }; @@ -219,15 +219,15 @@ fn test_resolving_with_same_name() { #[test] fn test_resolving_with_dev_deps() { let reg = registry(vec![ - pkg!("foo" => ["bar", dep_kind("baz", Development)]), - pkg!("baz" => ["bat", dep_kind("bam", Development)]), + pkg!("foo" => ["bar", dep_kind("baz", Kind::Development)]), + pkg!("baz" => ["bat", dep_kind("bam", Kind::Development)]), pkg!("bar"), pkg!("bat"), ]); let res = resolve( &pkg_id("root"), - vec![dep("foo"), dep_kind("baz", Development)], + vec![dep("foo"), dep_kind("baz", Kind::Development)], ®, ) .unwrap(); @@ -598,13 +598,13 @@ fn resolving_with_many_equivalent_backtracking() { let next = format!("level{}", l + 1); for i in 1..BRANCHING_FACTOR { let vsn = format!("1.0.{}", i); - reglist.push(pkg!((name.as_str(), vsn.as_str()) => [dep_req(next.as_str(), "*")])); + reglist.push(pkg!((name.as_str(), vsn.as_str()) => [dep(next.as_str())])); } } let reg = registry(reglist.clone()); - let res = resolve(&pkg_id("root"), vec![dep_req("level0", "*")], ®); + let res = resolve(&pkg_id("root"), vec![dep("level0")], ®); assert!(res.is_err()); @@ -614,7 +614,7 @@ fn resolving_with_many_equivalent_backtracking() { let reg = registry(reglist.clone()); - let res = resolve(&pkg_id("root"), vec![dep_req("level0", "*")], ®).unwrap(); + let res = resolve(&pkg_id("root"), vec![dep("level0")], ®).unwrap(); assert_contains(&res, &names(&[("root", "1.0.0"), ("level0", "1.0.0")])); @@ -629,7 +629,7 @@ fn resolving_with_many_equivalent_backtracking() { let res = resolve( &pkg_id("root"), - vec![dep_req("level0", "*"), dep_req("constrained", "*")], + vec![dep("level0"), dep("constrained")], ®, ) .unwrap(); @@ -647,7 +647,7 @@ fn resolving_with_many_equivalent_backtracking() { let res = resolve( &pkg_id("root"), - vec![dep_req("level0", "1.0.1"), dep_req("constrained", "*")], + vec![dep_req("level0", "1.0.1"), dep("constrained")], ®, ) .unwrap(); @@ -686,7 +686,7 @@ fn resolving_with_deep_traps() { let next = format!("backtrack_trap{}", l + 1); for i in 1..BRANCHING_FACTOR { let vsn = format!("1.0.{}", i); - reglist.push(pkg!((name.as_str(), vsn.as_str()) => [dep_req(next.as_str(), "*")])); + reglist.push(pkg!((name.as_str(), vsn.as_str()) => [dep(next.as_str())])); } } { @@ -708,7 +708,7 @@ fn resolving_with_deep_traps() { let res = resolve( &pkg_id("root"), - vec![dep_req("backtrack_trap0", "*"), dep_req("cloaking", "*")], + vec![dep("backtrack_trap0"), dep("cloaking")], ®, ); @@ -729,7 +729,7 @@ fn resolving_with_constrained_cousins_backtrack() { let next = format!("backtrack_trap{}", l + 1); for i in 1..BRANCHING_FACTOR { let vsn = format!("1.0.{}", i); - reglist.push(pkg!((name.as_str(), vsn.as_str()) => [dep_req(next.as_str(), "*")])); + reglist.push(pkg!((name.as_str(), vsn.as_str()) => [dep(next.as_str())])); } } { @@ -761,9 +761,9 @@ fn resolving_with_constrained_cousins_backtrack() { let res = resolve( &pkg_id("root"), vec![ - dep_req("backtrack_trap0", "*"), + dep("backtrack_trap0"), dep_req("constrained", "2.0.1"), - dep_req("cloaking", "*"), + dep("cloaking"), ], ®, ); @@ -777,12 +777,12 @@ fn resolving_with_constrained_cousins_backtrack() { let next = format!("level{}", l + 1); for i in 1..BRANCHING_FACTOR { let vsn = format!("1.0.{}", i); - reglist.push(pkg!((name.as_str(), vsn.as_str()) => [dep_req(next.as_str(), "*")])); + reglist.push(pkg!((name.as_str(), vsn.as_str()) => [dep(next.as_str())])); } } reglist.push( - pkg!((format!("level{}", DEPTH).as_str(), "1.0.0") => [dep_req("backtrack_trap0", "*"), - dep_req("cloaking", "*") + pkg!((format!("level{}", DEPTH).as_str(), "1.0.0") => [dep("backtrack_trap0"), + dep("cloaking") ]), ); @@ -790,7 +790,7 @@ fn resolving_with_constrained_cousins_backtrack() { let res = resolve( &pkg_id("root"), - vec![dep_req("level0", "*"), dep_req("constrained", "2.0.1")], + vec![dep("level0"), dep_req("constrained", "2.0.1")], ®, ); @@ -798,7 +798,7 @@ fn resolving_with_constrained_cousins_backtrack() { let res = resolve( &pkg_id("root"), - vec![dep_req("level0", "*"), dep_req("constrained", "2.0.0")], + vec![dep("level0"), dep_req("constrained", "2.0.0")], ®, ) .unwrap(); @@ -985,7 +985,7 @@ fn incomplete_information_skiping_2() { dep("bad"), ]), pkg!(("h", "3.8.3") => [ - dep_req("g", "*"), + dep("g"), ]), pkg!(("h", "6.8.3") => [ dep("f"), @@ -994,10 +994,10 @@ fn incomplete_information_skiping_2() { dep_req("to_yank", "=8.8.1"), ]), pkg!("i" => [ - dep_req("b", "*"), - dep_req("c", "*"), - dep_req("e", "*"), - dep_req("h", "*"), + dep("b"), + dep("c"), + dep("e"), + dep("h"), ]), ]; let reg = registry(input.clone()); @@ -1043,7 +1043,7 @@ fn incomplete_information_skiping_3() { ] }, pkg!{("b", "2.0.2") => [ dep_req("to_yank", "3.3.0"), - dep_req("a", "*"), + dep("a"), ] }, pkg!{("b", "2.3.3") => [ dep_req("to_yank", "3.3.0"), @@ -1052,7 +1052,7 @@ fn incomplete_information_skiping_3() { ]; let reg = registry(input.clone()); - let res = resolve(&pkg_id("root"), vec![dep_req("b", "*")], ®).unwrap(); + let res = resolve(&pkg_id("root"), vec![dep("b")], ®).unwrap(); let package_to_yank = ("to_yank", "3.0.3").to_pkgid(); // this package is not used in the resolution. assert!(!res.contains(&package_to_yank)); @@ -1066,7 +1066,7 @@ fn incomplete_information_skiping_3() { ); assert_eq!(input.len(), new_reg.len() + 1); // it should still build - assert!(resolve(&pkg_id("root"), vec![dep_req("b", "*")], &new_reg).is_ok()); + assert!(resolve(&pkg_id("root"), vec![dep("b")], &new_reg).is_ok()); } #[test] diff --git a/tests/testsuite/support/resolver.rs b/tests/testsuite/support/resolver.rs index 7aa3cebca71..ae89eaf71f9 100644 --- a/tests/testsuite/support/resolver.rs +++ b/tests/testsuite/support/resolver.rs @@ -229,7 +229,7 @@ pub fn pkg_loc(name: &str, loc: &str) -> Summary { } pub fn dep(name: &str) -> Dependency { - dep_req(name, "1.0.0") + dep_req(name, "*") } pub fn dep_req(name: &str, req: &str) -> Dependency { Dependency::parse_no_deprecated(name, Some(req), ®istry_loc()).unwrap() @@ -281,7 +281,11 @@ impl fmt::Debug for PrettyPrintRegistry { } else { write!(f, "pkg!((\"{}\", \"{}\") => [", s.name(), s.version())?; for d in s.dependencies() { - if d.kind() == Kind::Normal { + if d.kind() == Kind::Normal + && &d.version_req().to_string() == "*" + { + write!(f, "dep(\"{}\"),", d.name_in_toml())?; + } else if d.kind() == Kind::Normal { write!( f, "dep_req(\"{}\", \"{}\"),", @@ -317,6 +321,7 @@ fn meta_test_deep_pretty_print_registry() { PrettyPrintRegistry(vec![ pkg!(("foo", "1.0.1") => [dep_req("bar", "1")]), pkg!(("foo", "1.0.0") => [dep_req("bar", "2")]), + pkg!(("foo", "2.0.0") => [dep_req("bar", "*")]), pkg!(("bar", "1.0.0") => [dep_req("baz", "=1.0.2"), dep_req("other", "1")]), pkg!(("bar", "2.0.0") => [dep_req("baz", "=1.0.1")]), @@ -330,6 +335,7 @@ fn meta_test_deep_pretty_print_registry() { ), "vec![pkg!((\"foo\", \"1.0.1\") => [dep_req(\"bar\", \"^1\"),]),\ pkg!((\"foo\", \"1.0.0\") => [dep_req(\"bar\", \"^2\"),]),\ + pkg!((\"foo\", \"2.0.0\") => [dep(\"bar\"),]),\ pkg!((\"bar\", \"1.0.0\") => [dep_req(\"baz\", \"= 1.0.2\"),dep_req(\"other\", \"^1\"),]),\ pkg!((\"bar\", \"2.0.0\") => [dep_req(\"baz\", \"= 1.0.1\"),]),\ pkg!((\"baz\", \"1.0.2\") => [dep_req(\"other\", \"^2\"),]),\ @@ -404,11 +410,18 @@ pub fn registry_strategy( continue; } let s = &crate_vers_by_name[dep_name]; + let s_last_index = s.len() - 1; let (c, d) = order_index(c, d, s.len()); dependency_by_pkgid[b].push(dep_req_kind( &dep_name, - &if c == d { + &if c == 0 && d == s_last_index { + "*".to_string() + } else if c == 0 { + format!("<={}", s[d].0) + } else if d == s_last_index { + format!(">={}", s[c].0) + } else if c == d { format!("={}", s[c].0) } else { format!(">={}, <={}", s[c].0, s[d].0) @@ -416,7 +429,7 @@ pub fn registry_strategy( match k { 0 => Kind::Normal, 1 => Kind::Build, - // => Kind::Development, + // => Kind::Development, // Development has not impact so don't gen _ => panic!("bad index for Kind"), }, )) From 20f55af20f7df663850ab758c826a73dda0212ff Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Thu, 1 Nov 2018 22:06:16 -0400 Subject: [PATCH 016/128] test that minimal-versions errors on the same input as normal resolution --- tests/testsuite/resolve.rs | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/testsuite/resolve.rs b/tests/testsuite/resolve.rs index 7afd1f4cac8..9ce7ccc4e42 100644 --- a/tests/testsuite/resolve.rs +++ b/tests/testsuite/resolve.rs @@ -33,6 +33,7 @@ proptest! { }, .. ProptestConfig::default() })] + #[test] fn passes_validation( PrettyPrintRegistry(input) in registry_strategy(50, 20, 60) @@ -49,6 +50,56 @@ proptest! { ); } } + + #[test] + fn minimum_version_errors_the_same( + PrettyPrintRegistry(input) in registry_strategy(50, 20, 60) + ) { + enable_nightly_features(); + + let mut config = Config::default().unwrap(); + config + .configure( + 1, + None, + &None, + false, + false, + &None, + &["minimal-versions".to_string()], + ) + .unwrap(); + + let reg = registry(input.clone()); + // there is only a small chance that eny one + // crate will be interesting. + // So we try some of the most complicated. + for this in input.iter().rev().take(10) { + // minimal-versions change what order the candidates + // are tried but not the existence of a solution + let res = resolve( + &pkg_id("root"), + vec![dep_req(&this.name(), &format!("={}", this.version()))], + ®, + ); + + let mres = resolve_with_config( + &pkg_id("root"), + vec![dep_req(&this.name(), &format!("={}", this.version()))], + ®, + Some(&config), + ); + + prop_assert_eq!( + res.is_ok(), + mres.is_ok(), + "minimal-versions and regular resolver disagree about weather `{} = \"={}\"` can resolve", + this.name(), + this.version() + ) + } + } + #[test] fn limited_independence_of_irrelevant_alternatives( PrettyPrintRegistry(input) in registry_strategy(50, 20, 60), From e307f047a00a0f1a8da490d68125c3c0ea45fc8b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 2 Nov 2018 07:07:48 -0700 Subject: [PATCH 017/128] Pass `--update-head-ok` when fetching via git CLI Discovered in a recent [comment] it looks like not passing this may cause the git CLI to fail in some situations. [comment]: https://github.com/rust-lang/cargo/issues/2078#issuecomment-435333292 --- src/cargo/sources/git/utils.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs index 66301c1da1b..65ae5db2702 100644 --- a/src/cargo/sources/git/utils.rs +++ b/src/cargo/sources/git/utils.rs @@ -755,6 +755,7 @@ fn fetch_with_cli( cmd.arg("fetch") .arg("--tags") // fetch all tags .arg("--quiet") + .arg("--update-head-ok") // see discussion in #2078 .arg(url.to_string()) .arg(refspec) .cwd(repo.path()); From 2a4cdc677c7dd093888bf9ff5e3ceb4f7604895d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 2 Nov 2018 07:46:11 -0700 Subject: [PATCH 018/128] Never use templates when managing git repos This commit disables usage of git templates whenever Cargo manages repositories in its internal git database. Templates don't want to be used at all in these situations and have been known to cause usability bugs. Closes #6240 --- src/cargo/sources/git/utils.rs | 22 +++++++++++------ tests/testsuite/git.rs | 45 ++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs index 66301c1da1b..4722dc2ce97 100644 --- a/src/cargo/sources/git/utils.rs +++ b/src/cargo/sources/git/utils.rs @@ -146,7 +146,7 @@ impl GitRemote { paths::remove_dir_all(dst)?; } fs::create_dir_all(dst)?; - let mut repo = git2::Repository::init_bare(dst)?; + let mut repo = init(dst, true)?; fetch( &mut repo, &self.url, @@ -385,7 +385,7 @@ impl<'a> GitCheckout<'a> { Err(..) => { let path = parent.workdir().unwrap().join(child.path()); let _ = paths::remove_dir_all(&path); - git2::Repository::init(&path)? + init(&path, false)? } }; @@ -833,7 +833,7 @@ fn reinitialize(repo: &mut git2::Repository) -> CargoResult<()> { debug!("reinitializing git repo at {:?}", path); let tmp = path.join("tmp"); let bare = !repo.path().ends_with(".git"); - *repo = git2::Repository::init(&tmp)?; + *repo = init(&tmp, false)?; for entry in path.read_dir()? { let entry = entry?; if entry.file_name().to_str() == Some("tmp") { @@ -842,15 +842,21 @@ fn reinitialize(repo: &mut git2::Repository) -> CargoResult<()> { let path = entry.path(); drop(paths::remove_file(&path).or_else(|_| paths::remove_dir_all(&path))); } - if bare { - *repo = git2::Repository::init_bare(path)?; - } else { - *repo = git2::Repository::init(path)?; - } + *repo = init(&path, bare)?; paths::remove_dir_all(&tmp)?; Ok(()) } +fn init(path: &Path, bare: bool) -> CargoResult { + let mut opts = git2::RepositoryInitOptions::new(); + // Skip anyting related to templates, they just call all sorts of issues as + // we really don't want to use them yet they insist on being used. See #6240 + // for an example issue that comes up. + opts.external_template(false); + opts.bare(bare); + Ok(git2::Repository::init_opts(&path, &opts)?) +} + /// Updating the index is done pretty regularly so we want it to be as fast as /// possible. For registries hosted on GitHub (like the crates.io index) there's /// a fast path available to use [1] to tell us that there's no updates to be diff --git a/tests/testsuite/git.rs b/tests/testsuite/git.rs index 2e4d4633903..ea89a964bdc 100644 --- a/tests/testsuite/git.rs +++ b/tests/testsuite/git.rs @@ -2625,3 +2625,48 @@ fn use_the_cli() { project.cargo("build -v").with_stderr(stderr).run(); } + +#[test] +fn templatedir_doesnt_cause_problems() { + let git_project2 = git::new("dep2", |project| { + project + .file("Cargo.toml", &basic_manifest("dep2", "0.5.0")) + .file("src/lib.rs", "") + }).unwrap(); + let git_project = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_manifest("dep1", "0.5.0")) + .file("src/lib.rs", "") + }).unwrap(); + let p = project() + .file( + "Cargo.toml", + &format!(r#" + [project] + name = "fo" + version = "0.5.0" + authors = [] + + [dependencies] + dep1 = {{ git = '{}' }} + "#, git_project.url()), + ).file("src/main.rs", "fn main() {}") + .build(); + + File::create(paths::home().join(".gitconfig")) + .unwrap() + .write_all( + &format!(r#" + [init] + templatedir = {} + "#, git_project2.url() + .to_file_path() + .unwrap() + .to_str() + .unwrap() + .replace("\\", "/") + ).as_bytes(), + ).unwrap(); + + p.cargo("build").run(); +} From 20b5ca3dec3384366e85a37eb3adaccd05ffeec3 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 2 Nov 2018 15:18:17 -0700 Subject: [PATCH 019/128] Fix slow MacOS Travis issue. --- .travis.yml | 1 + tests/testsuite/metabuild.rs | 11 ++++++++++- tests/testsuite/support/mod.rs | 22 +++++++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a3fdd804fb8..a421a7b9334 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,7 @@ matrix: - env: TARGET=x86_64-apple-darwin ALT=i686-apple-darwin os: osx + osx_image: xcode9.2 if: branch != master OR type = pull_request - env: TARGET=x86_64-unknown-linux-gnu diff --git a/tests/testsuite/metabuild.rs b/tests/testsuite/metabuild.rs index 6420edac657..c96f0c4b6b6 100644 --- a/tests/testsuite/metabuild.rs +++ b/tests/testsuite/metabuild.rs @@ -2,7 +2,8 @@ use glob::glob; use serde_json; use std::str; use support::{ - basic_lib_manifest, basic_manifest, project, registry::Package, rustc_host, Project, + basic_lib_manifest, basic_manifest, is_coarse_mtime, project, registry::Package, rustc_host, + Project, }; #[test] @@ -212,6 +213,14 @@ fn metabuild_lib_name() { #[test] fn metabuild_fresh() { + if is_coarse_mtime() { + // This test doesn't work on coarse mtimes very well. Because the + // metabuild script is created at build time, its mtime is almost + // always equal to the mtime of the output. The second call to `build` + // will then think it needs to be rebuilt when it should be fresh. + return; + } + // Check that rebuild is fresh. let p = project() .file( diff --git a/tests/testsuite/support/mod.rs b/tests/testsuite/support/mod.rs index f9ddb5380b4..9d818070ce6 100644 --- a/tests/testsuite/support/mod.rs +++ b/tests/testsuite/support/mod.rs @@ -113,11 +113,12 @@ use std::os; use std::path::{Path, PathBuf}; use std::process::{Command, Output}; use std::str; -use std::time::Duration; +use std::time::{self, Duration}; use std::usize; use cargo; use cargo::util::{CargoResult, ProcessBuilder, ProcessError, Rustc}; +use filetime; use serde_json::{self, Value}; use url::Url; @@ -279,8 +280,19 @@ impl ProjectBuilder { self._file(Path::new("Cargo.toml"), &basic_manifest("foo", "0.0.1")) } + let past = time::SystemTime::now() - Duration::new(1, 0); + let ftime = filetime::FileTime::from_system_time(past); + for file in self.files.iter() { file.mk(); + if is_coarse_mtime() { + // Place the entire project 1 second in the past to ensure + // that if cargo is called multiple times, the 2nd call will + // see targets as "fresh". Without this, if cargo finishes in + // under 1 second, the second call will see the mtime of + // source == mtime of output and consider it dirty. + filetime::set_file_times(&file.path, ftime, ftime).unwrap(); + } } for symlink in self.symlinks.iter() { @@ -1510,3 +1522,11 @@ pub fn git_process(s: &str) -> ProcessBuilder { pub fn sleep_ms(ms: u64) { ::std::thread::sleep(Duration::from_millis(ms)); } + +/// Returns true if the local filesystem has low-resolution mtimes. +pub fn is_coarse_mtime() -> bool { + // This should actually be a test that $CARGO_TARGET_DIR is on an HFS + // filesystem, (or any filesystem with low-resolution mtimes). However, + // that's tricky to detect, so for now just deal with CI. + cfg!(target_os = "macos") && env::var("CI").is_ok() +} From a1f241a3c63b4f5340ee214c3f97ff57001b317f Mon Sep 17 00:00:00 2001 From: eV Date: Sat, 3 Nov 2018 07:42:32 +0000 Subject: [PATCH 020/128] Tweak Layout to allow for non json file targets with internal "." --- src/cargo/core/compiler/layout.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/cargo/core/compiler/layout.rs b/src/cargo/core/compiler/layout.rs index d7a3e441304..233c23d5e68 100644 --- a/src/cargo/core/compiler/layout.rs +++ b/src/cargo/core/compiler/layout.rs @@ -86,13 +86,20 @@ impl Layout { /// adding the target triple and the profile (debug, release, ...). pub fn new(ws: &Workspace, triple: Option<&str>, dest: &str) -> CargoResult { let mut path = ws.target_dir(); - // Flexible target specifications often point at filenames, so interpret + // Flexible target specifications often point at json files, so interpret // the target triple as a Path and then just use the file stem as the - // component for the directory name. + // component for the directory name in that case. if let Some(triple) = triple { - path.push(Path::new(triple) - .file_stem() - .ok_or_else(|| format_err!("invalid target"))?); + let triple = Path::new(triple); + if triple.extension().and_then(|s| s.to_str()) == Some("json") { + path.push( + triple + .file_stem() + .ok_or_else(|| format_err!("invalid target"))?, + ); + } else { + path.push(triple); + } } path.push(dest); Layout::at(ws.config(), path) From 541e990681bc0c059a5fe8b32f60d87d00875de0 Mon Sep 17 00:00:00 2001 From: Khionu Sybiern Date: Sat, 3 Nov 2018 17:29:00 -0400 Subject: [PATCH 021/128] Configure tar to not set mtime Signed-off-by: Khionu Sybiern --- Cargo.toml | 4 ++++ src/cargo/ops/cargo_package.rs | 3 +++ 2 files changed, 7 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 0866ce233d6..c2f5ee2dede 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,10 @@ openssl = { version = '0.10.11', optional = true } # for more information. rustc-workspace-hack = "1.0.0" +# TODO: This patch will be removed before PR merge, when tar has a release containing this patch +[patch.crates-io] +tar = { git = "https://github.com/alexcrichton/tar-rs", rev = "f442964" } + [target.'cfg(target_os = "macos")'.dependencies] core-foundation = { version = "0.6.0", features = ["mac_os_10_7_support"] } diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index 2b062840d6e..37c82238ad5 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -418,6 +418,9 @@ fn run_verify(ws: &Workspace, tar: &FileLock, opts: &PackageOpts) -> CargoResult paths::remove_dir_all(&dst)?; } let mut archive = Archive::new(f); + // We don't need to set the Modified Time, as it's not relevant to verification + // and it errors on filesystems that don't support setting a modified timestamp + archive.set_preserve_mtime(false); archive.unpack(dst.parent().unwrap())?; // Manufacture an ephemeral workspace to ensure that even if the top-level From dd998a096b0e04bea7d84a8e975d84d820b725f0 Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Sun, 4 Nov 2018 08:59:20 -0800 Subject: [PATCH 022/128] Fix package::include/exclude tests so they work even if running them not in cargo.git --- tests/testsuite/package.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index b9c1cae0451..d34951f89b8 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -285,7 +285,8 @@ dependency `bar` does not specify a version. #[test] fn exclude() { - let p = project() + let root = paths::root().join("exclude"); + let repo = git::repo(&root) .file("Cargo.toml", r#" [project] name = "foo" @@ -348,7 +349,8 @@ fn exclude() { .file("some_dir/dir_deep_5/some_dir/file", "") .build(); - p.cargo("package --no-verify -v") + cargo_process("package --no-verify -v") + .cwd(repo.root()) .with_stdout("") .with_stderr( "\ @@ -366,7 +368,6 @@ See [..] See [..] [WARNING] [..] file `some_dir/file_deep_1` WILL be excluded [..] See [..] -[WARNING] No (git) Cargo.toml found at `[..]` in workdir `[..]` [PACKAGING] foo v0.0.1 ([..]) [ARCHIVING] [..] [ARCHIVING] [..] @@ -386,14 +387,17 @@ See [..] [ARCHIVING] [..] [ARCHIVING] [..] [ARCHIVING] [..] +[ARCHIVING] .cargo_vcs_info.json ", ).run(); - assert!(p.root().join("target/package/foo-0.0.1.crate").is_file()); + assert!(repo.root().join("target/package/foo-0.0.1.crate").is_file()); - p.cargo("package -l") + cargo_process("package -l") + .cwd(repo.root()) .with_stdout( "\ +.cargo_vcs_info.json Cargo.toml dir_root_1/some_dir/file dir_root_2/some_dir/file @@ -418,7 +422,8 @@ src/main.rs #[test] fn include() { - let p = project() + let root = paths::root().join("include"); + let repo = git::repo(&root) .file("Cargo.toml", r#" [project] name = "foo" @@ -432,16 +437,17 @@ fn include() { .file("src/bar.txt", "") // should be ignored when packaging .build(); - p.cargo("package --no-verify -v") + cargo_process("package --no-verify -v") + .cwd(repo.root()) .with_stderr( "\ [WARNING] manifest has no description[..] See http://doc.crates.io/manifest.html#package-metadata for more info. -[WARNING] No (git) Cargo.toml found at `[..]` in workdir `[..]` [PACKAGING] foo v0.0.1 ([..]) [ARCHIVING] [..] [ARCHIVING] [..] [ARCHIVING] [..] +[ARCHIVING] .cargo_vcs_info.json ", ).run(); } From f075f9c6cbf11c6484330d24b8a49fbbdb465d66 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 4 Nov 2018 10:38:51 -0800 Subject: [PATCH 023/128] Fix can_run_doc_tests order depends on hash. The deps are sorted, but the name is the same so the order depends on the metadata hash. Fix by sorting by the actual name, too. --- src/cargo/core/compiler/context/mod.rs | 2 ++ tests/testsuite/rename_deps.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cargo/core/compiler/context/mod.rs b/src/cargo/core/compiler/context/mod.rs index 225e6ebd53f..334a3876aa9 100644 --- a/src/cargo/core/compiler/context/mod.rs +++ b/src/cargo/core/compiler/context/mod.rs @@ -234,6 +234,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> { } } } + // Help with tests to get a stable order with renamed deps. + doctest_deps.sort(); self.compilation.to_doc_test.push(compilation::Doctest { package: unit.pkg.clone(), target: unit.target.clone(), diff --git a/tests/testsuite/rename_deps.rs b/tests/testsuite/rename_deps.rs index c444739b0f2..209987b89ca 100644 --- a/tests/testsuite/rename_deps.rs +++ b/tests/testsuite/rename_deps.rs @@ -334,8 +334,8 @@ fn can_run_doc_tests() { [DOCTEST] foo [RUNNING] `rustdoc --test [CWD]/src/lib.rs \ [..] \ - --extern baz=[CWD]/target/debug/deps/libbar-[..].rlib \ --extern bar=[CWD]/target/debug/deps/libbar-[..].rlib \ + --extern baz=[CWD]/target/debug/deps/libbar-[..].rlib \ [..]` ", ).run(); From 5a594941349fab8384c4f4cb70cb03ede3c0d0f3 Mon Sep 17 00:00:00 2001 From: Khionu Sybiern Date: Mon, 5 Nov 2018 11:42:19 -0500 Subject: [PATCH 024/128] Remove patch and bump tar to 0.4.18 Signed-off-by: Khionu Sybiern --- Cargo.toml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c2f5ee2dede..77cec84c9fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,7 @@ serde_derive = "1.0" serde_ignored = "0.0.4" serde_json = { version = "1.0.30", features = ["raw_value"] } shell-escape = "0.1.4" -tar = { version = "0.4.15", default-features = false } +tar = { version = "0.4.18", default-features = false } tempfile = "3.0" termcolor = "1.0" toml = "0.4.2" @@ -64,10 +64,6 @@ openssl = { version = '0.10.11', optional = true } # for more information. rustc-workspace-hack = "1.0.0" -# TODO: This patch will be removed before PR merge, when tar has a release containing this patch -[patch.crates-io] -tar = { git = "https://github.com/alexcrichton/tar-rs", rev = "f442964" } - [target.'cfg(target_os = "macos")'.dependencies] core-foundation = { version = "0.6.0", features = ["mac_os_10_7_support"] } From 89413bd41a8dd22a5490a3db502ebde53c239a45 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 5 Nov 2018 16:32:27 -0800 Subject: [PATCH 025/128] Fix fix_path_deps again. --- tests/testsuite/fix.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testsuite/fix.rs b/tests/testsuite/fix.rs index d37688368f0..a3775b889ef 100644 --- a/tests/testsuite/fix.rs +++ b/tests/testsuite/fix.rs @@ -183,7 +183,7 @@ fn fix_path_deps() { p.cargo("fix --allow-no-vcs -p foo -p bar") .env("__CARGO_FIX_YOLO", "1") .with_stdout("") - .with_stderr( + .with_stderr_unordered( "\ [CHECKING] bar v0.1.0 ([..]) [FIXING] bar/src/lib.rs (1 fix) From e295a900bb39dcbe7ad7644a57064e702bd749e8 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 3 Nov 2018 12:36:41 -0700 Subject: [PATCH 026/128] Treat "proc-macro" crate type the same as `proc-macro = true` --- src/cargo/util/toml/mod.rs | 9 ++++- tests/testsuite/proc_macro.rs | 66 +++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 367ef8b395f..d19bac3740d 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -1474,7 +1474,14 @@ impl TomlTarget { } fn proc_macro(&self) -> Option { - self.proc_macro.or(self.proc_macro2) + self.proc_macro.or(self.proc_macro2).or_else(|| { + if let Some(types) = self.crate_types() { + if types.contains(&"proc-macro".to_string()) { + return Some(true); + } + } + None + }) } fn crate_types(&self) -> Option<&Vec> { diff --git a/tests/testsuite/proc_macro.rs b/tests/testsuite/proc_macro.rs index e843eeaad6d..61ad6898eec 100644 --- a/tests/testsuite/proc_macro.rs +++ b/tests/testsuite/proc_macro.rs @@ -279,3 +279,69 @@ fn a() { .with_stdout_contains_n("test [..] ... ok", 2) .run(); } + +#[test] +fn proc_macro_crate_type() { + // Verify that `crate-type = ["proc-macro"]` is the same as `proc-macro = true` + // and that everything, including rustdoc, works correctly. + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + [dependencies] + pm = { path = "pm" } + "#, + ) + .file( + "src/lib.rs", + r#" + //! ``` + //! use foo::THING; + //! assert_eq!(THING, 123); + //! ``` + #[macro_use] + extern crate pm; + #[derive(MkItem)] + pub struct S; + #[cfg(test)] + mod tests { + use super::THING; + #[test] + fn it_works() { + assert_eq!(THING, 123); + } + } + "#, + ) + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + [lib] + crate-type = ["proc-macro"] + "#, + ) + .file( + "pm/src/lib.rs", + r#" + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro_derive(MkItem)] + pub fn mk_item(_input: TokenStream) -> TokenStream { + "pub const THING: i32 = 123;".parse().unwrap() + } + "#, + ) + .build(); + + foo.cargo("test") + .with_stdout_contains("test tests::it_works ... ok") + .with_stdout_contains_n("test [..] ... ok", 2) + .run(); +} From b0e767f314e3d2918e4ac081df3c45e7aca190db Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 6 Nov 2018 10:32:56 -0800 Subject: [PATCH 027/128] Add warnings for `crate-type = ["proc-macro"]`. --- src/cargo/util/toml/targets.rs | 17 ++++++++ tests/testsuite/proc_macro.rs | 76 ++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/src/cargo/util/toml/targets.rs b/src/cargo/util/toml/targets.rs index cc40b536ce3..b86300225fe 100644 --- a/src/cargo/util/toml/targets.rs +++ b/src/cargo/util/toml/targets.rs @@ -206,6 +206,23 @@ fn clean_lib( // A plugin requires exporting plugin_registrar so a crate cannot be // both at once. let crate_types = match (lib.crate_types(), lib.plugin, lib.proc_macro()) { + (Some(kinds), _, _) if kinds.contains(&"proc-macro".to_string()) => { + if let Some(true) = lib.plugin { + // This is a warning to retain backwards compatibility. + warnings.push(format!( + "proc-macro library `{}` should not specify `plugin = true`", + lib.name() + )); + } + warnings.push(format!( + "library `{}` should only specify `proc-macro = true` instead of setting `crate-type`", + lib.name() + )); + if kinds.len() > 1 { + bail!("cannot mix `proc-macro` crate type with others"); + } + vec![LibKind::ProcMacro] + } (_, Some(true), Some(true)) => bail!("lib.plugin and lib.proc-macro cannot both be true"), (Some(kinds), _, _) => kinds.iter().map(|s| s.into()).collect(), (None, Some(true), _) => vec![LibKind::Dylib], diff --git a/tests/testsuite/proc_macro.rs b/tests/testsuite/proc_macro.rs index 61ad6898eec..b5af731b411 100644 --- a/tests/testsuite/proc_macro.rs +++ b/tests/testsuite/proc_macro.rs @@ -345,3 +345,79 @@ fn proc_macro_crate_type() { .with_stdout_contains_n("test [..] ... ok", 2) .run(); } + +#[test] +fn proc_macro_crate_type_warning() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + [lib] + crate-type = ["proc-macro"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("build") + .with_stderr_contains( + "[WARNING] library `foo` should only specify `proc-macro = true` instead of setting `crate-type`") + .run(); +} + +#[test] +fn proc_macro_crate_type_warning_plugin() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + [lib] + crate-type = ["proc-macro"] + plugin = true + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("build") + .with_stderr_contains( + "[WARNING] proc-macro library `foo` should not specify `plugin = true`") + .with_stderr_contains( + "[WARNING] library `foo` should only specify `proc-macro = true` instead of setting `crate-type`") + .run(); +} + +#[test] +fn proc_macro_crate_type_multiple() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + [lib] + crate-type = ["proc-macro", "rlib"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("build") + .with_stderr( + "\ +[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml` + +Caused by: + cannot mix `proc-macro` crate type with others +", + ) + .with_status(101) + .run(); +} From b15dc1ac8265406bbfdbf69ec17eb040667b785f Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 6 Nov 2018 11:13:04 -0800 Subject: [PATCH 028/128] Don't treat rustc exit on signal as internal error. If rustc exits with a signal, previously all you saw was: ``` Compiling foo ... error: Could not compile `foo`. To learn more, run the command again with --verbose. ``` Now it shows the complete error by default: ``` Compiling foo ... error: Could not compile `foo`. Caused by: process didn't exit successfully: `rustc ...` (signal: 6, SIGABRT: process abort signal) ``` --- src/cargo/core/compiler/mod.rs | 20 +++++++++-- tests/testsuite/build.rs | 62 ++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 59834c40915..a2b5d8d59fd 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -5,13 +5,14 @@ use std::io::{self, Write}; use std::path::{self, Path, PathBuf}; use std::sync::Arc; +use failure::Error; use same_file::is_same_file; use serde_json; use core::manifest::TargetSourcePath; use core::profiles::{Lto, Profile}; use core::{PackageId, Target}; -use util::errors::{CargoResult, CargoResultExt, Internal}; +use util::errors::{CargoResult, CargoResultExt, Internal, ProcessError}; use util::paths; use util::{self, machine_message, Freshness, ProcessBuilder, process}; use util::{internal, join_paths, profile}; @@ -275,6 +276,18 @@ fn rustc<'a, 'cfg>( } } + fn internal_if_simple_exit_code(err: Error) -> Error { + if err + .downcast_ref::() + .as_ref() + .and_then(|perr| perr.exit.and_then(|e| e.code())) + .is_none() + { + return err; + } + Internal::new(err).into() + } + state.running(&rustc); if json_messages { exec.exec_json( @@ -284,13 +297,14 @@ fn rustc<'a, 'cfg>( mode, &mut assert_is_empty, &mut |line| json_stderr(line, &package_id, &target), - ).map_err(Internal::new) + ) + .map_err(internal_if_simple_exit_code) .chain_err(|| format!("Could not compile `{}`.", name))?; } else if build_plan { state.build_plan(buildkey, rustc.clone(), outputs.clone()); } else { exec.exec_and_capture_output(rustc, &package_id, &target, mode, state) - .map_err(Internal::new) + .map_err(internal_if_simple_exit_code) .chain_err(|| format!("Could not compile `{}`.", name))?; } diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index 928bddde6fc..5f5a69c8e38 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -4373,3 +4373,65 @@ fn target_filters_workspace_not_found() { .with_stderr("[ERROR] no library targets found in packages: a, b") .run(); } + +#[cfg(unix)] +#[test] +fn signal_display() { + // Cause the compiler to crash with a signal. + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + [dependencies] + pm = { path = "pm" } + "#, + ) + .file( + "src/lib.rs", + r#" + #[macro_use] + extern crate pm; + + #[derive(Foo)] + pub struct S; + "#, + ) + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + [lib] + proc-macro = true + "#, + ) + .file( + "pm/src/lib.rs", + r#" + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro_derive(Foo)] + pub fn derive(_input: TokenStream) -> TokenStream { + std::process::abort() + } + "#, + ) + .build(); + + foo.cargo("build") + .with_stderr("\ +[COMPILING] pm [..] +[COMPILING] foo [..] +[ERROR] Could not compile `foo`. + +Caused by: + process didn't exit successfully: `rustc [..]` (signal: 6, SIGABRT: process abort signal) +") + .with_status(101) + .run(); +} From 0203caedbc7fe3b15cc819ff869c1ae32b05ee0c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 6 Nov 2018 13:17:08 -0800 Subject: [PATCH 029/128] Show abnormal errors on windows, too. --- src/cargo/core/compiler/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index a2b5d8d59fd..10d65f55525 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -281,7 +281,7 @@ fn rustc<'a, 'cfg>( .downcast_ref::() .as_ref() .and_then(|perr| perr.exit.and_then(|e| e.code())) - .is_none() + != Some(1) { return err; } From 6bc5e7123e6d57fc916a12b1f8611e0a75aa3d67 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 6 Nov 2018 14:16:54 -0800 Subject: [PATCH 030/128] More conservative on error codes. --- src/cargo/core/compiler/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 10d65f55525..6f9a42df069 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -277,15 +277,16 @@ fn rustc<'a, 'cfg>( } fn internal_if_simple_exit_code(err: Error) -> Error { - if err + // If a signal on unix (code == None) or an abnormal termination + // on Windows (codes like 0xC0000409), don't hide the error details. + match err .downcast_ref::() .as_ref() .and_then(|perr| perr.exit.and_then(|e| e.code())) - != Some(1) { - return err; + Some(n) if n < 128 => Internal::new(err).into(), + _ => err, } - Internal::new(err).into() } state.running(&rustc); From d08fd375db0014f097ee3fbdc1c595b632669f6a Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Tue, 6 Nov 2018 19:50:19 -0500 Subject: [PATCH 031/128] the more recently added conflicts are more likely to still be relevant This fixes most of the cases fount in #6258, in practice if not in theory. --- src/cargo/core/resolver/conflict_cache.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cargo/core/resolver/conflict_cache.rs b/src/cargo/core/resolver/conflict_cache.rs index b35813bc35a..77f131a2581 100644 --- a/src/cargo/core/resolver/conflict_cache.rs +++ b/src/cargo/core/resolver/conflict_cache.rs @@ -35,9 +35,8 @@ pub(super) struct ConflictCache { // unconditionally true regardless of our resolution history of how we got // here. con_from_dep: HashMap>>, - // `past_conflict_triggers` is an - // of `past_conflicting_activations`. - // For every `PackageId` this lists the `Dependency`s that mention it in `past_conflicting_activations`. + // `dep_from_pid` is an inverse-index of `con_from_dep`. + // For every `PackageId` this lists the `Dependency`s that mention it in `dep_from_pid`. dep_from_pid: HashMap>, } @@ -62,6 +61,7 @@ impl ConflictCache { self.con_from_dep .get(dep)? .iter() + .rev() // more general cases are normally found letter. So start the search there. .filter(filter) .find(|conflicting| cx.is_conflicting(None, conflicting)) } From 90a54dd9ca269a63ca474a1ead5e729998fcce3b Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Tue, 6 Nov 2018 20:18:55 -0500 Subject: [PATCH 032/128] document that fuss tests are flaky, and how to report. --- tests/testsuite/resolve.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/testsuite/resolve.rs b/tests/testsuite/resolve.rs index 9ce7ccc4e42..392c6929c0e 100644 --- a/tests/testsuite/resolve.rs +++ b/tests/testsuite/resolve.rs @@ -16,6 +16,13 @@ use proptest::collection::vec; use proptest::prelude::*; proptest! { + /// NOTE: proptest is a form of fuzz testing. It generates random input and makes shore that + /// certain universal truths are upheld. Therefore, it can pass when there is a problem, + /// but if it fails then there really is something wrong. When testing something as + /// complicated as the resolver, the problems can be very subtle and hard to generate. + /// We have had a history of these tests only failing on PRs long after a bug is introduced. + /// If you have one of these test fail please report it on #6258, + /// and if you did not change the resolver then feel free to retry without concern. #![proptest_config(ProptestConfig { // Note that this is a little low in terms of cases we'd like to test, // but this number affects how long this function takes. It can be @@ -34,6 +41,7 @@ proptest! { .. ProptestConfig::default() })] + /// NOTE: if you think this test has failed spuriously see the note at the top of this macro. #[test] fn passes_validation( PrettyPrintRegistry(input) in registry_strategy(50, 20, 60) @@ -51,6 +59,7 @@ proptest! { } } + /// NOTE: if you think this test has failed spuriously see the note at the top of this macro. #[test] fn minimum_version_errors_the_same( PrettyPrintRegistry(input) in registry_strategy(50, 20, 60) @@ -100,6 +109,7 @@ proptest! { } } + /// NOTE: if you think this test has failed spuriously see the note at the top of this macro. #[test] fn limited_independence_of_irrelevant_alternatives( PrettyPrintRegistry(input) in registry_strategy(50, 20, 60), From 221908d2aebfaa0b48c890f79721bd31f14ab99d Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Tue, 6 Nov 2018 20:40:18 -0500 Subject: [PATCH 033/128] document that meta_fuss tests are flaky, and to ignore. --- tests/testsuite/support/resolver.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/testsuite/support/resolver.rs b/tests/testsuite/support/resolver.rs index ae89eaf71f9..4c7ad3288ae 100644 --- a/tests/testsuite/support/resolver.rs +++ b/tests/testsuite/support/resolver.rs @@ -460,12 +460,16 @@ pub fn registry_strategy( /// This test is to test the generator to ensure /// that it makes registries with large dependency trees +/// +/// This is a form of randomized testing, if you are unlucky it can fail. +/// A failure on it's own is not a big dael. If you did not change the +/// `registry_strategy` then feel free to retry without concern. #[test] fn meta_test_deep_trees_from_strategy() { let mut dis = [0; 21]; let strategy = registry_strategy(50, 20, 60); - for _ in 0..64 { + for _ in 0..128 { let PrettyPrintRegistry(input) = strategy .new_tree(&mut TestRunner::default()) .unwrap() @@ -488,19 +492,23 @@ fn meta_test_deep_trees_from_strategy() { } panic!( - "In 640 tries we did not see a wide enough distribution of dependency trees! dis: {:?}", + "In 1280 tries we did not see a wide enough distribution of dependency trees! dis: {:?}", dis ); } /// This test is to test the generator to ensure /// that it makes registries that include multiple versions of the same library +/// +/// This is a form of randomized testing, if you are unlucky it can fail. +/// A failure on its own is not a big deal. If you did not change the +/// `registry_strategy` then feel free to retry without concern. #[test] fn meta_test_multiple_versions_strategy() { let mut dis = [0; 10]; let strategy = registry_strategy(50, 20, 60); - for _ in 0..64 { + for _ in 0..128 { let PrettyPrintRegistry(input) = strategy .new_tree(&mut TestRunner::default()) .unwrap() @@ -524,7 +532,7 @@ fn meta_test_multiple_versions_strategy() { } } panic!( - "In 640 tries we did not see a wide enough distribution of multiple versions of the same library! dis: {:?}", + "In 1280 tries we did not see a wide enough distribution of multiple versions of the same library! dis: {:?}", dis ); } From 8cfa1dd3db490d9f277cf27aee89844128e6ba6c Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Tue, 6 Nov 2018 20:47:06 -0500 Subject: [PATCH 034/128] remove the hard to read start of names --- tests/testsuite/support/resolver.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testsuite/support/resolver.rs b/tests/testsuite/support/resolver.rs index 4c7ad3288ae..fd2a8d6f0ce 100644 --- a/tests/testsuite/support/resolver.rs +++ b/tests/testsuite/support/resolver.rs @@ -355,7 +355,7 @@ pub fn registry_strategy( max_versions: usize, shrinkage: usize, ) -> impl Strategy { - let name = string_regex("[A-Za-z_-][A-Za-z0-9_-]*(-sys)?").unwrap(); + let name = string_regex("[A-Za-z][A-Za-z0-9_-]*(-sys)?").unwrap(); let raw_version = [..max_versions; 3]; let version_from_raw = |v: &[usize; 3]| format!("{}.{}.{}", v[0], v[1], v[2]); From 7ca46cccbd8ccc1d2d9b31d6e3a9d87d121c4828 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Wed, 7 Nov 2018 10:41:37 -0500 Subject: [PATCH 035/128] move note to let it build --- tests/testsuite/resolve.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/testsuite/resolve.rs b/tests/testsuite/resolve.rs index 392c6929c0e..99a3ccf0e6e 100644 --- a/tests/testsuite/resolve.rs +++ b/tests/testsuite/resolve.rs @@ -15,14 +15,14 @@ use support::resolver::{ use proptest::collection::vec; use proptest::prelude::*; +/// NOTE: proptest is a form of fuzz testing. It generates random input and makes shore that +/// certain universal truths are upheld. Therefore, it can pass when there is a problem, +/// but if it fails then there really is something wrong. When testing something as +/// complicated as the resolver, the problems can be very subtle and hard to generate. +/// We have had a history of these tests only failing on PRs long after a bug is introduced. +/// If you have one of these test fail please report it on #6258, +/// and if you did not change the resolver then feel free to retry without concern. proptest! { - /// NOTE: proptest is a form of fuzz testing. It generates random input and makes shore that - /// certain universal truths are upheld. Therefore, it can pass when there is a problem, - /// but if it fails then there really is something wrong. When testing something as - /// complicated as the resolver, the problems can be very subtle and hard to generate. - /// We have had a history of these tests only failing on PRs long after a bug is introduced. - /// If you have one of these test fail please report it on #6258, - /// and if you did not change the resolver then feel free to retry without concern. #![proptest_config(ProptestConfig { // Note that this is a little low in terms of cases we'd like to test, // but this number affects how long this function takes. It can be From c181f490fc88a8a8fa1df283f4f0377b122aa482 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 6 Nov 2018 13:02:59 -0800 Subject: [PATCH 036/128] Enable HTTP/2 by default This commit switches Cargo to using HTTP/2 by default. This is controlled via the `http.multiplexing` configuration variable and has been messaged out for testing [1] (although got very few responses). There's been surprisingly little fallout from parallel downloads, so let's see how this goes! [1]: https://internals.rust-lang.org/t/testing-cargos-parallel-downloads/8466 --- Cargo.toml | 4 ++-- src/cargo/core/package.rs | 35 +++++++++++++++++++++++++-------- src/doc/src/reference/config.md | 2 +- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 51e0627d3e0..11236d32874 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,8 +22,8 @@ bytesize = "1.0" crates-io = { path = "src/crates-io", version = "0.21" } crossbeam-utils = "0.5" crypto-hash = "0.3.1" -curl = { version = "0.4.17", features = ['http2'] } -curl-sys = "0.4.12" +curl = { version = "0.4.19", features = ['http2'] } +curl-sys = "0.4.15" env_logger = "0.5.11" failure = "0.1.2" filetime = "0.2" diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 171ac27e33e..560fee64ff1 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -7,10 +7,11 @@ use std::path::{Path, PathBuf}; use std::time::{Instant, Duration}; use bytesize::ByteSize; -use curl; -use curl_sys; use curl::easy::{Easy, HttpVersion}; use curl::multi::{Multi, EasyHandle}; +use curl; +use curl_sys; +use failure::ResultExt; use lazycell::LazyCell; use semver::Version; use serde::ser; @@ -333,7 +334,7 @@ impl<'cfg> PackageSet<'cfg> { // proxies. let mut multi = Multi::new(); let multiplexing = config.get::>("http.multiplexing")? - .unwrap_or(false); + .unwrap_or(true); multi.pipelining(false, multiplexing) .chain_err(|| "failed to enable multiplexing/pipelining in curl")?; @@ -452,12 +453,30 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { handle.follow_location(true)?; // follow redirects // Enable HTTP/2 to be used as it'll allow true multiplexing which makes - // downloads much faster. Currently Cargo requests the `http2` feature - // of the `curl` crate which means it should always be built in, so - // treat it as a fatal error of http/2 support isn't found. + // downloads much faster. + // + // Currently Cargo requests the `http2` feature of the `curl` crate + // which means it should always be built in. On OSX, however, we ship + // cargo still linked against the system libcurl. Building curl with + // ALPN support for HTTP/2 requires newer versions of OSX (the + // SecureTransport API) than we want to ship Cargo for. By linking Cargo + // against the system libcurl then older curl installations won't use + // HTTP/2 but newer ones will. All that to basically say we ignore + // errors here on OSX, but consider this a fatal error to not activate + // HTTP/2 on all other platforms. if self.set.multiplexing { - handle.http_version(HttpVersion::V2) - .chain_err(|| "failed to enable HTTP2, is curl not built right?")?; + let result = handle.http_version(HttpVersion::V2); + if cfg!(target_os = "macos") { + if let Err(e) = result { + warn!("ignoring HTTP/2 activation error: {}", e) + } + } else { + result.with_context(|_| { + "failed to enable HTTP2, is curl not built right?" + })?; + } + } else { + handle.http_version(HttpVersion::V11)?; } // This is an option to `libcurl` which indicates that if there's a diff --git a/src/doc/src/reference/config.md b/src/doc/src/reference/config.md index 8a22e95f922..da95970b28e 100644 --- a/src/doc/src/reference/config.md +++ b/src/doc/src/reference/config.md @@ -102,7 +102,7 @@ timeout = 30 # Timeout for each HTTP request, in seconds cainfo = "cert.pem" # Path to Certificate Authority (CA) bundle (optional) check-revoke = true # Indicates whether SSL certs are checked for revocation low-speed-limit = 5 # Lower threshold for bytes/sec (10 = default, 0 = disabled) -multiplexing = false # whether or not to use HTTP/2 multiplexing where possible +multiplexing = true # whether or not to use HTTP/2 multiplexing where possible # This setting can be used to help debug what's going on with HTTP requests made # by Cargo. When set to `true` then Cargo's normal debug logging will be filled From 5b2b5f9598e427d507d4cdfa6878ffc883bf4a74 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 7 Nov 2018 09:00:54 -0800 Subject: [PATCH 037/128] Warn/err on some unused manifest keys in workspaces. --- src/cargo/core/workspace.rs | 26 ++++++---- src/cargo/util/toml/mod.rs | 18 +++++++ tests/testsuite/workspaces.rs | 90 +++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 8 deletions(-) diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index e6fc45d091d..3fccc4ee081 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -658,18 +658,28 @@ impl<'cfg> Workspace<'cfg> { for pkg in self.members() .filter(|p| p.manifest_path() != root_manifest) { - if pkg.manifest().original().has_profiles() { - let message = &format!( - "profiles for the non root package will be ignored, \ - specify profiles at the workspace root:\n\ + let manifest = pkg.manifest(); + let emit_warning = |what| -> CargoResult<()> { + let msg = format!( + "{} for the non root package will be ignored, \ + specify {} at the workspace root:\n\ package: {}\n\ workspace: {}", + what, + what, pkg.manifest_path().display(), - root_manifest.display() + root_manifest.display(), ); - - //TODO: remove `Eq` bound from `Profiles` when the warning is removed. - self.config.shell().warn(&message)?; + self.config.shell().warn(&msg) + }; + if manifest.original().has_profiles() { + emit_warning("profiles")?; + } + if !manifest.replace().is_empty() { + emit_warning("replace")?; + } + if !manifest.patch().is_empty() { + emit_warning("patch")?; } } } diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index d19bac3740d..514dbbbc7d7 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -1086,6 +1086,24 @@ impl TomlManifest { if me.bench.is_some() { bail!("virtual manifests do not specify [[bench]]"); } + if me.dependencies.is_some() { + bail!("virtual manifests do not specify [dependencies]"); + } + if me.dev_dependencies.is_some() || me.dev_dependencies2.is_some() { + bail!("virtual manifests do not specify [dev-dependencies]"); + } + if me.build_dependencies.is_some() || me.build_dependencies2.is_some() { + bail!("virtual manifests do not specify [build-dependencies]"); + } + if me.features.is_some() { + bail!("virtual manifests do not specify [features]"); + } + if me.target.is_some() { + bail!("virtual manifests do not specify [target]"); + } + if me.badges.is_some() { + bail!("virtual manifests do not specify [badges]"); + } let mut nested_paths = Vec::new(); let mut warnings = Vec::new(); diff --git a/tests/testsuite/workspaces.rs b/tests/testsuite/workspaces.rs index e9338487829..88398174d8a 100644 --- a/tests/testsuite/workspaces.rs +++ b/tests/testsuite/workspaces.rs @@ -1879,3 +1879,93 @@ fn ws_rustc_err() { .with_stderr("[ERROR] [..]against an actual package[..]") .run(); } + +#[test] +fn ws_err_unused() { + for key in &[ + "[lib]", + "[[bin]]", + "[[example]]", + "[[test]]", + "[[bench]]", + "[dependencies]", + "[dev-dependencies]", + "[build-dependencies]", + "[features]", + "[target]", + "[badges]", + ] { + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [workspace] + members = ["a"] + + {} + "#, + key + ), + ) + .file("a/Cargo.toml", &basic_lib_manifest("a")) + .file("a/src/lib.rs", "") + .build(); + p.cargo("check") + .with_status(101) + .with_stderr(&format!( + "\ +[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml` + +Caused by: + virtual manifests do not specify {} +", + key + )) + .run(); + } +} + +#[test] +fn ws_warn_unused() { + for (key, name) in &[ + ("[profile.dev]\nopt-level = 1", "profiles"), + ("[replace]\n\"bar:0.1.0\" = { path = \"bar\" }", "replace"), + ("[patch.crates-io]\nbar = { path = \"bar\" }", "patch"), + ] { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a"] + "#, + ) + .file( + "a/Cargo.toml", + &format!( + r#" + [package] + name = "a" + version = "0.1.0" + + {} + "#, + key + ), + ) + .file("a/src/lib.rs", "") + .build(); + p.cargo("check") + .with_status(0) + .with_stderr_contains(&format!( + "\ +[WARNING] {} for the non root package will be ignored, specify {} at the workspace root: +package: [..]/foo/a/Cargo.toml +workspace: [..]/foo/Cargo.toml +", + name, name + )) + .run(); + } +} From 6ad77940272bfd34074411f064a8aab0ff94e300 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 7 Nov 2018 10:43:19 -0800 Subject: [PATCH 038/128] Include path to manifest in workspace warnings. --- src/cargo/core/workspace.rs | 10 +++++++++- tests/testsuite/bad_config.rs | 2 +- tests/testsuite/workspaces.rs | 29 +++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index 3fccc4ee081..e09bdf11268 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -741,6 +741,7 @@ impl<'cfg> Workspace<'cfg> { MaybePackage::Package(pkg) => pkg.manifest().warnings().warnings(), MaybePackage::Virtual(vm) => vm.warnings().warnings(), }; + let path = path.join("Cargo.toml"); for warning in warnings { if warning.is_critical { let err = format_err!("{}", warning.message); @@ -750,7 +751,14 @@ impl<'cfg> Workspace<'cfg> { ); return Err(err.context(cx).into()); } else { - self.config.shell().warn(&warning.message)? + let msg = if self.root_manifest.is_none() { + warning.message.to_string() + } else { + // In a workspace, it can be confusing where a warning + // originated, so include the path. + format!("{}: {}", path.display(), warning.message) + }; + self.config.shell().warn(msg)? } } } diff --git a/tests/testsuite/bad_config.rs b/tests/testsuite/bad_config.rs index bcef703002a..8036d32d7cf 100644 --- a/tests/testsuite/bad_config.rs +++ b/tests/testsuite/bad_config.rs @@ -734,7 +734,7 @@ fn unused_keys_in_virtual_manifest() { p.cargo("build --all") .with_stderr( "\ -warning: unused manifest key: workspace.bulid +[WARNING] [..]/foo/Cargo.toml: unused manifest key: workspace.bulid [COMPILING] bar [..] [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] ", diff --git a/tests/testsuite/workspaces.rs b/tests/testsuite/workspaces.rs index 88398174d8a..fb3d64ac558 100644 --- a/tests/testsuite/workspaces.rs +++ b/tests/testsuite/workspaces.rs @@ -1969,3 +1969,32 @@ workspace: [..]/foo/Cargo.toml .run(); } } + +#[test] +fn ws_warn_path() { + // Warnings include path to manifest. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + cargo-features = ["edition"] + [package] + name = "foo" + version = "0.1.0" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(0) + .with_stderr_contains("[WARNING] [..]/foo/a/Cargo.toml: the cargo feature `edition`[..]") + .run(); +} From f06a9e9c821eb813ccf5a8c2c923de66ab7ace4f Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 7 Nov 2018 14:43:24 -0800 Subject: [PATCH 039/128] Disable progress bar on CI. --- src/cargo/util/progress.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cargo/util/progress.rs b/src/cargo/util/progress.rs index 15347690cd2..fe90d311914 100644 --- a/src/cargo/util/progress.rs +++ b/src/cargo/util/progress.rs @@ -38,11 +38,13 @@ struct Format { impl<'cfg> Progress<'cfg> { pub fn with_style(name: &str, style: ProgressStyle, cfg: &'cfg Config) -> Progress<'cfg> { // report no progress when -q (for quiet) or TERM=dumb are set + // or if running on Continuous Integration service like Travis where the + // output logs get mangled. let dumb = match env::var("TERM") { Ok(term) => term == "dumb", Err(_) => false, }; - if cfg.shell().verbosity() == Verbosity::Quiet || dumb { + if cfg.shell().verbosity() == Verbosity::Quiet || dumb || env::var("CI").is_ok() { return Progress { state: None }; } From 04e1564481b1d8573174a9e4a2004d8137ebb054 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Tue, 6 Nov 2018 18:52:23 -0500 Subject: [PATCH 040/128] add a test that defets `iter.rev` --- tests/testsuite/resolve.rs | 152 ++++++++++++++++++++++++++++++++++--- 1 file changed, 142 insertions(+), 10 deletions(-) diff --git a/tests/testsuite/resolve.rs b/tests/testsuite/resolve.rs index 99a3ccf0e6e..13c65914c44 100644 --- a/tests/testsuite/resolve.rs +++ b/tests/testsuite/resolve.rs @@ -7,8 +7,8 @@ use cargo::util::Config; use support::project; use support::registry::Package; use support::resolver::{ - assert_contains, assert_same, dep, dep_kind, dep_loc, dep_req, loc_names, names, - pkg, pkg_dep, pkg_id, pkg_loc, registry, registry_strategy, resolve, resolve_and_validated, + assert_contains, assert_same, dep, dep_kind, dep_loc, dep_req, loc_names, names, pkg, pkg_dep, + pkg_id, pkg_loc, registry, registry_strategy, resolve, resolve_and_validated, resolve_with_config, PrettyPrintRegistry, ToDep, ToPkgId, }; @@ -433,14 +433,12 @@ fn resolving_incompat_versions() { pkg!("bar" => [dep_req("foo", "=1.0.2")]), ]); - assert!( - resolve( - &pkg_id("root"), - vec![dep_req("foo", "=1.0.1"), dep("bar")], - ® - ) - .is_err() - ); + assert!(resolve( + &pkg_id("root"), + vec![dep_req("foo", "=1.0.1"), dep("bar")], + ® + ) + .is_err()); } #[test] @@ -1174,3 +1172,137 @@ fn hard_equality() { &names(&[("root", "1.0.0"), ("foo", "1.0.0"), ("bar", "1.0.0")]), ); } + +#[test] +fn slow_case() { + let reg = registry(vec![ + pkg!(("-a-sys", "0.0.0") => [dep("bad"),]), + pkg!(("-a-sys", "0.0.1") => [dep("bad"),]), + pkg!(("-a-sys", "0.0.2") => [dep("bad"),]), + pkg!(("-a-sys", "0.0.3") => [dep("bad"),]), + pkg!(("-a-sys", "0.0.4")), + pkg!(("-a-sys", "0.0.5")), + pkg!(("-a-sys", "0.0.6")), + pkg!(("-a-sys", "0.0.7")), + pkg!(("-a-sys", "0.0.8")), + pkg!(("-a-sys", "0.0.9") => [dep("bad"),]), + pkg!(("-a-sys", "0.0.10")), + pkg!(("-a-sys", "0.0.11")), + pkg!(("-a-sys", "0.1.0")), + pkg!(("-a-sys", "0.1.1")), + pkg!(("-a-sys", "0.1.2")), + pkg!(("-a-sys", "0.1.3")), + pkg!(("-a-sys", "0.2.0")), + pkg!(("-a-sys", "0.2.1")), + pkg!(("A_-sys", "0.0.0") => [dep("bad"),]), + pkg!(("A_-sys", "0.0.1") => [dep("bad"),]), + pkg!(("A_-sys", "0.0.2") => [dep("bad"),]), + pkg!(("A_-sys", "0.0.3") =>[dep("bad"),]), + pkg!(("A_-sys", "0.0.4") => [dep("bad"),]), + pkg!(("A_-sys", "0.0.5") => [dep("bad"),]), + pkg!(("A_-sys", "0.0.6") => [dep("bad"),]), + pkg!(("A_-sys", "0.0.7") => [dep("bad"),]), + pkg!(("A_-sys", "0.1.0") => [dep("bad"),]), + pkg!(("A_-sys", "0.1.1") => [dep("bad"),]), + pkg!(("A_-sys", "0.1.2")), + pkg!(("A_-sys", "0.1.3")), + pkg!(("A_-sys", "0.1.4")), + pkg!(("A_-sys", "0.1.5")), + pkg!(("A_-sys", "0.1.6")), + pkg!(("A_-sys", "0.2.0")), + pkg!(("A_-sys", "0.2.1")), + pkg!(("A_-sys", "0.2.2")), + pkg!(("A_-sys", "0.3.0")), + pkg!(("A_-sys", "1.0.0")), + pkg!(("__-sys", "0.0.0") => [dep("bad"),]), + pkg!(("__-sys", "0.0.1") => [dep("bad"),]), + pkg!(("__-sys", "0.0.2")), + pkg!(("__-sys", "0.0.3")), + pkg!(("__-sys", "0.0.4") => [dep_req("-a-sys", ">= 0.0.1, <= 0.0.8"),]), + pkg!(("__-sys", "0.0.5") => [dep("bad"),]), + pkg!(("a-sys", "0.0.0") => [dep("bad"),]), + pkg!(("a-sys", "0.0.1") => [dep("bad"),]), + pkg!(("a-sys", "0.0.2") => [dep("bad"),]), + pkg!(("a-sys", "0.0.3") => [dep("bad"),]), + pkg!(("a-sys", "0.0.4")), + pkg!(("a-sys", "0.0.5") => [dep("bad"),]), + pkg!(("a-sys", "0.0.6")), + pkg!(("a-sys", "0.1.0") => [dep("bad"),]), + pkg!(("a-sys", "0.1.1")), + pkg!(("a-sys", "0.1.2")), + pkg!(("a-sys", "0.1.3")), + pkg!(("a-sys", "0.1.4")), + pkg!(("a-sys", "0.1.5")), + pkg!(("c-sys", "0.0.0")), + pkg!(("c-sys", "0.0.1")), + pkg!(("c-sys", "0.0.2")), + pkg!(("c-sys", "0.0.3") => [dep("bad"),]), + pkg!(("c-sys", "0.0.4")), + pkg!(("c-sys", "0.0.5") => [dep("bad"),]), + pkg!(("c-sys", "0.0.6")), + pkg!(("c-sys", "0.0.7") => [dep("bad"),]), + pkg!(("c-sys", "0.0.8") => [dep("bad"),]), + pkg!(("c-sys", "0.0.9") => [dep("bad"),]), + pkg!(("c-sys", "0.1.0")), + pkg!(("c-sys", "1.0.0") => [dep("bad"),]), + pkg!(("c-sys", "1.0.1")), + pkg!(("c-sys", "1.0.2") => [dep("bad"),]), + pkg!(("c-sys", "1.0.3") => [dep("bad"),]), + pkg!(("d-sys", "0.0.0") => [dep("bad"),]), + pkg!(("d-sys", "0.0.1") => [dep("bad"),]), + pkg!(("d-sys", "0.0.2") => [dep("bad"),]), + pkg!(("d-sys", "0.0.3") => [dep("bad"),]), + pkg!(("d-sys", "0.0.4") => [dep("bad"),]), + pkg!(("d-sys", "0.0.5") => [dep("bad"),]), + pkg!(("d-sys", "0.1.0") => [dep("bad"),]), + pkg!(("d-sys", "0.1.1") => [dep("bad"),]), + pkg!(("d-sys", "0.1.2") => [dep_req("__-sys", "<= 0.0.4"),]), + pkg!(("d-sys", "0.2.0") => [dep_req("__-sys", "<= 0.0.4"),]), + pkg!(("f", "0.0.0") => [dep("bad"),]), + pkg!(("f", "0.0.1") => [dep("bad"),]), + pkg!(("f", "0.0.2") => [dep("bad"),]), + pkg!(("f", "0.0.3") => [dep("bad"),]), + pkg!(("f", "0.0.4") => [dep("bad"),]), + pkg!(("f", "0.0.5") => [dep("bad"),]), + pkg!(("f", "0.0.6") => [dep("bad"),]), + pkg!(("f", "0.0.7") => [dep("bad"),]), + pkg!(("f", "0.0.8") => [dep("bad"),]), + pkg!(("f", "0.0.9") => [dep("bad"),]), + pkg!(("f", "0.0.10") => [dep("bad"),]), + pkg!(("f", "0.0.11") => [dep("bad"),]), + pkg!(("f", "0.1.0") => [dep("bad"),]), + pkg!(("f", "0.1.1") => [dep("bad"),]), + pkg!(("f", "0.1.2") => [dep("bad"),]), + pkg!(("f", "1.0.0") => [dep("bad"),]), + pkg!(("f", "1.0.1") => [dep_req("a-sys", "= 0.1.5"),]), + pkg!(("f", "1.0.2") => [dep_req("c-sys", "= 0.0.5"),]), + pkg!(("fa", "0.0.0") => [dep("bad"),]), + pkg!(("fa", "0.0.1") => [dep("bad"),]), + pkg!(("fa", "0.0.2") => [dep("bad"),]), + pkg!(("fa", "0.0.3") => [dep("bad"),]), + pkg!(("fa", "0.0.4") => [dep("bad"),]), + pkg!(("fa", "0.1.0") => [dep("bad"),]), + pkg!(("fa", "0.2.0") => [dep("bad"),]), + pkg!(("fa", "0.2.1") => [dep_req("c-sys", "<= 0.0.4"),]), + pkg!(("fa", "0.2.2") => [dep_req("c-sys", ">= 0.0.5, <= 0.1.0"),]), + pkg!(("s", "0.0.0") => [dep("bad"),]), + pkg!(("s", "0.0.1") => [dep("bad"),]), + pkg!(("s", "0.0.2") => [dep("bad"),]), + pkg!(("s", "0.0.3") => [dep_req("__-sys", "= 0.0.5"),]), + pkg!(("s", "0.0.4") => [dep("bad"),]), + pkg!(("s", "0.0.5") => [dep_req("d-sys", "<= 0.0.0"),]), + pkg!(("s", "0.1.0") => [dep("f"),]), + pkg!(("s", "0.1.1") => [dep_req("-a-sys", ">= 0.0.10, <= 0.0.11"),dep_req("__-sys", "= 0.0.4"),]), + pkg!(("s", "0.1.2") => [dep("bad"),]), + pkg!(("s", "0.1.3") => [dep("bad"),]), + pkg!(("s", "0.1.4") => [dep_req("A_-sys", "= 0.3.0"),]), + pkg!(("sA", "1.0.1") => [ + dep_req("A_-sys", ">= 0.1.1, <= 0.2.2"), + dep_req("a-sys", ">= 0.0.4, <= 0.1.4"), + dep_req("d-sys", ">= 0.0.1"), + dep("fa"), + dep("s"), + ]), + ]); + let _ = resolve(&pkg_id("root"), vec![dep("sA")], ®); +} From 1e90c0a9cc1ec5045d1e84d315d47c7d1b038ca5 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Wed, 7 Nov 2018 12:10:45 -0500 Subject: [PATCH 041/128] a more pure version of the test --- tests/testsuite/resolve.rs | 157 ++++++------------------------------- 1 file changed, 26 insertions(+), 131 deletions(-) diff --git a/tests/testsuite/resolve.rs b/tests/testsuite/resolve.rs index 13c65914c44..a9d4b722a14 100644 --- a/tests/testsuite/resolve.rs +++ b/tests/testsuite/resolve.rs @@ -1174,135 +1174,30 @@ fn hard_equality() { } #[test] -fn slow_case() { - let reg = registry(vec![ - pkg!(("-a-sys", "0.0.0") => [dep("bad"),]), - pkg!(("-a-sys", "0.0.1") => [dep("bad"),]), - pkg!(("-a-sys", "0.0.2") => [dep("bad"),]), - pkg!(("-a-sys", "0.0.3") => [dep("bad"),]), - pkg!(("-a-sys", "0.0.4")), - pkg!(("-a-sys", "0.0.5")), - pkg!(("-a-sys", "0.0.6")), - pkg!(("-a-sys", "0.0.7")), - pkg!(("-a-sys", "0.0.8")), - pkg!(("-a-sys", "0.0.9") => [dep("bad"),]), - pkg!(("-a-sys", "0.0.10")), - pkg!(("-a-sys", "0.0.11")), - pkg!(("-a-sys", "0.1.0")), - pkg!(("-a-sys", "0.1.1")), - pkg!(("-a-sys", "0.1.2")), - pkg!(("-a-sys", "0.1.3")), - pkg!(("-a-sys", "0.2.0")), - pkg!(("-a-sys", "0.2.1")), - pkg!(("A_-sys", "0.0.0") => [dep("bad"),]), - pkg!(("A_-sys", "0.0.1") => [dep("bad"),]), - pkg!(("A_-sys", "0.0.2") => [dep("bad"),]), - pkg!(("A_-sys", "0.0.3") =>[dep("bad"),]), - pkg!(("A_-sys", "0.0.4") => [dep("bad"),]), - pkg!(("A_-sys", "0.0.5") => [dep("bad"),]), - pkg!(("A_-sys", "0.0.6") => [dep("bad"),]), - pkg!(("A_-sys", "0.0.7") => [dep("bad"),]), - pkg!(("A_-sys", "0.1.0") => [dep("bad"),]), - pkg!(("A_-sys", "0.1.1") => [dep("bad"),]), - pkg!(("A_-sys", "0.1.2")), - pkg!(("A_-sys", "0.1.3")), - pkg!(("A_-sys", "0.1.4")), - pkg!(("A_-sys", "0.1.5")), - pkg!(("A_-sys", "0.1.6")), - pkg!(("A_-sys", "0.2.0")), - pkg!(("A_-sys", "0.2.1")), - pkg!(("A_-sys", "0.2.2")), - pkg!(("A_-sys", "0.3.0")), - pkg!(("A_-sys", "1.0.0")), - pkg!(("__-sys", "0.0.0") => [dep("bad"),]), - pkg!(("__-sys", "0.0.1") => [dep("bad"),]), - pkg!(("__-sys", "0.0.2")), - pkg!(("__-sys", "0.0.3")), - pkg!(("__-sys", "0.0.4") => [dep_req("-a-sys", ">= 0.0.1, <= 0.0.8"),]), - pkg!(("__-sys", "0.0.5") => [dep("bad"),]), - pkg!(("a-sys", "0.0.0") => [dep("bad"),]), - pkg!(("a-sys", "0.0.1") => [dep("bad"),]), - pkg!(("a-sys", "0.0.2") => [dep("bad"),]), - pkg!(("a-sys", "0.0.3") => [dep("bad"),]), - pkg!(("a-sys", "0.0.4")), - pkg!(("a-sys", "0.0.5") => [dep("bad"),]), - pkg!(("a-sys", "0.0.6")), - pkg!(("a-sys", "0.1.0") => [dep("bad"),]), - pkg!(("a-sys", "0.1.1")), - pkg!(("a-sys", "0.1.2")), - pkg!(("a-sys", "0.1.3")), - pkg!(("a-sys", "0.1.4")), - pkg!(("a-sys", "0.1.5")), - pkg!(("c-sys", "0.0.0")), - pkg!(("c-sys", "0.0.1")), - pkg!(("c-sys", "0.0.2")), - pkg!(("c-sys", "0.0.3") => [dep("bad"),]), - pkg!(("c-sys", "0.0.4")), - pkg!(("c-sys", "0.0.5") => [dep("bad"),]), - pkg!(("c-sys", "0.0.6")), - pkg!(("c-sys", "0.0.7") => [dep("bad"),]), - pkg!(("c-sys", "0.0.8") => [dep("bad"),]), - pkg!(("c-sys", "0.0.9") => [dep("bad"),]), - pkg!(("c-sys", "0.1.0")), - pkg!(("c-sys", "1.0.0") => [dep("bad"),]), - pkg!(("c-sys", "1.0.1")), - pkg!(("c-sys", "1.0.2") => [dep("bad"),]), - pkg!(("c-sys", "1.0.3") => [dep("bad"),]), - pkg!(("d-sys", "0.0.0") => [dep("bad"),]), - pkg!(("d-sys", "0.0.1") => [dep("bad"),]), - pkg!(("d-sys", "0.0.2") => [dep("bad"),]), - pkg!(("d-sys", "0.0.3") => [dep("bad"),]), - pkg!(("d-sys", "0.0.4") => [dep("bad"),]), - pkg!(("d-sys", "0.0.5") => [dep("bad"),]), - pkg!(("d-sys", "0.1.0") => [dep("bad"),]), - pkg!(("d-sys", "0.1.1") => [dep("bad"),]), - pkg!(("d-sys", "0.1.2") => [dep_req("__-sys", "<= 0.0.4"),]), - pkg!(("d-sys", "0.2.0") => [dep_req("__-sys", "<= 0.0.4"),]), - pkg!(("f", "0.0.0") => [dep("bad"),]), - pkg!(("f", "0.0.1") => [dep("bad"),]), - pkg!(("f", "0.0.2") => [dep("bad"),]), - pkg!(("f", "0.0.3") => [dep("bad"),]), - pkg!(("f", "0.0.4") => [dep("bad"),]), - pkg!(("f", "0.0.5") => [dep("bad"),]), - pkg!(("f", "0.0.6") => [dep("bad"),]), - pkg!(("f", "0.0.7") => [dep("bad"),]), - pkg!(("f", "0.0.8") => [dep("bad"),]), - pkg!(("f", "0.0.9") => [dep("bad"),]), - pkg!(("f", "0.0.10") => [dep("bad"),]), - pkg!(("f", "0.0.11") => [dep("bad"),]), - pkg!(("f", "0.1.0") => [dep("bad"),]), - pkg!(("f", "0.1.1") => [dep("bad"),]), - pkg!(("f", "0.1.2") => [dep("bad"),]), - pkg!(("f", "1.0.0") => [dep("bad"),]), - pkg!(("f", "1.0.1") => [dep_req("a-sys", "= 0.1.5"),]), - pkg!(("f", "1.0.2") => [dep_req("c-sys", "= 0.0.5"),]), - pkg!(("fa", "0.0.0") => [dep("bad"),]), - pkg!(("fa", "0.0.1") => [dep("bad"),]), - pkg!(("fa", "0.0.2") => [dep("bad"),]), - pkg!(("fa", "0.0.3") => [dep("bad"),]), - pkg!(("fa", "0.0.4") => [dep("bad"),]), - pkg!(("fa", "0.1.0") => [dep("bad"),]), - pkg!(("fa", "0.2.0") => [dep("bad"),]), - pkg!(("fa", "0.2.1") => [dep_req("c-sys", "<= 0.0.4"),]), - pkg!(("fa", "0.2.2") => [dep_req("c-sys", ">= 0.0.5, <= 0.1.0"),]), - pkg!(("s", "0.0.0") => [dep("bad"),]), - pkg!(("s", "0.0.1") => [dep("bad"),]), - pkg!(("s", "0.0.2") => [dep("bad"),]), - pkg!(("s", "0.0.3") => [dep_req("__-sys", "= 0.0.5"),]), - pkg!(("s", "0.0.4") => [dep("bad"),]), - pkg!(("s", "0.0.5") => [dep_req("d-sys", "<= 0.0.0"),]), - pkg!(("s", "0.1.0") => [dep("f"),]), - pkg!(("s", "0.1.1") => [dep_req("-a-sys", ">= 0.0.10, <= 0.0.11"),dep_req("__-sys", "= 0.0.4"),]), - pkg!(("s", "0.1.2") => [dep("bad"),]), - pkg!(("s", "0.1.3") => [dep("bad"),]), - pkg!(("s", "0.1.4") => [dep_req("A_-sys", "= 0.3.0"),]), - pkg!(("sA", "1.0.1") => [ - dep_req("A_-sys", ">= 0.1.1, <= 0.2.2"), - dep_req("a-sys", ">= 0.0.4, <= 0.1.4"), - dep_req("d-sys", ">= 0.0.1"), - dep("fa"), - dep("s"), - ]), - ]); - let _ = resolve(&pkg_id("root"), vec![dep("sA")], ®); +fn large_conflict_cache() { + let mut input = vec![ + pkg!(("last", "0.0.0") => [dep("bad")]) // just to make sure last is less constrained + ]; + let mut root_deps = vec![dep("last")]; + const NUM_VERSIONS: u8 = 3; + for name in 0..=NUM_VERSIONS { + // a large number of conflicts can easily be generated by a sys crate. + let sys_name = format!("{}-sys", (b'a' + name) as char); + let in_len = input.len(); + input.push(pkg!(("last", format!("{}.0.0", in_len)) => [dep_req(&sys_name, "=0.0.0")])); + root_deps.push(dep_req(&sys_name, ">= 0.0.1")); + + // a large number of conflicts can also easily be generated by a major release version. + let plane_name = format!("{}", (b'a' + name) as char); + let in_len = input.len(); + input.push(pkg!(("last", format!("{}.0.0", in_len)) => [dep_req(&plane_name, "=1.0.0")])); + root_deps.push(dep_req(&plane_name, ">= 1.0.1")); + + for i in 0..=NUM_VERSIONS { + input.push(pkg!((&sys_name, format!("{}.0.0", i)))); + input.push(pkg!((&plane_name, format!("1.0.{}", i)))); + } + } + let reg = registry(input); + let _ = resolve(&pkg_id("root"), root_deps, ®); } From e1ff48b550ca92cd3405cb5bc00e32fa79b54b27 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Wed, 7 Nov 2018 17:07:28 -0500 Subject: [PATCH 042/128] remove the O(n) insertion, but loos the hack for lookup --- src/cargo/core/resolver/conflict_cache.rs | 16 ++++++++-------- src/cargo/core/resolver/context.rs | 15 ++++++++------- src/cargo/core/resolver/errors.rs | 4 ++-- src/cargo/core/resolver/mod.rs | 8 ++++---- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/cargo/core/resolver/conflict_cache.rs b/src/cargo/core/resolver/conflict_cache.rs index 77f131a2581..feacf37486a 100644 --- a/src/cargo/core/resolver/conflict_cache.rs +++ b/src/cargo/core/resolver/conflict_cache.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use super::types::ConflictReason; use core::resolver::Context; @@ -34,7 +34,7 @@ pub(super) struct ConflictCache { // as a global cache which we never delete from. Any entry in this map is // unconditionally true regardless of our resolution history of how we got // here. - con_from_dep: HashMap>>, + con_from_dep: HashMap>>, // `dep_from_pid` is an inverse-index of `con_from_dep`. // For every `PackageId` this lists the `Dependency`s that mention it in `dep_from_pid`. dep_from_pid: HashMap>, @@ -54,9 +54,9 @@ impl ConflictCache { cx: &Context, dep: &Dependency, filter: F, - ) -> Option<&HashMap> + ) -> Option<&BTreeMap> where - for<'r> F: FnMut(&'r &HashMap) -> bool, + for<'r> F: FnMut(&'r &BTreeMap) -> bool, { self.con_from_dep .get(dep)? @@ -69,18 +69,18 @@ impl ConflictCache { &self, cx: &Context, dep: &Dependency, - ) -> Option<&HashMap> { + ) -> Option<&BTreeMap> { self.find_conflicting(cx, dep, |_| true) } /// Add to the cache a conflict of the form: /// `dep` is known to be unresolvable if /// all the `PackageId` entries are activated - pub fn insert(&mut self, dep: &Dependency, con: &HashMap) { + pub fn insert(&mut self, dep: &Dependency, con: &BTreeMap) { let past = self .con_from_dep .entry(dep.clone()) - .or_insert_with(Vec::new); + .or_insert_with(BTreeSet::new); if !past.contains(con) { trace!( "{} = \"{}\" adding a skip {:?}", @@ -88,7 +88,7 @@ impl ConflictCache { dep.version_req(), con ); - past.push(con.clone()); + past.insert(con.clone()); for c in con.keys() { self.dep_from_pid .entry(c.clone()) diff --git a/src/cargo/core/resolver/context.rs b/src/cargo/core/resolver/context.rs index d3c5d545e9a..346ba1e6ed6 100644 --- a/src/cargo/core/resolver/context.rs +++ b/src/cargo/core/resolver/context.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeMap, HashMap, HashSet}; use std::rc::Rc; use core::interning::InternedString; @@ -6,8 +6,8 @@ use core::{Dependency, FeatureValue, PackageId, SourceId, Summary}; use util::CargoResult; use util::Graph; -use super::types::{ConflictReason, DepInfo, GraphNode, Method, RcList, RegistryQueryer}; use super::errors::ActivateResult; +use super::types::{ConflictReason, DepInfo, GraphNode, Method, RcList, RegistryQueryer}; pub use super::encode::{EncodableDependency, EncodablePackageId, EncodableResolve}; pub use super::encode::{Metadata, WorkspaceResolve}; @@ -145,7 +145,7 @@ impl Context { pub fn is_conflicting( &self, parent: Option<&PackageId>, - conflicting_activations: &HashMap, + conflicting_activations: &BTreeMap, ) -> bool { conflicting_activations .keys() @@ -186,10 +186,11 @@ impl Context { // name. let base = reqs.deps.get(&dep.name_in_toml()).unwrap_or(&default_dep); used_features.insert(dep.name_in_toml()); - let always_required = !dep.is_optional() && !s - .dependencies() - .iter() - .any(|d| d.is_optional() && d.name_in_toml() == dep.name_in_toml()); + let always_required = !dep.is_optional() + && !s + .dependencies() + .iter() + .any(|d| d.is_optional() && d.name_in_toml() == dep.name_in_toml()); if always_required && base.0 { self.warnings.push(format!( "Package `{}` does not have feature `{}`. It has a required dependency \ diff --git a/src/cargo/core/resolver/errors.rs b/src/cargo/core/resolver/errors.rs index fbfe5e79e8c..5111abbb6be 100644 --- a/src/cargo/core/resolver/errors.rs +++ b/src/cargo/core/resolver/errors.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::BTreeMap; use std::fmt; use core::{Dependency, PackageId, Registry, Summary}; @@ -73,7 +73,7 @@ pub(super) fn activation_error( registry: &mut Registry, parent: &Summary, dep: &Dependency, - conflicting_activations: &HashMap, + conflicting_activations: &BTreeMap, candidates: &[Candidate], config: Option<&Config>, ) -> ResolveError { diff --git a/src/cargo/core/resolver/mod.rs b/src/cargo/core/resolver/mod.rs index 851dcd85b8f..961c9bd666f 100644 --- a/src/cargo/core/resolver/mod.rs +++ b/src/cargo/core/resolver/mod.rs @@ -247,7 +247,7 @@ fn activate_deps_loop( // // This is a map of package id to a reason why that packaged caused a // conflict for us. - let mut conflicting_activations = HashMap::new(); + let mut conflicting_activations = BTreeMap::new(); // When backtracking we don't fully update `conflicting_activations` // especially for the cases that we didn't make a backtrack frame in the @@ -641,7 +641,7 @@ struct BacktrackFrame { parent: Summary, dep: Dependency, features: Rc>, - conflicting_activations: HashMap, + conflicting_activations: BTreeMap, } /// A helper "iterator" used to extract candidates within a current `Context` of @@ -688,7 +688,7 @@ impl RemainingCandidates { /// original list for the reason listed. fn next( &mut self, - conflicting_prev_active: &mut HashMap, + conflicting_prev_active: &mut BTreeMap, cx: &Context, dep: &Dependency, ) -> Option<(Candidate, bool)> { @@ -781,7 +781,7 @@ fn find_candidate( backtrack_stack: &mut Vec, parent: &Summary, backtracked: bool, - conflicting_activations: &HashMap, + conflicting_activations: &BTreeMap, ) -> Option<(Candidate, bool, BacktrackFrame)> { while let Some(mut frame) = backtrack_stack.pop() { let next = frame.remaining_candidates.next( From 4c8ab5e2eb9ddaae9a5e4fa850520723770ef4f3 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Wed, 7 Nov 2018 21:22:49 -0500 Subject: [PATCH 043/128] remove the O(n) lookup --- src/cargo/core/resolver/conflict_cache.rs | 120 ++++++++++++++++------ src/cargo/core/resolver/context.rs | 2 +- src/cargo/lib.rs | 2 +- tests/testsuite/resolve.rs | 4 +- 4 files changed, 91 insertions(+), 37 deletions(-) diff --git a/src/cargo/core/resolver/conflict_cache.rs b/src/cargo/core/resolver/conflict_cache.rs index feacf37486a..8499dc5666f 100644 --- a/src/cargo/core/resolver/conflict_cache.rs +++ b/src/cargo/core/resolver/conflict_cache.rs @@ -1,40 +1,81 @@ -use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; +use std::collections::{BTreeMap, HashMap, HashSet}; use super::types::ConflictReason; use core::resolver::Context; use core::{Dependency, PackageId}; +enum ConflictStore { + Con(BTreeMap), + Map(HashMap), +} + +impl ConflictStore { + /// Finds any known set of conflicts, if any, + /// which are activated in `cx` and pass the `filter` specified? + pub fn find_conflicting( + &self, + cx: &Context, + filter: &F, + ) -> Option<&BTreeMap> + where + for<'r> F: Fn(&'r &BTreeMap) -> bool, + { + match self { + ConflictStore::Con(c) => { + if filter(&c) { + Some(c) + } else { + None + } + } + ConflictStore::Map(m) => { + for (pid, store) in m { + if cx.is_active(pid) { + if let Some(o) = store.find_conflicting(cx, filter) { + return Some(o); + } + } + } + None + } + } + } +} + pub(super) struct ConflictCache { // `con_from_dep` is a cache of the reasons for each time we // backtrack. For example after several backtracks we may have: // - // con_from_dep[`foo = "^1.0.2"`] = vec![ - // map!{`foo=1.0.1`: Semver}, - // map!{`foo=1.0.0`: Semver}, - // ]; + // con_from_dep[`foo = "^1.0.2"`] = map!{ + // `foo=1.0.1`: map!{`foo=1.0.1`: Semver}, + // `foo=1.0.0`: map!{`foo=1.0.0`: Semver}, + // }; // // This can be read as "we cannot find a candidate for dep `foo = "^1.0.2"` // if either `foo=1.0.1` OR `foo=1.0.0` are activated". // // Another example after several backtracks we may have: // - // con_from_dep[`foo = ">=0.8.2, <=0.9.3"`] = vec![ - // map!{`foo=0.8.1`: Semver, `foo=0.9.4`: Semver}, - // ]; + // con_from_dep[`foo = ">=0.8.2, <=0.9.3"`] = map!{ + // `foo=0.8.1`: map!{ + // `foo=0.9.4`: map!{`foo=0.8.1`: Semver, `foo=0.9.4`: Semver}, + // } + // }; // // This can be read as "we cannot find a candidate for dep `foo = ">=0.8.2, // <=0.9.3"` if both `foo=0.8.1` AND `foo=0.9.4` are activated". // // This is used to make sure we don't queue work we know will fail. See the // discussion in https://github.com/rust-lang/cargo/pull/5168 for why this - // is so important, and there can probably be a better data structure here - // but for now this works well enough! + // is so important. The nested HashMaps act as a kind of btree, that lets us + // look up a witch entry's are still active without + // linearly scanning through the full list. // // Also, as a final note, this map is *not* ever removed from. This remains // as a global cache which we never delete from. Any entry in this map is // unconditionally true regardless of our resolution history of how we got // here. - con_from_dep: HashMap>>, + con_from_dep: HashMap, // `dep_from_pid` is an inverse-index of `con_from_dep`. // For every `PackageId` this lists the `Dependency`s that mention it in `dep_from_pid`. dep_from_pid: HashMap>, @@ -56,14 +97,9 @@ impl ConflictCache { filter: F, ) -> Option<&BTreeMap> where - for<'r> F: FnMut(&'r &BTreeMap) -> bool, + for<'r> F: Fn(&'r &BTreeMap) -> bool, { - self.con_from_dep - .get(dep)? - .iter() - .rev() // more general cases are normally found letter. So start the search there. - .filter(filter) - .find(|conflicting| cx.is_conflicting(None, conflicting)) + self.con_from_dep.get(dep)?.find_conflicting(cx, &filter) } pub fn conflicting( &self, @@ -77,25 +113,43 @@ impl ConflictCache { /// `dep` is known to be unresolvable if /// all the `PackageId` entries are activated pub fn insert(&mut self, dep: &Dependency, con: &BTreeMap) { - let past = self + let mut past = self .con_from_dep .entry(dep.clone()) - .or_insert_with(BTreeSet::new); - if !past.contains(con) { - trace!( - "{} = \"{}\" adding a skip {:?}", - dep.package_name(), - dep.version_req(), - con - ); - past.insert(con.clone()); - for c in con.keys() { - self.dep_from_pid - .entry(c.clone()) - .or_insert_with(HashSet::new) - .insert(dep.clone()); + .or_insert_with(|| ConflictStore::Map(HashMap::new())); + + for pid in con.keys() { + match past { + ConflictStore::Con(_) => { + // We already have a subset of this in the ConflictStore + return; + } + ConflictStore::Map(p) => { + past = p + .entry(pid.clone()) + .or_insert_with(|| ConflictStore::Map(HashMap::new())); + } } } + + if let ConflictStore::Con(_) = past { + // We already have this in the ConflictStore + return; + } + *past = ConflictStore::Con(con.clone()); + trace!( + "{} = \"{}\" adding a skip {:?}", + dep.package_name(), + dep.version_req(), + con + ); + + for c in con.keys() { + self.dep_from_pid + .entry(c.clone()) + .or_insert_with(HashSet::new) + .insert(dep.clone()); + } } pub fn dependencies_conflicting_with(&self, pid: &PackageId) -> Option<&HashSet> { self.dep_from_pid.get(pid) diff --git a/src/cargo/core/resolver/context.rs b/src/cargo/core/resolver/context.rs index 346ba1e6ed6..96fdfd40daf 100644 --- a/src/cargo/core/resolver/context.rs +++ b/src/cargo/core/resolver/context.rs @@ -133,7 +133,7 @@ impl Context { .unwrap_or(&[]) } - fn is_active(&self, id: &PackageId) -> bool { + pub fn is_active(&self, id: &PackageId) -> bool { self.activations .get(&(id.name(), id.source_id().clone())) .map(|v| v.iter().any(|s| s.package_id() == id)) diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs index e7fcac41d24..4d55c9993a2 100644 --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -1,5 +1,5 @@ #![cfg_attr(test, deny(warnings))] - +#![feature(nll)] // Clippy isn't enforced by CI, and know that @alexcrichton isn't a fan :) #![cfg_attr(feature = "cargo-clippy", allow(boxed_local))] // bug rust-lang-nursery/rust-clippy#1123 #![cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))] // large project diff --git a/tests/testsuite/resolve.rs b/tests/testsuite/resolve.rs index a9d4b722a14..3cae07b282c 100644 --- a/tests/testsuite/resolve.rs +++ b/tests/testsuite/resolve.rs @@ -1175,8 +1175,8 @@ fn hard_equality() { #[test] fn large_conflict_cache() { - let mut input = vec![ - pkg!(("last", "0.0.0") => [dep("bad")]) // just to make sure last is less constrained + let mut input = vec![ + pkg!(("last", "0.0.0") => [dep("bad")]), // just to make sure last is less constrained ]; let mut root_deps = vec![dep("last")]; const NUM_VERSIONS: u8 = 3; From 53b535fa26e3e275309873c222e42565b873c1a5 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Thu, 8 Nov 2018 10:44:42 -0500 Subject: [PATCH 044/128] remove the use of NLL --- src/cargo/core/resolver/conflict_cache.rs | 42 +++++++++++------------ src/cargo/lib.rs | 2 +- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/cargo/core/resolver/conflict_cache.rs b/src/cargo/core/resolver/conflict_cache.rs index 8499dc5666f..39423c98faa 100644 --- a/src/cargo/core/resolver/conflict_cache.rs +++ b/src/cargo/core/resolver/conflict_cache.rs @@ -40,6 +40,23 @@ impl ConflictStore { } } } + + pub fn insert<'a>( + &mut self, + mut iter: impl Iterator, + con: BTreeMap, + ) { + if let Some(pid) = iter.next() { + if let ConflictStore::Map(p) = self { + p.entry(pid.clone()) + .or_insert_with(|| ConflictStore::Map(HashMap::new())) + .insert(iter, con); + } + // else, We already have a subset of this in the ConflictStore + } else { + *self = ConflictStore::Con(con) + } + } } pub(super) struct ConflictCache { @@ -113,30 +130,11 @@ impl ConflictCache { /// `dep` is known to be unresolvable if /// all the `PackageId` entries are activated pub fn insert(&mut self, dep: &Dependency, con: &BTreeMap) { - let mut past = self - .con_from_dep + self.con_from_dep .entry(dep.clone()) - .or_insert_with(|| ConflictStore::Map(HashMap::new())); - - for pid in con.keys() { - match past { - ConflictStore::Con(_) => { - // We already have a subset of this in the ConflictStore - return; - } - ConflictStore::Map(p) => { - past = p - .entry(pid.clone()) - .or_insert_with(|| ConflictStore::Map(HashMap::new())); - } - } - } + .or_insert_with(|| ConflictStore::Map(HashMap::new())) + .insert(con.keys(), con.clone()); - if let ConflictStore::Con(_) = past { - // We already have this in the ConflictStore - return; - } - *past = ConflictStore::Con(con.clone()); trace!( "{} = \"{}\" adding a skip {:?}", dep.package_name(), diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs index 4d55c9993a2..e7fcac41d24 100644 --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -1,5 +1,5 @@ #![cfg_attr(test, deny(warnings))] -#![feature(nll)] + // Clippy isn't enforced by CI, and know that @alexcrichton isn't a fan :) #![cfg_attr(feature = "cargo-clippy", allow(boxed_local))] // bug rust-lang-nursery/rust-clippy#1123 #![cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))] // large project From 4e1e3f74239d322daeb32688d2d1a93da60bd870 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 8 Nov 2018 07:06:32 -0800 Subject: [PATCH 045/128] Timeout batch downloads, not each download This commit switches the timeout logic implemented in #6130 to timeout an entire batch of downloads instead of each download individually. Previously if *any* pending download didn't receive data in 30s we would time out, or if *any* pending download didn't receive 10 bytes in 30s we would time out. On very slow network connections this is highly likely to happen as a trickle of incoming bytes may not be spread equally amongst all connections, and not all connections may actually be active at any one point in time. The fix is to instead apply timeout logic for an entire batch of downloads. Only if zero total data isn't received in the timeout window do we time out. Or in other words, if any data for any download is receive we consider it as not being timed out. Similarly any progress on any download counts as progress towards our speed limit. Closes #6284 --- src/cargo/core/package.rs | 81 +++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 41 deletions(-) diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 171ac27e33e..89908ad5e53 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -267,6 +267,17 @@ pub struct Downloads<'a, 'cfg: 'a> { largest: (u64, String), start: Instant, success: bool, + + /// Timeout management, both of timeout thresholds as well as whether or not + /// our connection has timed out (and accompanying message if it has). + /// + /// Note that timeout management is done manually here instead of in libcurl + /// because we want to apply timeouts to an entire batch of operations, not + /// any one particular single operatino + timeout: ops::HttpTimeout, // timeout configuration + updated_at: Cell, // last time we received bytes + next_speed_check: Cell, // if threshold isn't 0 by this time, error + next_speed_check_bytes_threshold: Cell, // decremented when we receive bytes } struct Download<'cfg> { @@ -293,24 +304,7 @@ struct Download<'cfg> { /// The moment we started this transfer at start: Instant, - - /// Last time we noticed that we got some more data from libcurl - updated_at: Cell, - - /// Timeout management, both of timeout thresholds as well as whether or not - /// our connection has timed out (and accompanying message if it has). - /// - /// Note that timeout management is done manually here because we have a - /// `Multi` with a lot of active transfers but between transfers finishing - /// we perform some possibly slow synchronous work (like grabbing file - /// locks, extracting tarballs, etc). The default timers on our `Multi` keep - /// running during this work, but we don't want them to count towards timing - /// everythig out. As a result, we manage this manually and take the time - /// for synchronous work into account manually. - timeout: ops::HttpTimeout, timed_out: Cell>, - next_speed_check: Cell, - next_speed_check_bytes_threshold: Cell, /// Logic used to track retrying this download if it's a spurious failure. retry: Retry<'cfg>, @@ -359,6 +353,7 @@ impl<'cfg> PackageSet<'cfg> { pub fn enable_download<'a>(&'a self) -> CargoResult> { assert!(!self.downloading.replace(true)); + let timeout = ops::HttpTimeout::new(self.config)?; Ok(Downloads { start: Instant::now(), set: self, @@ -375,6 +370,10 @@ impl<'cfg> PackageSet<'cfg> { downloaded_bytes: 0, largest: (0, String::new()), success: false, + updated_at: Cell::new(Instant::now()), + timeout, + next_speed_check: Cell::new(Instant::now()), + next_speed_check_bytes_threshold: Cell::new(0), }) } @@ -446,7 +445,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { debug!("downloading {} as {}", id, token); assert!(self.pending_ids.insert(id.clone())); - let (mut handle, timeout) = ops::http_handle_and_timeout(self.set.config)?; + let (mut handle, _timeout) = ops::http_handle_and_timeout(self.set.config)?; handle.get(true)?; handle.url(&url)?; handle.follow_location(true)?; // follow redirects @@ -501,7 +500,6 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { self.set.config.shell().status("Downloading", "crates ...")?; } - let now = Instant::now(); let dl = Download { token, data: RefCell::new(Vec::new()), @@ -511,11 +509,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { total: Cell::new(0), current: Cell::new(0), start: Instant::now(), - updated_at: Cell::new(now), - timeout, timed_out: Cell::new(None), - next_speed_check: Cell::new(now), - next_speed_check_bytes_threshold: Cell::new(0), retry: Retry::new(self.set.config)?, }; self.enqueue(dl, handle)?; @@ -638,10 +632,8 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { // active downloads to make sure they don't fire because of a slowly // extracted tarball. let finish_dur = start.elapsed(); - for (dl, _) in self.pending.values_mut() { - dl.updated_at.set(dl.updated_at.get() + finish_dur); - dl.next_speed_check.set(dl.next_speed_check.get() + finish_dur); - } + self.updated_at.set(self.updated_at.get() + finish_dur); + self.next_speed_check.set(self.next_speed_check.get() + finish_dur); let slot = &self.set.packages[&dl.id]; assert!(slot.fill(pkg).is_ok()); @@ -652,12 +644,12 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { let mut handle = self.set.multi.add(handle)?; let now = Instant::now(); handle.set_token(dl.token)?; + self.updated_at.set(now); + self.next_speed_check.set(now + self.timeout.dur); + self.next_speed_check_bytes_threshold.set(self.timeout.low_speed_limit as u64); dl.timed_out.set(None); - dl.updated_at.set(now); dl.current.set(0); dl.total.set(0); - dl.next_speed_check.set(now + dl.timeout.dur); - dl.next_speed_check_bytes_threshold.set(dl.timeout.low_speed_limit as u64); self.pending.insert(dl.token, (dl, handle)); Ok(()) } @@ -712,14 +704,19 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { dl.total.set(total); let now = Instant::now(); if cur != dl.current.get() { + let delta = cur - dl.current.get(); + let threshold = self.next_speed_check_bytes_threshold.get(); + dl.current.set(cur); - dl.updated_at.set(now); + self.updated_at.set(now); - if dl.current.get() >= dl.next_speed_check_bytes_threshold.get() { - dl.next_speed_check.set(now + dl.timeout.dur); - dl.next_speed_check_bytes_threshold.set( - dl.current.get() + dl.timeout.low_speed_limit as u64, + if delta >= threshold { + self.next_speed_check.set(now + self.timeout.dur); + self.next_speed_check_bytes_threshold.set( + self.timeout.low_speed_limit as u64, ); + } else { + self.next_speed_check_bytes_threshold.set(threshold - delta); } } if !self.tick(WhyTick::DownloadUpdate).is_ok() { @@ -727,10 +724,11 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { } // If we've spent too long not actually receiving any data we time out. - if now - dl.updated_at.get() > dl.timeout.dur { + if now - self.updated_at.get() > self.timeout.dur { + self.updated_at.set(now); let msg = format!("failed to download any data for `{}` within {}s", dl.id, - dl.timeout.dur.as_secs()); + self.timeout.dur.as_secs()); dl.timed_out.set(Some(msg)); return false } @@ -739,13 +737,14 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { // limit, see if we've transferred enough data during this threshold. If // it fails this check then we fail because the download is going too // slowly. - if now >= dl.next_speed_check.get() { - assert!(dl.current.get() < dl.next_speed_check_bytes_threshold.get()); + if now >= self.next_speed_check.get() { + self.next_speed_check.set(now + self.timeout.dur); + assert!(self.next_speed_check_bytes_threshold.get() > 0); let msg = format!("download of `{}` failed to transfer more \ than {} bytes in {}s", dl.id, - dl.timeout.low_speed_limit, - dl.timeout.dur.as_secs()); + self.timeout.low_speed_limit, + self.timeout.dur.as_secs()); dl.timed_out.set(Some(msg)); return false } From 17b6df9c42b61777d8482a465814822ac58b397a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 7 Nov 2018 19:24:25 -0800 Subject: [PATCH 046/128] Avoid retaining all rustc output in memory. --- src/cargo/core/compiler/job_queue.rs | 4 +-- src/cargo/util/process_builder.rs | 40 +++++++++++++++++----------- tests/testsuite/support/mod.rs | 2 +- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/cargo/core/compiler/job_queue.rs b/src/cargo/core/compiler/job_queue.rs index 5ee957d7f31..f97c7421a9e 100644 --- a/src/cargo/core/compiler/job_queue.rs +++ b/src/cargo/core/compiler/job_queue.rs @@ -113,7 +113,7 @@ impl<'a> JobState<'a> { &self, cmd: &ProcessBuilder, prefix: Option, - print_output: bool, + capture_output: bool, ) -> CargoResult { let prefix = prefix.unwrap_or_else(|| String::new()); cmd.exec_with_streaming( @@ -125,7 +125,7 @@ impl<'a> JobState<'a> { let _ = self.tx.send(Message::Stderr(format!("{}{}", prefix, err))); Ok(()) }, - print_output, + capture_output, ) } } diff --git a/src/cargo/util/process_builder.rs b/src/cargo/util/process_builder.rs index e6a4c03eb01..26655d31fdd 100644 --- a/src/cargo/util/process_builder.rs +++ b/src/cargo/util/process_builder.rs @@ -202,7 +202,7 @@ impl ProcessBuilder { &self, on_stdout_line: &mut FnMut(&str) -> CargoResult<()>, on_stderr_line: &mut FnMut(&str) -> CargoResult<()>, - print_output: bool, + capture_output: bool, ) -> CargoResult { let mut stdout = Vec::new(); let mut stderr = Vec::new(); @@ -226,23 +226,33 @@ impl ProcessBuilder { None => return, } }; - let data = data.drain(..idx); - let dst = if is_out { &mut stdout } else { &mut stderr }; - let start = dst.len(); - dst.extend(data); - for line in String::from_utf8_lossy(&dst[start..]).lines() { - if callback_error.is_some() { - break; - } - let callback_result = if is_out { - on_stdout_line(line) + { // scope for new_lines + let new_lines = if capture_output { + let dst = if is_out { &mut stdout } else { &mut stderr }; + let start = dst.len(); + let data = data.drain(..idx); + dst.extend(data); + &dst[start..] } else { - on_stderr_line(line) + &data[..idx] }; - if let Err(e) = callback_result { - callback_error = Some(e); + for line in String::from_utf8_lossy(new_lines).lines() { + if callback_error.is_some() { + break; + } + let callback_result = if is_out { + on_stdout_line(line) + } else { + on_stderr_line(line) + }; + if let Err(e) = callback_result { + callback_error = Some(e); + } } } + if !capture_output { + data.drain(..idx); + } })?; child.wait() })() @@ -260,7 +270,7 @@ impl ProcessBuilder { }; { - let to_print = if print_output { Some(&output) } else { None }; + let to_print = if capture_output { Some(&output) } else { None }; if !output.status.success() { return Err(process_error( &format!("process didn't exit successfully: {}", self), diff --git a/tests/testsuite/support/mod.rs b/tests/testsuite/support/mod.rs index 9d818070ce6..06b7c6c3df9 100644 --- a/tests/testsuite/support/mod.rs +++ b/tests/testsuite/support/mod.rs @@ -770,7 +770,7 @@ impl Execs { process.exec_with_streaming( &mut |out| Ok(println!("{}", out)), &mut |err| Ok(eprintln!("{}", err)), - false, + true, ) } else { process.exec_with_output() From 61f9588cfd8a797544c9a91b4458ba6499b372fd Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 8 Nov 2018 21:05:17 -0800 Subject: [PATCH 047/128] Don't hardlink rmeta files. --- .../compiler/context/compilation_files.rs | 10 ++--- tests/testsuite/check.rs | 45 ++++++++++--------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/cargo/core/compiler/context/compilation_files.rs b/src/cargo/core/compiler/context/compilation_files.rs index cbb479e44f8..829ca306b55 100644 --- a/src/cargo/core/compiler/context/compilation_files.rs +++ b/src/cargo/core/compiler/context/compilation_files.rs @@ -245,16 +245,12 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { let mut unsupported = Vec::new(); { if unit.mode.is_check() { - // This is not quite correct for non-lib targets. rustc - // currently does not emit rmeta files, so there is nothing to - // check for! See #3624. + // This may be confusing. rustc outputs a file named `lib*.rmeta` + // for both libraries and binaries. let path = out_dir.join(format!("lib{}.rmeta", file_stem)); - let hardlink = link_stem - .clone() - .map(|(ld, ls)| ld.join(format!("lib{}.rmeta", ls))); ret.push(OutputFile { path, - hardlink, + hardlink: None, flavor: FileFlavor::Linkable, }); } else { diff --git a/tests/testsuite/check.rs b/tests/testsuite/check.rs index 3322986ad67..f743991b240 100644 --- a/tests/testsuite/check.rs +++ b/tests/testsuite/check.rs @@ -2,7 +2,6 @@ use std::fmt::{self, Write}; use glob::glob; use support::install::exe; -use support::is_nightly; use support::paths::CargoPathExt; use support::registry::Package; use support::{basic_manifest, project}; @@ -573,39 +572,44 @@ fn check_artifacts() { .file("examples/ex1.rs", "fn main() {}") .file("benches/b1.rs", "") .build(); + + let assert_glob = |path: &str, count: usize| { + assert_eq!( + glob(&p.root().join(path).to_str().unwrap()) + .unwrap() + .count(), + count + ); + }; + p.cargo("check").run(); - assert!(p.root().join("target/debug/libfoo.rmeta").is_file()); + assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); + assert_glob("target/debug/deps/libfoo-*.rmeta", 2); p.root().join("target").rm_rf(); p.cargo("check --lib").run(); - assert!(p.root().join("target/debug/libfoo.rmeta").is_file()); + assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); + assert_glob("target/debug/deps/libfoo-*.rmeta", 1); p.root().join("target").rm_rf(); p.cargo("check --bin foo").run(); - if is_nightly() { - // The nightly check can be removed once 1.27 is stable. - // Bins now generate `rmeta` files. - // See: https://github.com/rust-lang/rust/pull/49289 - assert!(p.root().join("target/debug/libfoo.rmeta").is_file()); - } + assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); + assert_glob("target/debug/deps/libfoo-*.rmeta", 2); p.root().join("target").rm_rf(); p.cargo("check --test t1").run(); assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); - assert_eq!( - glob(&p.root().join("target/debug/t1-*").to_str().unwrap()) - .unwrap() - .count(), - 0 - ); + assert_glob("target/debug/t1-*", 0); + assert_glob("target/debug/deps/libfoo-*.rmeta", 1); + assert_glob("target/debug/deps/libt1-*.rmeta", 1); p.root().join("target").rm_rf(); p.cargo("check --example ex1").run(); @@ -617,18 +621,17 @@ fn check_artifacts() { .join(exe("ex1")) .is_file() ); + assert_glob("target/debug/deps/libfoo-*.rmeta", 1); + assert_glob("target/debug/examples/libex1-*.rmeta", 1); p.root().join("target").rm_rf(); p.cargo("check --bench b1").run(); assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); - assert_eq!( - glob(&p.root().join("target/debug/b1-*").to_str().unwrap()) - .unwrap() - .count(), - 0 - ); + assert_glob("target/debug/b1-*", 0); + assert_glob("target/debug/deps/libfoo-*.rmeta", 1); + assert_glob("target/debug/deps/libb1-*.rmeta", 1); } #[test] From 3f0c788aed7e4a3804b099ed1dba23c038d3ee5d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 8 Nov 2018 17:40:08 -0800 Subject: [PATCH 048/128] Show error on JSON parse error and nonzero exit. --- src/cargo/util/process_builder.rs | 18 ++++---- tests/testsuite/build.rs | 68 +++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/src/cargo/util/process_builder.rs b/src/cargo/util/process_builder.rs index 26655d31fdd..ca44042c33b 100644 --- a/src/cargo/util/process_builder.rs +++ b/src/cargo/util/process_builder.rs @@ -5,6 +5,7 @@ use std::fmt; use std::path::Path; use std::process::{Command, Output, Stdio}; +use failure::Fail; use jobserver::Client; use shell_escape::escape; @@ -271,19 +272,20 @@ impl ProcessBuilder { { let to_print = if capture_output { Some(&output) } else { None }; - if !output.status.success() { - return Err(process_error( - &format!("process didn't exit successfully: {}", self), - Some(output.status), - to_print, - ).into()); - } else if let Some(e) = callback_error { + if let Some(e) = callback_error { let cx = process_error( &format!("failed to parse process output: {}", self), Some(output.status), to_print, ); - return Err(e.context(cx).into()); + return Err(cx.context(e).into()); + } else if !output.status.success() { + return Err(process_error( + &format!("process didn't exit successfully: {}", self), + Some(output.status), + to_print, + ) + .into()); } } diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index 5f5a69c8e38..dc72669a48c 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -4435,3 +4435,71 @@ Caused by: .with_status(101) .run(); } + +#[test] +fn json_parse_fail() { + // Ensure when json parsing fails, and rustc exits with non-zero exit + // code, that a useful error message is displayed. + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + [dependencies] + pm = { path = "pm" } + "#, + ) + .file( + "src/lib.rs", + r#" + #[macro_use] + extern crate pm; + + #[derive(Foo)] + pub struct S; + "#, + ) + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + [lib] + proc-macro = true + "#, + ) + .file( + "pm/src/lib.rs", + r#" + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro_derive(Foo)] + pub fn derive(_input: TokenStream) -> TokenStream { + eprintln!("{{evil proc macro}}"); + panic!("something went wrong"); + } + "#, + ) + .build(); + + foo.cargo("build --message-format=json") + .with_stderr( + "\ +[COMPILING] pm [..] +[COMPILING] foo [..] +[ERROR] Could not compile `foo`. + +Caused by: + compiler produced invalid json: `{evil proc macro}` + +Caused by: + failed to parse process output: `rustc [..] +", + ) + .with_status(101) + .run(); +} From d070f06e04dbf2929d868e31094dfff284c3dba9 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Fri, 9 Nov 2018 11:23:36 -0500 Subject: [PATCH 049/128] add comments and pick better names --- src/cargo/core/resolver/conflict_cache.rs | 47 ++++++++++++++++------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/cargo/core/resolver/conflict_cache.rs b/src/cargo/core/resolver/conflict_cache.rs index 39423c98faa..75fd528622d 100644 --- a/src/cargo/core/resolver/conflict_cache.rs +++ b/src/cargo/core/resolver/conflict_cache.rs @@ -4,15 +4,20 @@ use super::types::ConflictReason; use core::resolver::Context; use core::{Dependency, PackageId}; +/// This is a data structure for storing a large number of Sets designed to +/// efficiently see if any of the stored Sets are a subset of a search Set. enum ConflictStore { - Con(BTreeMap), - Map(HashMap), + /// a Leaf is one of the stored Sets. + Leaf(BTreeMap), + /// a Node is a map from an element to a subset of the stored data + /// where all the Sets in the subset contains that element. + Node(HashMap), } impl ConflictStore { /// Finds any known set of conflicts, if any, /// which are activated in `cx` and pass the `filter` specified? - pub fn find_conflicting( + fn find_conflicting( &self, cx: &Context, filter: &F, @@ -21,17 +26,23 @@ impl ConflictStore { for<'r> F: Fn(&'r &BTreeMap) -> bool, { match self { - ConflictStore::Con(c) => { + ConflictStore::Leaf(c) => { if filter(&c) { Some(c) } else { None } } - ConflictStore::Map(m) => { + ConflictStore::Node(m) => { for (pid, store) in m { + // if the key is active then we need to check all of the corresponding subset, + // but if it is not active then there is no way any of the corresponding subset + // will be conflicting. if cx.is_active(pid) { if let Some(o) = store.find_conflicting(cx, filter) { + debug_assert!(cx.is_conflicting(None, o)); + // is_conflicting checks that all the elements are active, + // but we have checked each one by the recursion of this function. return Some(o); } } @@ -41,20 +52,30 @@ impl ConflictStore { } } - pub fn insert<'a>( + fn insert<'a>( &mut self, mut iter: impl Iterator, con: BTreeMap, ) { if let Some(pid) = iter.next() { - if let ConflictStore::Map(p) = self { + if let ConflictStore::Node(p) = self { p.entry(pid.clone()) - .or_insert_with(|| ConflictStore::Map(HashMap::new())) + .or_insert_with(|| ConflictStore::Node(HashMap::new())) .insert(iter, con); - } - // else, We already have a subset of this in the ConflictStore + } // else, We already have a subset of this in the ConflictStore } else { - *self = ConflictStore::Con(con) + // we are at the end of the set we are adding, there are 3 cases for what to do next: + // 1. self is a empty dummy Node inserted by `or_insert_with` + // in witch case we should replace it with `Leaf(con)`. + // 2. self is a Node because we previously inserted a superset of + // the thing we are working on (I don't know if this happens in practice) + // but the subset that we are working on will + // always match any time the larger set would have + // in witch case we can replace it with `Leaf(con)`. + // 3. self is a Leaf that is in the same spot in the structure as + // the thing we are working on. So it is equivalent. + // We can replace it with `Leaf(con)`. + *self = ConflictStore::Leaf(con) } } } @@ -85,7 +106,7 @@ pub(super) struct ConflictCache { // This is used to make sure we don't queue work we know will fail. See the // discussion in https://github.com/rust-lang/cargo/pull/5168 for why this // is so important. The nested HashMaps act as a kind of btree, that lets us - // look up a witch entry's are still active without + // look up which entries are still active without // linearly scanning through the full list. // // Also, as a final note, this map is *not* ever removed from. This remains @@ -132,7 +153,7 @@ impl ConflictCache { pub fn insert(&mut self, dep: &Dependency, con: &BTreeMap) { self.con_from_dep .entry(dep.clone()) - .or_insert_with(|| ConflictStore::Map(HashMap::new())) + .or_insert_with(|| ConflictStore::Node(HashMap::new())) .insert(con.keys(), con.clone()); trace!( From 178ee0b611c97859086a33252dc6f1f9260b602e Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Fri, 9 Nov 2018 13:04:00 -0500 Subject: [PATCH 050/128] address suggestions --- src/cargo/core/resolver/conflict_cache.rs | 46 +++++++++++++---------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/cargo/core/resolver/conflict_cache.rs b/src/cargo/core/resolver/conflict_cache.rs index 75fd528622d..670bf48b362 100644 --- a/src/cargo/core/resolver/conflict_cache.rs +++ b/src/cargo/core/resolver/conflict_cache.rs @@ -4,17 +4,17 @@ use super::types::ConflictReason; use core::resolver::Context; use core::{Dependency, PackageId}; -/// This is a data structure for storing a large number of Sets designed to +/// This is a Trie for storing a large number of Sets designed to /// efficiently see if any of the stored Sets are a subset of a search Set. -enum ConflictStore { +enum ConflictStoreTrie { /// a Leaf is one of the stored Sets. Leaf(BTreeMap), - /// a Node is a map from an element to a subset of the stored data - /// where all the Sets in the subset contains that element. - Node(HashMap), + /// a Node is a map from an element to a subTrie where + /// all the Sets in the subTrie contains that element. + Node(HashMap), } -impl ConflictStore { +impl ConflictStoreTrie { /// Finds any known set of conflicts, if any, /// which are activated in `cx` and pass the `filter` specified? fn find_conflicting( @@ -26,26 +26,25 @@ impl ConflictStore { for<'r> F: Fn(&'r &BTreeMap) -> bool, { match self { - ConflictStore::Leaf(c) => { + ConflictStoreTrie::Leaf(c) => { if filter(&c) { + // is_conflicting checks that all the elements are active, + // but we have checked each one by the recursion of this function. + debug_assert!(cx.is_conflicting(None, c)); Some(c) } else { None } } - ConflictStore::Node(m) => { + ConflictStoreTrie::Node(m) => { for (pid, store) in m { - // if the key is active then we need to check all of the corresponding subset, - // but if it is not active then there is no way any of the corresponding subset - // will be conflicting. + // if the key is active then we need to check all of the corresponding subTrie. if cx.is_active(pid) { if let Some(o) = store.find_conflicting(cx, filter) { - debug_assert!(cx.is_conflicting(None, o)); - // is_conflicting checks that all the elements are active, - // but we have checked each one by the recursion of this function. return Some(o); } - } + } // else, if it is not active then there is no way any of the corresponding + // subTrie will be conflicting. } None } @@ -58,9 +57,9 @@ impl ConflictStore { con: BTreeMap, ) { if let Some(pid) = iter.next() { - if let ConflictStore::Node(p) = self { + if let ConflictStoreTrie::Node(p) = self { p.entry(pid.clone()) - .or_insert_with(|| ConflictStore::Node(HashMap::new())) + .or_insert_with(|| ConflictStoreTrie::Node(HashMap::new())) .insert(iter, con); } // else, We already have a subset of this in the ConflictStore } else { @@ -75,7 +74,14 @@ impl ConflictStore { // 3. self is a Leaf that is in the same spot in the structure as // the thing we are working on. So it is equivalent. // We can replace it with `Leaf(con)`. - *self = ConflictStore::Leaf(con) + if cfg!(debug_assertions) { + if let ConflictStoreTrie::Leaf(c) = self { + let a: Vec<_> = con.keys().collect(); + let b: Vec<_> = c.keys().collect(); + assert_eq!(a, b); + } + } + *self = ConflictStoreTrie::Leaf(con) } } } @@ -113,7 +119,7 @@ pub(super) struct ConflictCache { // as a global cache which we never delete from. Any entry in this map is // unconditionally true regardless of our resolution history of how we got // here. - con_from_dep: HashMap, + con_from_dep: HashMap, // `dep_from_pid` is an inverse-index of `con_from_dep`. // For every `PackageId` this lists the `Dependency`s that mention it in `dep_from_pid`. dep_from_pid: HashMap>, @@ -153,7 +159,7 @@ impl ConflictCache { pub fn insert(&mut self, dep: &Dependency, con: &BTreeMap) { self.con_from_dep .entry(dep.clone()) - .or_insert_with(|| ConflictStore::Node(HashMap::new())) + .or_insert_with(|| ConflictStoreTrie::Node(HashMap::new())) .insert(con.keys(), con.clone()); trace!( From 1abf5a08d0937d826c3b232c133b8e8379427c67 Mon Sep 17 00:00:00 2001 From: tangentstorm Date: Sat, 10 Nov 2018 11:19:54 -0500 Subject: [PATCH 051/128] try out to" -> "try to" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit specifying dependencies: "try out to" -> "try to" … "try out to" just doesn't sound quite right in English. --- src/doc/src/reference/specifying-dependencies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/src/reference/specifying-dependencies.md b/src/doc/src/reference/specifying-dependencies.md index e2401838cb5..6fa8dfecb3d 100644 --- a/src/doc/src/reference/specifying-dependencies.md +++ b/src/doc/src/reference/specifying-dependencies.md @@ -200,7 +200,7 @@ section here. Let's say you're working with the [`uuid` crate] but while you're working on it you discover a bug. You are, however, quite enterprising so you decide to also -try out to fix the bug! Originally your manifest will look like: +try to fix the bug! Originally your manifest will look like: [`uuid` crate]: https://crates.io/crates/uuid From e66c413b864c1ca17e751ac01a5312b8666a86fe Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Wed, 31 Oct 2018 08:34:04 -0400 Subject: [PATCH 052/128] Support untyped warnings from crates.io with successful publish --- src/cargo/ops/registry.rs | 6 ++++++ src/crates-io/lib.rs | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index 3932abdbece..2993fb7060d 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -276,6 +276,12 @@ fn transmit( config.shell().warn(&msg)?; } + if !warnings.other.is_empty() { + for msg in warnings.other { + config.shell().warn(&msg)?; + } + } + Ok(()) } Err(e) => Err(e), diff --git a/src/crates-io/lib.rs b/src/crates-io/lib.rs index 6de2f30533a..65843e7dcca 100644 --- a/src/crates-io/lib.rs +++ b/src/crates-io/lib.rs @@ -86,6 +86,7 @@ pub struct User { pub struct Warnings { pub invalid_categories: Vec, pub invalid_badges: Vec, + pub other: Vec, } #[derive(Deserialize)] @@ -223,9 +224,17 @@ impl Registry { .map(|x| x.iter().flat_map(|j| j.as_str()).map(Into::into).collect()) .unwrap_or_else(Vec::new); + let other: Vec = response + .get("warnings") + .and_then(|j| j.get("other")) + .and_then(|j| j.as_array()) + .map(|x| x.iter().flat_map(|j| j.as_str()).map(Into::into).collect()) + .unwrap_or_else(Vec::new); + Ok(Warnings { invalid_categories, invalid_badges, + other, }) } From 27e6b1840cb6a77aaf38d800151a191cce38c1aa Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 10 Nov 2018 09:48:07 -0800 Subject: [PATCH 053/128] Don't include build scripts in --out-dir. --- src/cargo/core/compiler/mod.rs | 10 ++++++---- tests/testsuite/out_dir.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 6f9a42df069..af8eb2c0192 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -437,11 +437,13 @@ fn link_targets<'a, 'cfg>( destinations.push(dst.display().to_string()); hardlink_or_copy(src, dst)?; if let Some(ref path) = export_dir { - if !path.exists() { - fs::create_dir_all(path)?; - } + if !target.is_custom_build() { + if !path.exists() { + fs::create_dir_all(path)?; + } - hardlink_or_copy(src, &path.join(dst.file_name().unwrap()))?; + hardlink_or_copy(src, &path.join(dst.file_name().unwrap()))?; + } } } diff --git a/tests/testsuite/out_dir.rs b/tests/testsuite/out_dir.rs index 2700e528d2c..04a224052ad 100644 --- a/tests/testsuite/out_dir.rs +++ b/tests/testsuite/out_dir.rs @@ -203,6 +203,37 @@ fn replaces_artifacts() { .run(); } +#[test] +fn avoid_build_scripts() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/main.rs", "fn main() {}") + .file("a/build.rs", r#"fn main() { println!("hello-build-a"); }"#) + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/main.rs", "fn main() {}") + .file("b/build.rs", r#"fn main() { println!("hello-build-b"); }"#) + .build(); + + p.cargo("build -Z unstable-options --out-dir out -vv") + .masquerade_as_nightly_cargo() + .with_stdout_contains("[a 0.0.1] hello-build-a") + .with_stdout_contains("[b 0.0.1] hello-build-b") + .run(); + check_dir_contents( + &p.root().join("out"), + &["a", "b"], + &["a", "a.dSYM", "b", "b.dSYM"], + &["a.exe", "a.pdb", "b.exe", "b.pdb"], + ); +} + fn check_dir_contents( out_dir: &Path, expected_linux: &[&str], From d3e22d81fdd390ecb147ab3e65f1f827717005a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Mon, 12 Nov 2018 05:44:45 +0000 Subject: [PATCH 054/128] Update env_logger requirement from 0.5.11 to 0.6.0 Updates the requirements on [env_logger](https://github.com/sebasmagri/env_logger) to permit the latest version. - [Release notes](https://github.com/sebasmagri/env_logger/releases) - [Commits](https://github.com/sebasmagri/env_logger/commits/v0.6.0) Signed-off-by: dependabot[bot] --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 11236d32874..7f7636f3ca9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ crossbeam-utils = "0.5" crypto-hash = "0.3.1" curl = { version = "0.4.19", features = ['http2'] } curl-sys = "0.4.15" -env_logger = "0.5.11" +env_logger = "0.6.0" failure = "0.1.2" filetime = "0.2" flate2 = "1.0.3" From 630067e34f2a7b1d5194211024dc93b32d0cf2cd Mon Sep 17 00:00:00 2001 From: Squirrel Date: Mon, 12 Nov 2018 08:27:39 +0000 Subject: [PATCH 055/128] Git repos pointing to workspaces Docs were not clear that member crates in workspaces could be accessed via a git dependency. Please feel free to edit my edit to make it clearer! --- src/doc/src/reference/specifying-dependencies.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/src/reference/specifying-dependencies.md b/src/doc/src/reference/specifying-dependencies.md index 6fa8dfecb3d..4bc4dedac4c 100644 --- a/src/doc/src/reference/specifying-dependencies.md +++ b/src/doc/src/reference/specifying-dependencies.md @@ -113,7 +113,8 @@ rand = { git = "https://github.com/rust-lang-nursery/rand" } Cargo will fetch the `git` repository at this location then look for a `Cargo.toml` for the requested crate anywhere inside the `git` repository -(not necessarily at the root). +(not necessarily at the root - for example, specifying a member crate name +of a workspace and setting `git` to the repository containing the workspace). Since we haven’t specified any other information, Cargo assumes that we intend to use the latest commit on the `master` branch to build our package. From 5e71ad6c5b4b4f9d63400464d331c6d210ac8e70 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 12 Nov 2018 08:04:28 -0800 Subject: [PATCH 056/128] Upgrade crossbeam-utils to 0.6.0 --- Cargo.toml | 2 +- src/cargo/core/compiler/job_queue.rs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 11236d32874..0643972ffc8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ path = "src/cargo/lib.rs" atty = "0.2" bytesize = "1.0" crates-io = { path = "src/crates-io", version = "0.21" } -crossbeam-utils = "0.5" +crossbeam-utils = "0.6" crypto-hash = "0.3.1" curl = { version = "0.4.19", features = ['http2'] } curl-sys = "0.4.15" diff --git a/src/cargo/core/compiler/job_queue.rs b/src/cargo/core/compiler/job_queue.rs index f97c7421a9e..806412bcda0 100644 --- a/src/cargo/core/compiler/job_queue.rs +++ b/src/cargo/core/compiler/job_queue.rs @@ -201,7 +201,9 @@ impl<'a> JobQueue<'a> { srv.start(move |msg| drop(tx2.send(Message::FixDiagnostic(msg)))) }); - crossbeam_utils::thread::scope(|scope| self.drain_the_queue(cx, plan, scope, &helper)) + crossbeam_utils::thread::scope(|scope| { + self.drain_the_queue(cx, plan, scope, &helper) + }).expect("child threads should't panic") } fn drain_the_queue( @@ -409,7 +411,7 @@ impl<'a> JobQueue<'a> { match fresh { Freshness::Fresh => doit(), Freshness::Dirty => { - scope.spawn(doit); + scope.spawn(move |_| doit()); } } From fa0787aaf7720f5f2b671b8e3bd594c0d228dc5c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 12 Nov 2018 07:13:13 -0800 Subject: [PATCH 057/128] Check for duplicate output filenames. --- src/cargo/core/compiler/build_config.rs | 2 +- .../compiler/context/compilation_files.rs | 15 ++- src/cargo/core/compiler/context/mod.rs | 109 ++++++++++++++---- src/cargo/core/compiler/fingerprint.rs | 11 +- src/cargo/core/compiler/mod.rs | 13 +-- src/cargo/core/manifest.rs | 17 ++- src/cargo/core/package.rs | 13 +++ src/cargo/core/profiles.rs | 4 +- tests/testsuite/build.rs | 4 +- tests/testsuite/collisions.rs | 103 +++++++++++++++++ tests/testsuite/main.rs | 1 + 11 files changed, 247 insertions(+), 45 deletions(-) create mode 100644 tests/testsuite/collisions.rs diff --git a/src/cargo/core/compiler/build_config.rs b/src/cargo/core/compiler/build_config.rs index 77ed087eee3..1add81d0e58 100644 --- a/src/cargo/core/compiler/build_config.rs +++ b/src/cargo/core/compiler/build_config.rs @@ -111,7 +111,7 @@ pub enum MessageFormat { /// `compile_ws` to tell it the general execution strategy. This influences /// the default targets selected. The other use is in the `Unit` struct /// to indicate what is being done with a specific target. -#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)] pub enum CompileMode { /// A target being built for a test. Test, diff --git a/src/cargo/core/compiler/context/compilation_files.rs b/src/cargo/core/compiler/context/compilation_files.rs index 829ca306b55..121eba773ed 100644 --- a/src/cargo/core/compiler/context/compilation_files.rs +++ b/src/cargo/core/compiler/context/compilation_files.rs @@ -38,11 +38,13 @@ pub struct CompilationFiles<'a, 'cfg: 'a> { #[derive(Debug)] pub struct OutputFile { - /// File name that will be produced by the build process (in `deps`). + /// Absolute path to the file that will be produced by the build process. pub path: PathBuf, /// If it should be linked into `target`, and what it should be called /// (e.g. without metadata). pub hardlink: Option, + /// If `--out-dir` is specified, the absolute path to the exported file. + pub export_path: Option, /// Type of the file (library / debug symbol / else). pub flavor: FileFlavor, } @@ -251,6 +253,7 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { ret.push(OutputFile { path, hardlink: None, + export_path: None, flavor: FileFlavor::Linkable, }); } else { @@ -273,9 +276,19 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { let hardlink = link_stem .as_ref() .map(|&(ref ld, ref ls)| ld.join(file_type.filename(ls))); + let export_path = if unit.target.is_custom_build() { + None + } else { + self.export_dir.as_ref().and_then(|export_dir| { + hardlink.as_ref().and_then(|hardlink| { + Some(export_dir.join(hardlink.file_name().unwrap())) + }) + }) + }; ret.push(OutputFile { path, hardlink, + export_path, flavor: file_type.flavor, }); }, diff --git a/src/cargo/core/compiler/context/mod.rs b/src/cargo/core/compiler/context/mod.rs index 334a3876aa9..83d18f8f152 100644 --- a/src/cargo/core/compiler/context/mod.rs +++ b/src/cargo/core/compiler/context/mod.rs @@ -4,8 +4,8 @@ use std::ffi::OsStr; use std::fmt::Write; use std::path::PathBuf; use std::sync::Arc; -use std::cmp::Ordering; +use failure::Error; use jobserver::Client; use core::{Package, PackageId, Resolve, Target}; @@ -42,7 +42,7 @@ use self::compilation_files::CompilationFiles; /// example, it needs to know the target architecture (OS, chip arch etc.) and it needs to know /// whether you want a debug or release build. There is enough information in this struct to figure /// all that out. -#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug, PartialOrd, Ord)] pub struct Unit<'a> { /// Information about available targets, which files to include/exclude, etc. Basically stuff in /// `Cargo.toml`. @@ -72,18 +72,6 @@ impl<'a> Unit<'a> { } } -impl<'a> Ord for Unit<'a> { - fn cmp(&self, other: &Unit) -> Ordering { - self.buildkey().cmp(&other.buildkey()) - } -} - -impl<'a> PartialOrd for Unit<'a> { - fn partial_cmp(&self, other: &Unit) -> Option { - Some(self.cmp(other)) - } -} - pub struct Context<'a, 'cfg: 'a> { pub bcx: &'a BuildContext<'a, 'cfg>, pub compilation: Compilation<'cfg>, @@ -150,6 +138,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> { self.prepare_units(export_dir, units)?; self.prepare()?; custom_build::build_map(&mut self, units)?; + self.check_collistions()?; for unit in units.iter() { // Build up a list of pending jobs, each of which represent @@ -353,13 +342,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> { self.files.as_mut().unwrap() } - /// Return the filenames that the given target for the given profile will - /// generate as a list of 3-tuples (filename, link_dst, linkable) - /// - /// - filename: filename rustc compiles to. (Often has metadata suffix). - /// - link_dst: Optional file to link/copy the result to (without metadata suffix) - /// - linkable: Whether possible to link against file (eg it's a library) - pub fn outputs(&mut self, unit: &Unit<'a>) -> CargoResult>> { + /// Return the filenames that the given unit will generate. + pub fn outputs(&self, unit: &Unit<'a>) -> CargoResult>> { self.files.as_ref().unwrap().outputs(unit, self.bcx) } @@ -468,6 +452,89 @@ impl<'a, 'cfg> Context<'a, 'cfg> { inputs.sort(); Ok(inputs) } + + fn check_collistions(&self) -> CargoResult<()> { + let mut output_collisions = HashMap::new(); + let describe_collision = |unit: &Unit, other_unit: &Unit, path: &PathBuf| -> String { + format!( + "The {} target `{}` in package `{}` has the same output \ + filename as the {} target `{}` in package `{}`.\n\ + Colliding filename is: {}\n", + unit.target.kind().description(), + unit.target.name(), + unit.pkg.package_id(), + other_unit.target.kind().description(), + other_unit.target.name(), + other_unit.pkg.package_id(), + path.display() + ) + }; + let suggestion = "Consider changing their names to be unique or compiling them separately."; + let report_collision = |unit: &Unit, other_unit: &Unit, path: &PathBuf| -> Error { + if unit.target.name() == other_unit.target.name() { + format_err!( + "output filename collision.\n\ + {}\ + The targets must have unique names.\n\ + {}", + describe_collision(unit, other_unit, path), + suggestion + ) + } else { + format_err!( + "output filename collision.\n\ + {}\ + The output filenames must be unique.\n\ + {}\n\ + If this looks unexpected, it may be a bug in Cargo. Please file a bug report at\n\ + https://github.com/rust-lang/cargo/issues/ with as much information as you\n\ + can provide.\n\ + {} running on `{}` target `{}`\n\ + First unit: {:?}\n\ + Second unit: {:?}", + describe_collision(unit, other_unit, path), + suggestion, + ::version(), self.bcx.host_triple(), self.bcx.target_triple(), + unit, other_unit) + } + }; + let mut keys = self + .unit_dependencies + .keys() + .filter(|unit| !unit.mode.is_run_custom_build()) + .collect::>(); + // Sort for consistent error messages. + keys.sort_unstable(); + for unit in keys { + for output in self.outputs(unit)?.iter() { + if let Some(other_unit) = + output_collisions.insert(output.path.clone(), unit) + { + return Err(report_collision(unit, &other_unit, &output.path)); + } + if let Some(hardlink) = output.hardlink.as_ref() { + if let Some(other_unit) = output_collisions.insert(hardlink.clone(), unit) + { + return Err(report_collision(unit, &other_unit, hardlink)); + } + } + if let Some(ref export_path) = output.export_path { + if let Some(other_unit) = + output_collisions.insert(export_path.clone(), unit) + { + bail!("`--out-dir` filename collision.\n\ + {}\ + The exported filenames must be unique.\n\ + {}", + describe_collision(unit, &other_unit, &export_path), + suggestion + ); + } + } + } + } + Ok(()) + } } #[derive(Default)] diff --git a/src/cargo/core/compiler/fingerprint.rs b/src/cargo/core/compiler/fingerprint.rs index 6acb85a79bf..c2ecec2c970 100644 --- a/src/cargo/core/compiler/fingerprint.rs +++ b/src/cargo/core/compiler/fingerprint.rs @@ -9,7 +9,7 @@ use serde::de::{self, Deserialize}; use serde::ser; use serde_json; -use core::{Edition, Package, TargetKind}; +use core::{Edition, Package}; use util; use util::errors::{CargoResult, CargoResultExt}; use util::paths; @@ -780,14 +780,7 @@ fn filename<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> String { // fingerprint for every metadata hash version. This works because // even if the package is fresh, we'll still link the fresh target let file_stem = cx.files().file_stem(unit); - let kind = match *unit.target.kind() { - TargetKind::Lib(..) => "lib", - TargetKind::Bin => "bin", - TargetKind::Test => "integration-test", - TargetKind::ExampleBin | TargetKind::ExampleLib(..) => "example", - TargetKind::Bench => "bench", - TargetKind::CustomBuild => "build-script", - }; + let kind = unit.target.kind().description(); let flavor = if unit.mode.is_any_test() { "test-" } else if unit.mode.is_doc() { diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index af8eb2c0192..d371dc68216 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -436,14 +436,13 @@ fn link_targets<'a, 'cfg>( }; destinations.push(dst.display().to_string()); hardlink_or_copy(src, dst)?; - if let Some(ref path) = export_dir { - if !target.is_custom_build() { - if !path.exists() { - fs::create_dir_all(path)?; - } - - hardlink_or_copy(src, &path.join(dst.file_name().unwrap()))?; + if let Some(ref path) = output.export_path { + let export_dir = export_dir.as_ref().unwrap(); + if !export_dir.exists() { + fs::create_dir_all(export_dir)?; } + + hardlink_or_copy(src, path)?; } } diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 8bc6fcb8ab8..aebf39a896e 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -181,9 +181,22 @@ impl fmt::Debug for TargetKind { } } +impl TargetKind { + pub fn description(&self) -> &'static str { + match self { + TargetKind::Lib(..) => "lib", + TargetKind::Bin => "bin", + TargetKind::Test => "integration-test", + TargetKind::ExampleBin | TargetKind::ExampleLib(..) => "example", + TargetKind::Bench => "bench", + TargetKind::CustomBuild => "build-script", + } + } +} + /// Information about a binary, a library, an example, etc. that is part of the /// package. -#[derive(Clone, Hash, PartialEq, Eq)] +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Target { kind: TargetKind, name: String, @@ -202,7 +215,7 @@ pub struct Target { edition: Edition, } -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum TargetSourcePath { Path(PathBuf), Metabuild, diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 43cd18e95d3..8db4758aaca 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -1,4 +1,5 @@ use std::cell::{Ref, RefCell, Cell}; +use std::cmp::Ordering; use std::collections::{HashMap, HashSet}; use std::fmt; use std::hash; @@ -38,6 +39,18 @@ pub struct Package { manifest_path: PathBuf, } +impl Ord for Package { + fn cmp(&self, other: &Package) -> Ordering { + self.package_id().cmp(other.package_id()) + } +} + +impl PartialOrd for Package { + fn partial_cmp(&self, other: &Package) -> Option { + Some(self.cmp(other)) + } +} + /// A Package in a form where `Serialize` can be derived. #[derive(Serialize)] struct SerializedPackage<'a> { diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index 6120007c560..998f270521e 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -371,7 +371,7 @@ fn merge_profile(profile: &mut Profile, toml: &TomlProfile) { /// Profile settings used to determine which compiler flags to use for a /// target. -#[derive(Clone, Copy, Eq)] +#[derive(Clone, Copy, Eq, PartialOrd, Ord)] pub struct Profile { pub name: &'static str, pub opt_level: InternedString, @@ -523,7 +523,7 @@ impl Profile { } /// The link-time-optimization setting. -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)] pub enum Lto { /// False = no LTO /// True = "Fat" LTO diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index dc72669a48c..f84b2e4090c 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -4327,8 +4327,8 @@ fn target_filters_workspace() { .file("a/src/lib.rs", "") .file("a/examples/ex1.rs", "fn main() {}") .file("b/Cargo.toml", &basic_bin_manifest("b")) + .file("b/src/lib.rs", "") .file("b/src/main.rs", "fn main() {}") - .file("b/examples/ex1.rs", "fn main() {}") .build(); ws.cargo("build -v --example ex") @@ -4343,12 +4343,12 @@ Did you mean `ex1`?", ws.cargo("build -v --lib") .with_status(0) .with_stderr_contains("[RUNNING] `rustc [..]a/src/lib.rs[..]") + .with_stderr_contains("[RUNNING] `rustc [..]b/src/lib.rs[..]") .run(); ws.cargo("build -v --example ex1") .with_status(0) .with_stderr_contains("[RUNNING] `rustc [..]a/examples/ex1.rs[..]") - .with_stderr_contains("[RUNNING] `rustc [..]b/examples/ex1.rs[..]") .run(); } diff --git a/tests/testsuite/collisions.rs b/tests/testsuite/collisions.rs new file mode 100644 index 00000000000..2b3045d777d --- /dev/null +++ b/tests/testsuite/collisions.rs @@ -0,0 +1,103 @@ +use std::env; +use support::{basic_manifest, project}; + +#[test] +fn collision_dylib() { + // Path dependencies don't include metadata hash in filename for dylibs. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "1.0.0" + + [lib] + crate-type = ["dylib"] + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "1.0.0" + + [lib] + crate-type = ["dylib"] + name = "a" + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("build") + .with_stderr(&format!("\ +[ERROR] output filename collision. +The lib target `a` in package `b v1.0.0 ([..]/foo/b)` has the same output filename as the lib target `a` in package `a v1.0.0 ([..]/foo/a)`. +Colliding filename is: [..]/foo/target/debug/deps/{}a{} +The targets must have unique names. +Consider changing their names to be unique or compiling them separately. +", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX)) + .with_status(101) + .run(); +} + +#[test] +fn collision_example() { + // Examples in a workspace can easily collide. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "1.0.0")) + .file("a/examples/ex1.rs", "fn main() {}") + .file("b/Cargo.toml", &basic_manifest("b", "1.0.0")) + .file("b/examples/ex1.rs", "fn main() {}") + .build(); + + p.cargo("build --examples") + .with_stderr("\ +[ERROR] output filename collision. +The example target `ex1` in package `b v1.0.0 ([..]/foo/b)` has the same output filename as the example target `ex1` in package `a v1.0.0 ([..]/foo/a)`. +Colliding filename is: [..]/foo/target/debug/examples/ex1[EXE] +The targets must have unique names. +Consider changing their names to be unique or compiling them separately. +") + .with_status(101) + .run(); +} + +#[test] +fn collision_export() { + // --out-dir combines some things which can cause conflicts. + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("examples/foo.rs", "fn main() {}") + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build --out-dir=out -Z unstable-options --bins --examples") + .masquerade_as_nightly_cargo() + .with_stderr("\ +[ERROR] `--out-dir` filename collision. +The example target `foo` in package `foo v1.0.0 ([..]/foo)` has the same output filename as the bin target `foo` in package `foo v1.0.0 ([..]/foo)`. +Colliding filename is: [..]/foo/out/foo[EXE] +The exported filenames must be unique. +Consider changing their names to be unique or compiling them separately. +") + .with_status(101) + .run(); +} diff --git a/tests/testsuite/main.rs b/tests/testsuite/main.rs index bd1dc338886..969fe69f619 100644 --- a/tests/testsuite/main.rs +++ b/tests/testsuite/main.rs @@ -43,6 +43,7 @@ mod cargo_features; mod cfg; mod check; mod clean; +mod collisions; mod concurrent; mod config; mod corrupt_git; From 739c272f05164ae4ceaea7d6c59c1cf4dd5fb136 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 12 Nov 2018 13:10:54 -0800 Subject: [PATCH 058/128] Use "test" profile for `cargo build` benchmarks. --- src/cargo/core/profiles.rs | 3 +- src/cargo/ops/cargo_compile.rs | 20 ++++++------- tests/testsuite/build.rs | 47 ++++++++++++------------------ tests/testsuite/profile_targets.rs | 13 ++------- tests/testsuite/rustc.rs | 4 --- 5 files changed, 30 insertions(+), 57 deletions(-) diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index 6120007c560..6257858cc9b 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -74,7 +74,7 @@ impl Profiles { release: bool, ) -> Profile { let maker = match mode { - CompileMode::Test => { + CompileMode::Test | CompileMode::Bench => { if release { &self.bench } else { @@ -95,7 +95,6 @@ impl Profiles { &self.dev } } - CompileMode::Bench => &self.bench, CompileMode::Doc { .. } => &self.doc, }; let mut profile = maker.get_profile(Some(pkg_id), is_member, unit_for); diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 54f2c41e829..7b188507112 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -532,6 +532,15 @@ fn generate_targets<'a>( TargetKind::Bench => CompileMode::Bench, _ => CompileMode::Build, }, + // CompileMode::Bench is only used to inform filter_default_targets + // which command is being used (`cargo bench`). Afterwards, tests + // and benches are treated identically. Switching the mode allows + // de-duplication of units that are essentially identical. For + // example, `cargo build --all-targets --release` creates the units + // (lib profile:bench, mode:test) and (lib profile:bench, mode:bench) + // and since these are the same, we want them to be de-duped in + // `unit_dependencies`. + CompileMode::Bench => CompileMode::Test, _ => target_mode, }; // Plugins or proc-macro should be built for the host. @@ -547,17 +556,6 @@ fn generate_targets<'a>( target_mode, build_config.release, ); - // Once the profile has been selected for benchmarks, we don't need to - // distinguish between benches and tests. Switching the mode allows - // de-duplication of units that are essentially identical. For - // example, `cargo build --all-targets --release` creates the units - // (lib profile:bench, mode:test) and (lib profile:bench, mode:bench) - // and since these are the same, we want them to be de-duped in - // `unit_dependencies`. - let target_mode = match target_mode { - CompileMode::Bench => CompileMode::Test, - _ => target_mode, - }; Unit { pkg, target, diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index dc72669a48c..1dbae9c117e 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -4147,43 +4147,40 @@ fn build_filter_infer_profile() { p.cargo("build -v") .with_stderr_contains( - "\ - [RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ + "[RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ --emit=dep-info,link[..]", ).with_stderr_contains( - "\ - [RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ + "[RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ --emit=dep-info,link[..]", ).run(); p.root().join("target").rm_rf(); p.cargo("build -v --test=t1") .with_stderr_contains( - "\ - [RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link[..]", + "[RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ + --emit=dep-info,link -C debuginfo=2 [..]", ).with_stderr_contains( - "[RUNNING] `rustc --crate-name t1 tests/t1.rs --color never --emit=dep-info,link[..]", + "[RUNNING] `rustc --crate-name t1 tests/t1.rs --color never --emit=dep-info,link \ + -C debuginfo=2 [..]", ).with_stderr_contains( - "\ - [RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ - --emit=dep-info,link[..]", + "[RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ + --emit=dep-info,link -C debuginfo=2 [..]", ).run(); p.root().join("target").rm_rf(); + // Bench uses test profile without `--release`. p.cargo("build -v --bench=b1") .with_stderr_contains( - "\ - [RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ - --emit=dep-info,link[..]", + "[RUNNING] `rustc --crate-name foo src/lib.rs --color never --crate-type lib \ + --emit=dep-info,link -C debuginfo=2 [..]", ).with_stderr_contains( - "\ - [RUNNING] `rustc --crate-name b1 benches/b1.rs --color never --emit=dep-info,link \ - -C opt-level=3[..]", - ).with_stderr_contains( - "\ - [RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ - --emit=dep-info,link[..]", + "[RUNNING] `rustc --crate-name b1 benches/b1.rs --color never --emit=dep-info,link \ + -C debuginfo=2 [..]", + ) + .with_stderr_does_not_contain("opt-level") + .with_stderr_contains( + "[RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ + --emit=dep-info,link -C debuginfo=2 [..]", ).run(); } @@ -4213,10 +4210,6 @@ fn targets_selected_all() { .with_stderr_contains("\ [RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ --emit=dep-info,link[..]") - // bench - .with_stderr_contains("\ - [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \ - -C opt-level=3 --test [..]") // unit test .with_stderr_contains("\ [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \ @@ -4231,10 +4224,6 @@ fn all_targets_no_lib() { .with_stderr_contains("\ [RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ --emit=dep-info,link[..]") - // bench - .with_stderr_contains("\ - [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \ - -C opt-level=3 --test [..]") // unit test .with_stderr_contains("\ [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \ diff --git a/tests/testsuite/profile_targets.rs b/tests/testsuite/profile_targets.rs index cc8a226f5f8..c5598cae6da 100644 --- a/tests/testsuite/profile_targets.rs +++ b/tests/testsuite/profile_targets.rs @@ -137,9 +137,6 @@ fn profile_selection_build_all_targets() { // - bdep `panic` is not set because it thinks `build.rs` is a plugin. // - build_script_build is built without panic because it thinks // `build.rs` is a plugin. - // - build_script_build is being run two times. Once for the `dev` and - // `test` targets, once for the `bench` targets. - // TODO: "PROFILE" says debug both times, though! // - Benchmark dependencies are compiled in `dev` mode, which may be // surprising. See https://github.com/rust-lang/cargo/issues/4929. // @@ -157,11 +154,9 @@ fn profile_selection_build_all_targets() { // lib dev+panic build (a normal lib target) // lib dev-panic build (used by tests/benches) // lib test test - // lib bench test(bench) // test test test - // bench bench test(bench) + // bench test test // bin test test - // bin bench test(bench) // bin dev build // example dev build p.cargo("build --all-targets -vv").with_stderr_unordered("\ @@ -173,17 +168,13 @@ fn profile_selection_build_all_targets() { [COMPILING] foo [..] [RUNNING] `rustc --crate-name build_script_build build.rs [..]--crate-type bin --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..] [RUNNING] `[..]/target/debug/build/foo-[..]/build-script-build` -[RUNNING] `[..]/target/debug/build/foo-[..]/build-script-build` -[foo 0.0.1] foo custom build PROFILE=debug DEBUG=false OPT_LEVEL=3 [foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0 [RUNNING] `rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]` [RUNNING] `rustc --crate-name foo src/lib.rs [..]--emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..]` [RUNNING] `rustc --crate-name foo src/lib.rs [..]--crate-type lib --emit=dep-info,link -C codegen-units=1 -C debuginfo=2 [..]` -[RUNNING] `rustc --crate-name foo src/lib.rs [..]--emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]` [RUNNING] `rustc --crate-name foo src/main.rs [..]--emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..]` [RUNNING] `rustc --crate-name test1 tests/test1.rs [..]--emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..]` -[RUNNING] `rustc --crate-name bench1 benches/bench1.rs [..]--emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]` -[RUNNING] `rustc --crate-name foo src/main.rs [..]--emit=dep-info,link -C opt-level=3 -C codegen-units=4 --test [..]` +[RUNNING] `rustc --crate-name bench1 benches/bench1.rs [..]--emit=dep-info,link -C codegen-units=3 -C debuginfo=2 --test [..]` [RUNNING] `rustc --crate-name foo src/main.rs [..]--crate-type bin --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]` [RUNNING] `rustc --crate-name ex1 examples/ex1.rs [..]--crate-type bin --emit=dep-info,link -C panic=abort -C codegen-units=1 -C debuginfo=2 [..]` [FINISHED] dev [unoptimized + debuginfo] [..] diff --git a/tests/testsuite/rustc.rs b/tests/testsuite/rustc.rs index 76ff321fb38..44b8a45f174 100644 --- a/tests/testsuite/rustc.rs +++ b/tests/testsuite/rustc.rs @@ -243,10 +243,6 @@ fn targets_selected_all() { .with_stderr_contains("\ [RUNNING] `rustc --crate-name foo src/main.rs --color never --crate-type bin \ --emit=dep-info,link[..]") - // bench - .with_stderr_contains("\ - [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \ - -C opt-level=3 --test [..]") // unit test .with_stderr_contains("\ [RUNNING] `rustc --crate-name foo src/main.rs --color never --emit=dep-info,link \ From 1533a0493a499e9cf0faa7f09b85b8b25d5041f6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 13 Nov 2018 11:37:49 -0800 Subject: [PATCH 059/128] Stabilize the `rename-dependency` feature This commit stabilizes Cargo's `rename-dependency` feature which allows renaming packages in `Cargo.toml`, enabling importing multiple versions of a single crate or simply avoiding a `use foo as bar` in `src/lib.rs`. Closes #5653 --- src/cargo/core/features.rs | 2 +- .../src/reference/specifying-dependencies.md | 61 ++++++++++- src/doc/src/reference/unstable.md | 55 ---------- tests/testsuite/rename_deps.rs | 100 ++---------------- 4 files changed, 67 insertions(+), 151 deletions(-) diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index bdf369bb3dc..7f20a490096 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -177,7 +177,7 @@ features! { [stable] edition: bool, // Renaming a package in the manifest via the `package` key - [unstable] rename_dependency: bool, + [stable] rename_dependency: bool, // Whether a lock file is published with this crate [unstable] publish_lockfile: bool, diff --git a/src/doc/src/reference/specifying-dependencies.md b/src/doc/src/reference/specifying-dependencies.md index 4bc4dedac4c..512862e5e9b 100644 --- a/src/doc/src/reference/specifying-dependencies.md +++ b/src/doc/src/reference/specifying-dependencies.md @@ -113,7 +113,7 @@ rand = { git = "https://github.com/rust-lang-nursery/rand" } Cargo will fetch the `git` repository at this location then look for a `Cargo.toml` for the requested crate anywhere inside the `git` repository -(not necessarily at the root - for example, specifying a member crate name +(not necessarily at the root - for example, specifying a member crate name of a workspace and setting `git` to the repository containing the workspace). Since we haven’t specified any other information, Cargo assumes that @@ -535,3 +535,62 @@ features = ["secure-password", "civet"] More information about features can be found in the [manifest documentation](reference/manifest.html#the-features-section). + +### Renaming dependencies in `Cargo.toml` + +When writing a `[dependencies]` section in `Cargo.toml` the key you write for a +dependency typically matches up to the name of the crate you import from in the +code. For some projects, though, you may wish to reference the crate with a +different name in the code regardless of how it's published on crates.io. For +example you may wish to: + +* Avoid the need to `use foo as bar` in Rust source. +* Depend on multiple versions of a crate. +* Depend on crates with the same name from different registries. + +To support this Cargo supports a `package` key in the `[dependencies]` section +of which package should be depended on: + +```toml +[package] +name = "mypackage" +version = "0.0.1" + +[dependencies] +foo = "0.1" +bar = { git = "https://github.com/example/project", package = "foo" } +baz = { version = "0.1", registry = "custom", package = "foo" } +``` + +In this example, three crates are now available in your Rust code: + +```rust +extern crate foo; // crates.io +extern crate bar; // git repository +extern crate baz; // registry `custom` +``` + +All three of these crates have the package name of `foo` in their own +`Cargo.toml`, so we're explicitly using the `package` key to inform Cargo that +we want the `foo` package even though we're calling it something else locally. +The `package` key, if not specified, defaults to the name of the dependency +being requested. + +Note that if you have an optional dependency like: + +```toml +[dependencies] +foo = { version = "0.1", package = 'bar', optional = true } +``` + +you're depending on the crate `bar` from crates.io, but your crate has a `foo` +feature instead of a `bar` feature. That is, names of features take after the +name of the dependency, not the package name, when renamed. + +Enabling transitive dependencies works similarly, for example we could add the +following to the above manifest: + +```toml +[features] +log-debug = ['foo/log-debug'] # using 'bar/log-debug' would be an error! +``` diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index d273a91b5ba..aeb52afff5e 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -63,61 +63,6 @@ publish = ["my-registry"] ``` -### rename-dependency -* Original Issue: [#1311](https://github.com/rust-lang/cargo/issues/1311) -* PR: [#4953](https://github.com/rust-lang/cargo/pull/4953) -* Tracking Issue: [#5653](https://github.com/rust-lang/cargo/issues/5653) - -The rename-dependency feature allows you to import a dependency -with a different name from the source. This can be useful in a few scenarios: - -* Depending on crates with the same name from different registries. -* Depending on multiple versions of a crate. -* Avoid needing `extern crate foo as bar` in Rust source. - -Just include the `package` key to specify the actual name of the dependency. -You must include `cargo-features` at the top of your `Cargo.toml`. - -```toml -cargo-features = ["rename-dependency"] - -[package] -name = "mypackage" -version = "0.0.1" - -[dependencies] -foo = "0.1" -bar = { version = "0.1", registry = "custom", package = "foo" } -baz = { git = "https://github.com/example/project", package = "foo" } -``` - -In this example, three crates are now available in your Rust code: - -```rust -extern crate foo; // crates.io -extern crate bar; // registry `custom` -extern crate baz; // git repository -``` - -Note that if you have an optional dependency like: - -```toml -[dependencies] -foo = { version = "0.1", package = 'bar', optional = true } -``` - -you're depending on the crate `bar` from crates.io, but your crate has a `foo` -feature instead of a `bar` feature. That is, names of features take after the -name of the dependency, not the package name, when renamed. - -Enabling transitive dependencies works similarly, for example we could add the -following to the above manifest: - -```toml -[features] -log-debug = ['foo/log-debug'] # using 'bar/log-debug' would be an error! -``` - ### publish-lockfile * Original Issue: [#2263](https://github.com/rust-lang/cargo/issues/2263) * PR: [#5093](https://github.com/rust-lang/cargo/pull/5093) diff --git a/tests/testsuite/rename_deps.rs b/tests/testsuite/rename_deps.rs index 209987b89ca..c8ee06dbcaa 100644 --- a/tests/testsuite/rename_deps.rs +++ b/tests/testsuite/rename_deps.rs @@ -3,68 +3,6 @@ use support::paths; use support::registry::Package; use support::{basic_manifest, project}; -#[test] -fn gated() { - let p = project() - .file( - "Cargo.toml", - r#" - [project] - name = "foo" - version = "0.0.1" - authors = [] - - [dependencies] - bar = { package = "foo", version = "0.1" } - "#, - ).file("src/lib.rs", "") - .build(); - - p.cargo("build") - .masquerade_as_nightly_cargo() - .with_status(101) - .with_stderr( - "\ -error: failed to parse manifest at `[..]` - -Caused by: - feature `rename-dependency` is required - -consider adding `cargo-features = [\"rename-dependency\"]` to the manifest -", - ).run(); - - let p = project() - .at("bar") - .file( - "Cargo.toml", - r#" - [project] - name = "foo" - version = "0.0.1" - authors = [] - - [dependencies] - bar = { version = "0.1", package = "baz" } - "#, - ).file("src/lib.rs", "") - .build(); - - p.cargo("build") - .masquerade_as_nightly_cargo() - .with_status(101) - .with_stderr( - "\ -error: failed to parse manifest at `[..]` - -Caused by: - feature `rename-dependency` is required - -consider adding `cargo-features = [\"rename-dependency\"]` to the manifest -", - ).run(); -} - #[test] fn rename_dependency() { Package::new("bar", "0.1.0").publish(); @@ -74,8 +12,6 @@ fn rename_dependency() { .file( "Cargo.toml", r#" - cargo-features = ["rename-dependency"] - [project] name = "foo" version = "0.0.1" @@ -88,7 +24,7 @@ fn rename_dependency() { ).file("src/lib.rs", "extern crate bar; extern crate baz;") .build(); - p.cargo("build").masquerade_as_nightly_cargo().run(); + p.cargo("build").run(); } #[test] @@ -97,8 +33,6 @@ fn rename_with_different_names() { .file( "Cargo.toml", r#" - cargo-features = ["rename-dependency"] - [project] name = "foo" version = "0.0.1" @@ -122,7 +56,7 @@ fn rename_with_different_names() { ).file("bar/src/lib.rs", "") .build(); - p.cargo("build").masquerade_as_nightly_cargo().run(); + p.cargo("build").run(); } #[test] @@ -148,8 +82,7 @@ fn lots_of_names() { "Cargo.toml", &format!( r#" - cargo-features = ["alternative-registries", "rename-dependency"] - + cargo-features = ["alternative-registries"] [package] name = "test" version = "0.1.0" @@ -196,8 +129,6 @@ fn rename_and_patch() { .file( "Cargo.toml", r#" - cargo-features = ["rename-dependency"] - [package] name = "test" version = "0.1.0" @@ -216,7 +147,7 @@ fn rename_and_patch() { .file("foo/src/lib.rs", "pub fn foo() {}") .build(); - p.cargo("build -v").masquerade_as_nightly_cargo().run(); + p.cargo("build -v").run(); } #[test] @@ -227,8 +158,6 @@ fn rename_twice() { .file( "Cargo.toml", r#" - cargo-features = ["rename-dependency"] - [package] name = "test" version = "0.1.0" @@ -243,7 +172,6 @@ fn rename_twice() { .build(); p.cargo("build -v") - .masquerade_as_nightly_cargo() .with_status(101) .with_stderr( "\ @@ -264,8 +192,6 @@ fn rename_affects_fingerprint() { .file( "Cargo.toml", r#" - cargo-features = ["rename-dependency"] - [package] name = "test" version = "0.1.0" @@ -277,13 +203,11 @@ fn rename_affects_fingerprint() { ).file("src/lib.rs", "extern crate foo;") .build(); - p.cargo("build -v").masquerade_as_nightly_cargo().run(); + p.cargo("build -v").run(); p.change_file( "Cargo.toml", r#" - cargo-features = ["rename-dependency"] - [package] name = "test" version = "0.1.0" @@ -295,7 +219,6 @@ fn rename_affects_fingerprint() { ); p.cargo("build -v") - .masquerade_as_nightly_cargo() .with_status(101) .run(); } @@ -309,8 +232,6 @@ fn can_run_doc_tests() { .file( "Cargo.toml", r#" - cargo-features = ["rename-dependency"] - [project] name = "foo" version = "0.0.1" @@ -328,7 +249,6 @@ fn can_run_doc_tests() { ).build(); foo.cargo("test -v") - .masquerade_as_nightly_cargo() .with_stderr_contains( "\ [DOCTEST] foo @@ -363,8 +283,6 @@ fn features_still_work() { .file( "a/Cargo.toml", r#" - cargo-features = ["rename-dependency"] - [package] name = "p1" version = "0.1.0" @@ -377,8 +295,6 @@ fn features_still_work() { .file( "b/Cargo.toml", r#" - cargo-features = ["rename-dependency"] - [package] name = "p2" version = "0.1.0" @@ -393,7 +309,7 @@ fn features_still_work() { ).file("b/src/lib.rs", "extern crate b;") .build(); - p.cargo("build -v").masquerade_as_nightly_cargo().run(); + p.cargo("build -v").run(); } #[test] @@ -405,7 +321,6 @@ fn features_not_working() { .file( "Cargo.toml", r#" - cargo-features = ["rename-dependency"] [package] name = "test" version = "0.1.0" @@ -422,7 +337,6 @@ fn features_not_working() { .build(); p.cargo("build -v") - .masquerade_as_nightly_cargo() .with_status(101) .with_stderr( "\ @@ -440,7 +354,6 @@ fn rename_with_dash() { .file( "Cargo.toml", r#" - cargo-features = ["rename-dependency"] [package] name = "qwerty" version = "0.1.0" @@ -455,6 +368,5 @@ fn rename_with_dash() { .build(); p.cargo("build") - .masquerade_as_nightly_cargo() .run(); } From a10eb011503a901e2740a2029fa28b2158cd3e7a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 13 Nov 2018 14:31:56 -0800 Subject: [PATCH 060/128] Change error to warning. --- src/cargo/core/compiler/context/mod.rs | 28 +++++++++++++------------- tests/testsuite/collisions.rs | 24 +++++++++++----------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/cargo/core/compiler/context/mod.rs b/src/cargo/core/compiler/context/mod.rs index 83d18f8f152..3bc78fd8b38 100644 --- a/src/cargo/core/compiler/context/mod.rs +++ b/src/cargo/core/compiler/context/mod.rs @@ -5,7 +5,6 @@ use std::fmt::Write; use std::path::PathBuf; use std::sync::Arc; -use failure::Error; use jobserver::Client; use core::{Package, PackageId, Resolve, Target}; @@ -469,22 +468,23 @@ impl<'a, 'cfg> Context<'a, 'cfg> { path.display() ) }; - let suggestion = "Consider changing their names to be unique or compiling them separately."; - let report_collision = |unit: &Unit, other_unit: &Unit, path: &PathBuf| -> Error { + let suggestion = "Consider changing their names to be unique or compiling them separately.\n\ + This may become a hard error in the future, see https://github.com/rust-lang/cargo/issues/6313"; + let report_collision = |unit: &Unit, other_unit: &Unit, path: &PathBuf| -> CargoResult<()> { if unit.target.name() == other_unit.target.name() { - format_err!( + self.bcx.config.shell().warn(format!( "output filename collision.\n\ {}\ - The targets must have unique names.\n\ + The targets should have unique names.\n\ {}", describe_collision(unit, other_unit, path), suggestion - ) + )) } else { - format_err!( + self.bcx.config.shell().warn(format!( "output filename collision.\n\ {}\ - The output filenames must be unique.\n\ + The output filenames should be unique.\n\ {}\n\ If this looks unexpected, it may be a bug in Cargo. Please file a bug report at\n\ https://github.com/rust-lang/cargo/issues/ with as much information as you\n\ @@ -495,7 +495,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> { describe_collision(unit, other_unit, path), suggestion, ::version(), self.bcx.host_triple(), self.bcx.target_triple(), - unit, other_unit) + unit, other_unit)) } }; let mut keys = self @@ -510,25 +510,25 @@ impl<'a, 'cfg> Context<'a, 'cfg> { if let Some(other_unit) = output_collisions.insert(output.path.clone(), unit) { - return Err(report_collision(unit, &other_unit, &output.path)); + report_collision(unit, &other_unit, &output.path)?; } if let Some(hardlink) = output.hardlink.as_ref() { if let Some(other_unit) = output_collisions.insert(hardlink.clone(), unit) { - return Err(report_collision(unit, &other_unit, hardlink)); + report_collision(unit, &other_unit, hardlink)?; } } if let Some(ref export_path) = output.export_path { if let Some(other_unit) = output_collisions.insert(export_path.clone(), unit) { - bail!("`--out-dir` filename collision.\n\ + self.bcx.config.shell().warn(format!("`--out-dir` filename collision.\n\ {}\ - The exported filenames must be unique.\n\ + The exported filenames should be unique.\n\ {}", describe_collision(unit, &other_unit, &export_path), suggestion - ); + ))?; } } } diff --git a/tests/testsuite/collisions.rs b/tests/testsuite/collisions.rs index 2b3045d777d..1ce197fb88e 100644 --- a/tests/testsuite/collisions.rs +++ b/tests/testsuite/collisions.rs @@ -40,14 +40,14 @@ fn collision_dylib() { .build(); p.cargo("build") - .with_stderr(&format!("\ -[ERROR] output filename collision. + .with_stderr_contains(&format!("\ +[WARNING] output filename collision. The lib target `a` in package `b v1.0.0 ([..]/foo/b)` has the same output filename as the lib target `a` in package `a v1.0.0 ([..]/foo/a)`. Colliding filename is: [..]/foo/target/debug/deps/{}a{} -The targets must have unique names. +The targets should have unique names. Consider changing their names to be unique or compiling them separately. +This may become a hard error in the future, see https://github.com/rust-lang/cargo/issues/6313 ", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX)) - .with_status(101) .run(); } @@ -69,14 +69,14 @@ fn collision_example() { .build(); p.cargo("build --examples") - .with_stderr("\ -[ERROR] output filename collision. + .with_stderr_contains("\ +[WARNING] output filename collision. The example target `ex1` in package `b v1.0.0 ([..]/foo/b)` has the same output filename as the example target `ex1` in package `a v1.0.0 ([..]/foo/a)`. Colliding filename is: [..]/foo/target/debug/examples/ex1[EXE] -The targets must have unique names. +The targets should have unique names. Consider changing their names to be unique or compiling them separately. +This may become a hard error in the future, see https://github.com/rust-lang/cargo/issues/6313 ") - .with_status(101) .run(); } @@ -91,13 +91,13 @@ fn collision_export() { p.cargo("build --out-dir=out -Z unstable-options --bins --examples") .masquerade_as_nightly_cargo() - .with_stderr("\ -[ERROR] `--out-dir` filename collision. + .with_stderr_contains("\ +[WARNING] `--out-dir` filename collision. The example target `foo` in package `foo v1.0.0 ([..]/foo)` has the same output filename as the bin target `foo` in package `foo v1.0.0 ([..]/foo)`. Colliding filename is: [..]/foo/out/foo[EXE] -The exported filenames must be unique. +The exported filenames should be unique. Consider changing their names to be unique or compiling them separately. +This may become a hard error in the future, see https://github.com/rust-lang/cargo/issues/6313 ") - .with_status(101) .run(); } From 69c6363418830cbb94038b8f0bd3649104bf2e72 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 13 Nov 2018 16:31:24 -0800 Subject: [PATCH 061/128] Fix windows failure on collision_dylib. --- tests/testsuite/collisions.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/testsuite/collisions.rs b/tests/testsuite/collisions.rs index 1ce197fb88e..6fc4406ae4a 100644 --- a/tests/testsuite/collisions.rs +++ b/tests/testsuite/collisions.rs @@ -39,7 +39,9 @@ fn collision_dylib() { .file("b/src/lib.rs", "") .build(); - p.cargo("build") + // j=1 is required because on windows you'll get an error because + // two processes will be writing to the file at the same time. + p.cargo("build -j=1") .with_stderr_contains(&format!("\ [WARNING] output filename collision. The lib target `a` in package `b v1.0.0 ([..]/foo/b)` has the same output filename as the lib target `a` in package `a v1.0.0 ([..]/foo/a)`. From 08dc6da03018ced6da3590e6b541d98623794858 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 13 Nov 2018 12:08:57 -0800 Subject: [PATCH 062/128] fix: Don't back out changes with `--broken-code` This commit updates the behavior of `cargo fix` when the `--broken-code` flag is passed to Cargo. Previously Cargo would always back out automatically applied changes to files whenever the fixed code failed to compile. Now, with the `--broken-code` flag, fixed code is left as-is. This means that if the fixed code can be more easily inspected by humans to detect bugs and such. The main use case intended here is that if you're working with a large code base then lints like the edition idiom lints aren't 100% finished yet to work as smoothly as `cargo fix`. The idiom lints are often useful, however, to transition code to be idiomatic (who would have guessed!) in the new edition. To ease the experience of using not-quite-ready lints this flag can be used to hopefully "fix 90% of lint warnings" and then the remaining compiler errors can be sifted through manually. The intention is that we have edition documentation indicating this workflow which also encourages filing bugs for anything that fails to fix, and hopefully this new behavior will make it easier for us to narrow down what the minimal test case is too! --- src/cargo/ops/fix.rs | 8 +++-- tests/testsuite/fix.rs | 71 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/cargo/ops/fix.rs b/src/cargo/ops/fix.rs index 2e09303a1ac..2c1a9cf445a 100644 --- a/src/cargo/ops/fix.rs +++ b/src/cargo/ops/fix.rs @@ -205,9 +205,11 @@ pub fn fix_maybe_exec_rustc() -> CargoResult { // user's code with our changes. Back out everything and fall through // below to recompile again. if !output.status.success() { - for (path, file) in fixes.files.iter() { - fs::write(path, &file.original_code) - .with_context(|_| format!("failed to write file `{}`", path))?; + if env::var_os(BROKEN_CODE_ENV).is_none() { + for (path, file) in fixes.files.iter() { + fs::write(path, &file.original_code) + .with_context(|_| format!("failed to write file `{}`", path))?; + } } log_failed_fix(&output.stderr)?; } diff --git a/tests/testsuite/fix.rs b/tests/testsuite/fix.rs index a3775b889ef..dedbec5c638 100644 --- a/tests/testsuite/fix.rs +++ b/tests/testsuite/fix.rs @@ -1116,3 +1116,74 @@ fn only_warn_for_relevant_crates() { ") .run(); } + +#[test] +fn fix_to_broken_code() { + if !is_nightly() { + return; + } + let p = project() + .file( + "foo/Cargo.toml", + r#" + [package] + name = 'foo' + version = '0.1.0' + [workspace] + "#, + ).file( + "foo/src/main.rs", + r##" + use std::env; + use std::fs; + use std::io::Write; + use std::path::{Path, PathBuf}; + use std::process::{self, Command}; + + fn main() { + let is_lib_rs = env::args_os() + .map(PathBuf::from) + .any(|l| l == Path::new("src/lib.rs")); + if is_lib_rs { + let path = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let path = path.join("foo"); + if path.exists() { + panic!() + } else { + fs::File::create(&path).unwrap(); + } + } + + let status = Command::new("rustc") + .args(env::args().skip(1)) + .status() + .expect("failed to run rustc"); + process::exit(status.code().unwrap_or(2)); + } + "##, + ).file( + "bar/Cargo.toml", + r#" + [package] + name = 'bar' + version = '0.1.0' + [workspace] + "#, + ).file("bar/build.rs", "fn main() {}") + .file( + "bar/src/lib.rs", + "pub fn foo() { let mut x = 3; drop(x); }", + ).build(); + + // Build our rustc shim + p.cargo("build").cwd(p.root().join("foo")).run(); + + // Attempt to fix code, but our shim will always fail the second compile + p.cargo("fix --allow-no-vcs --broken-code") + .cwd(p.root().join("bar")) + .env("RUSTC", p.root().join("foo/target/debug/foo")) + .with_status(101) + .run(); + + assert_eq!(p.read_file("bar/src/lib.rs"), "pub fn foo() { let x = 3; drop(x); }"); +} From d9eca8c764eb147d4616c6c32d6be380b9aedcf2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 14 Nov 2018 07:56:43 -0800 Subject: [PATCH 063/128] Enable the `zlib` feature of `flate2` We're already pulling in zlib for other dependencies like curl/libgit2 so there's not really much use in duplicating the compression code with miniz, so let's instruct `flate2` to use libz as well to compress and decompress chunks. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 124afaa3d0f..8c3065fb162 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ curl-sys = "0.4.15" env_logger = "0.6.0" failure = "0.1.2" filetime = "0.2" -flate2 = "1.0.3" +flate2 = { version = "1.0.3", features = ['zlib'] } fs2 = "0.4" git2 = "0.7.5" git2-curl = "0.8.1" From f11f6c23e6d7697befff809e6d6c66e213c74da9 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 16 Nov 2018 09:22:43 -0800 Subject: [PATCH 064/128] Add a glossary. --- src/doc/src/SUMMARY.md | 1 + src/doc/src/appendix/glossary.md | 179 +++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 src/doc/src/appendix/glossary.md diff --git a/src/doc/src/SUMMARY.md b/src/doc/src/SUMMARY.md index 8b3dfac20c0..667d7cf4080 100644 --- a/src/doc/src/SUMMARY.md +++ b/src/doc/src/SUMMARY.md @@ -30,3 +30,4 @@ * [Unstable Features](reference/unstable.md) * [FAQ](faq.md) +* [Appendix: Glossary](appendix/glossary.md) diff --git a/src/doc/src/appendix/glossary.md b/src/doc/src/appendix/glossary.md new file mode 100644 index 00000000000..bdcd4ed6d94 --- /dev/null +++ b/src/doc/src/appendix/glossary.md @@ -0,0 +1,179 @@ +# Glossary + +### Artifact + +An *artifact* is the file or set of files created as a result of the +compilation process. This includes linkable libraries and executable binaries. + +### Crate + +A *crate* is one of the targets in a package. Crates are either libraries or +executable binaries. It may loosely refer to either the source code of the +target, or the compiled artifact that the target produces. A crate may also +refer to a compressed package fetched from a registry. + +### Edition + +A *Rust edition* is a developmental landmark of the Rust language. The +[edition of a package][edition-field] is specified in the `Cargo.toml` +manifest, and individual targets can specify which edition they use. See the +[Edition Guide] for more information. + +### Feature + +A [*feature*][feature] is a named flag which allows for conditional +compilation. A feature can refer to an optional dependency, or an arbitrary +name defined in a `Cargo.toml` manifest that can be checked within source +code. + +Cargo has [*unstable feature flags*][cargo-unstable] which can be used to +enable experimental behavior of Cargo itself. The Rust compiler also has its +own unstable feature flags (see [The Unstable Book][unstable-book]) and +Rustdoc also has its own unstable feature flags (see [The Rustdoc +Book][rustdoc-unstable]). + +### Index + +The index is the searchable list of crates in a registry. + +### Lock file + +The `Cargo.lock` *lock file* is a file that captures the exact version of +every dependency used in a workspace or package. It is automatically generated +by Cargo. See [Cargo.toml vs Cargo.lock]. + +### Manifest + +A [*manifest*][manifest] is a description of a package or a workspace in a +file named `Cargo.toml`. + +A [*virtual manifest*][virtual] is a `Cargo.toml` file that only describes a +workspace, and does not include a package. + +### Member + +A *member* is a package that belongs to a workspace. + +### Package + +A *package* is a collection of source files and a `Cargo.toml` manifest which +describes the package. A package has a name and version which is used for +specifying dependencies between packages. A package contains multiple targets, +which are either libraries or executable binaries. + +The *package root* is the directory where the package's `Cargo.toml` manifest +is located. + +The [*package id specification*][pkgid-spec], or *SPEC*, is a string used to +uniquely reference a specific version of a package from a specific source. + +### Project + +Another name for a [package](#package). + +### Registry + +A *registry* is a service that contains a collection of downloadable crates +that can be installed or used as dependencies for a package. The default +registry is [crates.io](https://crates.io). The registry has an *index* which +contains a list of all crates, and tells Cargo how to download the crates that +are needed. + +### Source + +A *source* is a provider that contains crates that may be included as +dependencies for a package. There are several kinds of sources: + +- **Registry source** — See [registry](#registry). +- **Local registry source** — A set of crates stored as compressed files on + the filesystem. See [Local Registry Sources]. +- **Directory source** — A set of crates stored as uncompressed files on the + filesystem. See [Directory Sources]. +- **Path source** — An individual package located on the filesystem (such as a + [path dependency]) or a set of multiple packages (such as [path overrides]). +- **Git source** — Packages located in a git repository (such as a [git + dependency] or [git source]). + +See [Source Replacement] for more information. + +### Spec + +See [package id specification](#package). + +### Target + +The meaning of the term *target* depends on the context: + +- **Target Crate** — Cargo packages consist of *targets* which correspond to + artifacts that will be produced. Packages can have library, binary, example, + test, and benchmark targets. The [list of targets][targets] are configured + in the `Cargo.toml` manifest, often inferred automatically by the [directory + layout] of the source files. +- **Target Architecture** — The OS and machine architecture for the built + artifacts are typically referred to as a *target*. +- **Target Triple** — A triple is a specific format for specifying a target + architecture. See the [clang documentation] for details. Triples may be + referred to as a *target triple* which is the architecture for the artifact + produced, and the *host triple* which is the architecture that the compiler + is running on. The target triple can be specified with the `--target` + command-line option or the `build.target` [config option]. +- **Target Directory** — Cargo places all built artifacts and intermediate + files in the *target* directory. By default this is a directory named + `target` at the workspace root, or the package root if not using a + workspace. The directory be changed with the `--target` command-line option, + the `CARGO_TARGET_DIR` [environment variable], or the `build.target-dir` + [config option]. + +### Test Targets + +Cargo *test targets* generate binaries which help verify proper operation and +correctness of code. There are two types of test artifacts: + +* **Unit test** — A *unit test* is an executable binary compiled directly from + a library or a binary target. It contains the entire contents of the library + or binary code, and runs `#[test]` annotated functions, intended to verify + individual units of code. +* **Integration test target** — An [*integration test + target*][integration-tests] is an executable binary compiled from a *test + target* which is a distinct crate whose source is located in the `tests` + directory or specified by the [`[[test]]` table][targets] in the + `Cargo.toml` manifest. It is intended to only test the public API of a + library, or execute a binary to verify its operation. + +### Workspace + +A [*workspace*][workspace] is a collection of one or more packages that share +common dependency resolution (with a shared `Cargo.lock`), output directory, +and various settings such as profiles. + +A [*virtual workspace*][virtual] is a workspace where the root `Cargo.toml` +manifest does not define a package, and only lists the workspace members. + +The *workspace root* is the directory where the workspace's `Cargo.toml` +manifest is located. + + +[Cargo.toml vs Cargo.lock]: guide/cargo-toml-vs-cargo-lock.html +[Directory Sources]: reference/source-replacement.html#directory-sources +[Local Registry Sources]: reference/source-replacement.html#local-registry-sources +[Source Replacement]: reference/source-replacement.html +[cargo-unstable]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html +[clang documentation]: http://clang.llvm.org/docs/CrossCompilation.html#target-triple +[config option]: reference/config.html +[directory layout]: reference/manifest.html#the-project-layout +[edition guide]: https://rust-lang-nursery.github.io/edition-guide/ +[edition-field]: reference/manifest.html#the-edition-field-optional +[environment variable]: reference/environment-variables.html +[feature]: reference/manifest.html#the-features-section +[git dependency]: reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories +[git source]: reference/source-replacement.html +[integration-tests]: reference/manifest.html#integration-tests +[manifest]: reference/manifest.html +[path dependency]: reference/specifying-dependencies.html#specifying-path-dependencies +[path overrides]: reference/specifying-dependencies.html#overriding-with-local-dependencies +[pkgid-spec]: reference/pkgid-spec.html +[rustdoc-unstable]: https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html +[targets]: reference/manifest.html#configuring-a-target +[unstable-book]: https://doc.rust-lang.org/nightly/unstable-book/index.html +[virtual]: reference/manifest.html#virtual-manifest +[workspace]: reference/manifest.html#the-workspace-section From 6de96b493715c6f62761775c327f02d9d9d14747 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 16 Nov 2018 10:22:34 -0800 Subject: [PATCH 065/128] Fix unstable sentence. --- src/doc/src/appendix/glossary.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/doc/src/appendix/glossary.md b/src/doc/src/appendix/glossary.md index bdcd4ed6d94..7508800207b 100644 --- a/src/doc/src/appendix/glossary.md +++ b/src/doc/src/appendix/glossary.md @@ -27,10 +27,9 @@ name defined in a `Cargo.toml` manifest that can be checked within source code. Cargo has [*unstable feature flags*][cargo-unstable] which can be used to -enable experimental behavior of Cargo itself. The Rust compiler also has its -own unstable feature flags (see [The Unstable Book][unstable-book]) and -Rustdoc also has its own unstable feature flags (see [The Rustdoc -Book][rustdoc-unstable]). +enable experimental behavior of Cargo itself. The Rust compiler and Rustdoc +also have their own unstable feature flags (see [The Unstable +Book][unstable-book] and [The Rustdoc Book][rustdoc-unstable]). ### Index From 091fa8c21483968662154de677e8ea2743924b10 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 17 Nov 2018 14:33:33 -0800 Subject: [PATCH 066/128] Crate/target clarification. --- src/doc/src/appendix/glossary.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/src/appendix/glossary.md b/src/doc/src/appendix/glossary.md index 7508800207b..e5d957acf6a 100644 --- a/src/doc/src/appendix/glossary.md +++ b/src/doc/src/appendix/glossary.md @@ -7,7 +7,7 @@ compilation process. This includes linkable libraries and executable binaries. ### Crate -A *crate* is one of the targets in a package. Crates are either libraries or +Every target in a package is a *crate*. Crates are either libraries or executable binaries. It may loosely refer to either the source code of the target, or the compiled artifact that the target produces. A crate may also refer to a compressed package fetched from a registry. @@ -103,7 +103,7 @@ See [package id specification](#package). The meaning of the term *target* depends on the context: -- **Target Crate** — Cargo packages consist of *targets* which correspond to +- **Cargo Target** — Cargo packages consist of *targets* which correspond to artifacts that will be produced. Packages can have library, binary, example, test, and benchmark targets. The [list of targets][targets] are configured in the `Cargo.toml` manifest, often inferred automatically by the [directory From 104ab6c2bc19cad3a61e338a324a4980a8920711 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sat, 17 Nov 2018 22:57:06 +0000 Subject: [PATCH 067/128] Make verify-project honour unstable features --- src/bin/cargo/commands/verify_project.rs | 19 ++----------------- tests/testsuite/verify_project.rs | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/bin/cargo/commands/verify_project.rs b/src/bin/cargo/commands/verify_project.rs index eea65c77598..b7887591bd8 100644 --- a/src/bin/cargo/commands/verify_project.rs +++ b/src/bin/cargo/commands/verify_project.rs @@ -2,10 +2,6 @@ use command_prelude::*; use std::collections::HashMap; use std::process; -use std::fs::File; -use std::io::Read; - -use toml; use cargo::print_json; @@ -23,19 +19,8 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { process::exit(1) } - let mut contents = String::new(); - let filename = match args.root_manifest(config) { - Ok(filename) => filename, - Err(e) => fail("invalid", &e.to_string()), - }; - - let file = File::open(&filename); - match file.and_then(|mut f| f.read_to_string(&mut contents)) { - Ok(_) => {} - Err(e) => fail("invalid", &format!("error reading file: {}", e)), - }; - if contents.parse::().is_err() { - fail("invalid", "invalid-format"); + if let Err(e) = args.workspace(config) { + fail("invalid", &e.to_string()) } let mut h = HashMap::new(); diff --git a/tests/testsuite/verify_project.rs b/tests/testsuite/verify_project.rs index d368b7c9fb4..060e3e3df52 100644 --- a/tests/testsuite/verify_project.rs +++ b/tests/testsuite/verify_project.rs @@ -42,3 +42,27 @@ fn cargo_verify_project_cwd() { .with_stdout(verify_project_success_output()) .run(); } + +#[test] +fn cargo_verify_project_honours_unstable_features() { + let p = project() + .file("Cargo.toml", r#" + cargo-features = ["test-dummy-unstable"] + + [package] + name = "foo" + version = "0.0.1" + "#) + .file("src/lib.rs", "") + .build(); + + p.cargo("verify-project") + .masquerade_as_nightly_cargo() + .with_stdout(verify_project_success_output()) + .run(); + + p.cargo("verify-project") + .with_status(1) + .with_stdout(r#"{"invalid":"failed to parse manifest at `[CWD]/Cargo.toml`"}"#) + .run(); +} From 83ff57a4ad7df63adfd4f3ed14fa6071b4a0d901 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 17 Nov 2018 15:42:19 -0800 Subject: [PATCH 068/128] Fix add_plugin_deps-related tests. --- tests/testsuite/build_script.rs | 34 ++++++++++++------------ tests/testsuite/plugins.rs | 46 +++++++++++++-------------------- 2 files changed, 35 insertions(+), 45 deletions(-) diff --git a/tests/testsuite/build_script.rs b/tests/testsuite/build_script.rs index 0f41f355ad8..8b850ae2f56 100644 --- a/tests/testsuite/build_script.rs +++ b/tests/testsuite/build_script.rs @@ -1376,18 +1376,8 @@ fn test_dev_dep_build_script() { #[test] fn build_script_with_dynamic_native_dependency() { - let _workspace = project() - .at("ws") - .file( - "Cargo.toml", - r#" - [workspace] - members = ["builder", "foo"] - "#, - ).build(); - let build = project() - .at("ws/builder") + .at("builder") .file( "Cargo.toml", r#" @@ -1399,13 +1389,11 @@ fn build_script_with_dynamic_native_dependency() { [lib] name = "builder" crate-type = ["dylib"] - plugin = true "#, ).file("src/lib.rs", "#[no_mangle] pub extern fn foo() {}") .build(); let foo = project() - .at("ws/foo") .file( "Cargo.toml", r#" @@ -1433,12 +1421,23 @@ fn build_script_with_dynamic_native_dependency() { "bar/build.rs", r#" use std::env; + use std::fs; use std::path::PathBuf; fn main() { - let src = PathBuf::from(env::var("SRC").unwrap()); - println!("cargo:rustc-link-search=native={}/target/debug/deps", - src.display()); + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let root = PathBuf::from(env::var("BUILDER_ROOT").unwrap()); + let file = format!("{}builder{}", + env::consts::DLL_PREFIX, + env::consts::DLL_SUFFIX); + let src = root.join(&file); + let dst = out_dir.join(&file); + fs::copy(src, dst).unwrap(); + if cfg!(windows) { + fs::copy(root.join("builder.dll.lib"), + out_dir.join("builder.dll.lib")).unwrap(); + } + println!("cargo:rustc-link-search=native={}", out_dir.display()); } "#, ).file( @@ -1458,8 +1457,9 @@ fn build_script_with_dynamic_native_dependency() { .env("RUST_LOG", "cargo::ops::cargo_rustc") .run(); + let root = build.root().join("target").join("debug"); foo.cargo("build -v") - .env("SRC", build.root()) + .env("BUILDER_ROOT", root) .env("RUST_LOG", "cargo::ops::cargo_rustc") .run(); } diff --git a/tests/testsuite/plugins.rs b/tests/testsuite/plugins.rs index 2c5653eba7e..01f46bcb5e8 100644 --- a/tests/testsuite/plugins.rs +++ b/tests/testsuite/plugins.rs @@ -1,6 +1,3 @@ -use std::env; -use std::fs; - use support::{basic_manifest, project}; use support::{is_nightly, rustc_host}; @@ -103,18 +100,8 @@ fn plugin_with_dynamic_native_dependency() { return; } - let workspace = project() - .at("ws") - .file( - "Cargo.toml", - r#" - [workspace] - members = ["builder", "foo"] - "#, - ).build(); - let build = project() - .at("ws/builder") + .at("builder") .file( "Cargo.toml", r#" @@ -131,7 +118,6 @@ fn plugin_with_dynamic_native_dependency() { .build(); let foo = project() - .at("ws/foo") .file( "Cargo.toml", r#" @@ -167,12 +153,24 @@ fn plugin_with_dynamic_native_dependency() { ).file( "bar/build.rs", r#" - use std::path::PathBuf; use std::env; + use std::fs; + use std::path::PathBuf; fn main() { - let src = PathBuf::from(env::var("SRC").unwrap()); - println!("cargo:rustc-flags=-L {}/deps", src.parent().unwrap().display()); + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let root = PathBuf::from(env::var("BUILDER_ROOT").unwrap()); + let file = format!("{}builder{}", + env::consts::DLL_PREFIX, + env::consts::DLL_SUFFIX); + let src = root.join(&file); + let dst = out_dir.join(&file); + fs::copy(src, dst).unwrap(); + if cfg!(windows) { + fs::copy(root.join("builder.dll.lib"), + out_dir.join("builder.dll.lib")).unwrap(); + } + println!("cargo:rustc-flags=-L {}", out_dir.display()); } "#, ).file( @@ -196,16 +194,8 @@ fn plugin_with_dynamic_native_dependency() { build.cargo("build").run(); - let src = workspace.root().join("target/debug"); - let lib = fs::read_dir(&src) - .unwrap() - .map(|s| s.unwrap().path()) - .find(|lib| { - let lib = lib.file_name().unwrap().to_str().unwrap(); - lib.starts_with(env::consts::DLL_PREFIX) && lib.ends_with(env::consts::DLL_SUFFIX) - }).unwrap(); - - foo.cargo("build -v").env("SRC", &lib).run(); + let root = build.root().join("target").join("debug"); + foo.cargo("build -v").env("BUILDER_ROOT", root).run(); } #[test] From d1045c9cc29b79e799be327d8cd6f864b6b0e41a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 12 Nov 2018 19:41:01 -0800 Subject: [PATCH 069/128] Fix renaming directory project using build scripts with cross-compiling. --- .../compiler/context/compilation_files.rs | 9 +++ src/cargo/core/compiler/custom_build.rs | 67 ++++++++++--------- tests/testsuite/build_script.rs | 32 +++++++-- 3 files changed, 71 insertions(+), 37 deletions(-) diff --git a/src/cargo/core/compiler/context/compilation_files.rs b/src/cargo/core/compiler/context/compilation_files.rs index 121eba773ed..3a50fa418a1 100644 --- a/src/cargo/core/compiler/context/compilation_files.rs +++ b/src/cargo/core/compiler/context/compilation_files.rs @@ -402,6 +402,15 @@ fn compute_metadata<'a, 'cfg>( let mut hasher = SipHasher::new_with_keys(0, 0); + // This is a generic version number that can be changed to make + // backwards-incompatible changes to any file structures in the output + // directory. For example, the fingerprint files or the build-script + // output files. Normally cargo updates ship with rustc updates which will + // cause a new hash due to the rustc version changing, but this allows + // cargo to be extra careful to deal with different versions of cargo that + // use the same rustc version. + 1.hash(&mut hasher); + // Unique metadata per (name, source, version) triple. This'll allow us // to pull crates from anywhere w/o worrying about conflicts unit.pkg diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index cb4a4537ce6..d2cab26b1c9 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -28,6 +28,7 @@ pub struct BuildOutput { /// Metadata to pass to the immediate dependencies pub metadata: Vec<(String, String)>, /// Paths to trigger a rerun of this build script. + /// May be absolute or relative paths (relative to package root). pub rerun_if_changed: Vec, /// Environment variables which, when changed, will cause a rebuild. pub rerun_if_env_changed: Vec, @@ -129,8 +130,8 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes .iter() .find(|d| !d.mode.is_run_custom_build() && d.target.is_custom_build()) .expect("running a script not depending on an actual script"); - let script_output = cx.files().build_script_dir(build_script_unit); - let build_output = cx.files().build_script_out_dir(unit); + let script_dir = cx.files().build_script_dir(build_script_unit); + let script_out_dir = cx.files().build_script_out_dir(unit); let build_plan = bcx.build_config.build_plan; let invocation_name = unit.buildkey(); @@ -139,7 +140,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes } // Building the command to execute - let to_exec = script_output.join(unit.target.name()); + let to_exec = script_dir.join(unit.target.name()); // Start preparing the process to execute, starting out with some // environment variables. Note that the profile-related environment @@ -151,7 +152,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes let to_exec = to_exec.into_os_string(); let mut cmd = cx.compilation.host_process(to_exec, unit.pkg)?; let debug = unit.profile.debuginfo.unwrap_or(0) != 0; - cmd.env("OUT_DIR", &build_output) + cmd.env("OUT_DIR", &script_out_dir) .env("CARGO_MANIFEST_DIR", unit.pkg.root()) .env("NUM_JOBS", &bcx.jobs().to_string()) .env( @@ -241,19 +242,19 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes let build_state = Arc::clone(&cx.build_state); let id = unit.pkg.package_id().clone(); let (output_file, err_file, root_output_file) = { - let build_output_parent = build_output.parent().unwrap(); + let build_output_parent = script_out_dir.parent().unwrap(); let output_file = build_output_parent.join("output"); let err_file = build_output_parent.join("stderr"); let root_output_file = build_output_parent.join("root-output"); (output_file, err_file, root_output_file) }; - let root_output = cx.files().target_root().to_path_buf(); + let host_target_root = cx.files().target_root().to_path_buf(); let all = ( id.clone(), pkg_name.clone(), Arc::clone(&build_state), output_file.clone(), - root_output.clone(), + script_out_dir.clone(), ); let build_scripts = super::load_build_deps(cx, unit); let kind = unit.kind; @@ -262,16 +263,17 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes // Check to see if the build script has already run, and if it has keep // track of whether it has told us about some explicit dependencies - let prev_root_output = paths::read_bytes(&root_output_file) + let prev_script_out_dir = paths::read_bytes(&root_output_file) .and_then(|bytes| util::bytes2path(&bytes)) - .unwrap_or_else(|_| cmd.get_cwd().unwrap().to_path_buf()); + .unwrap_or_else(|_| script_out_dir.clone()); + let prev_output = - BuildOutput::parse_file(&output_file, &pkg_name, &prev_root_output, &root_output).ok(); + BuildOutput::parse_file(&output_file, &pkg_name, &prev_script_out_dir, &script_out_dir).ok(); let deps = BuildDeps::new(&output_file, prev_output.as_ref()); cx.build_explicit_deps.insert(*unit, deps); - fs::create_dir_all(&script_output)?; - fs::create_dir_all(&build_output)?; + fs::create_dir_all(&script_dir)?; + fs::create_dir_all(&script_out_dir)?; // Prepare the unit of "dirty work" which will actually run the custom build // command. @@ -283,8 +285,8 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes // // If we have an old build directory, then just move it into place, // otherwise create it! - if fs::metadata(&build_output).is_err() { - fs::create_dir(&build_output).chain_err(|| { + if fs::metadata(&script_out_dir).is_err() { + fs::create_dir(&script_out_dir).chain_err(|| { internal( "failed to create script output directory for \ build command", @@ -316,7 +318,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes } } if let Some(build_scripts) = build_scripts { - super::add_plugin_deps(&mut cmd, &build_state, &build_scripts, &root_output)?; + super::add_plugin_deps(&mut cmd, &build_state, &build_scripts, &host_target_root)?; } } @@ -348,9 +350,9 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes // well. paths::write(&output_file, &output.stdout)?; paths::write(&err_file, &output.stderr)?; - paths::write(&root_output_file, util::path2bytes(&root_output)?)?; + paths::write(&root_output_file, util::path2bytes(&script_out_dir)?)?; let parsed_output = - BuildOutput::parse(&output.stdout, &pkg_name, &root_output, &root_output)?; + BuildOutput::parse(&output.stdout, &pkg_name, &script_out_dir, &script_out_dir)?; if json_messages { emit_build_output(&parsed_output, &id); @@ -364,11 +366,11 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes // itself to run when we actually end up just discarding what we calculated // above. let fresh = Work::new(move |_tx| { - let (id, pkg_name, build_state, output_file, root_output) = all; + let (id, pkg_name, build_state, output_file, script_out_dir) = all; let output = match prev_output { Some(output) => output, None => { - BuildOutput::parse_file(&output_file, &pkg_name, &prev_root_output, &root_output)? + BuildOutput::parse_file(&output_file, &pkg_name, &prev_script_out_dir, &script_out_dir)? } }; @@ -406,11 +408,11 @@ impl BuildOutput { pub fn parse_file( path: &Path, pkg_name: &str, - root_output_when_generated: &Path, - root_output: &Path, + script_out_dir_when_generated: &Path, + script_out_dir: &Path, ) -> CargoResult { let contents = paths::read_bytes(path)?; - BuildOutput::parse(&contents, pkg_name, root_output_when_generated, root_output) + BuildOutput::parse(&contents, pkg_name, script_out_dir_when_generated, script_out_dir) } // Parses the output of a script. @@ -418,8 +420,8 @@ impl BuildOutput { pub fn parse( input: &[u8], pkg_name: &str, - root_output_when_generated: &Path, - root_output: &Path, + script_out_dir_when_generated: &Path, + script_out_dir: &Path, ) -> CargoResult { let mut library_paths = Vec::new(); let mut library_links = Vec::new(); @@ -456,23 +458,24 @@ impl BuildOutput { _ => bail!("Wrong output in {}: `{}`", whence, line), }; - let path = |val: &str| match Path::new(val).strip_prefix(root_output_when_generated) { - Ok(path) => root_output.join(path), - Err(_) => PathBuf::from(val), - }; + // This will rewrite paths if the target directory has been moved. + let value = value.replace( + script_out_dir_when_generated.to_str().unwrap(), + script_out_dir.to_str().unwrap(), + ); match key { "rustc-flags" => { - let (paths, links) = BuildOutput::parse_rustc_flags(value, &whence)?; + let (paths, links) = BuildOutput::parse_rustc_flags(&value, &whence)?; library_links.extend(links.into_iter()); library_paths.extend(paths.into_iter()); } "rustc-link-lib" => library_links.push(value.to_string()), - "rustc-link-search" => library_paths.push(path(value)), + "rustc-link-search" => library_paths.push(PathBuf::from(value)), "rustc-cfg" => cfgs.push(value.to_string()), - "rustc-env" => env.push(BuildOutput::parse_rustc_env(value, &whence)?), + "rustc-env" => env.push(BuildOutput::parse_rustc_env(&value, &whence)?), "warning" => warnings.push(value.to_string()), - "rerun-if-changed" => rerun_if_changed.push(path(value)), + "rerun-if-changed" => rerun_if_changed.push(PathBuf::from(value)), "rerun-if-env-changed" => rerun_if_env_changed.push(value.to_string()), _ => metadata.push((key.to_string(), value.to_string())), } diff --git a/tests/testsuite/build_script.rs b/tests/testsuite/build_script.rs index 0f41f355ad8..0a48df6be19 100644 --- a/tests/testsuite/build_script.rs +++ b/tests/testsuite/build_script.rs @@ -3191,6 +3191,24 @@ failed to select a version for `a` which could resolve this conflict #[test] fn rename_with_link_search_path() { + _rename_with_link_search_path(false); +} + +#[test] +fn rename_with_link_search_path_cross() { + if cross_compile::disabled() { + return; + } + + _rename_with_link_search_path(true); +} + +fn _rename_with_link_search_path(cross: bool) { + let target_arg = if cross { + format!(" --target={}", cross_compile::alternate()) + } else { + "".to_string() + }; let p = project() .file( "Cargo.toml", @@ -3209,7 +3227,7 @@ fn rename_with_link_search_path() { ); let p = p.build(); - p.cargo("build").run(); + p.cargo(&format!("build{}", target_arg)).run(); let p2 = project() .at("bar") @@ -3242,7 +3260,7 @@ fn rename_with_link_search_path() { } else { println!("cargo:rustc-link-lib=foo"); } - println!("cargo:rustc-link-search={}", + println!("cargo:rustc-link-search=all={}", dst.parent().unwrap().display()); } "#, @@ -3265,7 +3283,11 @@ fn rename_with_link_search_path() { // the `p` project. On OSX the `libfoo.dylib` artifact references the // original path in `p` so we want to make sure that it can't find it (hence // the deletion). - let root = p.root().join("target").join("debug").join("deps"); + let root = if cross { + p.root().join("target").join(cross_compile::alternate()).join("debug").join("deps") + } else { + p.root().join("target").join("debug").join("deps") + }; let file = format!("{}foo{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX); let src = root.join(&file); @@ -3280,7 +3302,7 @@ fn rename_with_link_search_path() { remove_dir_all(p.root()).unwrap(); // Everything should work the first time - p2.cargo("run").run(); + p2.cargo(&format!("run{}", target_arg)).run(); // Now rename the root directory and rerun `cargo run`. Not only should we // not build anything but we also shouldn't crash. @@ -3309,7 +3331,7 @@ fn rename_with_link_search_path() { thread::sleep(Duration::from_millis(100)); } - p2.cargo("run") + p2.cargo(&format!("run{}", target_arg)) .cwd(&new) .with_stderr( "\ From ea1f525c028e88668a58c8b2416c11d176edbba3 Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Sun, 4 Nov 2018 17:27:18 +0900 Subject: [PATCH 070/128] Allow user aliases to override built-in aliases --- src/bin/cargo/cli.rs | 33 +++++++++++++------- src/bin/cargo/commands/build.rs | 3 +- src/bin/cargo/commands/mod.rs | 25 +++++++++++---- src/bin/cargo/commands/run.rs | 3 +- src/bin/cargo/commands/test.rs | 3 +- tests/testsuite/cargo_alias_config.rs | 45 +++++++++++++++------------ 6 files changed, 71 insertions(+), 41 deletions(-) diff --git a/src/bin/cargo/cli.rs b/src/bin/cargo/cli.rs index a53a6fe6f75..33927c44500 100644 --- a/src/bin/cargo/cli.rs +++ b/src/bin/cargo/cli.rs @@ -4,8 +4,8 @@ use clap::{AppSettings, Arg, ArgMatches}; use cargo::{self, CliResult, Config}; +use super::commands::{self, BuiltinExec}; use super::list_commands; -use super::commands; use command_prelude::*; pub fn main(config: &mut Config) -> CliResult { @@ -107,26 +107,34 @@ fn expand_aliases( commands::builtin_exec(cmd), super::aliased_command(config, cmd)?, ) { - (None, Some(mut alias)) => { - alias.extend( + ( + Some(BuiltinExec { + alias_for: None, .. + }), + Some(_), + ) => { + // User alias conflicts with a built-in subcommand + config.shell().warn(format!( + "user-defined alias `{}` is ignored, because it is shadowed by a built-in command", + cmd, + ))?; + } + (_, Some(mut user_alias)) => { + // User alias takes precedence over built-in aliases + user_alias.extend( args.values_of("") .unwrap_or_default() .map(|s| s.to_string()), ); let args = cli() .setting(AppSettings::NoBinaryName) - .get_matches_from_safe(alias)?; + .get_matches_from_safe(user_alias)?; return expand_aliases(config, args); } - (Some(_), Some(_)) => { - config.shell().warn(format!( - "alias `{}` is ignored, because it is shadowed by a built in command", - cmd - ))?; - } (_, None) => {} } }; + Ok(args) } @@ -152,11 +160,12 @@ fn execute_subcommand(config: &mut Config, args: &ArgMatches) -> CliResult { args.is_present("frozen"), args.is_present("locked"), arg_target_dir, - &args.values_of_lossy("unstable-features") + &args + .values_of_lossy("unstable-features") .unwrap_or_default(), )?; - if let Some(exec) = commands::builtin_exec(cmd) { + if let Some(BuiltinExec { exec, .. }) = commands::builtin_exec(cmd) { return exec(config, subcommand_args); } diff --git a/src/bin/cargo/commands/build.rs b/src/bin/cargo/commands/build.rs index 4004c25b888..d919936c9b0 100644 --- a/src/bin/cargo/commands/build.rs +++ b/src/bin/cargo/commands/build.rs @@ -4,7 +4,8 @@ use cargo::ops; pub fn cli() -> App { subcommand("build") - .alias("b") + // subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases() + // .alias("b") .about("Compile a local package and all of its dependencies") .arg_package_spec( "Package to build (see `cargo help pkgid`)", diff --git a/src/bin/cargo/commands/mod.rs b/src/bin/cargo/commands/mod.rs index 057dc2f07b4..6e3670f84a5 100644 --- a/src/bin/cargo/commands/mod.rs +++ b/src/bin/cargo/commands/mod.rs @@ -35,10 +35,15 @@ pub fn builtin() -> Vec { ] } -pub fn builtin_exec(cmd: &str) -> Option CliResult> { - let f = match cmd { +pub struct BuiltinExec<'a> { + pub exec: fn(&'a mut Config, &'a ArgMatches) -> CliResult, + pub alias_for: Option<&'static str>, +} + +pub fn builtin_exec(cmd: &str) -> Option { + let exec = match cmd { "bench" => bench::exec, - "build" => build::exec, + "build" | "b" => build::exec, "check" => check::exec, "clean" => clean::exec, "doc" => doc::exec, @@ -57,11 +62,11 @@ pub fn builtin_exec(cmd: &str) -> Option CliResu "pkgid" => pkgid::exec, "publish" => publish::exec, "read-manifest" => read_manifest::exec, - "run" => run::exec, + "run" | "r" => run::exec, "rustc" => rustc::exec, "rustdoc" => rustdoc::exec, "search" => search::exec, - "test" => test::exec, + "test" | "t" => test::exec, "uninstall" => uninstall::exec, "update" => update::exec, "verify-project" => verify_project::exec, @@ -69,7 +74,15 @@ pub fn builtin_exec(cmd: &str) -> Option CliResu "yank" => yank::exec, _ => return None, }; - Some(f) + + let alias_for = match cmd { + "b" => Some("build"), + "r" => Some("run"), + "t" => Some("test"), + _ => None, + }; + + Some(BuiltinExec { exec, alias_for }) } pub mod bench; diff --git a/src/bin/cargo/commands/run.rs b/src/bin/cargo/commands/run.rs index 8ddf2623aff..6b1b8d06914 100644 --- a/src/bin/cargo/commands/run.rs +++ b/src/bin/cargo/commands/run.rs @@ -5,7 +5,8 @@ use cargo::ops::{self, CompileFilter}; pub fn cli() -> App { subcommand("run") - .alias("r") + // subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases() + // .alias("r") .setting(AppSettings::TrailingVarArg) .about("Run the main binary of the local package (src/main.rs)") .arg(Arg::with_name("args").multiple(true)) diff --git a/src/bin/cargo/commands/test.rs b/src/bin/cargo/commands/test.rs index 0e9b577b594..19c50e854f6 100644 --- a/src/bin/cargo/commands/test.rs +++ b/src/bin/cargo/commands/test.rs @@ -4,7 +4,8 @@ use cargo::ops::{self, CompileFilter}; pub fn cli() -> App { subcommand("test") - .alias("t") + // subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases() + // .alias("t") .setting(AppSettings::TrailingVarArg) .about("Execute all unit and integration tests of a local package") .arg( diff --git a/tests/testsuite/cargo_alias_config.rs b/tests/testsuite/cargo_alias_config.rs index 6226adbea78..c1893d1609f 100644 --- a/tests/testsuite/cargo_alias_config.rs +++ b/tests/testsuite/cargo_alias_config.rs @@ -22,24 +22,6 @@ expected a list, but found a integer for [..]", ).run(); } -#[test] -fn alias_default_config_overrides_config() { - let p = project() - .file("Cargo.toml", &basic_bin_manifest("foo")) - .file("src/main.rs", "fn main() {}") - .file( - ".cargo/config", - r#" - [alias] - b = "not_build" - "#, - ).build(); - - p.cargo("b -v") - .with_stderr_contains("[COMPILING] foo v0.5.0 [..]") - .run(); -} - #[test] fn alias_config() { let p = project() @@ -122,7 +104,7 @@ fn alias_with_flags_config() { } #[test] -fn cant_shadow_builtin() { +fn alias_cannot_shadow_builtin_command() { let p = project() .file("Cargo.toml", &basic_bin_manifest("foo")) .file("src/main.rs", "fn main() {}") @@ -137,9 +119,32 @@ fn cant_shadow_builtin() { p.cargo("build") .with_stderr( "\ -[WARNING] alias `build` is ignored, because it is shadowed by a built in command +[WARNING] user-defined alias `build` is ignored, because it is shadowed by a built-in command +[COMPILING] foo v0.5.0 ([..]) +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +", + ).run(); +} + +#[test] +fn alias_override_builtin_alias() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config", + r#" + [alias] + b = "run" + "#, + ).build(); + + p.cargo("b") + .with_stderr( + "\ [COMPILING] foo v0.5.0 ([..]) [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +[RUNNING] `target/debug/foo[EXE]` ", ).run(); } From b088539de834d698352f9c543fb5079e481a44d3 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 18 Nov 2018 09:08:15 +0000 Subject: [PATCH 071/128] Handle backslash-escaped backslashes --- tests/testsuite/support/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/testsuite/support/mod.rs b/tests/testsuite/support/mod.rs index 06b7c6c3df9..6392df5654c 100644 --- a/tests/testsuite/support/mod.rs +++ b/tests/testsuite/support/mod.rs @@ -1188,6 +1188,9 @@ enum MatchKind { /// See `substitute_macros` for a complete list of macros. pub fn lines_match(expected: &str, actual: &str) -> bool { // Let's not deal with / vs \ (windows...) + // First replace backslash-escaped backslashes with forward slashes + // which can occur in, for example, JSON output + let expected = expected.replace("\\\\", "/"); let expected = expected.replace("\\", "/"); let mut actual: &str = &actual.replace("\\", "/"); let expected = substitute_macros(&expected); From 6afca122e556d2c08f1d2990be0147c404e566eb Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 18 Nov 2018 12:08:03 +0000 Subject: [PATCH 072/128] Handle backslash-escaped backslashes in actual output too --- tests/testsuite/support/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/testsuite/support/mod.rs b/tests/testsuite/support/mod.rs index 6392df5654c..9c8fbec795c 100644 --- a/tests/testsuite/support/mod.rs +++ b/tests/testsuite/support/mod.rs @@ -1190,9 +1190,8 @@ pub fn lines_match(expected: &str, actual: &str) -> bool { // Let's not deal with / vs \ (windows...) // First replace backslash-escaped backslashes with forward slashes // which can occur in, for example, JSON output - let expected = expected.replace("\\\\", "/"); - let expected = expected.replace("\\", "/"); - let mut actual: &str = &actual.replace("\\", "/"); + let expected = expected.replace("\\\\", "/").replace("\\", "/"); + let mut actual: &str = &actual.replace("\\\\", "/").replace("\\", "/"); let expected = substitute_macros(&expected); for (i, part) in expected.split("[..]").enumerate() { match actual.find(part) { From 49f73b9c4e686d237b043a5320ed82bc797995a3 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 18 Nov 2018 13:38:33 +0000 Subject: [PATCH 073/128] Simplify cargo_command::cargo_subcommand_args test --- tests/testsuite/cargo_command.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/testsuite/cargo_command.rs b/tests/testsuite/cargo_command.rs index 8e0b6e19f15..e5adabe4fe6 100644 --- a/tests/testsuite/cargo_command.rs +++ b/tests/testsuite/cargo_command.rs @@ -264,13 +264,8 @@ fn cargo_subcommand_args() { cargo_process("foo bar -v --help") .env("PATH", &path) - .with_stdout( - if cfg!(windows) { // weird edge-case w/ CWD & (windows vs unix) - format!(r#"[{:?}, "foo", "bar", "-v", "--help"]"#, cargo_foo_bin) - } else { - r#"["[CWD]/cargo-foo/target/debug/cargo-foo", "foo", "bar", "-v", "--help"]"#.to_string() - } - ).run(); + .with_stdout(r#"["[CWD]/cargo-foo/target/debug/cargo-foo", "foo", "bar", "-v", "--help"]"#) + .run(); } #[test] From 092f7baea3bda0e1bc32de572a6cb3693120d884 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 18 Nov 2018 14:44:16 +0000 Subject: [PATCH 074/128] Fix cargo_command::cargo_subcommand_args test --- tests/testsuite/cargo_command.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/testsuite/cargo_command.rs b/tests/testsuite/cargo_command.rs index e5adabe4fe6..793ed50299c 100644 --- a/tests/testsuite/cargo_command.rs +++ b/tests/testsuite/cargo_command.rs @@ -264,7 +264,9 @@ fn cargo_subcommand_args() { cargo_process("foo bar -v --help") .env("PATH", &path) - .with_stdout(r#"["[CWD]/cargo-foo/target/debug/cargo-foo", "foo", "bar", "-v", "--help"]"#) + .with_stdout( + r#"["[CWD]/cargo-foo/target/debug/cargo-foo[EXE]", "foo", "bar", "-v", "--help"]"#, + ) .run(); } From dc6b5be30d604d5e14a17a834fef710e3653ec41 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 18 Nov 2018 14:45:28 +0000 Subject: [PATCH 075/128] Simplify tool_paths::absolute_tools test ... by reusing the new [ROOT] macro. --- tests/testsuite/tool_paths.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tests/testsuite/tool_paths.rs b/tests/testsuite/tool_paths.rs index 5bd256715d6..d952991f322 100644 --- a/tests/testsuite/tool_paths.rs +++ b/tests/testsuite/tool_paths.rs @@ -33,7 +33,6 @@ fn pathless_tools() { #[test] fn absolute_tools() { let target = rustc_host(); - let root = if cfg!(windows) { r#"C:\"# } else { "/" }; // Escaped as they appear within a TOML config file let config = if cfg!(windows) { @@ -62,14 +61,11 @@ fn absolute_tools() { ), ).build(); - foo.cargo("build --verbose").with_stderr(&format!( - "\ + foo.cargo("build --verbose").with_stderr("\ [COMPILING] foo v0.5.0 ([CWD]) -[RUNNING] `rustc [..] -C ar={root}bogus/nonexistent-ar -C linker={root}bogus/nonexistent-linker [..]` +[RUNNING] `rustc [..] -C ar=[ROOT]bogus/nonexistent-ar -C linker=[ROOT]bogus/nonexistent-linker [..]` [FINISHED] dev [unoptimized + debuginfo] target(s) in [..] -", - root = root, - )).run(); +").run(); } #[test] From 8d996a2df00c2a905a196ea672cf88bac6020286 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 18 Nov 2018 15:57:54 +0000 Subject: [PATCH 076/128] Make autodiscovery disable inferred targets --- src/cargo/util/toml/targets.rs | 7 ++++++- tests/testsuite/run.rs | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/cargo/util/toml/targets.rs b/src/cargo/util/toml/targets.rs index b86300225fe..81afec90926 100644 --- a/src/cargo/util/toml/targets.rs +++ b/src/cargo/util/toml/targets.rs @@ -634,7 +634,12 @@ fn toml_targets_and_inferred( ) -> Vec { let inferred_targets = inferred_to_toml_targets(inferred); match toml_targets { - None => inferred_targets, + None => + if let Some(false) = autodiscover { + vec![] + } else { + inferred_targets + }, Some(targets) => { let mut targets = targets.clone(); diff --git a/tests/testsuite/run.rs b/tests/testsuite/run.rs index d9d15e2790d..ac4bdb46415 100644 --- a/tests/testsuite/run.rs +++ b/tests/testsuite/run.rs @@ -463,6 +463,28 @@ fn run_example_autodiscover_2018() { .run(); } +#[test] +fn autobins_disables() { + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + autobins = false + "# + ) + .file("src/lib.rs", "pub mod bin;") + .file("src/bin/mod.rs", "// empty") + .build(); + + p.cargo("run") + .with_status(101) + .with_stderr("[ERROR] a bin target must be available for `cargo run`") + .run(); +} + #[test] fn run_bins() { let p = project() From e95036467ee6c3d60a920a26e8669e2b62124341 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 18 Nov 2018 17:32:42 +0000 Subject: [PATCH 077/128] Allow crate_type=bin examples to run --- src/cargo/core/manifest.rs | 6 +++++- tests/testsuite/run.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index aebf39a896e..f65778df45d 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -660,7 +660,11 @@ impl Target { required_features: Option>, edition: Edition, ) -> Target { - let kind = if crate_targets.is_empty() { + let kind = if crate_targets.is_empty() + || crate_targets + .iter() + .all(|t| *t == LibKind::Other("bin".into())) + { TargetKind::ExampleBin } else { TargetKind::ExampleLib(crate_targets) diff --git a/tests/testsuite/run.rs b/tests/testsuite/run.rs index d9d15e2790d..21858630939 100644 --- a/tests/testsuite/run.rs +++ b/tests/testsuite/run.rs @@ -349,6 +349,35 @@ fn run_library_example() { .run(); } +#[test] +fn run_bin_example() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + [[example]] + name = "bar" + crate_type = ["bin"] + "#, + ) + .file("src/lib.rs", "") + .file("examples/bar.rs", r#"fn main() { println!("example"); }"#) + .build(); + + p.cargo("run --example bar") + .with_stderr( + "\ +[COMPILING] foo v0.0.1 ([CWD]) +[FINISHED] dev [unoptimized + debuginfo] target(s) in [..] +[RUNNING] `target/debug/examples/bar[EXE]`", + ) + .with_stdout("example") + .run(); +} + fn autodiscover_examples_project(rust_edition: &str, autoexamples: Option) -> Project { let autoexamples = match autoexamples { None => "".to_string(), From 7b081569edeb88ffdeecb2855c8eea5954917c66 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 18 Nov 2018 17:59:05 +0000 Subject: [PATCH 078/128] Distinguish custom build invocations Distinguish building a build script from running it, in build plan invocations. --- src/cargo/core/compiler/build_config.rs | 2 +- src/cargo/core/compiler/build_plan.rs | 4 +++- tests/testsuite/build_plan.rs | 18 ++++++++++++------ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/cargo/core/compiler/build_config.rs b/src/cargo/core/compiler/build_config.rs index 1add81d0e58..bb25de07e84 100644 --- a/src/cargo/core/compiler/build_config.rs +++ b/src/cargo/core/compiler/build_config.rs @@ -111,7 +111,7 @@ pub enum MessageFormat { /// `compile_ws` to tell it the general execution strategy. This influences /// the default targets selected. The other use is in the `Unit` struct /// to indicate what is being done with a specific target. -#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)] +#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord, Serialize)] pub enum CompileMode { /// A target being built for a test. Test, diff --git a/src/cargo/core/compiler/build_plan.rs b/src/cargo/core/compiler/build_plan.rs index 5813e29906b..28625c7de9e 100644 --- a/src/cargo/core/compiler/build_plan.rs +++ b/src/cargo/core/compiler/build_plan.rs @@ -9,7 +9,7 @@ use std::collections::BTreeMap; use core::TargetKind; -use super::{Context, Kind, Unit}; +use super::{CompileMode, Context, Kind, Unit}; use super::context::OutputFile; use util::{internal, CargoResult, ProcessBuilder}; use std::path::PathBuf; @@ -22,6 +22,7 @@ struct Invocation { package_version: semver::Version, target_kind: TargetKind, kind: Kind, + compile_mode: CompileMode, deps: Vec, outputs: Vec, links: BTreeMap, @@ -51,6 +52,7 @@ impl Invocation { package_version: id.version().clone(), kind: unit.kind, target_kind: unit.target.kind().clone(), + compile_mode: unit.mode, deps, outputs: Vec::new(), links: BTreeMap::new(), diff --git a/tests/testsuite/build_plan.rs b/tests/testsuite/build_plan.rs index fa17a79067d..c4ed1e09874 100644 --- a/tests/testsuite/build_plan.rs +++ b/tests/testsuite/build_plan.rs @@ -28,7 +28,8 @@ fn cargo_build_plan_simple() { "package_name": "foo", "package_version": "0.5.0", "program": "rustc", - "target_kind": ["bin"] + "target_kind": ["bin"], + "compile_mode": "Build" } ] } @@ -86,7 +87,8 @@ fn cargo_build_plan_single_dep() { "package_name": "bar", "package_version": "0.0.1", "program": "rustc", - "target_kind": ["lib"] + "target_kind": ["lib"], + "compile_mode": "Build" }, { "args": "{...}", @@ -101,7 +103,8 @@ fn cargo_build_plan_single_dep() { "package_name": "foo", "package_version": "0.5.0", "program": "rustc", - "target_kind": ["lib"] + "target_kind": ["lib"], + "compile_mode": "Build" } ] } @@ -148,7 +151,8 @@ fn cargo_build_plan_build_script() { "package_name": "foo", "package_version": "0.5.0", "program": "rustc", - "target_kind": ["custom-build"] + "target_kind": ["custom-build"], + "compile_mode": "Build" }, { "args": "{...}", @@ -161,7 +165,8 @@ fn cargo_build_plan_build_script() { "package_name": "foo", "package_version": "0.5.0", "program": "[..]/build-script-build", - "target_kind": ["custom-build"] + "target_kind": ["custom-build"], + "compile_mode": "RunCustomBuild" }, { "args": "{...}", @@ -174,7 +179,8 @@ fn cargo_build_plan_build_script() { "package_name": "foo", "package_version": "0.5.0", "program": "rustc", - "target_kind": ["bin"] + "target_kind": ["bin"], + "compile_mode": "Build" } ] } From 27424e2dbaf5ff4ee53da92713d2b4ea04804df6 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 18 Nov 2018 18:32:54 +0000 Subject: [PATCH 079/128] Use kebab-case for CompileMode, & discard some info --- src/cargo/core/compiler/build_config.rs | 22 +++++++++++++++++++++- tests/testsuite/build_plan.rs | 12 ++++++------ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/cargo/core/compiler/build_config.rs b/src/cargo/core/compiler/build_config.rs index bb25de07e84..2de8fb575d9 100644 --- a/src/cargo/core/compiler/build_config.rs +++ b/src/cargo/core/compiler/build_config.rs @@ -1,6 +1,8 @@ use std::path::Path; use std::cell::RefCell; +use serde::ser; + use util::{CargoResult, CargoResultExt, Config, RustfixDiagnosticServer}; /// Configuration information for a rustc build. @@ -111,7 +113,7 @@ pub enum MessageFormat { /// `compile_ws` to tell it the general execution strategy. This influences /// the default targets selected. The other use is in the `Unit` struct /// to indicate what is being done with a specific target. -#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)] pub enum CompileMode { /// A target being built for a test. Test, @@ -136,6 +138,24 @@ pub enum CompileMode { RunCustomBuild, } +impl ser::Serialize for CompileMode { + fn serialize(&self, s: S) -> Result + where + S: ser::Serializer, + { + use self::CompileMode::*; + match *self { + Test => "test".serialize(s), + Build => "build".serialize(s), + Check { .. } => "check".serialize(s), + Bench => "bench".serialize(s), + Doc { .. } => "doc".serialize(s), + Doctest => "doctest".serialize(s), + RunCustomBuild => "run-custom-build".serialize(s), + } + } +} + impl CompileMode { /// Returns true if the unit is being checked. pub fn is_check(self) -> bool { diff --git a/tests/testsuite/build_plan.rs b/tests/testsuite/build_plan.rs index c4ed1e09874..7b520cfd699 100644 --- a/tests/testsuite/build_plan.rs +++ b/tests/testsuite/build_plan.rs @@ -29,7 +29,7 @@ fn cargo_build_plan_simple() { "package_version": "0.5.0", "program": "rustc", "target_kind": ["bin"], - "compile_mode": "Build" + "compile_mode": "build" } ] } @@ -88,7 +88,7 @@ fn cargo_build_plan_single_dep() { "package_version": "0.0.1", "program": "rustc", "target_kind": ["lib"], - "compile_mode": "Build" + "compile_mode": "build" }, { "args": "{...}", @@ -104,7 +104,7 @@ fn cargo_build_plan_single_dep() { "package_version": "0.5.0", "program": "rustc", "target_kind": ["lib"], - "compile_mode": "Build" + "compile_mode": "build" } ] } @@ -152,7 +152,7 @@ fn cargo_build_plan_build_script() { "package_version": "0.5.0", "program": "rustc", "target_kind": ["custom-build"], - "compile_mode": "Build" + "compile_mode": "build" }, { "args": "{...}", @@ -166,7 +166,7 @@ fn cargo_build_plan_build_script() { "package_version": "0.5.0", "program": "[..]/build-script-build", "target_kind": ["custom-build"], - "compile_mode": "RunCustomBuild" + "compile_mode": "run-custom-build" }, { "args": "{...}", @@ -180,7 +180,7 @@ fn cargo_build_plan_build_script() { "package_version": "0.5.0", "program": "rustc", "target_kind": ["bin"], - "compile_mode": "Build" + "compile_mode": "build" } ] } From e8c1811f83a71deecdc44788645855b2b08b9057 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 18 Nov 2018 18:39:08 +0000 Subject: [PATCH 080/128] Fix metabuild::metabuild_build_plan --- tests/testsuite/metabuild.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/testsuite/metabuild.rs b/tests/testsuite/metabuild.rs index c96f0c4b6b6..7837042b1d1 100644 --- a/tests/testsuite/metabuild.rs +++ b/tests/testsuite/metabuild.rs @@ -433,6 +433,7 @@ fn metabuild_build_plan() { "package_name": "mb", "package_version": "0.5.0", "target_kind": ["lib"], + "compile_mode": "build", "kind": "Host", "deps": [], "outputs": ["[..]/target/debug/deps/libmb-[..].rlib"], @@ -446,6 +447,7 @@ fn metabuild_build_plan() { "package_name": "mb-other", "package_version": "0.0.1", "target_kind": ["lib"], + "compile_mode": "build", "kind": "Host", "deps": [], "outputs": ["[..]/target/debug/deps/libmb_other-[..].rlib"], @@ -459,6 +461,7 @@ fn metabuild_build_plan() { "package_name": "foo", "package_version": "0.0.1", "target_kind": ["custom-build"], + "compile_mode": "build", "kind": "Host", "deps": [0, 1], "outputs": ["[..]/target/debug/build/foo-[..]/metabuild_foo-[..][EXE]"], @@ -472,6 +475,7 @@ fn metabuild_build_plan() { "package_name": "foo", "package_version": "0.0.1", "target_kind": ["custom-build"], + "compile_mode": "run-custom-build", "kind": "Host", "deps": [2], "outputs": [], @@ -485,6 +489,7 @@ fn metabuild_build_plan() { "package_name": "foo", "package_version": "0.0.1", "target_kind": ["lib"], + "compile_mode": "build", "kind": "Host", "deps": [3], "outputs": ["[..]/foo/target/debug/deps/libfoo-[..].rlib"], From 2a667323ef9ffe601af12c97143168cb0c74aba7 Mon Sep 17 00:00:00 2001 From: Hidehito Yabuuchi Date: Wed, 24 Oct 2018 23:34:25 +0900 Subject: [PATCH 081/128] Add `c` alias for `check` --- src/bin/cargo/commands/check.rs | 2 ++ src/bin/cargo/commands/mod.rs | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bin/cargo/commands/check.rs b/src/bin/cargo/commands/check.rs index c9bbac1e74a..2edb6089c1b 100644 --- a/src/bin/cargo/commands/check.rs +++ b/src/bin/cargo/commands/check.rs @@ -4,6 +4,8 @@ use cargo::ops; pub fn cli() -> App { subcommand("check") + // subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases() + // .alias("c") .about("Check a local package and all of its dependencies for errors") .arg_package_spec( "Package(s) to check", diff --git a/src/bin/cargo/commands/mod.rs b/src/bin/cargo/commands/mod.rs index 6e3670f84a5..3f7e4bf26e2 100644 --- a/src/bin/cargo/commands/mod.rs +++ b/src/bin/cargo/commands/mod.rs @@ -44,7 +44,7 @@ pub fn builtin_exec(cmd: &str) -> Option { let exec = match cmd { "bench" => bench::exec, "build" | "b" => build::exec, - "check" => check::exec, + "check" | "c" => check::exec, "clean" => clean::exec, "doc" => doc::exec, "fetch" => fetch::exec, @@ -77,6 +77,7 @@ pub fn builtin_exec(cmd: &str) -> Option { let alias_for = match cmd { "b" => Some("build"), + "c" => Some("check"), "r" => Some("run"), "t" => Some("test"), _ => None, From a703851abe68c3e9b64db42a86e46387876eff71 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Thu, 21 Jun 2018 16:06:09 -0400 Subject: [PATCH 082/128] try im-rs --- Cargo.toml | 1 + src/cargo/core/resolver/context.rs | 16 +++++++--------- src/cargo/lib.rs | 1 + 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8c3065fb162..2eb0a7d5894 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,7 @@ url = "1.1" clap = "2.31.2" unicode-width = "0.1.5" openssl = { version = '0.10.11', optional = true } +im-rc = "12.1.0" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` diff --git a/src/cargo/core/resolver/context.rs b/src/cargo/core/resolver/context.rs index 96fdfd40daf..4a6629f93c5 100644 --- a/src/cargo/core/resolver/context.rs +++ b/src/cargo/core/resolver/context.rs @@ -5,6 +5,7 @@ use core::interning::InternedString; use core::{Dependency, FeatureValue, PackageId, SourceId, Summary}; use util::CargoResult; use util::Graph; +use im_rc; use super::errors::ActivateResult; use super::types::{ConflictReason, DepInfo, GraphNode, Method, RcList, RegistryQueryer}; @@ -19,12 +20,9 @@ pub use super::resolve::Resolve; // possible. #[derive(Clone)] pub struct Context { - // TODO: Both this and the two maps below are super expensive to clone. We should - // switch to persistent hash maps if we can at some point or otherwise - // make these much cheaper to clone in general. pub activations: Activations, - pub resolve_features: HashMap>>, - pub links: HashMap, + pub resolve_features: im_rc::HashMap>>, + pub links: im_rc::HashMap, // These are two cheaply-cloneable lists (O(1) clone) which are effectively // hash maps but are built up as "construction lists". We'll iterate these @@ -36,16 +34,16 @@ pub struct Context { pub warnings: RcList, } -pub type Activations = HashMap<(InternedString, SourceId), Rc>>; +pub type Activations = im_rc::HashMap<(InternedString, SourceId), Rc>>; impl Context { pub fn new() -> Context { Context { resolve_graph: RcList::new(), - resolve_features: HashMap::new(), - links: HashMap::new(), + resolve_features: im_rc::HashMap::new(), + links: im_rc::HashMap::new(), resolve_replacements: RcList::new(), - activations: HashMap::new(), + activations: im_rc::HashMap::new(), warnings: RcList::new(), } } diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs index e7fcac41d24..8359faceabe 100644 --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -62,6 +62,7 @@ extern crate termcolor; extern crate toml; extern crate unicode_width; extern crate url; +extern crate im_rc; use std::fmt; From e3b44cc3258eab458b79bd45cf8e7a50c4105d4a Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Thu, 27 Sep 2018 15:50:25 -0400 Subject: [PATCH 083/128] use im-rs for RemainingDeps --- src/cargo/core/resolver/types.rs | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/cargo/core/resolver/types.rs b/src/cargo/core/resolver/types.rs index 0f39783a99e..d916d7ad62c 100644 --- a/src/cargo/core/resolver/types.rs +++ b/src/cargo/core/resolver/types.rs @@ -1,5 +1,5 @@ use std::cmp::Ordering; -use std::collections::{BinaryHeap, HashMap, HashSet}; +use std::collections::{HashMap, HashSet}; use std::ops::Range; use std::rc::Rc; use std::time::{Duration, Instant}; @@ -9,6 +9,8 @@ use core::{Dependency, PackageId, PackageIdSpec, Registry, Summary}; use util::errors::CargoResult; use util::Config; +use im_rc; + pub struct ResolverProgress { ticks: u16, start: Instant, @@ -299,33 +301,30 @@ impl Ord for DepsFrame { fn cmp(&self, other: &DepsFrame) -> Ordering { self.just_for_error_messages .cmp(&other.just_for_error_messages) - .then_with(|| - // the frame with the sibling that has the least number of candidates - // needs to get bubbled up to the top of the heap we use below, so - // reverse comparison here. - self.min_candidates().cmp(&other.min_candidates()).reverse()) + .reverse() + .then_with(|| self.min_candidates().cmp(&other.min_candidates())) } } -/// Note that a `BinaryHeap` is used for the remaining dependencies that need -/// activation. This heap is sorted such that the "largest value" is the most -/// constrained dependency, or the one with the least candidates. +/// Note that a `OrdSet` is used for the remaining dependencies that need +/// activation. This set is sorted by how many candidates each dependency has. /// /// This helps us get through super constrained portions of the dependency /// graph quickly and hopefully lock down what later larger dependencies can /// use (those with more candidates). #[derive(Clone)] -pub struct RemainingDeps(BinaryHeap); +pub struct RemainingDeps(usize, im_rc::OrdSet<(DepsFrame, usize)>); impl RemainingDeps { pub fn new() -> RemainingDeps { - RemainingDeps(BinaryHeap::new()) + RemainingDeps(0, im_rc::OrdSet::new()) } pub fn push(&mut self, x: DepsFrame) { - self.0.push(x) + self.1.insert((x, self.0)); + self.0 += 1; } pub fn pop_most_constrained(&mut self) -> Option<(bool, (Summary, (usize, DepInfo)))> { - while let Some(mut deps_frame) = self.0.pop() { + while let Some((mut deps_frame, i)) = self.1.remove_min() { let just_here_for_the_error_messages = deps_frame.just_for_error_messages; // Figure out what our next dependency to activate is, and if nothing is @@ -333,14 +332,14 @@ impl RemainingDeps { // move on to the next frame. if let Some(sibling) = deps_frame.remaining_siblings.next() { let parent = Summary::clone(&deps_frame.parent); - self.0.push(deps_frame); + self.1.insert((deps_frame, i)); return Some((just_here_for_the_error_messages, (parent, sibling))); } } None } pub fn iter(&mut self) -> impl Iterator { - self.0.iter().flat_map(|other| other.flatten()) + self.1.iter().flat_map(|(other, _)| other.flatten()) } } From fd06af4e0bf38e174dd27babffe2a5dc19c1ba16 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Thu, 4 Oct 2018 13:18:18 -0400 Subject: [PATCH 084/128] better error for benchmarking --- src/cargo/core/resolver/types.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cargo/core/resolver/types.rs b/src/cargo/core/resolver/types.rs index d916d7ad62c..db1570f3705 100644 --- a/src/cargo/core/resolver/types.rs +++ b/src/cargo/core/resolver/types.rs @@ -54,7 +54,11 @@ impl ResolverProgress { // with all the algorithm improvements. // If any of them are removed then it takes more than I am willing to measure. // So lets fail the test fast if we have ben running for two long. - debug_assert!(self.ticks < 50_000); + debug_assert!( + self.ticks < 50_000, + "got to 50_000 ticks in {:?}", + self.start.elapsed() + ); // The largest test in our suite takes less then 30 sec // with all the improvements to how fast a tick can go. // If any of them are removed then it takes more than I am willing to measure. From 077a31adb3922202ada72623d40c3a9e371e3df0 Mon Sep 17 00:00:00 2001 From: Andy Caldwell Date: Mon, 19 Nov 2018 21:41:09 +0000 Subject: [PATCH 085/128] Move command prelude into main library --- src/bin/cargo/main.rs | 3 +-- .../cargo => cargo/util}/command_prelude.rs | 18 +++++++++--------- src/cargo/util/mod.rs | 1 + 3 files changed, 11 insertions(+), 11 deletions(-) rename src/{bin/cargo => cargo/util}/command_prelude.rs (97%) diff --git a/src/bin/cargo/main.rs b/src/bin/cargo/main.rs index e0333ee1081..979d8949427 100644 --- a/src/bin/cargo/main.rs +++ b/src/bin/cargo/main.rs @@ -19,11 +19,10 @@ use std::path::{Path, PathBuf}; use std::collections::BTreeSet; use cargo::core::shell::Shell; -use cargo::util::{self, lev_distance, CargoResult, CliResult, Config}; +use cargo::util::{self, command_prelude, lev_distance, CargoResult, CliResult, Config}; use cargo::util::{CliError, ProcessError}; mod cli; -mod command_prelude; mod commands; use command_prelude::*; diff --git a/src/bin/cargo/command_prelude.rs b/src/cargo/util/command_prelude.rs similarity index 97% rename from src/bin/cargo/command_prelude.rs rename to src/cargo/util/command_prelude.rs index c8f2fc824b0..774e0fce6af 100644 --- a/src/bin/cargo/command_prelude.rs +++ b/src/cargo/util/command_prelude.rs @@ -2,17 +2,17 @@ use std::path::PathBuf; use std::fs; use clap::{self, SubCommand}; -use cargo::CargoResult; -use cargo::core::Workspace; -use cargo::core::compiler::{BuildConfig, MessageFormat}; -use cargo::ops::{CompileFilter, CompileOptions, NewOptions, Packages, VersionControl}; -use cargo::sources::CRATES_IO_REGISTRY; -use cargo::util::paths; -use cargo::util::important_paths::find_root_manifest_for_wd; +use CargoResult; +use core::Workspace; +use core::compiler::{BuildConfig, MessageFormat}; +use ops::{CompileFilter, CompileOptions, NewOptions, Packages, VersionControl}; +use sources::CRATES_IO_REGISTRY; +use util::paths; +use util::important_paths::find_root_manifest_for_wd; pub use clap::{AppSettings, Arg, ArgMatches}; -pub use cargo::{CliError, CliResult, Config}; -pub use cargo::core::compiler::CompileMode; +pub use {CliError, CliResult, Config}; +pub use core::compiler::CompileMode; pub type App = clap::App<'static, 'static>; diff --git a/src/cargo/util/mod.rs b/src/cargo/util/mod.rs index c18914954f6..69f2d0e6852 100644 --- a/src/cargo/util/mod.rs +++ b/src/cargo/util/mod.rs @@ -38,6 +38,7 @@ pub mod profile; pub mod to_semver; pub mod to_url; pub mod toml; +pub mod command_prelude; mod cfg; mod dependency_queue; mod rustc; From 1699a5b1ce197596dae286fd39d48e7b91b3ed5f Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Tue, 20 Nov 2018 15:52:52 -0500 Subject: [PATCH 086/128] Clarify the need for a counter --- src/cargo/core/resolver/types.rs | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/cargo/core/resolver/types.rs b/src/cargo/core/resolver/types.rs index db1570f3705..6f940afbc3d 100644 --- a/src/cargo/core/resolver/types.rs +++ b/src/cargo/core/resolver/types.rs @@ -317,18 +317,29 @@ impl Ord for DepsFrame { /// graph quickly and hopefully lock down what later larger dependencies can /// use (those with more candidates). #[derive(Clone)] -pub struct RemainingDeps(usize, im_rc::OrdSet<(DepsFrame, usize)>); +pub struct RemainingDeps { + /// a monotonic counter, increased for each new insertion. + time: u32, + /// the data is augmented by the insertion time. + /// This insures that no two items will cmp eq. + /// Forcing the OrdSet into a multi set. + data: im_rc::OrdSet<(DepsFrame, u32)>, +} impl RemainingDeps { pub fn new() -> RemainingDeps { - RemainingDeps(0, im_rc::OrdSet::new()) + RemainingDeps { + time: 0, + data: im_rc::OrdSet::new(), + } } pub fn push(&mut self, x: DepsFrame) { - self.1.insert((x, self.0)); - self.0 += 1; + let insertion_time = self.time; + self.data.insert((x, insertion_time)); + self.time += 1; } pub fn pop_most_constrained(&mut self) -> Option<(bool, (Summary, (usize, DepInfo)))> { - while let Some((mut deps_frame, i)) = self.1.remove_min() { + while let Some((mut deps_frame, insertion_time)) = self.data.remove_min() { let just_here_for_the_error_messages = deps_frame.just_for_error_messages; // Figure out what our next dependency to activate is, and if nothing is @@ -336,14 +347,14 @@ impl RemainingDeps { // move on to the next frame. if let Some(sibling) = deps_frame.remaining_siblings.next() { let parent = Summary::clone(&deps_frame.parent); - self.1.insert((deps_frame, i)); + self.data.insert((deps_frame, insertion_time)); return Some((just_here_for_the_error_messages, (parent, sibling))); } } None } pub fn iter(&mut self) -> impl Iterator { - self.1.iter().flat_map(|(other, _)| other.flatten()) + self.data.iter().flat_map(|(other, _)| other.flatten()) } } From 3d91b795413e0c375c3df7e3f0c0eb6a2464ef67 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 18 Nov 2018 21:06:15 +0000 Subject: [PATCH 087/128] Intern SourceId --- src/cargo/core/source/source_id.rs | 45 ++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/cargo/core/source/source_id.rs b/src/cargo/core/source/source_id.rs index f30d18ffd05..6b640aefe73 100644 --- a/src/cargo/core/source/source_id.rs +++ b/src/cargo/core/source/source_id.rs @@ -1,8 +1,9 @@ use std::cmp::{self, Ordering}; +use std::collections::HashSet; use std::fmt::{self, Formatter}; use std::hash::{self, Hash}; use std::path::Path; -use std::sync::Arc; +use std::sync::Mutex; use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT}; use std::sync::atomic::Ordering::SeqCst; @@ -16,13 +17,17 @@ use sources::{GitSource, PathSource, RegistrySource, CRATES_IO_INDEX}; use sources::DirectorySource; use util::{CargoResult, Config, ToUrl}; +lazy_static! { + static ref SOURCE_ID_CACHE: Mutex> = Mutex::new(HashSet::new()); +} + /// Unique identifier for a source of packages. #[derive(Clone, Eq, Debug)] pub struct SourceId { - inner: Arc, + inner: &'static SourceIdInner, } -#[derive(Eq, Clone, Debug)] +#[derive(Eq, Clone, Debug, Hash)] struct SourceIdInner { /// The source URL url: Url, @@ -68,18 +73,28 @@ impl SourceId { /// /// The canonical url will be calculated, but the precise field will not fn new(kind: Kind, url: Url) -> CargoResult { - let source_id = SourceId { - inner: Arc::new(SourceIdInner { + let source_id = SourceId::wrap( + SourceIdInner { kind, canonical_url: git::canonicalize_url(&url)?, url, precise: None, name: None, - }), - }; + } + ); Ok(source_id) } + fn wrap(inner: SourceIdInner) -> SourceId { + let mut cache = SOURCE_ID_CACHE.lock().unwrap(); + let inner = cache.get(&inner).map(|&x| x).unwrap_or_else(|| { + let inner = Box::leak(Box::new(inner)); + cache.insert(inner); + inner + }); + SourceId { inner } + } + /// Parses a source URL and returns the corresponding ID. /// /// ## Example @@ -193,15 +208,15 @@ impl SourceId { pub fn alt_registry(config: &Config, key: &str) -> CargoResult { let url = config.get_registry_index(key)?; - Ok(SourceId { - inner: Arc::new(SourceIdInner { + Ok(SourceId::wrap( + SourceIdInner { kind: Kind::Registry, canonical_url: git::canonicalize_url(&url)?, url, precise: None, name: Some(key.to_string()), - }), - }) + } + )) } /// Get this source URL @@ -288,12 +303,12 @@ impl SourceId { /// Create a new SourceId from this source with the given `precise` pub fn with_precise(&self, v: Option) -> SourceId { - SourceId { - inner: Arc::new(SourceIdInner { + SourceId::wrap( + SourceIdInner { precise: v, ..(*self.inner).clone() - }), - } + } + ) } /// Whether the remote registry is the standard https://crates.io From 2dffd7c1d95beceafa21fda8b34983b64c1042b6 Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard Date: Thu, 22 Nov 2018 03:25:45 -0700 Subject: [PATCH 088/128] Correct Target Directory command-line option The option is `--target-dir`, not `--target`, which is discussed above. --- src/doc/src/appendix/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/src/appendix/glossary.md b/src/doc/src/appendix/glossary.md index e5d957acf6a..8b9a55915e4 100644 --- a/src/doc/src/appendix/glossary.md +++ b/src/doc/src/appendix/glossary.md @@ -119,7 +119,7 @@ The meaning of the term *target* depends on the context: - **Target Directory** — Cargo places all built artifacts and intermediate files in the *target* directory. By default this is a directory named `target` at the workspace root, or the package root if not using a - workspace. The directory be changed with the `--target` command-line option, + workspace. The directory be changed with the `--target-dir` command-line option, the `CARGO_TARGET_DIR` [environment variable], or the `build.target-dir` [config option]. From b606256fec5b111f7a0bed320c66aaad62fd8560 Mon Sep 17 00:00:00 2001 From: David Laehnemann Date: Fri, 23 Nov 2018 12:07:31 +0100 Subject: [PATCH 089/128] docs: correct profile usage of cargo test --release --- src/doc/src/reference/manifest.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/src/reference/manifest.md b/src/doc/src/reference/manifest.md index 9ff1bce7b22..8a024baf8be 100644 --- a/src/doc/src/reference/manifest.md +++ b/src/doc/src/reference/manifest.md @@ -341,7 +341,7 @@ incremental = true # whether or not incremental compilation is enabled overflow-checks = true # use overflow checks for integer arithmetic. # Passes the `-C overflow-checks=...` flag to the compiler. -# The release profile, used for `cargo build --release`. +# The release profile, used for `cargo build --release` and `cargo test --release`. [profile.release] opt-level = 3 debug = false @@ -365,7 +365,7 @@ panic = 'unwind' incremental = true overflow-checks = true -# The benchmarking profile, used for `cargo bench` and `cargo test --release`. +# The benchmarking profile, used for `cargo bench`. [profile.bench] opt-level = 3 debug = false From 653ce4d4c37766b0aa1858c25ae6fd63c63cbc13 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 25 Nov 2018 12:14:56 +0000 Subject: [PATCH 090/128] Move the custom equality up to SourceId That way we: * preserve that SourceIds that have slightly different URLs are actually equal * make SourceIdInner lawful in its Hash/Eq definition. --- src/cargo/core/source/source_id.rs | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/cargo/core/source/source_id.rs b/src/cargo/core/source/source_id.rs index 6b640aefe73..3b54003dcaa 100644 --- a/src/cargo/core/source/source_id.rs +++ b/src/cargo/core/source/source_id.rs @@ -27,7 +27,7 @@ pub struct SourceId { inner: &'static SourceIdInner, } -#[derive(Eq, Clone, Debug, Hash)] +#[derive(PartialEq, Eq, Clone, Debug, Hash)] struct SourceIdInner { /// The source URL url: Url, @@ -341,12 +341,6 @@ impl SourceId { } } -impl PartialEq for SourceId { - fn eq(&self, other: &SourceId) -> bool { - (*self.inner).eq(&*other.inner) - } -} - impl PartialOrd for SourceId { fn partial_cmp(&self, other: &SourceId) -> Option { Some(self.cmp(other)) @@ -440,24 +434,20 @@ impl fmt::Display for SourceId { } } -// This custom implementation handles situations such as when two git sources -// point at *almost* the same URL, but not quite, even when they actually point -// to the same repository. -/// This method tests for self and other values to be equal, and is used by ==. -/// -/// For git repositories, the canonical url is checked. -impl PartialEq for SourceIdInner { - fn eq(&self, other: &SourceIdInner) -> bool { - if self.kind != other.kind { +// Custom equality defined as canonical URL equality for git sources and +// URL equality for other sources, ignoring the `precise` and `name` fields. +impl PartialEq for SourceId { + fn eq(&self, other: &SourceId) -> bool { + if self.inner.kind != other.inner.kind { return false; } - if self.url == other.url { + if self.inner.url == other.inner.url { return true; } - match (&self.kind, &other.kind) { - (&Kind::Git(ref ref1), &Kind::Git(ref ref2)) => { - ref1 == ref2 && self.canonical_url == other.canonical_url + match (&self.inner.kind, &other.inner.kind) { + (Kind::Git(ref1), Kind::Git(ref2)) => { + ref1 == ref2 && self.inner.canonical_url == other.inner.canonical_url } _ => false, } From ba175dcc4da4a3fef0a872cf972a6ef722493d19 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 25 Nov 2018 12:23:45 +0000 Subject: [PATCH 091/128] Add pointer equality to PartialEq for SourceId --- src/cargo/core/source/source_id.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cargo/core/source/source_id.rs b/src/cargo/core/source/source_id.rs index 3b54003dcaa..63eb8773e89 100644 --- a/src/cargo/core/source/source_id.rs +++ b/src/cargo/core/source/source_id.rs @@ -3,6 +3,7 @@ use std::collections::HashSet; use std::fmt::{self, Formatter}; use std::hash::{self, Hash}; use std::path::Path; +use std::ptr; use std::sync::Mutex; use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT}; use std::sync::atomic::Ordering::SeqCst; @@ -438,6 +439,9 @@ impl fmt::Display for SourceId { // URL equality for other sources, ignoring the `precise` and `name` fields. impl PartialEq for SourceId { fn eq(&self, other: &SourceId) -> bool { + if ptr::eq(self.inner, other.inner) { + return true; + } if self.inner.kind != other.inner.kind { return false; } From 9b22eb1998752dbaccbd125c74f263e0ea6f7c3b Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 25 Nov 2018 13:00:34 +0000 Subject: [PATCH 092/128] Make SourceId derive Copy --- src/cargo/core/source/source_id.rs | 2 +- src/cargo/ops/resolve.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cargo/core/source/source_id.rs b/src/cargo/core/source/source_id.rs index 63eb8773e89..47e8ef546f1 100644 --- a/src/cargo/core/source/source_id.rs +++ b/src/cargo/core/source/source_id.rs @@ -23,7 +23,7 @@ lazy_static! { } /// Unique identifier for a source of packages. -#[derive(Clone, Eq, Debug)] +#[derive(Clone, Copy, Eq, Debug)] pub struct SourceId { inner: &'static SourceIdInner, } diff --git a/src/cargo/ops/resolve.rs b/src/cargo/ops/resolve.rs index da01a776318..275fbe752a4 100644 --- a/src/cargo/ops/resolve.rs +++ b/src/cargo/ops/resolve.rs @@ -150,7 +150,7 @@ pub fn resolve_with_previous<'a, 'cfg>( // // TODO: This seems like a hokey reason to single out the registry as being // different - let mut to_avoid_sources = HashSet::new(); + let mut to_avoid_sources: HashSet<&SourceId> = HashSet::new(); if let Some(to_avoid) = to_avoid { to_avoid_sources.extend( to_avoid @@ -161,7 +161,7 @@ pub fn resolve_with_previous<'a, 'cfg>( } let keep = |p: &&'a PackageId| { - !to_avoid_sources.contains(&p.source_id()) && match to_avoid { + !to_avoid_sources.contains(p.source_id()) && match to_avoid { Some(set) => !set.contains(p), None => true, } From e5a11190b31957b488bc1e2f0416ebab4b4658ec Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Sun, 25 Nov 2018 12:31:27 -0500 Subject: [PATCH 093/128] SourceId is copy, clippy thinks we dont need &SourceId or SourceId.clone() --- src/bin/cargo/cli.rs | 9 +- src/bin/cargo/commands/git_checkout.rs | 2 +- src/bin/cargo/commands/install.rs | 5 +- src/bin/cargo/commands/login.rs | 7 +- src/cargo/core/dependency.rs | 63 ++++--- src/cargo/core/interning.rs | 2 +- src/cargo/core/manifest.rs | 32 ++-- src/cargo/core/package.rs | 218 +++++++++++++---------- src/cargo/core/package_id.rs | 26 +-- src/cargo/core/package_id_spec.rs | 13 +- src/cargo/core/profiles.rs | 43 +++-- src/cargo/core/registry.rs | 70 ++++---- src/cargo/core/resolver/context.rs | 8 +- src/cargo/core/resolver/encode.rs | 20 +-- src/cargo/core/source/mod.rs | 26 +-- src/cargo/core/source/source_id.rs | 77 ++++---- src/cargo/core/summary.rs | 92 +++++----- src/cargo/core/workspace.rs | 36 ++-- src/cargo/ops/cargo_generate_lockfile.rs | 8 +- src/cargo/ops/cargo_install.rs | 88 ++++----- src/cargo/ops/cargo_package.rs | 52 +++--- src/cargo/ops/cargo_read_manifest.rs | 8 +- src/cargo/ops/registry.rs | 45 +++-- src/cargo/ops/resolve.rs | 17 +- src/cargo/sources/config.rs | 12 +- src/cargo/sources/directory.rs | 16 +- src/cargo/sources/git/source.rs | 32 ++-- src/cargo/sources/path.rs | 34 ++-- src/cargo/sources/registry/index.rs | 61 ++++--- src/cargo/sources/registry/mod.rs | 63 ++++--- src/cargo/sources/registry/remote.rs | 46 +++-- src/cargo/sources/replaced.rs | 86 ++++----- src/cargo/util/toml/mod.rs | 30 ++-- tests/testsuite/search.rs | 39 ++-- tests/testsuite/support/resolver.rs | 24 ++- 35 files changed, 756 insertions(+), 654 deletions(-) diff --git a/src/bin/cargo/cli.rs b/src/bin/cargo/cli.rs index 33927c44500..ad1ddd85297 100644 --- a/src/bin/cargo/cli.rs +++ b/src/bin/cargo/cli.rs @@ -81,7 +81,7 @@ Run with 'cargo -Z [FLAG] [SUBCOMMAND]'" pub fn get_version_string(is_verbose: bool) -> String { let version = cargo::version(); - let mut version_string = String::from(version.to_string()); + let mut version_string = version.to_string(); version_string.push_str("\n"); if is_verbose { version_string.push_str(&format!( @@ -218,9 +218,10 @@ See 'cargo help ' for more information on a specific command.\n", opt( "verbose", "Use verbose output (-vv very verbose/build.rs output)", - ).short("v") - .multiple(true) - .global(true), + ) + .short("v") + .multiple(true) + .global(true), ) .arg( opt("quiet", "No output printed to stdout") diff --git a/src/bin/cargo/commands/git_checkout.rs b/src/bin/cargo/commands/git_checkout.rs index a9401f1059b..80b236293d7 100644 --- a/src/bin/cargo/commands/git_checkout.rs +++ b/src/bin/cargo/commands/git_checkout.rs @@ -28,7 +28,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { let reference = GitReference::Branch(reference.to_string()); let source_id = SourceId::for_git(&url, reference)?; - let mut source = GitSource::new(&source_id, config)?; + let mut source = GitSource::new(source_id, config)?; source.update()?; diff --git a/src/bin/cargo/commands/install.rs b/src/bin/cargo/commands/install.rs index ba3c6699680..b6348d747d4 100644 --- a/src/bin/cargo/commands/install.rs +++ b/src/bin/cargo/commands/install.rs @@ -82,7 +82,8 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { compile_opts.build_config.release = !args.is_present("debug"); - let krates = args.values_of("crate") + let krates = args + .values_of("crate") .unwrap_or_default() .collect::>(); @@ -120,7 +121,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { ops::install( root, krates, - &source, + source, from_cwd, version, &compile_opts, diff --git a/src/bin/cargo/commands/login.rs b/src/bin/cargo/commands/login.rs index 39f53f342e5..0c743829624 100644 --- a/src/bin/cargo/commands/login.rs +++ b/src/bin/cargo/commands/login.rs @@ -3,9 +3,9 @@ use command_prelude::*; use std::io::{self, BufRead}; use cargo::core::{Source, SourceId}; +use cargo::ops; use cargo::sources::RegistrySource; use cargo::util::{CargoError, CargoResultExt}; -use cargo::ops; pub fn cli() -> App { subcommand("login") @@ -29,11 +29,12 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { return Err(format_err!( "token must be provided when \ --registry is provided." - ).into()); + ) + .into()); } None => { let src = SourceId::crates_io(config)?; - let mut src = RegistrySource::remote(&src, config); + let mut src = RegistrySource::remote(src, config); src.update()?; let config = src.config()?.unwrap(); args.value_of("host") diff --git a/src/cargo/core/dependency.rs b/src/cargo/core/dependency.rs index f96c2069136..bdb04e36a7a 100644 --- a/src/cargo/core/dependency.rs +++ b/src/cargo/core/dependency.rs @@ -2,14 +2,14 @@ use std::fmt; use std::rc::Rc; use std::str::FromStr; -use semver::VersionReq; use semver::ReqParseError; +use semver::VersionReq; use serde::ser; -use core::{PackageId, SourceId, Summary}; use core::interning::InternedString; -use util::{Cfg, CfgExpr, Config}; +use core::{PackageId, SourceId, Summary}; use util::errors::{CargoError, CargoResult, CargoResultExt}; +use util::{Cfg, CfgExpr, Config}; /// Information about a dependency requested by a Cargo manifest. /// Cheap to copy. @@ -48,7 +48,7 @@ pub enum Platform { #[derive(Serialize)] struct SerializedDependency<'a> { name: &'a str, - source: &'a SourceId, + source: SourceId, req: String, kind: Kind, rename: Option<&'a str>, @@ -74,7 +74,8 @@ impl ser::Serialize for Dependency { features: self.features(), target: self.platform(), rename: self.explicit_name_in_toml().map(|s| s.as_str()), - }.serialize(s) + } + .serialize(s) } } @@ -116,7 +117,7 @@ this warning. config.shell().warn(&msg)?; Ok(requirement) - }, + } Err(e) => { let err: CargoResult = Err(e.into()); let v: VersionReq = err.chain_err(|| { @@ -126,7 +127,7 @@ this warning. ) })?; Ok(v) - }, + } Ok(v) => Ok(v), } } @@ -140,7 +141,8 @@ impl ser::Serialize for Kind { Kind::Normal => None, Kind::Development => Some("dev"), Kind::Build => Some("build"), - }.serialize(s) + } + .serialize(s) } } @@ -149,7 +151,7 @@ impl Dependency { pub fn parse( name: &str, version: Option<&str>, - source_id: &SourceId, + source_id: SourceId, inside: &PackageId, config: &Config, ) -> CargoResult { @@ -173,7 +175,7 @@ impl Dependency { pub fn parse_no_deprecated( name: &str, version: Option<&str>, - source_id: &SourceId, + source_id: SourceId, ) -> CargoResult { let (specified_req, version_req) = match version { Some(v) => (true, parse_req_with_deprecated(name, v, None)?), @@ -190,12 +192,12 @@ impl Dependency { Ok(ret) } - pub fn new_override(name: &str, source_id: &SourceId) -> Dependency { + pub fn new_override(name: &str, source_id: SourceId) -> Dependency { assert!(!name.is_empty()); Dependency { inner: Rc::new(Inner { name: InternedString::new(name), - source_id: source_id.clone(), + source_id, registry_id: None, req: VersionReq::any(), kind: Kind::Normal, @@ -260,16 +262,16 @@ impl Dependency { self.inner.name } - pub fn source_id(&self) -> &SourceId { - &self.inner.source_id + pub fn source_id(&self) -> SourceId { + self.inner.source_id } - pub fn registry_id(&self) -> Option<&SourceId> { - self.inner.registry_id.as_ref() + pub fn registry_id(&self) -> Option { + self.inner.registry_id } - pub fn set_registry_id(&mut self, registry_id: &SourceId) -> &mut Dependency { - Rc::make_mut(&mut self.inner).registry_id = Some(registry_id.clone()); + pub fn set_registry_id(&mut self, registry_id: SourceId) -> &mut Dependency { + Rc::make_mut(&mut self.inner).registry_id = Some(registry_id); self } @@ -301,9 +303,14 @@ impl Dependency { } /// Sets the list of features requested for the package. - pub fn set_features(&mut self, features: impl IntoIterator>) -> &mut Dependency { - Rc::make_mut(&mut self.inner).features = - features.into_iter().map(|s| InternedString::new(s.as_ref())).collect(); + pub fn set_features( + &mut self, + features: impl IntoIterator>, + ) -> &mut Dependency { + Rc::make_mut(&mut self.inner).features = features + .into_iter() + .map(|s| InternedString::new(s.as_ref())) + .collect(); self } @@ -343,7 +350,7 @@ impl Dependency { /// Lock this dependency to depending on the specified package id pub fn lock_to(&mut self, id: &PackageId) -> &mut Dependency { - assert_eq!(self.inner.source_id, *id.source_id()); + assert_eq!(self.inner.source_id, id.source_id()); assert!(self.inner.req.matches(id.version())); trace!( "locking dep from `{}` with `{}` at {} to {}", @@ -353,7 +360,7 @@ impl Dependency { id ); self.set_version_req(VersionReq::exact(id.version())) - .set_source_id(id.source_id().clone()) + .set_source_id(id.source_id()) } /// Returns whether this is a "locked" dependency, basically whether it has @@ -405,15 +412,14 @@ impl Dependency { pub fn matches_id(&self, id: &PackageId) -> bool { self.inner.name == id.name() && (self.inner.only_match_name - || (self.inner.req.matches(id.version()) - && &self.inner.source_id == id.source_id())) + || (self.inner.req.matches(id.version()) && self.inner.source_id == id.source_id())) } - pub fn map_source(mut self, to_replace: &SourceId, replace_with: &SourceId) -> Dependency { + pub fn map_source(mut self, to_replace: SourceId, replace_with: SourceId) -> Dependency { if self.source_id() != to_replace { self } else { - self.set_source_id(replace_with.clone()); + self.set_source_id(replace_with); self } } @@ -446,7 +452,8 @@ impl FromStr for Platform { fn from_str(s: &str) -> CargoResult { if s.starts_with("cfg(") && s.ends_with(')') { let s = &s[4..s.len() - 1]; - let p = s.parse() + let p = s + .parse() .map(Platform::Cfg) .chain_err(|| format_err!("failed to parse `{}` as a cfg expression", s))?; Ok(p) diff --git a/src/cargo/core/interning.rs b/src/cargo/core/interning.rs index c925034041b..1c580e6ded5 100644 --- a/src/cargo/core/interning.rs +++ b/src/cargo/core/interning.rs @@ -34,7 +34,7 @@ impl Eq for InternedString {} impl InternedString { pub fn new(str: &str) -> InternedString { let mut cache = STRING_CACHE.lock().unwrap(); - let s = cache.get(str).map(|&s| s).unwrap_or_else(|| { + let s = cache.get(str).cloned().unwrap_or_else(|| { let s = leak(str.to_string()); cache.insert(s); s diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index f65778df45d..8763e4e628e 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -15,7 +15,7 @@ use core::{Dependency, PackageId, PackageIdSpec, SourceId, Summary}; use core::{Edition, Feature, Features, WorkspaceConfig}; use util::errors::*; use util::toml::TomlManifest; -use util::{Config, Filesystem, short_hash}; +use util::{short_hash, Config, Filesystem}; pub enum EitherManifest { Real(Manifest), @@ -254,11 +254,7 @@ impl fmt::Debug for TargetSourcePath { impl From for TargetSourcePath { fn from(path: PathBuf) -> Self { - assert!( - path.is_absolute(), - "`{}` is not absolute", - path.display() - ); + assert!(path.is_absolute(), "`{}` is not absolute", path.display()); TargetSourcePath::Path(path) } } @@ -290,7 +286,8 @@ impl ser::Serialize for Target { .required_features .as_ref() .map(|rf| rf.iter().map(|s| &**s).collect()), - }.serialize(s) + } + .serialize(s) } } @@ -468,7 +465,7 @@ impl Manifest { self.summary = summary; } - pub fn map_source(self, to_replace: &SourceId, replace_with: &SourceId) -> Manifest { + pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Manifest { Manifest { summary: self.summary.map_source(to_replace, replace_with), ..self @@ -490,11 +487,7 @@ impl Manifest { if self.default_run.is_some() { self.features .require(Feature::default_run()) - .chain_err(|| { - format_err!( - "the `default-run` manifest key is unstable" - ) - })?; + .chain_err(|| format_err!("the `default-run` manifest key is unstable"))?; } Ok(()) @@ -627,11 +620,7 @@ impl Target { } /// Builds a `Target` corresponding to the `build = "build.rs"` entry. - pub fn custom_build_target( - name: &str, - src_path: PathBuf, - edition: Edition, - ) -> Target { + pub fn custom_build_target(name: &str, src_path: PathBuf, edition: Edition) -> Target { Target { kind: TargetKind::CustomBuild, name: name.to_string(), @@ -740,7 +729,9 @@ impl Target { pub fn for_host(&self) -> bool { self.for_host } - pub fn edition(&self) -> Edition { self.edition } + pub fn edition(&self) -> Edition { + self.edition + } pub fn benched(&self) -> bool { self.benched } @@ -839,7 +830,8 @@ impl Target { pub fn can_lto(&self) -> bool { match self.kind { TargetKind::Lib(ref v) => { - !v.contains(&LibKind::Rlib) && !v.contains(&LibKind::Dylib) + !v.contains(&LibKind::Rlib) + && !v.contains(&LibKind::Dylib) && !v.contains(&LibKind::Lib) } _ => true, diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 8db4758aaca..9ba5affad63 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -1,16 +1,16 @@ -use std::cell::{Ref, RefCell, Cell}; +use std::cell::{Cell, Ref, RefCell}; use std::cmp::Ordering; use std::collections::{HashMap, HashSet}; use std::fmt; use std::hash; use std::mem; use std::path::{Path, PathBuf}; -use std::time::{Instant, Duration}; +use std::time::{Duration, Instant}; use bytesize::ByteSize; -use curl::easy::{Easy, HttpVersion}; -use curl::multi::{Multi, EasyHandle}; use curl; +use curl::easy::{Easy, HttpVersion}; +use curl::multi::{EasyHandle, Multi}; use curl_sys; use failure::ResultExt; use lazycell::LazyCell; @@ -18,14 +18,14 @@ use semver::Version; use serde::ser; use toml; +use core::interning::InternedString; +use core::source::MaybePackage; use core::{Dependency, Manifest, PackageId, SourceId, Target}; use core::{FeatureMap, SourceMap, Summary}; -use core::source::MaybePackage; -use core::interning::InternedString; use ops; -use util::{self, internal, lev_distance, Config, Progress, ProgressStyle}; use util::errors::{CargoResult, CargoResultExt, HttpNot200}; use util::network::Retry; +use util::{self, internal, lev_distance, Config, Progress, ProgressStyle}; /// Information about a package that is available somewhere in the file system. /// @@ -60,7 +60,7 @@ struct SerializedPackage<'a> { license: Option<&'a str>, license_file: Option<&'a str>, description: Option<&'a str>, - source: &'a SourceId, + source: SourceId, dependencies: &'a [Dependency], targets: Vec<&'a Target>, features: &'a FeatureMap, @@ -122,7 +122,8 @@ impl ser::Serialize for Package { repository, edition: &self.manifest.edition().to_string(), metabuild: self.manifest.metabuild(), - }.serialize(s) + } + .serialize(s) } } @@ -200,7 +201,7 @@ impl Package { matches.min_by_key(|t| t.0).map(|t| t.1) } - pub fn map_source(self, to_replace: &SourceId, replace_with: &SourceId) -> Package { + pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Package { Package { manifest: self.manifest.map_source(to_replace, replace_with), manifest_path: self.manifest_path, @@ -289,7 +290,7 @@ pub struct Downloads<'a, 'cfg: 'a> { /// because we want to apply timeouts to an entire batch of operations, not /// any one particular single operatino timeout: ops::HttpTimeout, // timeout configuration - updated_at: Cell, // last time we received bytes + updated_at: Cell, // last time we received bytes next_speed_check: Cell, // if threshold isn't 0 by this time, error next_speed_check_bytes_threshold: Cell, // decremented when we receive bytes } @@ -340,9 +341,11 @@ impl<'cfg> PackageSet<'cfg> { // that it's buggy, and we've empirically seen that it's buggy with HTTP // proxies. let mut multi = Multi::new(); - let multiplexing = config.get::>("http.multiplexing")? + let multiplexing = config + .get::>("http.multiplexing")? .unwrap_or(true); - multi.pipelining(false, multiplexing) + multi + .pipelining(false, multiplexing) .chain_err(|| "failed to enable multiplexing/pipelining in curl")?; // let's not flood crates.io with connections @@ -395,9 +398,10 @@ impl<'cfg> PackageSet<'cfg> { Ok(self.get_many(Some(id))?.remove(0)) } - pub fn get_many<'a>(&self, ids: impl IntoIterator) - -> CargoResult> - { + pub fn get_many<'a>( + &self, + ids: impl IntoIterator, + ) -> CargoResult> { let mut pkgs = Vec::new(); let mut downloads = self.enable_download()?; for id in ids { @@ -424,7 +428,9 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { pub fn start(&mut self, id: &PackageId) -> CargoResult> { // First up see if we've already cached this package, in which case // there's nothing to do. - let slot = self.set.packages + let slot = self + .set + .packages .get(id) .ok_or_else(|| internal(format!("couldn't find `{}` in package set", id)))?; if let Some(pkg) = slot.borrow() { @@ -445,7 +451,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { MaybePackage::Ready(pkg) => { debug!("{} doesn't need a download", id); assert!(slot.fill(pkg).is_ok()); - return Ok(Some(slot.borrow().unwrap())) + return Ok(Some(slot.borrow().unwrap())); } MaybePackage::Download { url, descriptor } => (url, descriptor), }; @@ -483,9 +489,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { warn!("ignoring HTTP/2 activation error: {}", e) } } else { - result.with_context(|_| { - "failed to enable HTTP2, is curl not built right?" - })?; + result.with_context(|_| "failed to enable HTTP2, is curl not built right?")?; } } else { handle.http_version(HttpVersion::V11)?; @@ -504,7 +508,9 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { debug!("{} - {} bytes of data", token, buf.len()); tls::with(|downloads| { if let Some(downloads) = downloads { - downloads.pending[&token].0.data + downloads.pending[&token] + .0 + .data .borrow_mut() .extend_from_slice(buf); } @@ -514,22 +520,23 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { handle.progress(true)?; handle.progress_function(move |dl_total, dl_cur, _, _| { - tls::with(|downloads| { - match downloads { - Some(d) => d.progress(token, dl_total as u64, dl_cur as u64), - None => false, - } + tls::with(|downloads| match downloads { + Some(d) => d.progress(token, dl_total as u64, dl_cur as u64), + None => false, }) })?; // If the progress bar isn't enabled then it may be awhile before the // first crate finishes downloading so we inform immediately that we're // downloading crates here. - if self.downloads_finished == 0 && - self.pending.len() == 0 && - !self.progress.borrow().as_ref().unwrap().is_enabled() + if self.downloads_finished == 0 + && self.pending.len() == 0 + && !self.progress.borrow().as_ref().unwrap().is_enabled() { - self.set.config.shell().status("Downloading", "crates ...")?; + self.set + .config + .shell() + .status("Downloading", "crates ...")?; } let dl = Download { @@ -569,7 +576,9 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { let (token, result) = self.wait_for_curl()?; debug!("{} finished with {:?}", token, result); - let (mut dl, handle) = self.pending.remove(&token) + let (mut dl, handle) = self + .pending + .remove(&token) .expect("got a token for a non-in-progress transfer"); let data = mem::replace(&mut *dl.data.borrow_mut(), Vec::new()); let mut handle = self.set.multi.remove(handle)?; @@ -581,42 +590,44 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { let ret = { let timed_out = &dl.timed_out; let url = &dl.url; - dl.retry.try(|| { - if let Err(e) = result { - // If this error is "aborted by callback" then that's - // probably because our progress callback aborted due to - // a timeout. We'll find out by looking at the - // `timed_out` field, looking for a descriptive message. - // If one is found we switch the error code (to ensure - // it's flagged as spurious) and then attach our extra - // information to the error. - if !e.is_aborted_by_callback() { - return Err(e.into()) - } + dl.retry + .try(|| { + if let Err(e) = result { + // If this error is "aborted by callback" then that's + // probably because our progress callback aborted due to + // a timeout. We'll find out by looking at the + // `timed_out` field, looking for a descriptive message. + // If one is found we switch the error code (to ensure + // it's flagged as spurious) and then attach our extra + // information to the error. + if !e.is_aborted_by_callback() { + return Err(e.into()); + } - return Err(match timed_out.replace(None) { - Some(msg) => { - let code = curl_sys::CURLE_OPERATION_TIMEDOUT; - let mut err = curl::Error::new(code); - err.set_extra(msg); - err + return Err(match timed_out.replace(None) { + Some(msg) => { + let code = curl_sys::CURLE_OPERATION_TIMEDOUT; + let mut err = curl::Error::new(code); + err.set_extra(msg); + err + } + None => e, } - None => e, - }.into()) - } + .into()); + } - let code = handle.response_code()?; - if code != 200 && code != 0 { - let url = handle.effective_url()?.unwrap_or(url); - return Err(HttpNot200 { - code, - url: url.to_string(), - }.into()) - } - Ok(()) - }).chain_err(|| { - format!("failed to download from `{}`", dl.url) - })? + let code = handle.response_code()?; + if code != 200 && code != 0 { + let url = handle.effective_url()?.unwrap_or(url); + return Err(HttpNot200 { + code, + url: url.to_string(), + } + .into()); + } + Ok(()) + }) + .chain_err(|| format!("failed to download from `{}`", dl.url))? }; match ret { Some(()) => break (dl, data), @@ -631,7 +642,10 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { // semblance of progress of how we're downloading crates, and if the // progress bar is enabled this provides a good log of what's happening. self.progress.borrow_mut().as_mut().unwrap().clear(); - self.set.config.shell().status("Downloaded", &dl.descriptor)?; + self.set + .config + .shell() + .status("Downloaded", &dl.descriptor)?; self.downloads_finished += 1; self.downloaded_bytes += dl.total.get(); @@ -665,7 +679,8 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { // extracted tarball. let finish_dur = start.elapsed(); self.updated_at.set(self.updated_at.get() + finish_dur); - self.next_speed_check.set(self.next_speed_check.get() + finish_dur); + self.next_speed_check + .set(self.next_speed_check.get() + finish_dur); let slot = &self.set.packages[&dl.id]; assert!(slot.fill(pkg).is_ok()); @@ -678,7 +693,8 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { handle.set_token(dl.token)?; self.updated_at.set(now); self.next_speed_check.set(now + self.timeout.dur); - self.next_speed_check_bytes_threshold.set(self.timeout.low_speed_limit as u64); + self.next_speed_check_bytes_threshold + .set(self.timeout.low_speed_limit as u64); dl.timed_out.set(None); dl.current.set(0); dl.total.set(0); @@ -704,7 +720,9 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { // `wait` method on `multi`. loop { let n = tls::set(self, || { - self.set.multi.perform() + self.set + .multi + .perform() .chain_err(|| "failed to perform http requests") })?; debug!("handles remaining: {}", n); @@ -721,12 +739,13 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { }); if let Some(pair) = results.pop() { - break Ok(pair) + break Ok(pair); } assert!(self.pending.len() > 0); - let timeout = self.set.multi.get_timeout()? - .unwrap_or(Duration::new(5, 0)); - self.set.multi.wait(&mut [], timeout) + let timeout = self.set.multi.get_timeout()?.unwrap_or(Duration::new(5, 0)); + self.set + .multi + .wait(&mut [], timeout) .chain_err(|| "failed to wait on curl `Multi`")?; } } @@ -744,25 +763,26 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { if delta >= threshold { self.next_speed_check.set(now + self.timeout.dur); - self.next_speed_check_bytes_threshold.set( - self.timeout.low_speed_limit as u64, - ); + self.next_speed_check_bytes_threshold + .set(self.timeout.low_speed_limit as u64); } else { self.next_speed_check_bytes_threshold.set(threshold - delta); } } if !self.tick(WhyTick::DownloadUpdate).is_ok() { - return false + return false; } // If we've spent too long not actually receiving any data we time out. if now - self.updated_at.get() > self.timeout.dur { self.updated_at.set(now); - let msg = format!("failed to download any data for `{}` within {}s", - dl.id, - self.timeout.dur.as_secs()); + let msg = format!( + "failed to download any data for `{}` within {}s", + dl.id, + self.timeout.dur.as_secs() + ); dl.timed_out.set(Some(msg)); - return false + return false; } // If we reached the point in time that we need to check our speed @@ -772,13 +792,15 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { if now >= self.next_speed_check.get() { self.next_speed_check.set(now + self.timeout.dur); assert!(self.next_speed_check_bytes_threshold.get() > 0); - let msg = format!("download of `{}` failed to transfer more \ - than {} bytes in {}s", - dl.id, - self.timeout.low_speed_limit, - self.timeout.dur.as_secs()); + let msg = format!( + "download of `{}` failed to transfer more \ + than {} bytes in {}s", + dl.id, + self.timeout.low_speed_limit, + self.timeout.dur.as_secs() + ); dl.timed_out.set(Some(msg)); - return false + return false; } true @@ -790,7 +812,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { if let WhyTick::DownloadUpdate = why { if !progress.update_allowed() { - return Ok(()) + return Ok(()); } } let mut msg = format!("{} crates", self.pending.len()); @@ -833,20 +855,22 @@ impl<'a, 'cfg> Drop for Downloads<'a, 'cfg> { // Don't print a download summary if we're not using a progress bar, // we've already printed lots of `Downloading...` items. if !progress.is_enabled() { - return + return; } // If we didn't download anything, no need for a summary if self.downloads_finished == 0 { - return + return; } // If an error happened, let's not clutter up the output if !self.success { - return + return; } - let mut status = format!("{} crates ({}) in {}", - self.downloads_finished, - ByteSize(self.downloaded_bytes), - util::elapsed(self.start.elapsed())); + let mut status = format!( + "{} crates ({}) in {}", + self.downloads_finished, + ByteSize(self.downloaded_bytes), + util::elapsed(self.start.elapsed()) + ); if self.largest.0 > ByteSize::mb(1).0 { status.push_str(&format!( " (largest was `{}` at {})", @@ -872,9 +896,7 @@ mod tls { if ptr == 0 { f(None) } else { - unsafe { - f(Some(&*(ptr as *const Downloads))) - } + unsafe { f(Some(&*(ptr as *const Downloads))) } } } diff --git a/src/cargo/core/package_id.rs b/src/cargo/core/package_id.rs index 568bef5b6c4..0be2cd9e40d 100644 --- a/src/cargo/core/package_id.rs +++ b/src/cargo/core/package_id.rs @@ -1,7 +1,7 @@ use std::cmp::Ordering; use std::fmt::{self, Formatter}; -use std::hash::Hash; use std::hash; +use std::hash::Hash; use std::path::Path; use std::sync::Arc; @@ -9,9 +9,9 @@ use semver; use serde::de; use serde::ser; -use util::{CargoResult, ToSemver}; -use core::source::SourceId; use core::interning::InternedString; +use core::source::SourceId; +use util::{CargoResult, ToSemver}; /// Identifier for a specific version of a package in a specific source. #[derive(Clone)] @@ -100,13 +100,13 @@ impl Ord for PackageId { } impl PackageId { - pub fn new(name: &str, version: T, sid: &SourceId) -> CargoResult { + pub fn new(name: &str, version: T, sid: SourceId) -> CargoResult { let v = version.to_semver()?; Ok(PackageId { inner: Arc::new(PackageIdInner { name: InternedString::new(name), version: v, - source_id: sid.clone(), + source_id: sid, }), }) } @@ -117,8 +117,8 @@ impl PackageId { pub fn version(&self) -> &semver::Version { &self.inner.version } - pub fn source_id(&self) -> &SourceId { - &self.inner.source_id + pub fn source_id(&self) -> SourceId { + self.inner.source_id } pub fn with_precise(&self, precise: Option) -> PackageId { @@ -131,12 +131,12 @@ impl PackageId { } } - pub fn with_source_id(&self, source: &SourceId) -> PackageId { + pub fn with_source_id(&self, source: SourceId) -> PackageId { PackageId { inner: Arc::new(PackageIdInner { name: self.inner.name, version: self.inner.version.clone(), - source_id: source.clone(), + source_id: source, }), } } @@ -190,9 +190,9 @@ mod tests { let loc = CRATES_IO_INDEX.to_url().unwrap(); let repo = SourceId::for_registry(&loc).unwrap(); - assert!(PackageId::new("foo", "1.0", &repo).is_err()); - assert!(PackageId::new("foo", "1", &repo).is_err()); - assert!(PackageId::new("foo", "bar", &repo).is_err()); - assert!(PackageId::new("foo", "", &repo).is_err()); + assert!(PackageId::new("foo", "1.0", repo).is_err()); + assert!(PackageId::new("foo", "1", repo).is_err()); + assert!(PackageId::new("foo", "bar", repo).is_err()); + assert!(PackageId::new("foo", "", repo).is_err()); } } diff --git a/src/cargo/core/package_id_spec.rs b/src/cargo/core/package_id_spec.rs index 8acc65401b6..64312f0812a 100644 --- a/src/cargo/core/package_id_spec.rs +++ b/src/cargo/core/package_id_spec.rs @@ -6,8 +6,8 @@ use serde::{de, ser}; use url::Url; use core::PackageId; -use util::{ToSemver, ToUrl}; use util::errors::{CargoResult, CargoResultExt}; +use util::{ToSemver, ToUrl}; /// Some or all of the data required to identify a package: /// @@ -104,7 +104,8 @@ impl PackageIdSpec { let frag = url.fragment().map(|s| s.to_owned()); url.set_fragment(None); let (name, version) = { - let mut path = url.path_segments() + let mut path = url + .path_segments() .ok_or_else(|| format_err!("pkgid urls must have a path: {}", url))?; let path_name = path.next_back().ok_or_else(|| { format_err!( @@ -275,10 +276,10 @@ impl<'de> de::Deserialize<'de> for PackageIdSpec { #[cfg(test)] mod tests { - use core::{PackageId, SourceId}; use super::PackageIdSpec; - use url::Url; + use core::{PackageId, SourceId}; use semver::Version; + use url::Url; #[test] fn good_parsing() { @@ -367,8 +368,8 @@ mod tests { fn matching() { let url = Url::parse("http://example.com").unwrap(); let sid = SourceId::for_registry(&url).unwrap(); - let foo = PackageId::new("foo", "1.2.3", &sid).unwrap(); - let bar = PackageId::new("bar", "1.2.3", &sid).unwrap(); + let foo = PackageId::new("foo", "1.2.3", sid).unwrap(); + let bar = PackageId::new("bar", "1.2.3", sid).unwrap(); assert!(PackageIdSpec::parse("foo").unwrap().matches(&foo)); assert!(!PackageIdSpec::parse("foo").unwrap().matches(&bar)); diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index e635b5fdfa7..669fed83955 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -205,11 +205,13 @@ impl ProfileMaker { .keys() .filter_map(|key| match *key { ProfilePackageSpec::All => None, - ProfilePackageSpec::Spec(ref spec) => if spec.matches(pkg_id) { - Some(spec) - } else { - None - }, + ProfilePackageSpec::Spec(ref spec) => { + if spec.matches(pkg_id) { + Some(spec) + } else { + None + } + } }) .collect(); match matches.len() { @@ -313,11 +315,13 @@ fn merge_toml( .iter() .filter_map(|(key, spec_profile)| match *key { ProfilePackageSpec::All => None, - ProfilePackageSpec::Spec(ref s) => if s.matches(pkg_id) { - Some(spec_profile) - } else { - None - }, + ProfilePackageSpec::Spec(ref s) => { + if s.matches(pkg_id) { + Some(spec_profile) + } else { + None + } + } }); if let Some(spec_profile) = matches.next() { merge_profile(profile, spec_profile); @@ -586,7 +590,7 @@ impl UnitFor { pub fn with_for_host(self, for_host: bool) -> UnitFor { UnitFor { custom_build: self.custom_build, - panic_ok: self.panic_ok && !for_host + panic_ok: self.panic_ok && !for_host, } } @@ -597,16 +601,25 @@ impl UnitFor { } /// Returns true if this unit is allowed to set the `panic` compiler flag. - pub fn is_panic_ok(&self) -> bool { + pub fn is_panic_ok(self) -> bool { self.panic_ok } /// All possible values, used by `clean`. pub fn all_values() -> &'static [UnitFor] { static ALL: [UnitFor; 3] = [ - UnitFor { custom_build: false, panic_ok: true }, - UnitFor { custom_build: true, panic_ok: false }, - UnitFor { custom_build: false, panic_ok: false }, + UnitFor { + custom_build: false, + panic_ok: true, + }, + UnitFor { + custom_build: true, + panic_ok: false, + }, + UnitFor { + custom_build: false, + panic_ok: false, + }, ]; &ALL } diff --git a/src/cargo/core/registry.rs b/src/cargo/core/registry.rs index e5c975ef5fe..cc2cb1a81ea 100644 --- a/src/cargo/core/registry.rs +++ b/src/cargo/core/registry.rs @@ -3,11 +3,11 @@ use std::collections::HashMap; use semver::VersionReq; use url::Url; -use core::{Dependency, PackageId, Source, SourceId, SourceMap, Summary}; use core::PackageSet; -use util::{profile, Config}; -use util::errors::{CargoResult, CargoResultExt}; +use core::{Dependency, PackageId, Source, SourceId, SourceMap, Summary}; use sources::config::SourceConfigMap; +use util::errors::{CargoResult, CargoResultExt}; +use util::{profile, Config}; /// Source of information about a group of packages. /// @@ -22,8 +22,8 @@ pub trait Registry { Ok(ret) } - fn describe_source(&self, source: &SourceId) -> String; - fn is_replaced(&self, source: &SourceId) -> bool; + fn describe_source(&self, source: SourceId) -> String; + fn is_replaced(&self, source: SourceId) -> bool; } /// This structure represents a registry of known packages. It internally @@ -102,8 +102,8 @@ impl<'cfg> PackageRegistry<'cfg> { PackageSet::new(package_ids, self.sources, self.config) } - fn ensure_loaded(&mut self, namespace: &SourceId, kind: Kind) -> CargoResult<()> { - match self.source_ids.get(namespace) { + fn ensure_loaded(&mut self, namespace: SourceId, kind: Kind) -> CargoResult<()> { + match self.source_ids.get(&namespace) { // We've previously loaded this source, and we've already locked it, // so we're not allowed to change it even if `namespace` has a // slightly different precise version listed. @@ -138,8 +138,8 @@ impl<'cfg> PackageRegistry<'cfg> { Ok(()) } - pub fn add_sources(&mut self, ids: &[SourceId]) -> CargoResult<()> { - for id in ids.iter() { + pub fn add_sources(&mut self, ids: impl IntoIterator) -> CargoResult<()> { + for id in ids { self.ensure_loaded(id, Kind::Locked)?; } Ok(()) @@ -150,13 +150,13 @@ impl<'cfg> PackageRegistry<'cfg> { } fn add_source(&mut self, source: Box, kind: Kind) { - let id = source.source_id().clone(); + let id = source.source_id(); self.sources.insert(source); - self.source_ids.insert(id.clone(), (id, kind)); + self.source_ids.insert(id, (id, kind)); } pub fn add_override(&mut self, source: Box) { - self.overrides.push(source.source_id().clone()); + self.overrides.push(source.source_id()); self.add_source(source, Kind::Override); } @@ -165,8 +165,9 @@ impl<'cfg> PackageRegistry<'cfg> { for dep in deps.iter() { trace!("\t-> {}", dep); } - let sub_map = self.locked - .entry(id.source_id().clone()) + let sub_map = self + .locked + .entry(id.source_id()) .or_insert_with(HashMap::new); let sub_vec = sub_map .entry(id.name().to_string()) @@ -200,9 +201,14 @@ impl<'cfg> PackageRegistry<'cfg> { // Remember that each dependency listed in `[patch]` has to resolve to // precisely one package, so that's why we're just creating a flat list // of summaries which should be the same length as `deps` above. - let unlocked_summaries = deps.iter() + let unlocked_summaries = deps + .iter() .map(|dep| { - debug!("registring a patch for `{}` with `{}`", url, dep.package_name()); + debug!( + "registring a patch for `{}` with `{}`", + url, + dep.package_name() + ); // Go straight to the source for resolving `dep`. Load it as we // normally would and then ask it directly for the list of summaries @@ -216,7 +222,8 @@ impl<'cfg> PackageRegistry<'cfg> { ) })?; - let mut summaries = self.sources + let mut summaries = self + .sources .get_mut(dep.source_id()) .expect("loaded source not present") .query_vec(dep)? @@ -289,14 +296,14 @@ impl<'cfg> PackageRegistry<'cfg> { &self.patches } - fn load(&mut self, source_id: &SourceId, kind: Kind) -> CargoResult<()> { + fn load(&mut self, source_id: SourceId, kind: Kind) -> CargoResult<()> { (|| { debug!("loading source {}", source_id); let source = self.source_config.load(source_id)?; assert_eq!(source.source_id(), source_id); if kind == Kind::Override { - self.overrides.push(source_id.clone()); + self.overrides.push(source_id); } self.add_source(source, kind); @@ -304,12 +311,12 @@ impl<'cfg> PackageRegistry<'cfg> { let _p = profile::start(format!("updating: {}", source_id)); self.sources.get_mut(source_id).unwrap().update() })() - .chain_err(|| format_err!("Unable to update {}", source_id))?; + .chain_err(|| format_err!("Unable to update {}", source_id))?; Ok(()) } fn query_overrides(&mut self, dep: &Dependency) -> CargoResult> { - for s in self.overrides.iter() { + for &s in self.overrides.iter() { let src = self.sources.get_mut(s).unwrap(); let dep = Dependency::new_override(&*dep.package_name(), s); let mut results = src.query_vec(&dep)?; @@ -532,14 +539,14 @@ impl<'cfg> Registry for PackageRegistry<'cfg> { Ok(()) } - fn describe_source(&self, id: &SourceId) -> String { + fn describe_source(&self, id: SourceId) -> String { match self.sources.get(id) { Some(src) => src.describe(), None => id.to_string(), } } - fn is_replaced(&self, id: &SourceId) -> bool { + fn is_replaced(&self, id: SourceId) -> bool { match self.sources.get(id) { Some(src) => src.is_replaced(), None => false, @@ -549,7 +556,7 @@ impl<'cfg> Registry for PackageRegistry<'cfg> { fn lock(locked: &LockedMap, patches: &HashMap>, summary: Summary) -> Summary { let pair = locked - .get(summary.source_id()) + .get(&summary.source_id()) .and_then(|map| map.get(&*summary.name())) .and_then(|vec| vec.iter().find(|&&(ref id, _)| id == summary.package_id())); @@ -561,7 +568,12 @@ fn lock(locked: &LockedMap, patches: &HashMap>, summary: Sum None => summary, }; summary.map_dependencies(|dep| { - trace!("\t{}/{}/{}", dep.package_name(), dep.version_req(), dep.source_id()); + trace!( + "\t{}/{}/{}", + dep.package_name(), + dep.version_req(), + dep.source_id() + ); // If we've got a known set of overrides for this summary, then // one of a few cases can arise: @@ -596,7 +608,7 @@ fn lock(locked: &LockedMap, patches: &HashMap>, summary: Sum // all known locked packages to see if they match this dependency. // If anything does then we lock it to that and move on. let v = locked - .get(dep.source_id()) + .get(&dep.source_id()) .and_then(|map| map.get(&*dep.package_name())) .and_then(|vec| vec.iter().find(|&&(ref id, _)| dep.matches_id(id))); if let Some(&(ref id, _)) = v { @@ -610,16 +622,14 @@ fn lock(locked: &LockedMap, patches: &HashMap>, summary: Sum // this dependency. let v = patches.get(dep.source_id().url()).map(|vec| { let dep2 = dep.clone(); - let mut iter = vec.iter().filter(move |p| { - dep2.matches_ignoring_source(p) - }); + let mut iter = vec.iter().filter(move |p| dep2.matches_ignoring_source(p)); (iter.next(), iter) }); if let Some((Some(patch_id), mut remaining)) = v { assert!(remaining.next().is_none()); let patch_source = patch_id.source_id(); let patch_locked = locked - .get(patch_source) + .get(&patch_source) .and_then(|m| m.get(&*patch_id.name())) .map(|list| list.iter().any(|&(ref id, _)| id == patch_id)) .unwrap_or(false); diff --git a/src/cargo/core/resolver/context.rs b/src/cargo/core/resolver/context.rs index 4a6629f93c5..c1dd7e22e96 100644 --- a/src/cargo/core/resolver/context.rs +++ b/src/cargo/core/resolver/context.rs @@ -3,9 +3,9 @@ use std::rc::Rc; use core::interning::InternedString; use core::{Dependency, FeatureValue, PackageId, SourceId, Summary}; +use im_rc; use util::CargoResult; use util::Graph; -use im_rc; use super::errors::ActivateResult; use super::types::{ConflictReason, DepInfo, GraphNode, Method, RcList, RegistryQueryer}; @@ -55,7 +55,7 @@ impl Context { let id = summary.package_id(); let prev = self .activations - .entry((id.name(), id.source_id().clone())) + .entry((id.name(), id.source_id())) .or_insert_with(|| Rc::new(Vec::new())); if !prev.iter().any(|c| c == summary) { self.resolve_graph.push(GraphNode::Add(id.clone())); @@ -126,14 +126,14 @@ impl Context { pub fn prev_active(&self, dep: &Dependency) -> &[Summary] { self.activations - .get(&(dep.package_name(), dep.source_id().clone())) + .get(&(dep.package_name(), dep.source_id())) .map(|v| &v[..]) .unwrap_or(&[]) } pub fn is_active(&self, id: &PackageId) -> bool { self.activations - .get(&(id.name(), id.source_id().clone())) + .get(&(id.name(), id.source_id())) .map(|v| v.iter().any(|s| s.package_id() == id)) .unwrap_or(false) } diff --git a/src/cargo/core/resolver/encode.rs b/src/cargo/core/resolver/encode.rs index c80ce59dfee..25d55d7134f 100644 --- a/src/cargo/core/resolver/encode.rs +++ b/src/cargo/core/resolver/encode.rs @@ -50,7 +50,7 @@ impl EncodableResolve { let enc_id = EncodablePackageId { name: pkg.name.clone(), version: pkg.version.clone(), - source: pkg.source.clone(), + source: pkg.source, }; if !all_pkgs.insert(enc_id.clone()) { @@ -63,7 +63,7 @@ impl EncodableResolve { debug!("path dependency now missing {} v{}", pkg.name, pkg.version); continue; } - Some(source) => PackageId::new(&pkg.name, &pkg.version, source)?, + Some(&source) => PackageId::new(&pkg.name, &pkg.version, source)?, }; assert!(live_pkgs.insert(enc_id, (id, pkg)).is_none()) @@ -156,7 +156,7 @@ impl EncodableResolve { let mut unused_patches = Vec::new(); for pkg in self.patch.unused { let id = match pkg.source.as_ref().or_else(|| path_deps.get(&pkg.name)) { - Some(src) => PackageId::new(&pkg.name, &pkg.version, src)?, + Some(&src) => PackageId::new(&pkg.name, &pkg.version, src)?, None => continue, }; unused_patches.push(id); @@ -188,9 +188,9 @@ fn build_path_deps(ws: &Workspace) -> HashMap { for member in members.iter() { ret.insert( member.package_id().name().to_string(), - member.package_id().source_id().clone(), + member.package_id().source_id(), ); - visited.insert(member.package_id().source_id().clone()); + visited.insert(member.package_id().source_id()); } for member in members.iter() { build_pkg(member, ws, &mut ret, &mut visited); @@ -224,7 +224,7 @@ fn build_path_deps(ws: &Workspace) -> HashMap { visited: &mut HashSet, ) { let id = dep.source_id(); - if visited.contains(id) || !id.is_path() { + if visited.contains(&id) || !id.is_path() { return; } let path = match id.url().to_file_path() { @@ -235,8 +235,8 @@ fn build_path_deps(ws: &Workspace) -> HashMap { Ok(p) => p, Err(_) => return, }; - ret.insert(pkg.name().to_string(), pkg.package_id().source_id().clone()); - visited.insert(pkg.package_id().source_id().clone()); + ret.insert(pkg.name().to_string(), pkg.package_id().source_id()); + visited.insert(pkg.package_id().source_id()); build_pkg(&pkg, ws, ret, visited); } } @@ -412,10 +412,10 @@ pub fn encodable_package_id(id: &PackageId) -> EncodablePackageId { } } -fn encode_source(id: &SourceId) -> Option { +fn encode_source(id: SourceId) -> Option { if id.is_path() { None } else { - Some(id.clone()) + Some(id) } } diff --git a/src/cargo/core/source/mod.rs b/src/cargo/core/source/mod.rs index c03c29b3ed7..a6dc8aa0955 100644 --- a/src/cargo/core/source/mod.rs +++ b/src/cargo/core/source/mod.rs @@ -12,10 +12,10 @@ pub use self::source_id::{GitReference, SourceId}; /// versions. pub trait Source { /// Returns the `SourceId` corresponding to this source - fn source_id(&self) -> &SourceId; + fn source_id(&self) -> SourceId; /// Returns the replaced `SourceId` corresponding to this source - fn replaced_source_id(&self) -> &SourceId { + fn replaced_source_id(&self) -> SourceId { self.source_id() } @@ -92,12 +92,12 @@ pub enum MaybePackage { impl<'a, T: Source + ?Sized + 'a> Source for Box { /// Forwards to `Source::source_id` - fn source_id(&self) -> &SourceId { + fn source_id(&self) -> SourceId { (**self).source_id() } /// Forwards to `Source::replaced_source_id` - fn replaced_source_id(&self) -> &SourceId { + fn replaced_source_id(&self) -> SourceId { (**self).replaced_source_id() } @@ -155,11 +155,11 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box { } impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T { - fn source_id(&self) -> &SourceId { + fn source_id(&self) -> SourceId { (**self).source_id() } - fn replaced_source_id(&self) -> &SourceId { + fn replaced_source_id(&self) -> SourceId { (**self).replaced_source_id() } @@ -231,13 +231,13 @@ impl<'src> SourceMap<'src> { } /// Like `HashMap::contains_key` - pub fn contains(&self, id: &SourceId) -> bool { - self.map.contains_key(id) + pub fn contains(&self, id: SourceId) -> bool { + self.map.contains_key(&id) } /// Like `HashMap::get` - pub fn get(&self, id: &SourceId) -> Option<&(Source + 'src)> { - let source = self.map.get(id); + pub fn get(&self, id: SourceId) -> Option<&(Source + 'src)> { + let source = self.map.get(&id); source.map(|s| { let s: &(Source + 'src) = &**s; @@ -246,8 +246,8 @@ impl<'src> SourceMap<'src> { } /// Like `HashMap::get_mut` - pub fn get_mut(&mut self, id: &SourceId) -> Option<&mut (Source + 'src)> { - self.map.get_mut(id).map(|s| { + pub fn get_mut(&mut self, id: SourceId) -> Option<&mut (Source + 'src)> { + self.map.get_mut(&id).map(|s| { let s: &mut (Source + 'src) = &mut **s; s }) @@ -261,7 +261,7 @@ impl<'src> SourceMap<'src> { /// Like `HashMap::insert`, but derives the SourceId key from the Source pub fn insert(&mut self, source: Box) { - let id = source.source_id().clone(); + let id = source.source_id(); self.map.insert(id, source); } diff --git a/src/cargo/core/source/source_id.rs b/src/cargo/core/source/source_id.rs index 47e8ef546f1..ea29d39c863 100644 --- a/src/cargo/core/source/source_id.rs +++ b/src/cargo/core/source/source_id.rs @@ -4,18 +4,18 @@ use std::fmt::{self, Formatter}; use std::hash::{self, Hash}; use std::path::Path; use std::ptr; -use std::sync::Mutex; -use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT}; use std::sync::atomic::Ordering::SeqCst; +use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT}; +use std::sync::Mutex; -use serde::ser; use serde::de; +use serde::ser; use url::Url; use ops; use sources::git; -use sources::{GitSource, PathSource, RegistrySource, CRATES_IO_INDEX}; use sources::DirectorySource; +use sources::{GitSource, PathSource, RegistrySource, CRATES_IO_INDEX}; use util::{CargoResult, Config, ToUrl}; lazy_static! { @@ -74,21 +74,19 @@ impl SourceId { /// /// The canonical url will be calculated, but the precise field will not fn new(kind: Kind, url: Url) -> CargoResult { - let source_id = SourceId::wrap( - SourceIdInner { - kind, - canonical_url: git::canonicalize_url(&url)?, - url, - precise: None, - name: None, - } - ); + let source_id = SourceId::wrap(SourceIdInner { + kind, + canonical_url: git::canonicalize_url(&url)?, + url, + precise: None, + name: None, + }); Ok(source_id) } fn wrap(inner: SourceIdInner) -> SourceId { let mut cache = SOURCE_ID_CACHE.lock().unwrap(); - let inner = cache.get(&inner).map(|&x| x).unwrap_or_else(|| { + let inner = cache.get(&inner).cloned().unwrap_or_else(|| { let inner = Box::leak(Box::new(inner)); cache.insert(inner); inner @@ -209,15 +207,13 @@ impl SourceId { pub fn alt_registry(config: &Config, key: &str) -> CargoResult { let url = config.get_registry_index(key)?; - Ok(SourceId::wrap( - SourceIdInner { - kind: Kind::Registry, - canonical_url: git::canonicalize_url(&url)?, - url, - precise: None, - name: Some(key.to_string()), - } - )) + Ok(SourceId::wrap(SourceIdInner { + kind: Kind::Registry, + canonical_url: git::canonicalize_url(&url)?, + url, + precise: None, + name: Some(key.to_string()), + })) } /// Get this source URL @@ -225,7 +221,7 @@ impl SourceId { &self.inner.url } - pub fn display_registry(&self) -> String { + pub fn display_registry(self) -> String { if self.is_default_registry() { "crates.io index".to_string() } else { @@ -234,12 +230,12 @@ impl SourceId { } /// Is this source from a filesystem path - pub fn is_path(&self) -> bool { + pub fn is_path(self) -> bool { self.inner.kind == Kind::Path } /// Is this source from a registry (either local or not) - pub fn is_registry(&self) -> bool { + pub fn is_registry(self) -> bool { match self.inner.kind { Kind::Registry | Kind::LocalRegistry => true, _ => false, @@ -247,12 +243,12 @@ impl SourceId { } /// Is this source from an alternative registry - pub fn is_alt_registry(&self) -> bool { + pub fn is_alt_registry(self) -> bool { self.is_registry() && self.inner.name.is_some() } /// Is this source from a git repository - pub fn is_git(&self) -> bool { + pub fn is_git(self) -> bool { match self.inner.kind { Kind::Git(_) => true, _ => false, @@ -260,7 +256,7 @@ impl SourceId { } /// Creates an implementation of `Source` corresponding to this ID. - pub fn load<'a>(&self, config: &'a Config) -> CargoResult> { + pub fn load<'a>(self, config: &'a Config) -> CargoResult> { trace!("loading SourceId; {}", self); match self.inner.kind { Kind::Git(..) => Ok(Box::new(GitSource::new(self, config)?)), @@ -290,12 +286,12 @@ impl SourceId { } /// Get the value of the precise field - pub fn precise(&self) -> Option<&str> { + pub fn precise(self) -> Option<&'static str> { self.inner.precise.as_ref().map(|s| &s[..]) } /// Get the git reference if this is a git source, otherwise None. - pub fn git_reference(&self) -> Option<&GitReference> { + pub fn git_reference(self) -> Option<&'static GitReference> { match self.inner.kind { Kind::Git(ref s) => Some(s), _ => None, @@ -303,17 +299,15 @@ impl SourceId { } /// Create a new SourceId from this source with the given `precise` - pub fn with_precise(&self, v: Option) -> SourceId { - SourceId::wrap( - SourceIdInner { - precise: v, - ..(*self.inner).clone() - } - ) + pub fn with_precise(self, v: Option) -> SourceId { + SourceId::wrap(SourceIdInner { + precise: v, + ..(*self.inner).clone() + }) } /// Whether the remote registry is the standard https://crates.io - pub fn is_default_registry(&self) -> bool { + pub fn is_default_registry(self) -> bool { match self.inner.kind { Kind::Registry => {} _ => return false, @@ -325,9 +319,10 @@ impl SourceId { /// /// For paths, remove the workspace prefix so the same source will give the /// same hash in different locations. - pub fn stable_hash(&self, workspace: &Path, into: &mut S) { + pub fn stable_hash(self, workspace: &Path, into: &mut S) { if self.is_path() { - if let Ok(p) = self.inner + if let Ok(p) = self + .inner .url .to_file_path() .unwrap() diff --git a/src/cargo/core/summary.rs b/src/cargo/core/summary.rs index 727bcdb4f51..8610f500e97 100644 --- a/src/cargo/core/summary.rs +++ b/src/cargo/core/summary.rs @@ -39,7 +39,9 @@ impl Summary { links: Option>, namespaced_features: bool, ) -> CargoResult - where K: Borrow + Ord + Display { + where + K: Borrow + Ord + Display, + { for dep in dependencies.iter() { let feature = dep.name_in_toml(); if !namespaced_features && features.get(&*feature).is_some() { @@ -78,7 +80,7 @@ impl Summary { pub fn version(&self) -> &Version { self.package_id().version() } - pub fn source_id(&self) -> &SourceId { + pub fn source_id(&self) -> SourceId { self.package_id().source_id() } pub fn dependencies(&self) -> &[Dependency] { @@ -119,7 +121,7 @@ impl Summary { self } - pub fn map_source(self, to_replace: &SourceId, replace_with: &SourceId) -> Summary { + pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Summary { let me = if self.package_id().source_id() == to_replace { let new_id = self.package_id().with_source_id(replace_with); self.override_id(new_id) @@ -143,7 +145,9 @@ fn build_feature_map( dependencies: &[Dependency], namespaced: bool, ) -> CargoResult -where K: Borrow + Ord + Display { +where + K: Borrow + Ord + Display, +{ use self::FeatureValue::*; let mut dep_map = HashMap::new(); for dep in dependencies.iter() { @@ -258,42 +262,46 @@ where K: Borrow + Ord + Display { // not recognized as a feature is pegged as a `Crate`. Here we handle the case // where the dependency exists but is non-optional. It branches on namespaced // just to provide the correct string for the crate dependency in the error. - (&Crate(ref dep), true, false) => if namespaced { - bail!( - "Feature `{}` includes `crate:{}` which is not an \ - optional dependency.\nConsider adding \ - `optional = true` to the dependency", - feature, - dep - ) - } else { - bail!( - "Feature `{}` depends on `{}` which is not an \ - optional dependency.\nConsider adding \ - `optional = true` to the dependency", - feature, - dep - ) - }, + (&Crate(ref dep), true, false) => { + if namespaced { + bail!( + "Feature `{}` includes `crate:{}` which is not an \ + optional dependency.\nConsider adding \ + `optional = true` to the dependency", + feature, + dep + ) + } else { + bail!( + "Feature `{}` depends on `{}` which is not an \ + optional dependency.\nConsider adding \ + `optional = true` to the dependency", + feature, + dep + ) + } + } // If namespaced, the value was tagged as a dependency; if not namespaced, // this could be anything not defined as a feature. This handles the case // where no such dependency is actually defined; again, the branch on // namespaced here is just to provide the correct string in the error. - (&Crate(ref dep), false, _) => if namespaced { - bail!( - "Feature `{}` includes `crate:{}` which is not a known \ - dependency", - feature, - dep - ) - } else { - bail!( - "Feature `{}` includes `{}` which is neither a dependency nor \ - another feature", - feature, - dep - ) - }, + (&Crate(ref dep), false, _) => { + if namespaced { + bail!( + "Feature `{}` includes `crate:{}` which is not a known \ + dependency", + feature, + dep + ) + } else { + bail!( + "Feature `{}` includes `{}` which is neither a dependency nor \ + another feature", + feature, + dep + ) + } + } (&Crate(_), true, true) => {} // If the value is a feature for one of the dependencies, bail out if no such // dependency is actually defined in the manifest. @@ -372,11 +380,13 @@ impl FeatureValue { use self::FeatureValue::*; match *self { Feature(ref f) => f.to_string(), - Crate(ref c) => if s.namespaced_features() { - format!("crate:{}", &c) - } else { - c.to_string() - }, + Crate(ref c) => { + if s.namespaced_features() { + format!("crate:{}", &c) + } else { + c.to_string() + } + } CrateFeature(ref c, ref f) => [c.as_ref(), f.as_ref()].join("/"), } } diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index e09bdf11268..1b29eb62093 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -236,7 +236,8 @@ impl<'cfg> Workspace<'cfg> { } pub fn profiles(&self) -> &Profiles { - let root = self.root_manifest + let root = self + .root_manifest .as_ref() .unwrap_or(&self.current_manifest); match *self.packages.get(root) { @@ -253,8 +254,9 @@ impl<'cfg> Workspace<'cfg> { match self.root_manifest { Some(ref p) => p, None => &self.current_manifest, - }.parent() - .unwrap() + } + .parent() + .unwrap() } pub fn target_dir(&self) -> Filesystem { @@ -425,8 +427,8 @@ impl<'cfg> Workspace<'cfg> { let root_package = self.packages.load(&root_manifest_path)?; match *root_package.workspace_config() { WorkspaceConfig::Root(ref root_config) => { - members_paths = - root_config.members_paths(root_config.members.as_ref().unwrap_or(&vec![]))?; + members_paths = root_config + .members_paths(root_config.members.as_ref().unwrap_or(&vec![]))?; default_members_paths = if let Some(ref default) = root_config.default_members { Some(root_config.members_paths(default)?) } else { @@ -475,7 +477,8 @@ impl<'cfg> Workspace<'cfg> { if self.members.contains(&manifest_path) { return Ok(()); } - if is_path_dep && !manifest_path.parent().unwrap().starts_with(self.root()) + if is_path_dep + && !manifest_path.parent().unwrap().starts_with(self.root()) && self.find_root(&manifest_path)? != self.root_manifest { // If `manifest_path` is a path dependency outside of the workspace, @@ -655,7 +658,8 @@ impl<'cfg> Workspace<'cfg> { } if let Some(ref root_manifest) = self.root_manifest { - for pkg in self.members() + for pkg in self + .members() .filter(|p| p.manifest_path() != root_manifest) { let manifest = pkg.manifest(); @@ -699,7 +703,7 @@ impl<'cfg> Workspace<'cfg> { return Ok(p); } let source_id = SourceId::for_path(manifest_path.parent().unwrap())?; - let (package, _nested_paths) = ops::read_package(manifest_path, &source_id, self.config)?; + let (package, _nested_paths) = ops::read_package(manifest_path, source_id, self.config)?; loaded.insert(manifest_path.to_path_buf(), package.clone()); Ok(package) } @@ -745,10 +749,7 @@ impl<'cfg> Workspace<'cfg> { for warning in warnings { if warning.is_critical { let err = format_err!("{}", warning.message); - let cx = format_err!( - "failed to parse manifest at `{}`", - path.display() - ); + let cx = format_err!("failed to parse manifest at `{}`", path.display()); return Err(err.context(cx).into()); } else { let msg = if self.root_manifest.is_none() { @@ -782,7 +783,7 @@ impl<'cfg> Packages<'cfg> { Entry::Vacant(v) => { let source_id = SourceId::for_path(key)?; let (manifest, _nested_paths) = - read_manifest(manifest_path, &source_id, self.config)?; + read_manifest(manifest_path, source_id, self.config)?; Ok(v.insert(match manifest { EitherManifest::Real(manifest) => { MaybePackage::Package(Package::new(manifest, manifest_path)) @@ -843,7 +844,8 @@ impl WorkspaceRootConfig { /// /// This method does NOT consider the `members` list. fn is_excluded(&self, manifest_path: &Path) -> bool { - let excluded = self.exclude + let excluded = self + .exclude .iter() .any(|ex| manifest_path.starts_with(self.root_dir.join(ex))); @@ -886,9 +888,9 @@ impl WorkspaceRootConfig { None => return Ok(Vec::new()), }; let res = glob(path).chain_err(|| format_err!("could not parse pattern `{}`", &path))?; - let res = res.map(|p| { - p.chain_err(|| format_err!("unable to match path to pattern `{}`", &path)) - }).collect::, _>>()?; + let res = res + .map(|p| p.chain_err(|| format_err!("unable to match path to pattern `{}`", &path))) + .collect::, _>>()?; Ok(res) } } diff --git a/src/cargo/ops/cargo_generate_lockfile.rs b/src/cargo/ops/cargo_generate_lockfile.rs index cce7390aeed..f25b05e78ea 100644 --- a/src/cargo/ops/cargo_generate_lockfile.rs +++ b/src/cargo/ops/cargo_generate_lockfile.rs @@ -73,13 +73,13 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions) -> CargoResult<()> } else { precise.to_string() }; - dep.source_id().clone().with_precise(Some(precise)) + dep.source_id().with_precise(Some(precise)) } - None => dep.source_id().clone().with_precise(None), + None => dep.source_id().with_precise(None), }); } } - registry.add_sources(&sources)?; + registry.add_sources(sources)?; } let resolve = ops::resolve_with_previous( @@ -141,7 +141,7 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions) -> CargoResult<()> previous_resolve: &'a Resolve, resolve: &'a Resolve, ) -> Vec<(Vec<&'a PackageId>, Vec<&'a PackageId>)> { - fn key(dep: &PackageId) -> (&str, &SourceId) { + fn key(dep: &PackageId) -> (&str, SourceId) { (dep.name().as_str(), dep.source_id()) } diff --git a/src/cargo/ops/cargo_install.rs b/src/cargo/ops/cargo_install.rs index c38019af1d2..ec0ca5f387c 100644 --- a/src/cargo/ops/cargo_install.rs +++ b/src/cargo/ops/cargo_install.rs @@ -1,26 +1,26 @@ use std::collections::btree_map::Entry; use std::collections::{BTreeMap, BTreeSet}; -use std::{env, fs}; use std::io::prelude::*; use std::io::SeekFrom; use std::path::{Path, PathBuf}; use std::sync::Arc; +use std::{env, fs}; use semver::{Version, VersionReq}; use tempfile::Builder as TempFileBuilder; use toml; +use core::compiler::{DefaultExecutor, Executor}; +use core::package::PackageSet; +use core::source::SourceMap; use core::{Dependency, Edition, Package, PackageIdSpec, Source, SourceId}; use core::{PackageId, Workspace}; -use core::source::SourceMap; -use core::package::PackageSet; -use core::compiler::{DefaultExecutor, Executor}; use ops::{self, CompileFilter}; use sources::{GitSource, PathSource, SourceConfigMap}; -use util::{internal, Config}; -use util::{FileLock, Filesystem}; use util::errors::{CargoResult, CargoResultExt}; use util::paths; +use util::{internal, Config}; +use util::{FileLock, Filesystem}; #[derive(Deserialize, Serialize)] #[serde(untagged)] @@ -59,7 +59,7 @@ impl Drop for Transaction { pub fn install( root: Option<&str>, krates: Vec<&str>, - source_id: &SourceId, + source_id: SourceId, from_cwd: bool, vers: Option<&str>, opts: &ops::CompileOptions, @@ -154,7 +154,7 @@ fn install_one( root: &Filesystem, map: &SourceConfigMap, krate: Option<&str>, - source_id: &SourceId, + source_id: SourceId, from_cwd: bool, vers: Option<&str>, opts: &ops::CompileOptions, @@ -182,7 +182,9 @@ fn install_one( src.path().display() ) })?; - select_pkg(src, krate, vers, config, false, &mut |path| path.read_packages())? + select_pkg(src, krate, vers, config, false, &mut |path| { + path.read_packages() + })? } else { select_pkg( map.load(source_id)?, @@ -255,20 +257,19 @@ fn install_one( } let exec: Arc = Arc::new(DefaultExecutor); - let compile = - ops::compile_ws(&ws, Some(source), opts, &exec).chain_err(|| { - if let Some(td) = td_opt.take() { - // preserve the temporary directory, so the user can inspect it - td.into_path(); - } + let compile = ops::compile_ws(&ws, Some(source), opts, &exec).chain_err(|| { + if let Some(td) = td_opt.take() { + // preserve the temporary directory, so the user can inspect it + td.into_path(); + } - format_err!( - "failed to compile `{}`, intermediate artifacts can be \ - found at `{}`", - pkg, - ws.target_dir().display() - ) - })?; + format_err!( + "failed to compile `{}`, intermediate artifacts can be \ + found at `{}`", + pkg, + ws.target_dir().display() + ) + })?; let binaries: Vec<(&str, &Path)> = compile .binaries .iter() @@ -368,7 +369,8 @@ fn install_one( } // Remove empty metadata lines. - let pkgs = list.v1 + let pkgs = list + .v1 .iter() .filter_map(|(p, set)| { if set.is_empty() { @@ -410,7 +412,7 @@ fn install_one( Ok(()) } -fn path_source<'a>(source_id: &SourceId, config: &'a Config) -> CargoResult> { +fn path_source<'a>(source_id: SourceId, config: &'a Config) -> CargoResult> { let path = source_id .url() .to_file_path() @@ -439,7 +441,8 @@ where Some(v) => { // If the version begins with character <, >, =, ^, ~ parse it as a // version range, otherwise parse it as a specific version - let first = v.chars() + let first = v + .chars() .nth(0) .ok_or_else(|| format_err!("no version provided for the `--vers` flag"))?; @@ -495,16 +498,13 @@ where } else { vers }; - let dep = Dependency::parse_no_deprecated( - name, - vers_spec, - source.source_id(), - )?; + let dep = Dependency::parse_no_deprecated(name, vers_spec, source.source_id())?; let deps = source.query_vec(&dep)?; let pkgid = match deps.iter().map(|p| p.package_id()).max() { Some(pkgid) => pkgid, None => { - let vers_info = vers.map(|v| format!(" with version `{}`", v)) + let vers_info = vers + .map(|v| format!(" with version `{}`", v)) .unwrap_or_default(); bail!( "could not find `{}` in {}{}", @@ -624,7 +624,8 @@ fn find_duplicates( } }; match *filter { - CompileFilter::Default { .. } => pkg.targets() + CompileFilter::Default { .. } => pkg + .targets() .iter() .filter(|t| t.is_bin()) .filter_map(|t| check(t.name().to_string())) @@ -671,7 +672,7 @@ fn read_crate_list(file: &FileLock) -> CargoResult { }), } })() - .chain_err(|| { + .chain_err(|| { format_err!( "failed to parse crate metadata at `{}`", file.path().to_string_lossy() @@ -689,7 +690,7 @@ fn write_crate_list(file: &FileLock, listing: CrateListingV1) -> CargoResult<()> file.write_all(data.as_bytes())?; Ok(()) })() - .chain_err(|| { + .chain_err(|| { format_err!( "failed to write crate metadata at `{}`", file.path().to_string_lossy() @@ -782,17 +783,14 @@ pub fn uninstall_one( uninstall_pkgid(crate_metadata, metadata, &pkgid, bins, config) } -fn uninstall_cwd( - root: &Filesystem, - bins: &[String], - config: &Config, -) -> CargoResult<()> { +fn uninstall_cwd(root: &Filesystem, bins: &[String], config: &Config) -> CargoResult<()> { let crate_metadata = metadata(config, root)?; let metadata = read_crate_list(&crate_metadata)?; let source_id = SourceId::for_path(config.cwd())?; - let src = path_source(&source_id, config)?; - let (pkg, _source) = - select_pkg(src, None, None, config, true, &mut |path| path.read_packages())?; + let src = path_source(source_id, config)?; + let (pkg, _source) = select_pkg(src, None, None, config, true, &mut |path| { + path.read_packages() + })?; let pkgid = pkg.package_id(); uninstall_pkgid(crate_metadata, metadata, pkgid, bins, config) } @@ -821,7 +819,8 @@ fn uninstall_pkgid( } } - let bins = bins.iter() + let bins = bins + .iter() .map(|s| { if s.ends_with(env::consts::EXE_SUFFIX) { s.to_string() @@ -865,7 +864,8 @@ fn metadata(config: &Config, root: &Filesystem) -> CargoResult { fn resolve_root(flag: Option<&str>, config: &Config) -> CargoResult { let config_root = config.get_path("install.root")?; - Ok(flag.map(PathBuf::from) + Ok(flag + .map(PathBuf::from) .or_else(|| env::var_os("CARGO_INSTALL_ROOT").map(PathBuf::from)) .or_else(move || config_root.map(|v| v.val)) .map(Filesystem::new) diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index 37c82238ad5..b0b628102b1 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -10,13 +10,13 @@ use git2; use serde_json; use tar::{Archive, Builder, EntryType, Header}; -use core::{Package, Source, SourceId, Workspace}; use core::compiler::{BuildConfig, CompileMode, DefaultExecutor, Executor}; +use core::{Package, Source, SourceId, Workspace}; +use ops; use sources::PathSource; -use util::{self, internal, Config, FileLock}; -use util::paths; use util::errors::{CargoResult, CargoResultExt}; -use ops; +use util::paths; +use util::{self, internal, Config, FileLock}; pub struct PackageOpts<'cfg> { pub config: &'cfg Config, @@ -60,7 +60,8 @@ pub fn package(ws: &Workspace, opts: &PackageOpts) -> CargoResult = src.list_files(pkg)? + let mut list: Vec<_> = src + .list_files(pkg)? .iter() .map(|file| util::without_prefix(file, root).unwrap().to_path_buf()) .collect(); @@ -175,7 +176,7 @@ fn check_repo_state( p: &Package, src_files: &[PathBuf], config: &Config, - allow_dirty: bool + allow_dirty: bool, ) -> CargoResult> { if let Ok(repo) = git2::Repository::discover(p.root()) { if let Some(workdir) = repo.workdir() { @@ -194,7 +195,8 @@ fn check_repo_state( config.shell().verbose(|shell| { shell.warn(format!( "No (git) Cargo.toml found at `{}` in workdir `{}`", - path.display(), workdir.display() + path.display(), + workdir.display() )) })?; } @@ -212,7 +214,7 @@ fn check_repo_state( p: &Package, src_files: &[PathBuf], repo: &git2::Repository, - allow_dirty: bool + allow_dirty: bool, ) -> CargoResult> { let workdir = repo.workdir().unwrap(); let dirty = src_files @@ -256,12 +258,15 @@ fn check_repo_state( fn check_vcs_file_collision(pkg: &Package, src_files: &[PathBuf]) -> CargoResult<()> { let root = pkg.root(); let vcs_info_path = Path::new(VCS_INFO_FILE); - let collision = src_files.iter().find(|&p| { - util::without_prefix(&p, root).unwrap() == vcs_info_path - }); + let collision = src_files + .iter() + .find(|&p| util::without_prefix(&p, root).unwrap() == vcs_info_path); if collision.is_some() { - bail!("Invalid inclusion of reserved file name \ - {} in package source", VCS_INFO_FILE); + bail!( + "Invalid inclusion of reserved file name \ + {} in package source", + VCS_INFO_FILE + ); } Ok(()) } @@ -271,7 +276,7 @@ fn tar( src_files: &[PathBuf], vcs_info: Option<&serde_json::Value>, dst: &File, - filename: &str + filename: &str, ) -> CargoResult<()> { // Prepare the encoder and its header let filename = Path::new(filename); @@ -325,7 +330,8 @@ fn tar( .chain_err(|| format!("failed to add to archive: `{}`", relative))?; let mut file = File::open(file) .chain_err(|| format!("failed to open for archiving: `{}`", file.display()))?; - let metadata = file.metadata() + let metadata = file + .metadata() .chain_err(|| format!("could not learn metadata for: `{}`", relative))?; header.set_metadata(&metadata); @@ -367,9 +373,9 @@ fn tar( fnd ); let mut header = Header::new_ustar(); - header.set_path(&path).chain_err(|| { - format!("failed to add to archive: `{}`", fnd) - })?; + header + .set_path(&path) + .chain_err(|| format!("failed to add to archive: `{}`", fnd))?; let json = format!("{}\n", serde_json::to_string_pretty(json)?); let mut header = Header::new_ustar(); header.set_path(&path)?; @@ -377,9 +383,8 @@ fn tar( header.set_mode(0o644); header.set_size(json.len() as u64); header.set_cksum(); - ar.append(&header, json.as_bytes()).chain_err(|| { - internal(format!("could not archive source file `{}`", fnd)) - })?; + ar.append(&header, json.as_bytes()) + .chain_err(|| internal(format!("could not archive source file `{}`", fnd)))?; } if include_lockfile(pkg) { @@ -412,7 +417,8 @@ fn run_verify(ws: &Workspace, tar: &FileLock, opts: &PackageOpts) -> CargoResult config.shell().status("Verifying", pkg)?; let f = GzDecoder::new(tar.file()); - let dst = tar.parent() + let dst = tar + .parent() .join(&format!("{}-{}", pkg.name(), pkg.version())); if dst.exists() { paths::remove_dir_all(&dst)?; @@ -426,7 +432,7 @@ fn run_verify(ws: &Workspace, tar: &FileLock, opts: &PackageOpts) -> CargoResult // Manufacture an ephemeral workspace to ensure that even if the top-level // package has a workspace we can still build our new crate. let id = SourceId::for_path(&dst)?; - let mut src = PathSource::new(&dst, &id, ws.config()); + let mut src = PathSource::new(&dst, id, ws.config()); let new_pkg = src.root_package()?; let pkg_fingerprint = src.last_modified_file(&new_pkg)?; let ws = Workspace::ephemeral(new_pkg, config, None, true)?; diff --git a/src/cargo/ops/cargo_read_manifest.rs b/src/cargo/ops/cargo_read_manifest.rs index d3f9d3e4e15..540552b89bd 100644 --- a/src/cargo/ops/cargo_read_manifest.rs +++ b/src/cargo/ops/cargo_read_manifest.rs @@ -4,14 +4,14 @@ use std::io; use std::path::{Path, PathBuf}; use core::{EitherManifest, Package, PackageId, SourceId}; -use util::{self, Config}; use util::errors::{CargoError, CargoResult}; use util::important_paths::find_project_manifest_exact; use util::toml::read_manifest; +use util::{self, Config}; pub fn read_package( path: &Path, - source_id: &SourceId, + source_id: SourceId, config: &Config, ) -> CargoResult<(Package, Vec)> { trace!( @@ -34,7 +34,7 @@ pub fn read_package( pub fn read_packages( path: &Path, - source_id: &SourceId, + source_id: SourceId, config: &Config, ) -> CargoResult> { let mut all_packages = HashMap::new(); @@ -129,7 +129,7 @@ fn has_manifest(path: &Path) -> bool { fn read_nested_packages( path: &Path, all_packages: &mut HashMap, - source_id: &SourceId, + source_id: SourceId, config: &Config, visited: &mut HashSet, errors: &mut Vec, diff --git a/src/cargo/ops/registry.rs b/src/cargo/ops/registry.rs index 2993fb7060d..946e61fb6bd 100644 --- a/src/cargo/ops/registry.rs +++ b/src/cargo/ops/registry.rs @@ -5,9 +5,9 @@ use std::str; use std::time::Duration; use std::{cmp, env}; -use log::Level; -use curl::easy::{Easy, SslOpt, InfoType}; +use curl::easy::{Easy, InfoType, SslOpt}; use git2; +use log::Level; use registry::{NewCrate, NewCrateDependency, Registry}; use url::percent_encoding::{percent_encode, QUERY_ENCODE_SET}; @@ -68,7 +68,7 @@ pub fn publish(ws: &Workspace, opts: &PublishOpts) -> CargoResult<()> { opts.index.clone(), opts.registry.clone(), )?; - verify_dependencies(pkg, ®_id)?; + verify_dependencies(pkg, reg_id)?; // Prepare a tarball, with a non-surpressable warning if metadata // is missing since this is being put online. @@ -84,7 +84,8 @@ pub fn publish(ws: &Workspace, opts: &PublishOpts) -> CargoResult<()> { jobs: opts.jobs, registry: opts.registry.clone(), }, - )?.unwrap(); + )? + .unwrap(); // Upload said tarball to the specified destination opts.config @@ -95,14 +96,14 @@ pub fn publish(ws: &Workspace, opts: &PublishOpts) -> CargoResult<()> { pkg, tarball.file(), &mut registry, - ®_id, + reg_id, opts.dry_run, )?; Ok(()) } -fn verify_dependencies(pkg: &Package, registry_src: &SourceId) -> CargoResult<()> { +fn verify_dependencies(pkg: &Package, registry_src: SourceId) -> CargoResult<()> { for dep in pkg.dependencies().iter() { if dep.source_id().is_path() { if !dep.specified_req() { @@ -148,10 +149,11 @@ fn transmit( pkg: &Package, tarball: &File, registry: &mut Registry, - registry_id: &SourceId, + registry_id: SourceId, dry_run: bool, ) -> CargoResult<()> { - let deps = pkg.dependencies() + let deps = pkg + .dependencies() .iter() .map(|dep| { // If the dependency is from a different registry, then include the @@ -177,7 +179,8 @@ fn transmit( Kind::Normal => "normal", Kind::Build => "build", Kind::Development => "dev", - }.to_string(), + } + .to_string(), registry: dep_registry, explicit_name_in_toml: dep.explicit_name_in_toml().map(|s| s.to_string()), }) @@ -325,7 +328,7 @@ pub fn registry( let token = token.or(token_config); let sid = get_source_id(config, index_config.or(index), registry)?; let api_host = { - let mut src = RegistrySource::remote(&sid, config); + let mut src = RegistrySource::remote(sid, config); src.update() .chain_err(|| format!("failed to update {}", sid))?; (src.config()?).unwrap().api.unwrap() @@ -401,8 +404,7 @@ pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult< InfoType::HeaderOut => (">", Level::Debug), InfoType::DataIn => ("{", Level::Trace), InfoType::DataOut => ("}", Level::Trace), - InfoType::SslDataIn | - InfoType::SslDataOut => return, + InfoType::SslDataIn | InfoType::SslDataOut => return, _ => return, }; match str::from_utf8(data) { @@ -412,7 +414,12 @@ pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult< } } Err(_) => { - log!(level, "http-debug: {} ({} bytes of data)", prefix, data.len()); + log!( + level, + "http-debug: {} ({} bytes of data)", + prefix, + data.len() + ); } } })?; @@ -429,9 +436,11 @@ pub struct HttpTimeout { impl HttpTimeout { pub fn new(config: &Config) -> CargoResult { - let low_speed_limit = config.get::>("http.low-speed-limit")? + let low_speed_limit = config + .get::>("http.low-speed-limit")? .unwrap_or(10); - let seconds = config.get::>("http.timeout")? + let seconds = config + .get::>("http.timeout")? .or_else(|| env::var("HTTP_TIMEOUT").ok().and_then(|s| s.parse().ok())) .unwrap_or(30); Ok(HttpTimeout { @@ -623,8 +632,8 @@ fn get_source_id( (_, Some(i)) => SourceId::for_registry(&i.to_url()?), _ => { let map = SourceConfigMap::new(config)?; - let src = map.load(&SourceId::crates_io(config)?)?; - Ok(src.replaced_source_id().clone()) + let src = map.load(SourceId::crates_io(config)?)?; + Ok(src.replaced_source_id()) } } } @@ -650,7 +659,7 @@ pub fn search( let sid = get_source_id(config, index, reg)?; - let mut regsrc = RegistrySource::remote(&sid, config); + let mut regsrc = RegistrySource::remote(sid, config); let cfg = match regsrc.config() { Ok(c) => c, Err(_) => { diff --git a/src/cargo/ops/resolve.rs b/src/cargo/ops/resolve.rs index 275fbe752a4..e0a8aaf3d81 100644 --- a/src/cargo/ops/resolve.rs +++ b/src/cargo/ops/resolve.rs @@ -150,7 +150,7 @@ pub fn resolve_with_previous<'a, 'cfg>( // // TODO: This seems like a hokey reason to single out the registry as being // different - let mut to_avoid_sources: HashSet<&SourceId> = HashSet::new(); + let mut to_avoid_sources: HashSet = HashSet::new(); if let Some(to_avoid) = to_avoid { to_avoid_sources.extend( to_avoid @@ -161,10 +161,11 @@ pub fn resolve_with_previous<'a, 'cfg>( } let keep = |p: &&'a PackageId| { - !to_avoid_sources.contains(p.source_id()) && match to_avoid { - Some(set) => !set.contains(p), - None => true, - } + !to_avoid_sources.contains(&p.source_id()) + && match to_avoid { + Some(set) => !set.contains(p), + None => true, + } }; // In the case where a previous instance of resolve is available, we @@ -214,7 +215,7 @@ pub fn resolve_with_previous<'a, 'cfg>( } for member in ws.members() { - registry.add_sources(&[member.package_id().source_id().clone()])?; + registry.add_sources(Some(member.package_id().source_id()))?; } let mut summaries = Vec::new(); @@ -357,7 +358,7 @@ pub fn add_overrides<'a>( for (path, definition) in paths { let id = SourceId::for_path(&path)?; - let mut source = PathSource::new_recursive(&path, &id, ws.config()); + let mut source = PathSource::new_recursive(&path, id, ws.config()); source.update().chain_err(|| { format!( "failed to update path override `{}` \ @@ -401,7 +402,7 @@ fn register_previous_locks<'a>( resolve: &'a Resolve, keep: &Fn(&&'a PackageId) -> bool, ) { - let path_pkg = |id: &SourceId| { + let path_pkg = |id: SourceId| { if !id.is_path() { return None; } diff --git a/src/cargo/sources/config.rs b/src/cargo/sources/config.rs index ca52bc4d2b5..e70a2f8744b 100644 --- a/src/cargo/sources/config.rs +++ b/src/cargo/sources/config.rs @@ -11,9 +11,9 @@ use url::Url; use core::{GitReference, Source, SourceId}; use sources::{ReplacedSource, CRATES_IO_REGISTRY}; -use util::{Config, ToUrl}; use util::config::ConfigValue; use util::errors::{CargoResult, CargoResultExt}; +use util::{Config, ToUrl}; #[derive(Clone)] pub struct SourceConfigMap<'cfg> { @@ -72,9 +72,9 @@ impl<'cfg> SourceConfigMap<'cfg> { self.config } - pub fn load(&self, id: &SourceId) -> CargoResult> { + pub fn load(&self, id: SourceId) -> CargoResult> { debug!("loading: {}", id); - let mut name = match self.id2name.get(id) { + let mut name = match self.id2name.get(&id) { Some(name) => name, None => return Ok(id.load(self.config)?), }; @@ -98,7 +98,7 @@ impl<'cfg> SourceConfigMap<'cfg> { name = s; path = p; } - None if *id == cfg.id => return Ok(id.load(self.config)?), + None if id == cfg.id => return Ok(id.load(self.config)?), None => { new_id = cfg.id.with_precise(id.precise().map(|s| s.to_string())); break; @@ -143,11 +143,11 @@ restore the source replacement configuration to continue the build ); } - Ok(Box::new(ReplacedSource::new(id, &new_id, new_src))) + Ok(Box::new(ReplacedSource::new(id, new_id, new_src))) } fn add(&mut self, name: &str, cfg: SourceConfig) { - self.id2name.insert(cfg.id.clone(), name.to_string()); + self.id2name.insert(cfg.id, name.to_string()); self.cfgs.insert(name.to_string(), cfg); } diff --git a/src/cargo/sources/directory.rs b/src/cargo/sources/directory.rs index 0076b75d278..649ffaf4f19 100644 --- a/src/cargo/sources/directory.rs +++ b/src/cargo/sources/directory.rs @@ -8,12 +8,12 @@ use hex; use serde_json; -use core::{Dependency, Package, PackageId, Source, SourceId, Summary}; use core::source::MaybePackage; +use core::{Dependency, Package, PackageId, Source, SourceId, Summary}; use sources::PathSource; -use util::{Config, Sha256}; use util::errors::{CargoResult, CargoResultExt}; use util::paths; +use util::{Config, Sha256}; pub struct DirectorySource<'cfg> { source_id: SourceId, @@ -29,9 +29,9 @@ struct Checksum { } impl<'cfg> DirectorySource<'cfg> { - pub fn new(path: &Path, id: &SourceId, config: &'cfg Config) -> DirectorySource<'cfg> { + pub fn new(path: &Path, id: SourceId, config: &'cfg Config) -> DirectorySource<'cfg> { DirectorySource { - source_id: id.clone(), + source_id: id, root: path.to_path_buf(), config, packages: HashMap::new(), @@ -71,8 +71,8 @@ impl<'cfg> Source for DirectorySource<'cfg> { true } - fn source_id(&self) -> &SourceId { - &self.source_id + fn source_id(&self) -> SourceId { + self.source_id } fn update(&mut self) -> CargoResult<()> { @@ -116,7 +116,7 @@ impl<'cfg> Source for DirectorySource<'cfg> { continue; } - let mut src = PathSource::new(&path, &self.source_id, self.config); + let mut src = PathSource::new(&path, self.source_id, self.config); src.update()?; let pkg = src.root_package()?; @@ -188,7 +188,7 @@ impl<'cfg> Source for DirectorySource<'cfg> { } } })() - .chain_err(|| format!("failed to calculate checksum of: {}", file.display()))?; + .chain_err(|| format!("failed to calculate checksum of: {}", file.display()))?; let actual = hex::encode(h.finish()); if &*actual != cksum { diff --git a/src/cargo/sources/git/source.rs b/src/cargo/sources/git/source.rs index 4a899598558..ccd5d9e82d1 100644 --- a/src/cargo/sources/git/source.rs +++ b/src/cargo/sources/git/source.rs @@ -2,14 +2,14 @@ use std::fmt::{self, Debug, Formatter}; use url::Url; -use core::source::{Source, SourceId, MaybePackage}; +use core::source::{MaybePackage, Source, SourceId}; use core::GitReference; use core::{Dependency, Package, PackageId, Summary}; -use util::Config; +use sources::git::utils::{GitRemote, GitRevision}; +use sources::PathSource; use util::errors::CargoResult; use util::hex::short_hash; -use sources::PathSource; -use sources::git::utils::{GitRemote, GitRevision}; +use util::Config; pub struct GitSource<'cfg> { remote: GitRemote, @@ -22,7 +22,7 @@ pub struct GitSource<'cfg> { } impl<'cfg> GitSource<'cfg> { - pub fn new(source_id: &SourceId, config: &'cfg Config) -> CargoResult> { + pub fn new(source_id: SourceId, config: &'cfg Config) -> CargoResult> { assert!(source_id.is_git(), "id is not git, id={}", source_id); let remote = GitRemote::new(source_id.url()); @@ -36,7 +36,7 @@ impl<'cfg> GitSource<'cfg> { let source = GitSource { remote, reference, - source_id: source_id.clone(), + source_id, path_source: None, rev: None, ident, @@ -60,7 +60,8 @@ impl<'cfg> GitSource<'cfg> { fn ident(url: &Url) -> CargoResult { let url = canonicalize_url(url)?; - let ident = url.path_segments() + let ident = url + .path_segments() .and_then(|mut s| s.next_back()) .unwrap_or(""); @@ -124,14 +125,16 @@ impl<'cfg> Debug for GitSource<'cfg> { impl<'cfg> Source for GitSource<'cfg> { fn query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()> { - let src = self.path_source + let src = self + .path_source .as_mut() .expect("BUG: update() must be called before query()"); src.query(dep, f) } fn fuzzy_query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()> { - let src = self.path_source + let src = self + .path_source .as_mut() .expect("BUG: update() must be called before query()"); src.fuzzy_query(dep, f) @@ -145,8 +148,8 @@ impl<'cfg> Source for GitSource<'cfg> { true } - fn source_id(&self) -> &SourceId { - &self.source_id + fn source_id(&self) -> SourceId { + self.source_id } fn update(&mut self) -> CargoResult<()> { @@ -190,7 +193,8 @@ impl<'cfg> Source for GitSource<'cfg> { // https://github.com/servo/servo/pull/14397 let short_id = db.to_short_id(&actual_rev).unwrap(); - let checkout_path = lock.parent() + let checkout_path = lock + .parent() .join("checkouts") .join(&self.ident) .join(short_id.as_str()); @@ -203,7 +207,7 @@ impl<'cfg> Source for GitSource<'cfg> { db.copy_to(actual_rev.clone(), &checkout_path, self.config)?; let source_id = self.source_id.with_precise(Some(actual_rev.to_string())); - let path_source = PathSource::new_recursive(&checkout_path, &source_id, self.config); + let path_source = PathSource::new_recursive(&checkout_path, source_id, self.config); self.path_source = Some(path_source); self.rev = Some(actual_rev); @@ -237,8 +241,8 @@ impl<'cfg> Source for GitSource<'cfg> { #[cfg(test)] mod test { - use url::Url; use super::ident; + use url::Url; use util::ToUrl; #[test] diff --git a/src/cargo/sources/path.rs b/src/cargo/sources/path.rs index 6115b626c20..170162359b2 100644 --- a/src/cargo/sources/path.rs +++ b/src/cargo/sources/path.rs @@ -5,15 +5,15 @@ use std::path::{Path, PathBuf}; use filetime::FileTime; use git2; use glob::Pattern; -use ignore::Match; use ignore::gitignore::GitignoreBuilder; +use ignore::Match; -use core::{Dependency, Package, PackageId, Source, SourceId, Summary}; use core::source::MaybePackage; +use core::{Dependency, Package, PackageId, Source, SourceId, Summary}; use ops; -use util::{self, internal, CargoResult}; use util::paths; use util::Config; +use util::{self, internal, CargoResult}; pub struct PathSource<'cfg> { source_id: SourceId, @@ -29,9 +29,9 @@ impl<'cfg> PathSource<'cfg> { /// /// This source will only return the package at precisely the `path` /// specified, and it will be an error if there's not a package at `path`. - pub fn new(path: &Path, id: &SourceId, config: &'cfg Config) -> PathSource<'cfg> { + pub fn new(path: &Path, source_id: SourceId, config: &'cfg Config) -> PathSource<'cfg> { PathSource { - source_id: id.clone(), + source_id, path: path.to_path_buf(), updated: false, packages: Vec::new(), @@ -48,7 +48,7 @@ impl<'cfg> PathSource<'cfg> { /// /// Note that this should be used with care and likely shouldn't be chosen /// by default! - pub fn new_recursive(root: &Path, id: &SourceId, config: &'cfg Config) -> PathSource<'cfg> { + pub fn new_recursive(root: &Path, id: SourceId, config: &'cfg Config) -> PathSource<'cfg> { PathSource { recursive: true, ..PathSource::new(root, id, config) @@ -78,10 +78,10 @@ impl<'cfg> PathSource<'cfg> { if self.updated { Ok(self.packages.clone()) } else if self.recursive { - ops::read_packages(&self.path, &self.source_id, self.config) + ops::read_packages(&self.path, self.source_id, self.config) } else { let path = self.path.join("Cargo.toml"); - let (pkg, _) = ops::read_package(&path, &self.source_id, self.config)?; + let (pkg, _) = ops::read_package(&path, self.source_id, self.config)?; Ok(vec![pkg]) } } @@ -127,13 +127,15 @@ impl<'cfg> PathSource<'cfg> { .map_err(|e| format_err!("could not parse glob pattern `{}`: {}", p, e)) }; - let glob_exclude = pkg.manifest() + let glob_exclude = pkg + .manifest() .exclude() .iter() .map(|p| glob_parse(p)) .collect::, _>>()?; - let glob_include = pkg.manifest() + let glob_include = pkg + .manifest() .include() .iter() .map(|p| glob_parse(p)) @@ -302,7 +304,8 @@ impl<'cfg> PathSource<'cfg> { ) -> CargoResult> { warn!("list_files_git {}", pkg.package_id()); let index = repo.index()?; - let root = repo.workdir() + let root = repo + .workdir() .ok_or_else(|| internal("Can't list files on a bare repository."))?; let pkg_path = pkg.root(); @@ -374,7 +377,8 @@ impl<'cfg> PathSource<'cfg> { if is_dir.unwrap_or_else(|| file_path.is_dir()) { warn!(" found submodule {}", file_path.display()); let rel = util::without_prefix(&file_path, root).unwrap(); - let rel = rel.to_str() + let rel = rel + .to_str() .ok_or_else(|| format_err!("invalid utf-8 filename: {}", rel.display()))?; // Git submodules are currently only named through `/` path // separators, explicitly not `\` which windows uses. Who knew? @@ -398,8 +402,8 @@ impl<'cfg> PathSource<'cfg> { #[cfg(unix)] fn join(path: &Path, data: &[u8]) -> CargoResult { - use std::os::unix::prelude::*; use std::ffi::OsStr; + use std::os::unix::prelude::*; Ok(path.join(::from_bytes(data))) } #[cfg(windows)] @@ -527,8 +531,8 @@ impl<'cfg> Source for PathSource<'cfg> { false } - fn source_id(&self) -> &SourceId { - &self.source_id + fn source_id(&self) -> SourceId { + self.source_id } fn update(&mut self) -> CargoResult<()> { diff --git a/src/cargo/sources/registry/index.rs b/src/cargo/sources/registry/index.rs index e9db7cfd10e..c2556d3f9aa 100644 --- a/src/cargo/sources/registry/index.rs +++ b/src/cargo/sources/registry/index.rs @@ -38,29 +38,29 @@ impl<'s> Iterator for UncanonicalizedIter<'s> { type Item = String; fn next(&mut self) -> Option { - if self.hyphen_combination_num > 0 && self.hyphen_combination_num.trailing_zeros() >= self.num_hyphen_underscore { + if self.hyphen_combination_num > 0 + && self.hyphen_combination_num.trailing_zeros() >= self.num_hyphen_underscore + { return None; } - let ret = Some(self.input - .chars() - .scan(0u16, |s, c| { - // the check against 15 here's to prevent - // shift overflow on inputs with more then 15 hyphens - if (c == '_' || c == '-') && *s <= 15 { - let switch = (self.hyphen_combination_num & (1u16 << *s)) > 0; - let out = if (c == '_') ^ switch { - '_' + let ret = Some( + self.input + .chars() + .scan(0u16, |s, c| { + // the check against 15 here's to prevent + // shift overflow on inputs with more then 15 hyphens + if (c == '_' || c == '-') && *s <= 15 { + let switch = (self.hyphen_combination_num & (1u16 << *s)) > 0; + let out = if (c == '_') ^ switch { '_' } else { '-' }; + *s += 1; + Some(out) } else { - '-' - }; - *s += 1; - Some(out) - } else { - Some(c) - } - }) - .collect()); + Some(c) + } + }) + .collect(), + ); self.hyphen_combination_num += 1; ret } @@ -78,14 +78,21 @@ fn no_hyphen() { fn two_hyphen() { assert_eq!( UncanonicalizedIter::new("te-_st").collect::>(), - vec!["te-_st".to_string(), "te__st".to_string(), "te--st".to_string(), "te_-st".to_string()] + vec![ + "te-_st".to_string(), + "te__st".to_string(), + "te--st".to_string(), + "te_-st".to_string() + ] ) } #[test] fn overflow_hyphen() { assert_eq!( - UncanonicalizedIter::new("te-_-_-_-_-_-_-_-_-st").take(100).count(), + UncanonicalizedIter::new("te-_-_-_-_-_-_-_-_-st") + .take(100) + .count(), 100 ) } @@ -101,13 +108,13 @@ pub struct RegistryIndex<'cfg> { impl<'cfg> RegistryIndex<'cfg> { pub fn new( - id: &SourceId, + source_id: SourceId, path: &Filesystem, config: &'cfg Config, locked: bool, ) -> RegistryIndex<'cfg> { RegistryIndex { - source_id: id.clone(), + source_id, path: path.clone(), cache: HashMap::new(), hashes: HashMap::new(), @@ -185,7 +192,7 @@ impl<'cfg> RegistryIndex<'cfg> { _ => format!("{}/{}/{}", &fs_name[0..2], &fs_name[2..4], fs_name), }; let mut ret = Vec::new(); - for path in UncanonicalizedIter::new(&raw_path).take(1024) { + for path in UncanonicalizedIter::new(&raw_path).take(1024) { let mut hit_closure = false; let err = load.load(&root, Path::new(&path), &mut |contents| { hit_closure = true; @@ -247,11 +254,11 @@ impl<'cfg> RegistryIndex<'cfg> { yanked, links, } = serde_json::from_str(line)?; - let pkgid = PackageId::new(&name, &vers, &self.source_id)?; + let pkgid = PackageId::new(&name, &vers, self.source_id)?; let name = pkgid.name(); let deps = deps .into_iter() - .map(|dep| dep.into_dep(&self.source_id)) + .map(|dep| dep.into_dep(self.source_id)) .collect::>>()?; let summary = Summary::new(pkgid, deps, &features, links, false)?; let summary = summary.set_checksum(cksum.clone()); @@ -268,7 +275,7 @@ impl<'cfg> RegistryIndex<'cfg> { load: &mut RegistryData, f: &mut FnMut(Summary), ) -> CargoResult<()> { - let source_id = self.source_id.clone(); + let source_id = self.source_id; let name = dep.package_name().as_str(); let summaries = self.summaries(name, load)?; let summaries = summaries diff --git a/src/cargo/sources/registry/mod.rs b/src/cargo/sources/registry/mod.rs index b061716f8f9..60c3d87850c 100644 --- a/src/cargo/sources/registry/mod.rs +++ b/src/cargo/sources/registry/mod.rs @@ -228,15 +228,17 @@ pub struct RegistryPackage<'a> { #[test] fn escaped_cher_in_json() { let _: RegistryPackage = serde_json::from_str( - r#"{"name":"a","vers":"0.0.1","deps":[],"cksum":"bae3","features":{}}"# - ).unwrap(); + r#"{"name":"a","vers":"0.0.1","deps":[],"cksum":"bae3","features":{}}"#, + ) + .unwrap(); let _: RegistryPackage = serde_json::from_str( r#"{"name":"a","vers":"0.0.1","deps":[],"cksum":"bae3","features":{"test":["k","q"]},"links":"a-sys"}"# ).unwrap(); // Now we add escaped cher all the places they can go // these are not valid, but it should error later than json parsing - let _: RegistryPackage = serde_json::from_str(r#"{ + let _: RegistryPackage = serde_json::from_str( + r#"{ "name":"This name has a escaped cher in it \n\t\" ", "vers":"0.0.1", "deps":[{ @@ -251,8 +253,9 @@ fn escaped_cher_in_json() { }], "cksum":"bae3", "features":{"test \n\t\" ":["k \n\t\" ","q \n\t\" "]}, - "links":" \n\t\" "}"# - ).unwrap(); + "links":" \n\t\" "}"#, + ) + .unwrap(); } #[derive(Deserialize)] @@ -282,7 +285,7 @@ struct RegistryDependency<'a> { impl<'a> RegistryDependency<'a> { /// Converts an encoded dependency in the registry to a cargo dependency - pub fn into_dep(self, default: &SourceId) -> CargoResult { + pub fn into_dep(self, default: SourceId) -> CargoResult { let RegistryDependency { name, req, @@ -298,15 +301,11 @@ impl<'a> RegistryDependency<'a> { let id = if let Some(registry) = registry { SourceId::for_registry(®istry.to_url()?)? } else { - default.clone() + default }; - - let mut dep = Dependency::parse_no_deprecated( - package.as_ref().unwrap_or(&name), - Some(&req), - &id, - )?; + let mut dep = + Dependency::parse_no_deprecated(package.as_ref().unwrap_or(&name), Some(&req), id)?; if package.is_some() { dep.set_explicit_name_in_toml(&name); } @@ -350,8 +349,12 @@ pub trait RegistryData { fn config(&mut self) -> CargoResult>; fn update_index(&mut self) -> CargoResult<()>; fn download(&mut self, pkg: &PackageId, checksum: &str) -> CargoResult; - fn finish_download(&mut self, pkg: &PackageId, checksum: &str, data: &[u8]) - -> CargoResult; + fn finish_download( + &mut self, + pkg: &PackageId, + checksum: &str, + data: &[u8], + ) -> CargoResult; fn is_crate_downloaded(&self, _pkg: &PackageId) -> bool { true @@ -360,34 +363,34 @@ pub trait RegistryData { pub enum MaybeLock { Ready(FileLock), - Download { url: String, descriptor: String } + Download { url: String, descriptor: String }, } mod index; mod local; mod remote; -fn short_name(id: &SourceId) -> String { - let hash = hex::short_hash(id); +fn short_name(id: SourceId) -> String { + let hash = hex::short_hash(&id); let ident = id.url().host_str().unwrap_or("").to_string(); format!("{}-{}", ident, hash) } impl<'cfg> RegistrySource<'cfg> { - pub fn remote(source_id: &SourceId, config: &'cfg Config) -> RegistrySource<'cfg> { + pub fn remote(source_id: SourceId, config: &'cfg Config) -> RegistrySource<'cfg> { let name = short_name(source_id); let ops = remote::RemoteRegistry::new(source_id, config, &name); RegistrySource::new(source_id, config, &name, Box::new(ops), true) } - pub fn local(source_id: &SourceId, path: &Path, config: &'cfg Config) -> RegistrySource<'cfg> { + pub fn local(source_id: SourceId, path: &Path, config: &'cfg Config) -> RegistrySource<'cfg> { let name = short_name(source_id); let ops = local::LocalRegistry::new(path, config, &name); RegistrySource::new(source_id, config, &name, Box::new(ops), false) } fn new( - source_id: &SourceId, + source_id: SourceId, config: &'cfg Config, name: &str, ops: Box, @@ -396,7 +399,7 @@ impl<'cfg> RegistrySource<'cfg> { RegistrySource { src_path: config.registry_source_path().join(name), config, - source_id: source_id.clone(), + source_id, updated: false, index: index::RegistryIndex::new(source_id, ops.index_path(), config, index_locked), index_locked, @@ -468,7 +471,7 @@ impl<'cfg> RegistrySource<'cfg> { self.ops.update_index()?; let path = self.ops.index_path(); self.index = - index::RegistryIndex::new(&self.source_id, path, self.config, self.index_locked); + index::RegistryIndex::new(self.source_id, path, self.config, self.index_locked); Ok(()) } @@ -476,7 +479,7 @@ impl<'cfg> RegistrySource<'cfg> { let path = self .unpack_package(package, &path) .chain_err(|| internal(format!("failed to unpack package `{}`", package)))?; - let mut src = PathSource::new(&path, &self.source_id, self.config); + let mut src = PathSource::new(&path, self.source_id, self.config); src.update()?; let pkg = match src.download(package)? { MaybePackage::Ready(pkg) => pkg, @@ -543,8 +546,8 @@ impl<'cfg> Source for RegistrySource<'cfg> { false } - fn source_id(&self) -> &SourceId { - &self.source_id + fn source_id(&self) -> SourceId { + self.source_id } fn update(&mut self) -> CargoResult<()> { @@ -566,18 +569,14 @@ impl<'cfg> Source for RegistrySource<'cfg> { fn download(&mut self, package: &PackageId) -> CargoResult { let hash = self.index.hash(package, &mut *self.ops)?; match self.ops.download(package, &hash)? { - MaybeLock::Ready(file) => { - self.get_pkg(package, file).map(MaybePackage::Ready) - } + MaybeLock::Ready(file) => self.get_pkg(package, file).map(MaybePackage::Ready), MaybeLock::Download { url, descriptor } => { Ok(MaybePackage::Download { url, descriptor }) } } } - fn finish_download(&mut self, package: &PackageId, data: Vec) - -> CargoResult - { + fn finish_download(&mut self, package: &PackageId, data: Vec) -> CargoResult { let hash = self.index.hash(package, &mut *self.ops)?; let file = self.ops.finish_download(package, &hash, &data)?; self.get_pkg(package, file) diff --git a/src/cargo/sources/registry/remote.rs b/src/cargo/sources/registry/remote.rs index 854206d0f92..9c1bf4557a4 100644 --- a/src/cargo/sources/registry/remote.rs +++ b/src/cargo/sources/registry/remote.rs @@ -1,23 +1,25 @@ use std::cell::{Cell, Ref, RefCell}; use std::fmt::Write as FmtWrite; -use std::io::SeekFrom; use std::io::prelude::*; +use std::io::SeekFrom; use std::mem; use std::path::Path; use std::str; use git2; use hex; -use serde_json; use lazycell::LazyCell; +use serde_json; use core::{PackageId, SourceId}; use sources::git; -use sources::registry::{RegistryConfig, RegistryData, CRATE_TEMPLATE, INDEX_LOCK, VERSION_TEMPLATE}; use sources::registry::MaybeLock; -use util::{FileLock, Filesystem}; -use util::{Config, Sha256}; +use sources::registry::{ + RegistryConfig, RegistryData, CRATE_TEMPLATE, INDEX_LOCK, VERSION_TEMPLATE, +}; use util::errors::{CargoResult, CargoResultExt}; +use util::{Config, Sha256}; +use util::{FileLock, Filesystem}; pub struct RemoteRegistry<'cfg> { index_path: Filesystem, @@ -30,11 +32,11 @@ pub struct RemoteRegistry<'cfg> { } impl<'cfg> RemoteRegistry<'cfg> { - pub fn new(source_id: &SourceId, config: &'cfg Config, name: &str) -> RemoteRegistry<'cfg> { + pub fn new(source_id: SourceId, config: &'cfg Config, name: &str) -> RemoteRegistry<'cfg> { RemoteRegistry { index_path: config.registry_index_path().join(name), cache_path: config.registry_cache_path().join(name), - source_id: source_id.clone(), + source_id, config, tree: RefCell::new(None), repo: LazyCell::new(), @@ -54,9 +56,11 @@ impl<'cfg> RemoteRegistry<'cfg> { // Ok, now we need to lock and try the whole thing over again. trace!("acquiring registry index lock"); - let lock = - self.index_path - .open_rw(Path::new(INDEX_LOCK), self.config, "the registry index")?; + let lock = self.index_path.open_rw( + Path::new(INDEX_LOCK), + self.config, + "the registry index", + )?; match git2::Repository::open(&path) { Ok(repo) => Ok(repo), Err(_) => { @@ -79,9 +83,8 @@ impl<'cfg> RemoteRegistry<'cfg> { // things that we don't want. let mut opts = git2::RepositoryInitOptions::new(); opts.external_template(false); - Ok(git2::Repository::init_opts(&path, &opts).chain_err(|| { - "failed to initialized index git repository" - })?) + Ok(git2::Repository::init_opts(&path, &opts) + .chain_err(|| "failed to initialized index git repository")?) } } }) @@ -231,15 +234,22 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> { if !url.contains(CRATE_TEMPLATE) && !url.contains(VERSION_TEMPLATE) { write!(url, "/{}/{}/download", CRATE_TEMPLATE, VERSION_TEMPLATE).unwrap(); } - let url = url.replace(CRATE_TEMPLATE, &*pkg.name()) + let url = url + .replace(CRATE_TEMPLATE, &*pkg.name()) .replace(VERSION_TEMPLATE, &pkg.version().to_string()); - Ok(MaybeLock::Download { url, descriptor: pkg.to_string() }) + Ok(MaybeLock::Download { + url, + descriptor: pkg.to_string(), + }) } - fn finish_download(&mut self, pkg: &PackageId, checksum: &str, data: &[u8]) - -> CargoResult - { + fn finish_download( + &mut self, + pkg: &PackageId, + checksum: &str, + data: &[u8], + ) -> CargoResult { // Verify what we just downloaded let mut state = Sha256::new(); state.update(data); diff --git a/src/cargo/sources/replaced.rs b/src/cargo/sources/replaced.rs index e413de2d17b..006e514de0f 100644 --- a/src/cargo/sources/replaced.rs +++ b/src/cargo/sources/replaced.rs @@ -1,5 +1,5 @@ -use core::{Dependency, Package, PackageId, Source, SourceId, Summary}; use core::source::MaybePackage; +use core::{Dependency, Package, PackageId, Source, SourceId, Summary}; use util::errors::{CargoResult, CargoResultExt}; pub struct ReplacedSource<'cfg> { @@ -10,43 +10,25 @@ pub struct ReplacedSource<'cfg> { impl<'cfg> ReplacedSource<'cfg> { pub fn new( - to_replace: &SourceId, - replace_with: &SourceId, + to_replace: SourceId, + replace_with: SourceId, src: Box, ) -> ReplacedSource<'cfg> { ReplacedSource { - to_replace: to_replace.clone(), - replace_with: replace_with.clone(), + to_replace, + replace_with, inner: src, } } } impl<'cfg> Source for ReplacedSource<'cfg> { - fn query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()> { - let (replace_with, to_replace) = (&self.replace_with, &self.to_replace); - let dep = dep.clone().map_source(to_replace, replace_with); - - self.inner - .query( - &dep, - &mut |summary| f(summary.map_source(replace_with, to_replace)), - ) - .chain_err(|| format!("failed to query replaced source {}", self.to_replace))?; - Ok(()) + fn source_id(&self) -> SourceId { + self.to_replace } - fn fuzzy_query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()> { - let (replace_with, to_replace) = (&self.replace_with, &self.to_replace); - let dep = dep.clone().map_source(to_replace, replace_with); - - self.inner - .fuzzy_query( - &dep, - &mut |summary| f(summary.map_source(replace_with, to_replace)), - ) - .chain_err(|| format!("failed to query replaced source {}", self.to_replace))?; - Ok(()) + fn replaced_source_id(&self) -> SourceId { + self.replace_with } fn supports_checksums(&self) -> bool { @@ -57,12 +39,28 @@ impl<'cfg> Source for ReplacedSource<'cfg> { self.inner.requires_precise() } - fn source_id(&self) -> &SourceId { - &self.to_replace + fn query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()> { + let (replace_with, to_replace) = (self.replace_with, self.to_replace); + let dep = dep.clone().map_source(to_replace, replace_with); + + self.inner + .query(&dep, &mut |summary| { + f(summary.map_source(replace_with, to_replace)) + }) + .chain_err(|| format!("failed to query replaced source {}", self.to_replace))?; + Ok(()) } - fn replaced_source_id(&self) -> &SourceId { - &self.replace_with + fn fuzzy_query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()> { + let (replace_with, to_replace) = (self.replace_with, self.to_replace); + let dep = dep.clone().map_source(to_replace, replace_with); + + self.inner + .fuzzy_query(&dep, &mut |summary| { + f(summary.map_source(replace_with, to_replace)) + }) + .chain_err(|| format!("failed to query replaced source {}", self.to_replace))?; + Ok(()) } fn update(&mut self) -> CargoResult<()> { @@ -73,26 +71,26 @@ impl<'cfg> Source for ReplacedSource<'cfg> { } fn download(&mut self, id: &PackageId) -> CargoResult { - let id = id.with_source_id(&self.replace_with); - let pkg = self.inner + let id = id.with_source_id(self.replace_with); + let pkg = self + .inner .download(&id) .chain_err(|| format!("failed to download replaced source {}", self.to_replace))?; Ok(match pkg { MaybePackage::Ready(pkg) => { - MaybePackage::Ready(pkg.map_source(&self.replace_with, &self.to_replace)) + MaybePackage::Ready(pkg.map_source(self.replace_with, self.to_replace)) } other @ MaybePackage::Download { .. } => other, }) } - fn finish_download(&mut self, id: &PackageId, data: Vec) - -> CargoResult - { - let id = id.with_source_id(&self.replace_with); - let pkg = self.inner + fn finish_download(&mut self, id: &PackageId, data: Vec) -> CargoResult { + let id = id.with_source_id(self.replace_with); + let pkg = self + .inner .finish_download(&id, data) .chain_err(|| format!("failed to download replaced source {}", self.to_replace))?; - Ok(pkg.map_source(&self.replace_with, &self.to_replace)) + Ok(pkg.map_source(self.replace_with, self.to_replace)) } fn fingerprint(&self, id: &Package) -> CargoResult { @@ -100,12 +98,16 @@ impl<'cfg> Source for ReplacedSource<'cfg> { } fn verify(&self, id: &PackageId) -> CargoResult<()> { - let id = id.with_source_id(&self.replace_with); + let id = id.with_source_id(self.replace_with); self.inner.verify(&id) } fn describe(&self) -> String { - format!("{} (which is replacing {})", self.inner.describe(), self.to_replace) + format!( + "{} (which is replacing {})", + self.inner.describe(), + self.to_replace + ) } fn is_replaced(&self) -> bool { diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 514dbbbc7d7..d85219cc883 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -28,7 +28,7 @@ use self::targets::targets; pub fn read_manifest( path: &Path, - source_id: &SourceId, + source_id: SourceId, config: &Config, ) -> Result<(EitherManifest, Vec), ManifestError> { trace!( @@ -46,7 +46,7 @@ pub fn read_manifest( fn do_read_manifest( contents: &str, manifest_file: &Path, - source_id: &SourceId, + source_id: SourceId, config: &Config, ) -> CargoResult<(EitherManifest, Vec)> { let package_root = manifest_file.parent().unwrap(); @@ -517,7 +517,6 @@ impl<'de> de::Deserialize<'de> for StringOrVec { { let seq = de::value::SeqAccessDeserializer::new(v); Vec::deserialize(seq).map(StringOrVec) - } } @@ -661,7 +660,7 @@ pub struct TomlWorkspace { } impl TomlProject { - pub fn to_package_id(&self, source_id: &SourceId) -> CargoResult { + pub fn to_package_id(&self, source_id: SourceId) -> CargoResult { PackageId::new(&self.name, self.version.clone(), source_id) } } @@ -669,7 +668,7 @@ impl TomlProject { struct Context<'a, 'b> { pkgid: Option<&'a PackageId>, deps: &'a mut Vec, - source_id: &'a SourceId, + source_id: SourceId, nested_paths: &'a mut Vec, config: &'b Config, warnings: &'a mut Vec, @@ -789,7 +788,7 @@ impl TomlManifest { fn to_real_manifest( me: &Rc, - source_id: &SourceId, + source_id: SourceId, package_root: &Path, config: &Config, ) -> CargoResult<(Manifest, Vec)> { @@ -817,7 +816,11 @@ impl TomlManifest { if c == '_' || c == '-' { continue; } - bail!("Invalid character `{}` in package name: `{}`", c, package_name) + bail!( + "Invalid character `{}` in package name: `{}`", + c, + package_name + ) } let pkgid = project.to_package_id(source_id)?; @@ -1061,7 +1064,7 @@ impl TomlManifest { fn to_virtual_manifest( me: &Rc, - source_id: &SourceId, + source_id: SourceId, root: &Path, config: &Config, ) -> CargoResult<(VirtualManifest, Vec)> { @@ -1258,7 +1261,8 @@ impl TomlDependency { TomlDependency::Simple(ref version) => DetailedTomlDependency { version: Some(version.clone()), ..Default::default() - }.to_dependency(name, cx, kind), + } + .to_dependency(name, cx, kind), TomlDependency::Detailed(ref details) => details.to_dependency(name, cx, kind), } } @@ -1376,7 +1380,7 @@ impl DetailedTomlDependency { let path = util::normalize_path(&path); SourceId::for_path(&path)? } else { - cx.source_id.clone() + cx.source_id } } (None, None, Some(registry), None) => SourceId::alt_registry(cx.config, registry)?, @@ -1394,8 +1398,8 @@ impl DetailedTomlDependency { let version = self.version.as_ref().map(|v| &v[..]); let mut dep = match cx.pkgid { - Some(id) => Dependency::parse(pkg_name, version, &new_source_id, id, cx.config)?, - None => Dependency::parse_no_deprecated(pkg_name, version, &new_source_id)?, + Some(id) => Dependency::parse(pkg_name, version, new_source_id, id, cx.config)?, + None => Dependency::parse_no_deprecated(pkg_name, version, new_source_id)?, }; dep.set_features(self.features.iter().flat_map(|x| x)) .set_default_features( @@ -1405,7 +1409,7 @@ impl DetailedTomlDependency { ) .set_optional(self.optional.unwrap_or(false)) .set_platform(cx.platform.clone()) - .set_registry_id(®istry_id); + .set_registry_id(registry_id); if let Some(kind) = kind { dep.set_kind(kind); } diff --git a/tests/testsuite/search.rs b/tests/testsuite/search.rs index 714913acf7c..bd59b39e78c 100644 --- a/tests/testsuite/search.rs +++ b/tests/testsuite/search.rs @@ -67,7 +67,8 @@ fn setup() { .file( "config.json", &format!(r#"{{"dl":"{0}","api":"{0}"}}"#, api()), - ).build(); + ) + .build(); let base = api_path().join("api/v1/crates"); write_crates(&base); @@ -89,8 +90,10 @@ replace-with = 'dummy-registry' registry = '{reg}' "#, reg = registry_url(), - ).as_bytes(), - ).unwrap(); + ) + .as_bytes(), + ) + .unwrap(); } #[test] @@ -104,7 +107,7 @@ fn not_update() { let sid = SourceId::for_registry(®istry_url()).unwrap(); let cfg = Config::new(Shell::new(), paths::root(), paths::home().join(".cargo")); - let mut regsrc = RegistrySource::remote(&sid, &cfg); + let mut regsrc = RegistrySource::remote(sid, &cfg); regsrc.update().unwrap(); cargo_process("search postgres") @@ -142,9 +145,10 @@ fn simple() { fn simple_with_host() { setup(); - cargo_process("search postgres --host").arg(registry_url().to_string()) - .with_stderr( - "\ + cargo_process("search postgres --host") + .arg(registry_url().to_string()) + .with_stderr( + "\ [WARNING] The flag '--host' is no longer valid. Previous versions of Cargo accepted this flag, but it is being @@ -156,10 +160,8 @@ to update to a fixed version or contact the upstream maintainer about this warning. [UPDATING] `[CWD]/registry` index ", - ) - .with_stdout_contains( - "hoare = \"0.1.1\" # Design by contract style assertions for Rust", - ) + ) + .with_stdout_contains("hoare = \"0.1.1\" # Design by contract style assertions for Rust") .run(); } @@ -169,9 +171,12 @@ about this warning. fn simple_with_index_and_host() { setup(); - cargo_process("search postgres --index").arg(registry_url().to_string()).arg("--host").arg(registry_url().to_string()) - .with_stderr( - "\ + cargo_process("search postgres --index") + .arg(registry_url().to_string()) + .arg("--host") + .arg(registry_url().to_string()) + .with_stderr( + "\ [WARNING] The flag '--host' is no longer valid. Previous versions of Cargo accepted this flag, but it is being @@ -183,10 +188,8 @@ to update to a fixed version or contact the upstream maintainer about this warning. [UPDATING] `[CWD]/registry` index ", - ) - .with_stdout_contains( - "hoare = \"0.1.1\" # Design by contract style assertions for Rust", - ) + ) + .with_stdout_contains("hoare = \"0.1.1\" # Design by contract style assertions for Rust") .run(); } diff --git a/tests/testsuite/support/resolver.rs b/tests/testsuite/support/resolver.rs index fd2a8d6f0ce..a1544e30441 100644 --- a/tests/testsuite/support/resolver.rs +++ b/tests/testsuite/support/resolver.rs @@ -87,11 +87,11 @@ pub fn resolve_with_config_raw( Ok(()) } - fn describe_source(&self, _src: &SourceId) -> String { + fn describe_source(&self, _src: SourceId) -> String { String::new() } - fn is_replaced(&self, _src: &SourceId) -> bool { + fn is_replaced(&self, _src: SourceId) -> bool { false } } @@ -127,7 +127,7 @@ pub trait ToDep { impl ToDep for &'static str { fn to_dep(self) -> Dependency { - Dependency::parse_no_deprecated(self, Some("1.0.0"), ®istry_loc()).unwrap() + Dependency::parse_no_deprecated(self, Some("1.0.0"), registry_loc()).unwrap() } } @@ -149,14 +149,14 @@ impl ToPkgId for PackageId { impl<'a> ToPkgId for &'a str { fn to_pkgid(&self) -> PackageId { - PackageId::new(*self, "1.0.0", ®istry_loc()).unwrap() + PackageId::new(*self, "1.0.0", registry_loc()).unwrap() } } impl, U: AsRef> ToPkgId for (T, U) { fn to_pkgid(&self) -> PackageId { let (name, vers) = self; - PackageId::new(name.as_ref(), vers.as_ref(), ®istry_loc()).unwrap() + PackageId::new(name.as_ref(), vers.as_ref(), registry_loc()).unwrap() } } @@ -176,7 +176,7 @@ fn registry_loc() -> SourceId { static ref EXAMPLE_DOT_COM: SourceId = SourceId::for_registry(&"http://example.com".to_url().unwrap()).unwrap(); } - EXAMPLE_DOT_COM.clone() + *EXAMPLE_DOT_COM } pub fn pkg(name: T) -> Summary { @@ -201,7 +201,7 @@ pub fn pkg_dep(name: T, dep: Vec) -> Summary { } pub fn pkg_id(name: &str) -> PackageId { - PackageId::new(name, "1.0.0", ®istry_loc()).unwrap() + PackageId::new(name, "1.0.0", registry_loc()).unwrap() } fn pkg_id_loc(name: &str, loc: &str) -> PackageId { @@ -209,7 +209,7 @@ fn pkg_id_loc(name: &str, loc: &str) -> PackageId { let master = GitReference::Branch("master".to_string()); let source_id = SourceId::for_git(&remote.unwrap(), master).unwrap(); - PackageId::new(name, "1.0.0", &source_id).unwrap() + PackageId::new(name, "1.0.0", source_id).unwrap() } pub fn pkg_loc(name: &str, loc: &str) -> Summary { @@ -232,7 +232,7 @@ pub fn dep(name: &str) -> Dependency { dep_req(name, "*") } pub fn dep_req(name: &str, req: &str) -> Dependency { - Dependency::parse_no_deprecated(name, Some(req), ®istry_loc()).unwrap() + Dependency::parse_no_deprecated(name, Some(req), registry_loc()).unwrap() } pub fn dep_req_kind(name: &str, req: &str, kind: Kind) -> Dependency { let mut dep = dep_req(name, req); @@ -244,7 +244,7 @@ pub fn dep_loc(name: &str, location: &str) -> Dependency { let url = location.to_url().unwrap(); let master = GitReference::Branch("master".to_string()); let source_id = SourceId::for_git(&url, master).unwrap(); - Dependency::parse_no_deprecated(name, Some("1.0.0"), &source_id).unwrap() + Dependency::parse_no_deprecated(name, Some("1.0.0"), source_id).unwrap() } pub fn dep_kind(name: &str, kind: Kind) -> Dependency { dep(name).set_kind(kind).clone() @@ -281,9 +281,7 @@ impl fmt::Debug for PrettyPrintRegistry { } else { write!(f, "pkg!((\"{}\", \"{}\") => [", s.name(), s.version())?; for d in s.dependencies() { - if d.kind() == Kind::Normal - && &d.version_req().to_string() == "*" - { + if d.kind() == Kind::Normal && &d.version_req().to_string() == "*" { write!(f, "dep(\"{}\"),", d.name_in_toml())?; } else if d.kind() == Kind::Normal { write!( From 7cd4a94db8168848b2a4d7c25fb47cf788573380 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Sun, 25 Nov 2018 12:43:45 -0500 Subject: [PATCH 094/128] Other clippy things and fmt --- src/cargo/core/package.rs | 15 ++++--- src/cargo/core/profiles.rs | 2 +- src/cargo/core/resolver/encode.rs | 2 +- src/cargo/core/resolver/resolve.rs | 4 +- src/cargo/ops/cargo_install.rs | 8 ++-- src/cargo/ops/cargo_new.rs | 31 +++++++------ src/cargo/ops/lockfile.rs | 14 +++--- src/cargo/sources/registry/local.rs | 17 ++++--- src/cargo/sources/registry/mod.rs | 8 ++-- src/cargo/util/config.rs | 26 +++++------ src/cargo/util/toml/targets.rs | 70 ++++++++++++++--------------- 11 files changed, 101 insertions(+), 96 deletions(-) diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 9ba5affad63..0041c449bef 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -694,7 +694,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { self.updated_at.set(now); self.next_speed_check.set(now + self.timeout.dur); self.next_speed_check_bytes_threshold - .set(self.timeout.low_speed_limit as u64); + .set(u64::from(self.timeout.low_speed_limit)); dl.timed_out.set(None); dl.current.set(0); dl.total.set(0); @@ -741,8 +741,12 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { if let Some(pair) = results.pop() { break Ok(pair); } - assert!(self.pending.len() > 0); - let timeout = self.set.multi.get_timeout()?.unwrap_or(Duration::new(5, 0)); + assert!(!self.pending.is_empty()); + let timeout = self + .set + .multi + .get_timeout()? + .unwrap_or_else(|| Duration::new(5, 0)); self.set .multi .wait(&mut [], timeout) @@ -764,12 +768,12 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { if delta >= threshold { self.next_speed_check.set(now + self.timeout.dur); self.next_speed_check_bytes_threshold - .set(self.timeout.low_speed_limit as u64); + .set(u64::from(self.timeout.low_speed_limit)); } else { self.next_speed_check_bytes_threshold.set(threshold - delta); } } - if !self.tick(WhyTick::DownloadUpdate).is_ok() { + if self.tick(WhyTick::DownloadUpdate).is_err() { return false; } @@ -841,6 +845,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { } } +#[derive(Copy, Clone)] enum WhyTick<'a> { DownloadStarted, DownloadUpdate, diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index 669fed83955..beeabac6f01 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -596,7 +596,7 @@ impl UnitFor { /// Returns true if this unit is for a custom build script or one of its /// dependencies. - pub fn is_custom_build(&self) -> bool { + pub fn is_custom_build(self) -> bool { self.custom_build } diff --git a/src/cargo/core/resolver/encode.rs b/src/cargo/core/resolver/encode.rs index 25d55d7134f..c4e682da3d5 100644 --- a/src/cargo/core/resolver/encode.rs +++ b/src/cargo/core/resolver/encode.rs @@ -338,7 +338,7 @@ impl<'a, 'cfg> ser::Serialize for WorkspaceResolve<'a, 'cfg> { let encodable = ids .iter() - .filter_map(|&id| Some(encodable_resolve_node(id, self.resolve))) + .map(|&id| encodable_resolve_node(id, self.resolve)) .collect::>(); let mut metadata = self.resolve.metadata().clone(); diff --git a/src/cargo/core/resolver/resolve.rs b/src/cargo/core/resolver/resolve.rs index 14e37c54447..9b77065f9e5 100644 --- a/src/cargo/core/resolver/resolve.rs +++ b/src/cargo/core/resolver/resolve.rs @@ -239,9 +239,9 @@ unable to verify that `{0}` is the same as when the lockfile was generated let mut names = deps.iter().map(|d| { d.explicit_name_in_toml() .map(|s| s.as_str().replace("-", "_")) - .unwrap_or(crate_name.clone()) + .unwrap_or_else(|| crate_name.clone()) }); - let name = names.next().unwrap_or(crate_name.clone()); + let name = names.next().unwrap_or_else(|| crate_name.clone()); for n in names { if n == name { continue; diff --git a/src/cargo/ops/cargo_install.rs b/src/cargo/ops/cargo_install.rs index ec0ca5f387c..0b0dd026863 100644 --- a/src/cargo/ops/cargo_install.rs +++ b/src/cargo/ops/cargo_install.rs @@ -726,7 +726,7 @@ pub fn uninstall( let scheduled_error = if specs.len() == 1 { uninstall_one(&root, specs[0], bins, config)?; false - } else if specs.len() == 0 { + } else if specs.is_empty() { uninstall_cwd(&root, bins, config)?; false } else { @@ -780,7 +780,7 @@ pub fn uninstall_one( let crate_metadata = metadata(config, root)?; let metadata = read_crate_list(&crate_metadata)?; let pkgid = PackageIdSpec::query_str(spec, metadata.v1.keys())?.clone(); - uninstall_pkgid(crate_metadata, metadata, &pkgid, bins, config) + uninstall_pkgid(&crate_metadata, metadata, &pkgid, bins, config) } fn uninstall_cwd(root: &Filesystem, bins: &[String], config: &Config) -> CargoResult<()> { @@ -792,11 +792,11 @@ fn uninstall_cwd(root: &Filesystem, bins: &[String], config: &Config) -> CargoRe path.read_packages() })?; let pkgid = pkg.package_id(); - uninstall_pkgid(crate_metadata, metadata, pkgid, bins, config) + uninstall_pkgid(&crate_metadata, metadata, pkgid, bins, config) } fn uninstall_pkgid( - crate_metadata: FileLock, + crate_metadata: &FileLock, mut metadata: CrateListingV1, pkgid: &PackageId, bins: &[String], diff --git a/src/cargo/ops/cargo_new.rs b/src/cargo/ops/cargo_new.rs index 4be3af40a05..abcc0f38010 100644 --- a/src/cargo/ops/cargo_new.rs +++ b/src/cargo/ops/cargo_new.rs @@ -1,16 +1,16 @@ use std::collections::BTreeMap; use std::env; -use std::fs; use std::fmt; +use std::fs; use std::path::{Path, PathBuf}; use git2::Config as GitConfig; use git2::Repository as GitRepository; use core::{compiler, Workspace}; -use util::{internal, FossilRepo, GitRepo, HgRepo, PijulRepo, existing_vcs_repo}; -use util::{paths, Config}; use util::errors::{CargoResult, CargoResultExt}; +use util::{existing_vcs_repo, internal, FossilRepo, GitRepo, HgRepo, PijulRepo}; +use util::{paths, Config}; use toml; @@ -51,7 +51,8 @@ impl fmt::Display for NewProjectKind { match *self { NewProjectKind::Bin => "binary (application)", NewProjectKind::Lib => "library", - }.fmt(f) + } + .fmt(f) } } @@ -430,7 +431,8 @@ fn mk(config: &Config, opts: &MkOptions) -> CargoResult<()> { "/target\n", "**/*.rs.bk\n", if !opts.bin { "Cargo.lock\n" } else { "" }, - ].concat(); + ] + .concat(); // Mercurial glob ignores can't be rooted, so just sticking a 'syntax: glob' at the top of the // file will exclude too much. Instead, use regexp-based ignores. See 'hg help ignore' for // more. @@ -438,7 +440,8 @@ fn mk(config: &Config, opts: &MkOptions) -> CargoResult<()> { "^target/\n", "glob:*.rs.bk\n", if !opts.bin { "glob:Cargo.lock\n" } else { "" }, - ].concat(); + ] + .concat(); let vcs = opts.version_control.unwrap_or_else(|| { let in_existing_vcs = existing_vcs_repo(path.parent().unwrap_or(path), config.cwd()); @@ -553,15 +556,15 @@ edition = {} None => toml::Value::String("2018".to_string()), }, match opts.registry { - Some(registry) => { - format!("publish = {}\n", - toml::Value::Array(vec!(toml::Value::String(registry.to_string()))) - ) - } + Some(registry) => format!( + "publish = {}\n", + toml::Value::Array(vec!(toml::Value::String(registry.to_string()))) + ), None => "".to_string(), - }, + }, cargotoml_path_specifier - ).as_bytes(), + ) + .as_bytes(), )?; // Create all specified source files @@ -665,7 +668,7 @@ fn discover_author() -> CargoResult<(String, Option)> { // In some cases emails will already have <> remove them since they // are already added when needed. - if s.starts_with("<") && s.ends_with(">") { + if s.starts_with('<') && s.ends_with('>') { s = &s[1..s.len() - 1]; } diff --git a/src/cargo/ops/lockfile.rs b/src/cargo/ops/lockfile.rs index 5547a75059c..92ac5e1e393 100644 --- a/src/cargo/ops/lockfile.rs +++ b/src/cargo/ops/lockfile.rs @@ -20,12 +20,12 @@ pub fn load_pkg_lockfile(ws: &Workspace) -> CargoResult> { f.read_to_string(&mut s) .chain_err(|| format!("failed to read file: {}", f.path().display()))?; - let resolve = - (|| -> CargoResult> { - let resolve: toml::Value = cargo_toml::parse(&s, f.path(), ws.config())?; - let v: resolver::EncodableResolve = resolve.try_into()?; - Ok(Some(v.into_resolve(ws)?)) - })().chain_err(|| format!("failed to parse lock file at: {}", f.path().display()))?; + let resolve = (|| -> CargoResult> { + let resolve: toml::Value = cargo_toml::parse(&s, f.path(), ws.config())?; + let v: resolver::EncodableResolve = resolve.try_into()?; + Ok(Some(v.into_resolve(ws)?)) + })() + .chain_err(|| format!("failed to parse lock file at: {}", f.path().display()))?; Ok(resolve) } @@ -47,7 +47,7 @@ pub fn write_pkg_lockfile(ws: &Workspace, resolve: &Resolve) -> CargoResult<()> // This is in preparation for marking it as generated // https://github.com/rust-lang/cargo/issues/6180 if let Ok(orig) = &orig { - for line in orig.lines().take_while(|line| line.starts_with("#")) { + for line in orig.lines().take_while(|line| line.starts_with('#')) { out.push_str(line); out.push_str("\n"); } diff --git a/src/cargo/sources/registry/local.rs b/src/cargo/sources/registry/local.rs index 023e955b857..82c95052ee8 100644 --- a/src/cargo/sources/registry/local.rs +++ b/src/cargo/sources/registry/local.rs @@ -1,13 +1,13 @@ -use std::io::SeekFrom; use std::io::prelude::*; +use std::io::SeekFrom; use std::path::Path; use core::PackageId; use hex; -use sources::registry::{RegistryConfig, RegistryData, MaybeLock}; -use util::paths; -use util::{Config, Filesystem, Sha256, FileLock}; +use sources::registry::{MaybeLock, RegistryConfig, RegistryData}; use util::errors::{CargoResult, CargoResultExt}; +use util::paths; +use util::{Config, FileLock, Filesystem, Sha256}; pub struct LocalRegistry<'cfg> { index_path: Filesystem, @@ -104,9 +104,12 @@ impl<'cfg> RegistryData for LocalRegistry<'cfg> { Ok(MaybeLock::Ready(crate_file)) } - fn finish_download(&mut self, _pkg: &PackageId, _checksum: &str, _data: &[u8]) - -> CargoResult - { + fn finish_download( + &mut self, + _pkg: &PackageId, + _checksum: &str, + _data: &[u8], + ) -> CargoResult { panic!("this source doesn't download") } } diff --git a/src/cargo/sources/registry/mod.rs b/src/cargo/sources/registry/mod.rs index 60c3d87850c..7aa2fbf7dfd 100644 --- a/src/cargo/sources/registry/mod.rs +++ b/src/cargo/sources/registry/mod.rs @@ -475,9 +475,9 @@ impl<'cfg> RegistrySource<'cfg> { Ok(()) } - fn get_pkg(&mut self, package: &PackageId, path: FileLock) -> CargoResult { + fn get_pkg(&mut self, package: &PackageId, path: &FileLock) -> CargoResult { let path = self - .unpack_package(package, &path) + .unpack_package(package, path) .chain_err(|| internal(format!("failed to unpack package `{}`", package)))?; let mut src = PathSource::new(&path, self.source_id, self.config); src.update()?; @@ -569,7 +569,7 @@ impl<'cfg> Source for RegistrySource<'cfg> { fn download(&mut self, package: &PackageId) -> CargoResult { let hash = self.index.hash(package, &mut *self.ops)?; match self.ops.download(package, &hash)? { - MaybeLock::Ready(file) => self.get_pkg(package, file).map(MaybePackage::Ready), + MaybeLock::Ready(file) => self.get_pkg(package, &file).map(MaybePackage::Ready), MaybeLock::Download { url, descriptor } => { Ok(MaybePackage::Download { url, descriptor }) } @@ -579,7 +579,7 @@ impl<'cfg> Source for RegistrySource<'cfg> { fn finish_download(&mut self, package: &PackageId, data: Vec) -> CargoResult { let hash = self.index.hash(package, &mut *self.ops)?; let file = self.ops.finish_download(package, &hash, &data)?; - self.get_pkg(package, file) + self.get_pkg(package, &file) } fn fingerprint(&self, pkg: &Package) -> CargoResult { diff --git a/src/cargo/util/config.rs b/src/cargo/util/config.rs index 2faa31012e2..8a13f72813b 100644 --- a/src/cargo/util/config.rs +++ b/src/cargo/util/config.rs @@ -176,12 +176,10 @@ impl Config { /// The default cargo registry (`alternative-registry`) pub fn default_registry(&self) -> CargoResult> { - Ok( - match self.get_string("registry.default")? { - Some(registry) => Some(registry.val), - None => None, - } - ) + Ok(match self.get_string("registry.default")? { + Some(registry) => Some(registry.val), + None => None, + }) } /// Get a reference to the shell, for e.g. writing error messages @@ -245,7 +243,7 @@ impl Config { let argv0 = env::args_os() .map(PathBuf::from) .next() - .ok_or_else(||format_err!("no argv[0]"))?; + .ok_or_else(|| format_err!("no argv[0]"))?; paths::resolve_executable(&argv0) } @@ -458,10 +456,7 @@ impl Config { } } - pub fn get_path_and_args( - &self, - key: &str, - ) -> CargoResult)>> { + pub fn get_path_and_args(&self, key: &str) -> CargoResult)>> { if let Some(mut val) = self.get_list_or_split_string(key)? { if !val.val.is_empty() { return Ok(Some(Value { @@ -631,9 +626,7 @@ impl Config { self.load_values_from(&self.cwd) } - fn load_values_from(&self, path: &Path) - -> CargoResult> - { + fn load_values_from(&self, path: &Path) -> CargoResult> { let mut cfg = CV::Table(HashMap::new(), PathBuf::from(".")); let home = self.home_path.clone().into_path_unlocked(); @@ -654,7 +647,8 @@ impl Config { cfg.merge(value) .chain_err(|| format!("failed to merge configuration at `{}`", path.display()))?; Ok(()) - }).chain_err(|| "could not load Cargo configuration")?; + }) + .chain_err(|| "could not load Cargo configuration")?; self.load_credentials(&mut cfg)?; match cfg { @@ -790,7 +784,7 @@ impl Config { where F: FnMut() -> CargoResult, { - Ok(self.crates_io_source_id.try_borrow_with(f)?.clone()) + Ok(*(self.crates_io_source_id.try_borrow_with(f)?)) } pub fn creation_time(&self) -> Instant { diff --git a/src/cargo/util/toml/targets.rs b/src/cargo/util/toml/targets.rs index 81afec90926..69b0f85db77 100644 --- a/src/cargo/util/toml/targets.rs +++ b/src/cargo/util/toml/targets.rs @@ -10,16 +10,16 @@ //! It is a bit tricky because we need match explicit information from `Cargo.toml` //! with implicit info in directory layout. -use std::path::{Path, PathBuf}; -use std::fs::{self, DirEntry}; use std::collections::HashSet; +use std::fs::{self, DirEntry}; +use std::path::{Path, PathBuf}; -use core::{compiler, Edition, Feature, Features, Target}; -use util::errors::{CargoResult, CargoResultExt}; use super::{ LibKind, PathValue, StringOrBool, StringOrVec, TomlBenchTarget, TomlBinTarget, TomlExampleTarget, TomlLibTarget, TomlManifest, TomlTarget, TomlTestTarget, }; +use core::{compiler, Edition, Feature, Features, Target}; +use util::errors::{CargoResult, CargoResultExt}; pub fn targets( features: &Features, @@ -311,12 +311,8 @@ fn clean_bins( Err(e) => bail!("{}", e), }; - let mut target = Target::bin_target( - &bin.name(), - path, - bin.required_features.clone(), - edition, - ); + let mut target = + Target::bin_target(&bin.name(), path, bin.required_features.clone(), edition); configure(features, bin, &mut target)?; result.push(target); } @@ -413,12 +409,8 @@ fn clean_tests( let mut result = Vec::new(); for (path, toml) in targets { - let mut target = Target::test_target( - &toml.name(), - path, - toml.required_features.clone(), - edition, - ); + let mut target = + Target::test_target(&toml.name(), path, toml.required_features.clone(), edition); configure(features, &toml, &mut target)?; result.push(target); } @@ -472,12 +464,8 @@ fn clean_benches( let mut result = Vec::new(); for (path, toml) in targets { - let mut target = Target::bench_target( - &toml.name(), - path, - toml.required_features.clone(), - edition, - ); + let mut target = + Target::bench_target(&toml.name(), path, toml.required_features.clone(), edition); configure(features, &toml, &mut target)?; result.push(target); } @@ -544,7 +532,14 @@ fn clean_targets_with_legacy_path( validate_unique_names(&toml_targets, target_kind)?; let mut result = Vec::new(); for target in toml_targets { - let path = target_path(&target, inferred, target_kind, package_root, edition, legacy_path); + let path = target_path( + &target, + inferred, + target_kind, + package_root, + edition, + legacy_path, + ); let path = match path { Ok(path) => path, Err(e) => { @@ -634,12 +629,13 @@ fn toml_targets_and_inferred( ) -> Vec { let inferred_targets = inferred_to_toml_targets(inferred); match toml_targets { - None => + None => { if let Some(false) = autodiscover { vec![] } else { inferred_targets - }, + } + } Some(targets) => { let mut targets = targets.clone(); @@ -726,9 +722,11 @@ fn validate_has_name( target_kind: &str, ) -> CargoResult<()> { match target.name { - Some(ref name) => if name.trim().is_empty() { - bail!("{} target names cannot be empty", target_kind_human) - }, + Some(ref name) => { + if name.trim().is_empty() { + bail!("{} target names cannot be empty", target_kind_human) + } + } None => bail!( "{} target {}.name is required", target_kind_human, @@ -755,11 +753,7 @@ fn validate_unique_names(targets: &[TomlTarget], target_kind: &str) -> CargoResu Ok(()) } -fn configure( - features: &Features, - toml: &TomlTarget, - target: &mut Target, -) -> CargoResult<()> { +fn configure(features: &Features, toml: &TomlTarget, target: &mut Target) -> CargoResult<()> { let t2 = target.clone(); target .set_tested(toml.test.unwrap_or_else(|| t2.tested())) @@ -773,8 +767,14 @@ fn configure( (Some(false), _) | (_, Some(false)) => false, }); if let Some(edition) = toml.edition.clone() { - features.require(Feature::edition()).chain_err(|| "editions are unstable")?; - target.set_edition(edition.parse().chain_err(|| "failed to parse the `edition` key")?); + features + .require(Feature::edition()) + .chain_err(|| "editions are unstable")?; + target.set_edition( + edition + .parse() + .chain_err(|| "failed to parse the `edition` key")?, + ); } Ok(()) } From dad9fe6618a3a37ff752915d4dd8016d275935ea Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Sun, 25 Nov 2018 21:20:00 -0500 Subject: [PATCH 095/128] add `clippy::` --- src/bin/cargo/main.rs | 6 +++--- src/cargo/lib.rs | 37 +++++++++++++++++++------------------ 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/bin/cargo/main.rs b/src/bin/cargo/main.rs index 979d8949427..4dd90777f72 100644 --- a/src/bin/cargo/main.rs +++ b/src/bin/cargo/main.rs @@ -1,5 +1,5 @@ -#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] // large project -#![cfg_attr(feature = "cargo-clippy", allow(redundant_closure))] // there's a false positive +#![cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))] // large project +#![cfg_attr(feature = "cargo-clippy", allow(clippy::redundant_closure))] // there's a false positive extern crate cargo; extern crate clap; @@ -13,10 +13,10 @@ extern crate serde_derive; extern crate serde_json; extern crate toml; +use std::collections::BTreeSet; use std::env; use std::fs; use std::path::{Path, PathBuf}; -use std::collections::BTreeSet; use cargo::core::shell::Shell; use cargo::util::{self, command_prelude, lev_distance, CargoResult, CliResult, Config}; diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs index 8359faceabe..fe3f7f0ef0a 100644 --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -1,18 +1,17 @@ #![cfg_attr(test, deny(warnings))] - // Clippy isn't enforced by CI, and know that @alexcrichton isn't a fan :) -#![cfg_attr(feature = "cargo-clippy", allow(boxed_local))] // bug rust-lang-nursery/rust-clippy#1123 -#![cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))] // large project -#![cfg_attr(feature = "cargo-clippy", allow(derive_hash_xor_eq))] // there's an intentional incoherence -#![cfg_attr(feature = "cargo-clippy", allow(explicit_into_iter_loop))] // explicit loops are clearer -#![cfg_attr(feature = "cargo-clippy", allow(explicit_iter_loop))] // explicit loops are clearer -#![cfg_attr(feature = "cargo-clippy", allow(identity_op))] // used for vertical alignment -#![cfg_attr(feature = "cargo-clippy", allow(implicit_hasher))] // large project -#![cfg_attr(feature = "cargo-clippy", allow(large_enum_variant))] // large project -#![cfg_attr(feature = "cargo-clippy", allow(redundant_closure_call))] // closures over try catch blocks -#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] // large project -#![cfg_attr(feature = "cargo-clippy", allow(type_complexity))] // there's an exceptionally complex type -#![cfg_attr(feature = "cargo-clippy", allow(wrong_self_convention))] // perhaps Rc should be special cased in Clippy? +#![cfg_attr(feature = "cargo-clippy", allow(clippy::boxed_local))] // bug rust-lang-nursery/rust-clippy#1123 +#![cfg_attr(feature = "cargo-clippy", allow(clippy::cyclomatic_complexity))] // large project +#![cfg_attr(feature = "cargo-clippy", allow(clippy::derive_hash_xor_eq))] // there's an intentional incoherence +#![cfg_attr(feature = "cargo-clippy", allow(clippy::explicit_into_iter_loop))] // explicit loops are clearer +#![cfg_attr(feature = "cargo-clippy", allow(clippy::explicit_iter_loop))] // explicit loops are clearer +#![cfg_attr(feature = "cargo-clippy", allow(clippy::identity_op))] // used for vertical alignment +#![cfg_attr(feature = "cargo-clippy", allow(clippy::implicit_hasher))] // large project +#![cfg_attr(feature = "cargo-clippy", allow(clippy::large_enum_variant))] // large project +#![cfg_attr(feature = "cargo-clippy", allow(clippy::redundant_closure_call))] // closures over try catch blocks +#![cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))] // large project +#![cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))] // there's an exceptionally complex type +#![cfg_attr(feature = "cargo-clippy", allow(clippy::wrong_self_convention))] // perhaps Rc should be special cased in Clippy? extern crate atty; extern crate bytesize; @@ -55,6 +54,7 @@ extern crate serde_derive; extern crate serde_ignored; #[macro_use] extern crate serde_json; +extern crate im_rc; extern crate shell_escape; extern crate tar; extern crate tempfile; @@ -62,18 +62,17 @@ extern crate termcolor; extern crate toml; extern crate unicode_width; extern crate url; -extern crate im_rc; use std::fmt; -use serde::ser; use failure::Error; +use serde::ser; -use core::Shell; use core::shell::Verbosity::Verbose; +use core::Shell; -pub use util::{CargoError, CargoResult, CliError, CliResult, Config}; pub use util::errors::Internal; +pub use util::{CargoError, CargoResult, CliError, CliResult, Config}; pub const CARGO_ENV: &str = "CARGO"; @@ -210,7 +209,9 @@ fn handle_cause(cargo_err: &Error, shell: &mut Shell) -> bool { pub fn version() -> VersionInfo { macro_rules! option_env_str { - ($name:expr) => { option_env!($name).map(|s| s.to_string()) } + ($name:expr) => { + option_env!($name).map(|s| s.to_string()) + }; } // So this is pretty horrible... From 92485f8c14d29dc08a196f873f5b767e07c39429 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Sun, 25 Nov 2018 21:45:43 -0500 Subject: [PATCH 096/128] Other clippy things and fmt --- src/cargo/core/compiler/build_context/mod.rs | 30 +-- .../compiler/context/unit_dependencies.rs | 137 ++++++-------- src/cargo/core/compiler/job_queue.rs | 33 ++-- src/cargo/core/package.rs | 2 +- src/cargo/core/resolver/mod.rs | 23 ++- src/cargo/core/shell.rs | 22 +-- src/cargo/ops/fix.rs | 172 ++++++++++-------- src/cargo/util/lev_distance.rs | 2 +- src/cargo/util/read2.rs | 9 +- 9 files changed, 217 insertions(+), 213 deletions(-) diff --git a/src/cargo/core/compiler/build_context/mod.rs b/src/cargo/core/compiler/build_context/mod.rs index 358751c7f07..a6d8be47f35 100644 --- a/src/cargo/core/compiler/build_context/mod.rs +++ b/src/cargo/core/compiler/build_context/mod.rs @@ -88,7 +88,8 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> { } pub fn extern_crate_name(&self, unit: &Unit<'a>, dep: &Unit<'a>) -> CargoResult { - self.resolve.extern_crate_name(unit.pkg.package_id(), dep.pkg.package_id(), dep.target) + self.resolve + .extern_crate_name(unit.pkg.package_id(), dep.pkg.package_id(), dep.target) } /// Whether a dependency should be compiled for the host or target platform, @@ -266,10 +267,12 @@ impl TargetConfig { let list = value.list(k)?; output.cfgs.extend(list.iter().map(|v| v.0.clone())); } - "rustc-env" => for (name, val) in value.table(k)?.0 { - let val = val.string(name)?.0; - output.env.push((name.clone(), val.to_string())); - }, + "rustc-env" => { + for (name, val) in value.table(k)?.0 { + let val = val.string(name)?.0; + output.env.push((name.clone(), val.to_string())); + } + } "warning" | "rerun-if-changed" | "rerun-if-env-changed" => { bail!("`{}` is not supported in build script overrides", k); } @@ -342,7 +345,8 @@ fn env_args( // First try RUSTFLAGS from the environment if let Ok(a) = env::var(name) { - let args = a.split(' ') + let args = a + .split(' ') .map(str::trim) .filter(|s| !s.is_empty()) .map(str::to_string); @@ -351,7 +355,8 @@ fn env_args( let mut rustflags = Vec::new(); - let name = name.chars() + let name = name + .chars() .flat_map(|c| c.to_lowercase()) .collect::(); // Then the target.*.rustflags value... @@ -367,13 +372,10 @@ fn env_args( // ...including target.'cfg(...)'.rustflags if let Some(target_cfg) = target_cfg { if let Some(table) = config.get_table("target")? { - let cfgs = table.val.keys().filter_map(|key| { - if CfgExpr::matches_key(key, target_cfg) { - Some(key) - } else { - None - } - }); + let cfgs = table + .val + .keys() + .filter(|key| CfgExpr::matches_key(key, target_cfg)); // Note that we may have multiple matching `[target]` sections and // because we're passing flags to the compiler this can affect diff --git a/src/cargo/core/compiler/context/unit_dependencies.rs b/src/cargo/core/compiler/context/unit_dependencies.rs index afc819df21f..6c4d72976bd 100644 --- a/src/cargo/core/compiler/context/unit_dependencies.rs +++ b/src/cargo/core/compiler/context/unit_dependencies.rs @@ -18,12 +18,12 @@ use std::cell::RefCell; use std::collections::{HashMap, HashSet}; -use CargoResult; +use super::{BuildContext, CompileMode, Kind, Unit}; use core::dependency::Kind as DepKind; -use core::profiles::UnitFor; -use core::{Package, Target, PackageId}; use core::package::Downloads; -use super::{BuildContext, CompileMode, Kind, Unit}; +use core::profiles::UnitFor; +use core::{Package, PackageId, Target}; +use CargoResult; struct State<'a: 'tmp, 'cfg: 'a, 'tmp> { bcx: &'tmp BuildContext<'a, 'cfg>, @@ -74,11 +74,11 @@ pub fn build_unit_dependencies<'a, 'cfg>( deps_of(unit, &mut state, unit_for)?; } - if state.waiting_on_download.len() > 0 { + if !state.waiting_on_download.is_empty() { state.finish_some_downloads()?; state.deps.clear(); } else { - break + break; } } trace!("ALL UNIT DEPENDENCIES {:#?}", state.deps); @@ -128,46 +128,43 @@ fn compute_deps<'a, 'cfg, 'tmp>( let bcx = state.bcx; let id = unit.pkg.package_id(); - let deps = bcx.resolve.deps(id) - .filter(|&(_id, deps)| { - assert!(!deps.is_empty()); - deps.iter().any(|dep| { - // If this target is a build command, then we only want build - // dependencies, otherwise we want everything *other than* build - // dependencies. - if unit.target.is_custom_build() != dep.is_build() { - return false; - } + let deps = bcx.resolve.deps(id).filter(|&(_id, deps)| { + assert!(!deps.is_empty()); + deps.iter().any(|dep| { + // If this target is a build command, then we only want build + // dependencies, otherwise we want everything *other than* build + // dependencies. + if unit.target.is_custom_build() != dep.is_build() { + return false; + } - // If this dependency is *not* a transitive dependency, then it - // only applies to test/example targets - if !dep.is_transitive() && - !unit.target.is_test() && - !unit.target.is_example() && - !unit.mode.is_any_test() - { - return false; - } + // If this dependency is *not* a transitive dependency, then it + // only applies to test/example targets + if !dep.is_transitive() + && !unit.target.is_test() + && !unit.target.is_example() + && !unit.mode.is_any_test() + { + return false; + } - // If this dependency is only available for certain platforms, - // make sure we're only enabling it for that platform. - if !bcx.dep_platform_activated(dep, unit.kind) { - return false; - } + // If this dependency is only available for certain platforms, + // make sure we're only enabling it for that platform. + if !bcx.dep_platform_activated(dep, unit.kind) { + return false; + } - // If the dependency is optional, then we're only activating it - // if the corresponding feature was activated - if dep.is_optional() && - !bcx.resolve.features(id).contains(&*dep.name_in_toml()) - { - return false; - } + // If the dependency is optional, then we're only activating it + // if the corresponding feature was activated + if dep.is_optional() && !bcx.resolve.features(id).contains(&*dep.name_in_toml()) { + return false; + } - // If we've gotten past all that, then this dependency is - // actually used! - true - }) - }); + // If we've gotten past all that, then this dependency is + // actually used! + true + }) + }); let mut ret = Vec::new(); for (id, _) in deps { @@ -181,14 +178,7 @@ fn compute_deps<'a, 'cfg, 'tmp>( }; let mode = check_or_build_mode(unit.mode, lib); let dep_unit_for = unit_for.with_for_host(lib.for_host()); - let unit = new_unit( - bcx, - pkg, - lib, - dep_unit_for, - unit.kind.for_target(lib), - mode, - ); + let unit = new_unit(bcx, pkg, lib, dep_unit_for, unit.kind.for_target(lib), mode); ret.push((unit, dep_unit_for)); } @@ -211,7 +201,8 @@ fn compute_deps<'a, 'cfg, 'tmp>( // If any integration tests/benches are being run, make sure that // binaries are built as well. - if !unit.mode.is_check() && unit.mode.is_any_test() + if !unit.mode.is_check() + && unit.mode.is_any_test() && (unit.target.is_test() || unit.target.is_bench()) { ret.extend( @@ -282,7 +273,8 @@ fn compute_deps_doc<'a, 'cfg, 'tmp>( state: &mut State<'a, 'cfg, 'tmp>, ) -> CargoResult, UnitFor)>> { let bcx = state.bcx; - let deps = bcx.resolve + let deps = bcx + .resolve .deps(unit.pkg.package_id()) .filter(|&(_id, deps)| { deps.iter().any(|dep| match dep.kind() { @@ -308,14 +300,7 @@ fn compute_deps_doc<'a, 'cfg, 'tmp>( // However, for plugins/proc-macros, deps should be built like normal. let mode = check_or_build_mode(unit.mode, lib); let dep_unit_for = UnitFor::new_normal().with_for_host(lib.for_host()); - let lib_unit = new_unit( - bcx, - dep, - lib, - dep_unit_for, - unit.kind.for_target(lib), - mode, - ); + let lib_unit = new_unit(bcx, dep, lib, dep_unit_for, unit.kind.for_target(lib), mode); ret.push((lib_unit, dep_unit_for)); if let CompileMode::Doc { deps: true } = unit.mode { // Document this lib as well. @@ -348,14 +333,7 @@ fn maybe_lib<'a>( ) -> Option<(Unit<'a>, UnitFor)> { unit.pkg.targets().iter().find(|t| t.linkable()).map(|t| { let mode = check_or_build_mode(unit.mode, t); - let unit = new_unit( - bcx, - unit.pkg, - t, - unit_for, - unit.kind.for_target(t), - mode, - ); + let unit = new_unit(bcx, unit.pkg, t, unit_for, unit.kind.for_target(t), mode); (unit, unit_for) }) } @@ -453,7 +431,8 @@ fn connect_run_custom_build_deps(state: &mut State) { for (unit, deps) in state.deps.iter() { for dep in deps { if dep.mode == CompileMode::RunCustomBuild { - reverse_deps.entry(dep) + reverse_deps + .entry(dep) .or_insert_with(HashSet::new) .insert(unit); } @@ -469,7 +448,11 @@ fn connect_run_custom_build_deps(state: &mut State) { // `links`, then we depend on that package's build script! Here we use // `dep_build_script` to manufacture an appropriate build script unit to // depend on. - for unit in state.deps.keys().filter(|k| k.mode == CompileMode::RunCustomBuild) { + for unit in state + .deps + .keys() + .filter(|k| k.mode == CompileMode::RunCustomBuild) + { let reverse_deps = match reverse_deps.get(unit) { Some(set) => set, None => continue, @@ -479,9 +462,9 @@ fn connect_run_custom_build_deps(state: &mut State) { .iter() .flat_map(|reverse_dep| state.deps[reverse_dep].iter()) .filter(|other| { - other.pkg != unit.pkg && - other.target.linkable() && - other.pkg.manifest().links().is_some() + other.pkg != unit.pkg + && other.target.linkable() + && other.pkg.manifest().links().is_some() }) .filter_map(|other| dep_build_script(other, state.bcx).map(|p| p.0)) .collect::>(); @@ -502,15 +485,15 @@ impl<'a, 'cfg, 'tmp> State<'a, 'cfg, 'tmp> { fn get(&mut self, id: &'a PackageId) -> CargoResult> { let mut pkgs = self.pkgs.borrow_mut(); if let Some(pkg) = pkgs.get(id) { - return Ok(Some(pkg)) + return Ok(Some(pkg)); } if !self.waiting_on_download.insert(id) { - return Ok(None) + return Ok(None); } if let Some(pkg) = self.downloads.start(id)? { pkgs.insert(id, pkg); self.waiting_on_download.remove(id); - return Ok(Some(pkg)) + return Ok(Some(pkg)); } Ok(None) } @@ -535,7 +518,7 @@ impl<'a, 'cfg, 'tmp> State<'a, 'cfg, 'tmp> { // less than this let's recompute the whole unit dependency graph // again and try to find some more packages to download. if self.downloads.remaining() < 5 { - break + break; } } Ok(()) diff --git a/src/cargo/core/compiler/job_queue.rs b/src/cargo/core/compiler/job_queue.rs index 806412bcda0..687f74d3ebf 100644 --- a/src/cargo/core/compiler/job_queue.rs +++ b/src/cargo/core/compiler/job_queue.rs @@ -3,9 +3,9 @@ use std::collections::HashSet; use std::fmt; use std::io; use std::mem; +use std::process::Output; use std::sync::mpsc::{channel, Receiver, Sender}; use std::sync::Arc; -use std::process::Output; use crossbeam_utils; use crossbeam_utils::thread::Scope; @@ -15,14 +15,14 @@ use core::profiles::Profile; use core::{PackageId, Target, TargetKind}; use handle_error; use util; +use util::diagnostic_server::{self, DiagnosticPrinter}; use util::{internal, profile, CargoResult, CargoResultExt, ProcessBuilder}; use util::{Config, DependencyQueue, Dirty, Fresh, Freshness}; use util::{Progress, ProgressStyle}; -use util::diagnostic_server::{self, DiagnosticPrinter}; +use super::context::OutputFile; use super::job::Job; use super::{BuildContext, BuildPlan, CompileMode, Context, Kind, Unit}; -use super::context::OutputFile; /// A management structure of the entire dependency graph to compile. /// @@ -105,7 +105,8 @@ impl<'a> JobState<'a> { cmd: ProcessBuilder, filenames: Arc>, ) { - let _ = self.tx + let _ = self + .tx .send(Message::BuildPlanMsg(module_name, cmd, filenames)); } @@ -115,7 +116,7 @@ impl<'a> JobState<'a> { prefix: Option, capture_output: bool, ) -> CargoResult { - let prefix = prefix.unwrap_or_else(|| String::new()); + let prefix = prefix.unwrap_or_else(String::new); cmd.exec_with_streaming( &mut |out| { let _ = self.tx.send(Message::Stdout(format!("{}{}", prefix, out))); @@ -187,23 +188,23 @@ impl<'a> JobQueue<'a> { let tx = self.tx.clone(); let tx = unsafe { mem::transmute::>, Sender>>(tx) }; let tx2 = tx.clone(); - let helper = cx.jobserver + let helper = cx + .jobserver .clone() .into_helper_thread(move |token| { drop(tx.send(Message::Token(token))); }) .chain_err(|| "failed to create helper thread for jobserver management")?; - let _diagnostic_server = cx.bcx.build_config + let _diagnostic_server = cx + .bcx + .build_config .rustfix_diagnostic_server .borrow_mut() .take() - .map(move |srv| { - srv.start(move |msg| drop(tx2.send(Message::FixDiagnostic(msg)))) - }); + .map(move |srv| srv.start(move |msg| drop(tx2.send(Message::FixDiagnostic(msg))))); - crossbeam_utils::thread::scope(|scope| { - self.drain_the_queue(cx, plan, scope, &helper) - }).expect("child threads should't panic") + crossbeam_utils::thread::scope(|scope| self.drain_the_queue(cx, plan, scope, &helper)) + .expect("child threads should't panic") } fn drain_the_queue( @@ -276,7 +277,9 @@ impl<'a> JobQueue<'a> { tokens.truncate(self.active.len() - 1); let count = total - self.queue.len(); - let active_names = self.active.iter() + let active_names = self + .active + .iter() .map(Key::name_for_progress) .collect::>(); drop(progress.tick_now(count, total, &format!(": {}", active_names.join(", ")))); @@ -299,7 +302,7 @@ impl<'a> JobQueue<'a> { Message::Stderr(err) => { let mut shell = cx.bcx.config.shell(); shell.print_ansi(err.as_bytes())?; - shell.err().write(b"\n")?; + shell.err().write_all(b"\n")?; } Message::FixDiagnostic(msg) => { print.print(&msg)?; diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 0041c449bef..bb85567bdfd 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -530,7 +530,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { // first crate finishes downloading so we inform immediately that we're // downloading crates here. if self.downloads_finished == 0 - && self.pending.len() == 0 + && self.pending.is_empty() && !self.progress.borrow().as_ref().unwrap().is_enabled() { self.set diff --git a/src/cargo/core/resolver/mod.rs b/src/cargo/core/resolver/mod.rs index 961c9bd666f..9b22202608b 100644 --- a/src/cargo/core/resolver/mod.rs +++ b/src/cargo/core/resolver/mod.rs @@ -802,20 +802,19 @@ fn find_candidate( // active in this back up we know that we're guaranteed to not actually // make any progress. As a result if we hit this condition we can // completely skip this backtrack frame and move on to the next. - if !backtracked { - if frame + if !backtracked + && frame .context .is_conflicting(Some(parent.package_id()), conflicting_activations) - { - trace!( - "{} = \"{}\" skip as not solving {}: {:?}", - frame.dep.package_name(), - frame.dep.version_req(), - parent.package_id(), - conflicting_activations - ); - continue; - } + { + trace!( + "{} = \"{}\" skip as not solving {}: {:?}", + frame.dep.package_name(), + frame.dep.version_req(), + parent.package_id(), + conflicting_activations + ); + continue; } return Some((candidate, has_another, frame)); diff --git a/src/cargo/core/shell.rs b/src/cargo/core/shell.rs index 023a87e6562..cda5a2dceb2 100644 --- a/src/cargo/core/shell.rs +++ b/src/cargo/core/shell.rs @@ -28,10 +28,12 @@ pub struct Shell { impl fmt::Debug for Shell { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.err { - ShellOut::Write(_) => f.debug_struct("Shell") + ShellOut::Write(_) => f + .debug_struct("Shell") .field("verbosity", &self.verbosity) .finish(), - ShellOut::Stream { color_choice, .. } => f.debug_struct("Shell") + ShellOut::Stream { color_choice, .. } => f + .debug_struct("Shell") .field("verbosity", &self.verbosity) .field("color_choice", &color_choice) .finish(), @@ -376,13 +378,13 @@ mod imp { mod imp { extern crate winapi; - use std::{cmp, mem, ptr}; use self::winapi::um::fileapi::*; use self::winapi::um::handleapi::*; use self::winapi::um::processenv::*; use self::winapi::um::winbase::*; use self::winapi::um::wincon::*; use self::winapi::um::winnt::*; + use std::{cmp, mem, ptr}; pub(super) use super::default_err_erase_line as err_erase_line; @@ -391,19 +393,20 @@ mod imp { let stdout = GetStdHandle(STD_ERROR_HANDLE); let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed(); if GetConsoleScreenBufferInfo(stdout, &mut csbi) != 0 { - return Some((csbi.srWindow.Right - csbi.srWindow.Left) as usize) + return Some((csbi.srWindow.Right - csbi.srWindow.Left) as usize); } // On mintty/msys/cygwin based terminals, the above fails with // INVALID_HANDLE_VALUE. Use an alternate method which works // in that case as well. - let h = CreateFileA("CONOUT$\0".as_ptr() as *const CHAR, + let h = CreateFileA( + "CONOUT$\0".as_ptr() as *const CHAR, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, ptr::null_mut(), OPEN_EXISTING, 0, - ptr::null_mut() + ptr::null_mut(), ); if h == INVALID_HANDLE_VALUE { return None; @@ -424,15 +427,12 @@ mod imp { // GetConsoleScreenBufferInfo returns accurate information. return Some(cmp::min(60, width)); } - return None; + None } } } -#[cfg(any( - all(unix, not(any(target_os = "linux", target_os = "macos"))), - windows, -))] +#[cfg(any(all(unix, not(any(target_os = "linux", target_os = "macos"))), windows,))] fn default_err_erase_line(shell: &mut Shell) { if let Some(max_width) = imp::stderr_width() { let blank = " ".repeat(max_width); diff --git a/src/cargo/ops/fix.rs b/src/cargo/ops/fix.rs index 2c1a9cf445a..734ed54456c 100644 --- a/src/cargo/ops/fix.rs +++ b/src/cargo/ops/fix.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet, BTreeSet}; +use std::collections::{BTreeSet, HashMap, HashSet}; use std::env; use std::ffi::OsString; use std::fs; @@ -14,10 +14,10 @@ use serde_json; use core::Workspace; use ops::{self, CompileOptions}; -use util::errors::CargoResult; -use util::{LockServer, LockServerClient, existing_vcs_repo}; use util::diagnostic_server::{Message, RustfixDiagnosticServer}; +use util::errors::CargoResult; use util::paths; +use util::{existing_vcs_repo, LockServer, LockServerClient}; const FIX_ENV: &str = "__CARGO_FIX_PLZ"; const BROKEN_CODE_ENV: &str = "__CARGO_FIX_BROKEN_CODE"; @@ -43,37 +43,46 @@ pub fn fix(ws: &Workspace, opts: &mut FixOptions) -> CargoResult<()> { // Spin up our lock server which our subprocesses will use to synchronize // fixes. let lock_server = LockServer::new()?; - opts.compile_opts.build_config.extra_rustc_env.push(( - FIX_ENV.to_string(), - lock_server.addr().to_string(), - )); + opts.compile_opts + .build_config + .extra_rustc_env + .push((FIX_ENV.to_string(), lock_server.addr().to_string())); let _started = lock_server.start()?; opts.compile_opts.build_config.force_rebuild = true; if opts.broken_code { let key = BROKEN_CODE_ENV.to_string(); - opts.compile_opts.build_config.extra_rustc_env.push((key, "1".to_string())); + opts.compile_opts + .build_config + .extra_rustc_env + .push((key, "1".to_string())); } if opts.edition { let key = EDITION_ENV.to_string(); - opts.compile_opts.build_config.extra_rustc_env.push((key, "1".to_string())); + opts.compile_opts + .build_config + .extra_rustc_env + .push((key, "1".to_string())); } else if let Some(edition) = opts.prepare_for { - opts.compile_opts.build_config.extra_rustc_env.push(( - PREPARE_FOR_ENV.to_string(), - edition.to_string(), - )); + opts.compile_opts + .build_config + .extra_rustc_env + .push((PREPARE_FOR_ENV.to_string(), edition.to_string())); } if opts.idioms { - opts.compile_opts.build_config.extra_rustc_env.push(( - IDIOMS_ENV.to_string(), - "1".to_string(), - )); + opts.compile_opts + .build_config + .extra_rustc_env + .push((IDIOMS_ENV.to_string(), "1".to_string())); } opts.compile_opts.build_config.cargo_as_rustc_wrapper = true; - *opts.compile_opts.build_config.rustfix_diagnostic_server.borrow_mut() = - Some(RustfixDiagnosticServer::new()?); + *opts + .compile_opts + .build_config + .rustfix_diagnostic_server + .borrow_mut() = Some(RustfixDiagnosticServer::new()?); ops::compile(ws, &opts.compile_opts)?; Ok(()) @@ -81,17 +90,19 @@ pub fn fix(ws: &Workspace, opts: &mut FixOptions) -> CargoResult<()> { fn check_version_control(opts: &FixOptions) -> CargoResult<()> { if opts.allow_no_vcs { - return Ok(()) + return Ok(()); } let config = opts.compile_opts.config; if !existing_vcs_repo(config.cwd(), config.cwd()) { - bail!("no VCS found for this package and `cargo fix` can potentially \ - perform destructive changes; if you'd like to suppress this \ - error pass `--allow-no-vcs`") + bail!( + "no VCS found for this package and `cargo fix` can potentially \ + perform destructive changes; if you'd like to suppress this \ + error pass `--allow-no-vcs`" + ) } if opts.allow_dirty && opts.allow_staged { - return Ok(()) + return Ok(()); } let mut dirty_files = Vec::new(); @@ -103,26 +114,27 @@ fn check_version_control(opts: &FixOptions) -> CargoResult<()> { if let Some(path) = status.path() { match status.status() { git2::Status::CURRENT => (), - git2::Status::INDEX_NEW | - git2::Status::INDEX_MODIFIED | - git2::Status::INDEX_DELETED | - git2::Status::INDEX_RENAMED | - git2::Status::INDEX_TYPECHANGE => + git2::Status::INDEX_NEW + | git2::Status::INDEX_MODIFIED + | git2::Status::INDEX_DELETED + | git2::Status::INDEX_RENAMED + | git2::Status::INDEX_TYPECHANGE => { if !opts.allow_staged { staged_files.push(path.to_string()) - }, - _ => + } + } + _ => { if !opts.allow_dirty { dirty_files.push(path.to_string()) - }, + } + } }; } - } } if dirty_files.is_empty() && staged_files.is_empty() { - return Ok(()) + return Ok(()); } let mut files_list = String::new(); @@ -137,13 +149,16 @@ fn check_version_control(opts: &FixOptions) -> CargoResult<()> { files_list.push_str(" (staged)\n"); } - bail!("the working directory of this package has uncommitted changes, and \ - `cargo fix` can potentially perform destructive changes; if you'd \ - like to suppress this error pass `--allow-dirty`, `--allow-staged`, \ - or commit the changes to these files:\n\ - \n\ - {}\n\ - ", files_list); + bail!( + "the working directory of this package has uncommitted changes, and \ + `cargo fix` can potentially perform destructive changes; if you'd \ + like to suppress this error pass `--allow-dirty`, `--allow-staged`, \ + or commit the changes to these files:\n\ + \n\ + {}\n\ + ", + files_list + ); } pub fn fix_maybe_exec_rustc() -> CargoResult { @@ -190,7 +205,8 @@ pub fn fix_maybe_exec_rustc() -> CargoResult { Message::Fixing { file: path.clone(), fixes: file.fixes_applied, - }.post()?; + } + .post()?; } } @@ -231,9 +247,12 @@ struct FixedFile { original_code: String, } -fn rustfix_crate(lock_addr: &str, rustc: &Path, filename: &Path, args: &FixArgs) - -> Result -{ +fn rustfix_crate( + lock_addr: &str, + rustc: &Path, + filename: &Path, + args: &FixArgs, +) -> Result { args.verify_not_preparing_for_enabled_edition()?; // First up we want to make sure that each crate is only checked by one @@ -293,7 +312,7 @@ fn rustfix_crate(lock_addr: &str, rustc: &Path, filename: &Path, args: &FixArgs) let mut progress_yet_to_be_made = false; for (path, file) in fixes.files.iter_mut() { if file.errors_applying_fixes.is_empty() { - continue + continue; } // If anything was successfully fixed *and* there's at least one // error, then assume the error was spurious and we'll try again on @@ -303,7 +322,7 @@ fn rustfix_crate(lock_addr: &str, rustc: &Path, filename: &Path, args: &FixArgs) } } if !progress_yet_to_be_made { - break + break; } } @@ -314,7 +333,8 @@ fn rustfix_crate(lock_addr: &str, rustc: &Path, filename: &Path, args: &FixArgs) Message::ReplaceFailed { file: path.clone(), message: error, - }.post()?; + } + .post()?; } } @@ -325,9 +345,12 @@ fn rustfix_crate(lock_addr: &str, rustc: &Path, filename: &Path, args: &FixArgs) /// /// This will fill in the `fixes` map with original code, suggestions applied, /// and any errors encountered while fixing files. -fn rustfix_and_fix(fixes: &mut FixedCrate, rustc: &Path, filename: &Path, args: &FixArgs) - -> Result<(), Error> -{ +fn rustfix_and_fix( + fixes: &mut FixedCrate, + rustc: &Path, + filename: &Path, + args: &FixArgs, +) -> Result<(), Error> { // If not empty, filter by these lints // // TODO: Implement a way to specify this @@ -336,7 +359,8 @@ fn rustfix_and_fix(fixes: &mut FixedCrate, rustc: &Path, filename: &Path, args: let mut cmd = Command::new(rustc); cmd.arg("--error-format=json"); args.apply(&mut cmd); - let output = cmd.output() + let output = cmd + .output() .with_context(|_| format!("failed to execute `{}`", rustc.display()))?; // If rustc didn't succeed for whatever reasons then we're very likely to be @@ -361,13 +385,12 @@ fn rustfix_and_fix(fixes: &mut FixedCrate, rustc: &Path, filename: &Path, args: // indicating fixes that we can apply. let stderr = str::from_utf8(&output.stderr).context("failed to parse rustc stderr as utf-8")?; - let suggestions = stderr.lines() + let suggestions = stderr + .lines() .filter(|x| !x.is_empty()) .inspect(|y| trace!("line: {}", y)) - // Parse each line of stderr ignoring errors as they may not all be json .filter_map(|line| serde_json::from_str::(line).ok()) - // From each diagnostic try to extract suggestions from rustc .filter_map(|diag| rustfix::collect_suggestions(&diag, &only, fix_mode)); @@ -426,13 +449,13 @@ fn rustfix_and_fix(fixes: &mut FixedCrate, rustc: &Path, filename: &Path, args: // code, so save it. If the file already exists then the original code // doesn't need to be updated as we've just read an interim state with // some fixes but perhaps not all. - let fixed_file = fixes.files.entry(file.clone()) - .or_insert_with(|| { - FixedFile { - errors_applying_fixes: Vec::new(), - fixes_applied: 0, - original_code: code.clone(), - } + let fixed_file = fixes + .files + .entry(file.clone()) + .or_insert_with(|| FixedFile { + errors_applying_fixes: Vec::new(), + fixes_applied: 0, + original_code: code.clone(), }); let mut fixed = CodeFix::new(&code); @@ -446,8 +469,7 @@ fn rustfix_and_fix(fixes: &mut FixedCrate, rustc: &Path, filename: &Path, args: } } let new_code = fixed.finish()?; - fs::write(&file, new_code) - .with_context(|_| format!("failed to write file `{}`", file))?; + fs::write(&file, new_code).with_context(|_| format!("failed to write file `{}`", file))?; } Ok(()) @@ -525,17 +547,15 @@ impl FixArgs { let mut ret = FixArgs::default(); for arg in env::args_os().skip(1) { let path = PathBuf::from(arg); - if path.extension().and_then(|s| s.to_str()) == Some("rs") { - if path.exists() { - ret.file = Some(path); - continue - } + if path.extension().and_then(|s| s.to_str()) == Some("rs") && path.exists() { + ret.file = Some(path); + continue; } if let Some(s) = path.to_str() { let prefix = "--edition="; if s.starts_with(prefix) { ret.enabled_edition = Some(s[prefix.len()..].to_string()); - continue + continue; } } ret.other.push(path.into()); @@ -554,12 +574,11 @@ impl FixArgs { if let Some(path) = &self.file { cmd.arg(path); } - cmd.args(&self.other) - .arg("--cap-lints=warn"); + cmd.args(&self.other).arg("--cap-lints=warn"); if let Some(edition) = &self.enabled_edition { cmd.arg("--edition").arg(edition); - if self.idioms && self.primary_package { - if edition == "2018" { cmd.arg("-Wrust-2018-idioms"); } + if self.idioms && self.primary_package && edition == "2018" { + cmd.arg("-Wrust-2018-idioms"); } } if self.primary_package { @@ -586,7 +605,7 @@ impl FixArgs { None => return Ok(()), }; if edition != enabled { - return Ok(()) + return Ok(()); } let path = match &self.file { Some(s) => s, @@ -596,7 +615,8 @@ impl FixArgs { Message::EditionAlreadyEnabled { file: path.display().to_string(), edition: edition.to_string(), - }.post()?; + } + .post()?; process::exit(1); } diff --git a/src/cargo/util/lev_distance.rs b/src/cargo/util/lev_distance.rs index c4a7e9856bf..034fb728788 100644 --- a/src/cargo/util/lev_distance.rs +++ b/src/cargo/util/lev_distance.rs @@ -8,7 +8,7 @@ pub fn lev_distance(me: &str, t: &str) -> usize { return me.chars().count(); } - let mut dcol = (0..t.len() + 1).collect::>(); + let mut dcol = (0..=t.len()).collect::>(); let mut t_last = 0; for (i, sc) in me.chars().enumerate() { diff --git a/src/cargo/util/read2.rs b/src/cargo/util/read2.rs index 13a50a724ba..74ec2cc114a 100644 --- a/src/cargo/util/read2.rs +++ b/src/cargo/util/read2.rs @@ -2,12 +2,12 @@ pub use self::imp::read2; #[cfg(unix)] mod imp { - use std::io::prelude::*; + use libc; use std::io; + use std::io::prelude::*; use std::mem; use std::os::unix::prelude::*; use std::process::{ChildStderr, ChildStdout}; - use libc; pub fn read2( mut out_pipe: ChildStdout, @@ -177,9 +177,6 @@ mod imp { if v.capacity() == v.len() { v.reserve(1); } - slice::from_raw_parts_mut( - v.as_mut_ptr().offset(v.len() as isize), - v.capacity() - v.len(), - ) + slice::from_raw_parts_mut(v.as_mut_ptr().add(v.len()), v.capacity() - v.len()) } } From 5ddc8b13388b108512ea7981ad597b23ff1fb7a8 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 25 Nov 2018 14:16:49 +0000 Subject: [PATCH 097/128] Test PackageId Debug & Display --- src/cargo/core/package_id.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/cargo/core/package_id.rs b/src/cargo/core/package_id.rs index 0be2cd9e40d..ae7279291f3 100644 --- a/src/cargo/core/package_id.rs +++ b/src/cargo/core/package_id.rs @@ -195,4 +195,27 @@ mod tests { assert!(PackageId::new("foo", "bar", repo).is_err()); assert!(PackageId::new("foo", "", repo).is_err()); } + + #[test] + fn debug() { + let loc = CRATES_IO_INDEX.to_url().unwrap(); + let pkg_id = PackageId::new("foo", "1.0.0", SourceId::for_registry(&loc).unwrap()).unwrap(); + assert_eq!(r#"PackageId { name: "foo", version: "1.0.0", source: "registry `https://github.com/rust-lang/crates.io-index`" }"#, format!("{:?}", pkg_id)); + + let pretty = r#" +PackageId { + name: "foo", + version: "1.0.0", + source: "registry `https://github.com/rust-lang/crates.io-index`" +} +"#.trim(); + assert_eq!(pretty, format!("{:#?}", pkg_id)); + } + + #[test] + fn display() { + let loc = CRATES_IO_INDEX.to_url().unwrap(); + let pkg_id = PackageId::new("foo", "1.0.0", SourceId::for_registry(&loc).unwrap()).unwrap(); + assert_eq!("foo v1.0.0", pkg_id.to_string()); + } } From 2e35475121aaf00b11220f93d7a1c8a2cb70ea24 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 26 Nov 2018 10:50:26 +0000 Subject: [PATCH 098/128] Add debug info to git::two_deps_only_update_one test --- tests/testsuite/git.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/testsuite/git.rs b/tests/testsuite/git.rs index ea89a964bdc..027f5ec77e9 100644 --- a/tests/testsuite/git.rs +++ b/tests/testsuite/git.rs @@ -11,6 +11,7 @@ use std::thread; use support::paths::{self, CargoPathExt}; use support::sleep_ms; use support::{basic_lib_manifest, basic_manifest, git, main_file, path2url, project}; +use support::Project; #[test] fn cargo_compile_simple_git_dep() { @@ -1090,6 +1091,18 @@ fn two_deps_only_update_one() { ).file("src/main.rs", "fn main() {}") .build(); + fn oid_to_short_sha(oid: git2::Oid) -> String { + oid.to_string()[..8].to_string() + } + fn git_repo_head_sha(p: &Project) -> String { + let repo = git2::Repository::open(p.root()).unwrap(); + let head = repo.head().unwrap().target().unwrap(); + oid_to_short_sha(head) + } + + println!("dep1 head sha: {}", git_repo_head_sha(&git1)); + println!("dep2 head sha: {}", git_repo_head_sha(&git2)); + p.cargo("build") .with_stderr( "[UPDATING] git repository `[..]`\n\ @@ -1106,7 +1119,8 @@ fn two_deps_only_update_one() { .unwrap(); let repo = git2::Repository::open(&git1.root()).unwrap(); git::add(&repo); - git::commit(&repo); + let oid = git::commit(&repo); + println!("dep1 head sha: {}", oid_to_short_sha(oid)); p.cargo("update -p dep1") .with_stderr(&format!( From 0593e1c1670f1e38ade8f7358e7435a1f3bda66f Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 18 Nov 2018 21:03:55 +0000 Subject: [PATCH 099/128] Intern PackageId --- src/cargo/core/package_id.rs | 100 ++++++++++++++++------------- src/cargo/core/source/source_id.rs | 8 +++ 2 files changed, 62 insertions(+), 46 deletions(-) diff --git a/src/cargo/core/package_id.rs b/src/cargo/core/package_id.rs index ae7279291f3..4120f6779cc 100644 --- a/src/cargo/core/package_id.rs +++ b/src/cargo/core/package_id.rs @@ -1,9 +1,9 @@ -use std::cmp::Ordering; +use std::collections::HashSet; use std::fmt::{self, Formatter}; use std::hash; use std::hash::Hash; use std::path::Path; -use std::sync::Arc; +use std::sync::Mutex; use semver; use serde::de; @@ -13,19 +13,41 @@ use core::interning::InternedString; use core::source::SourceId; use util::{CargoResult, ToSemver}; +lazy_static! { + static ref PACKAGE_ID_CACHE: Mutex> = Mutex::new(HashSet::new()); +} + /// Identifier for a specific version of a package in a specific source. -#[derive(Clone)] +#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct PackageId { - inner: Arc, + inner: &'static PackageIdInner, } -#[derive(PartialEq, PartialOrd, Eq, Ord)] +#[derive(PartialOrd, Eq, Ord)] struct PackageIdInner { name: InternedString, version: semver::Version, source_id: SourceId, } +// Custom equality that uses full equality of SourceId, rather than its custom equality. +impl PartialEq for PackageIdInner { + fn eq(&self, other: &Self) -> bool { + self.name == other.name + && self.version == other.version + && self.source_id.full_eq(&other.source_id) + } +} + +// Custom hash that is coherent with the custom equality above. +impl Hash for PackageIdInner { + fn hash(&self, into: &mut S) { + self.name.hash(into); + self.version.hash(into); + self.source_id.full_hash(into); + } +} + impl ser::Serialize for PackageId { fn serialize(&self, s: S) -> Result where @@ -64,51 +86,37 @@ impl<'de> de::Deserialize<'de> for PackageId { }; let source_id = SourceId::from_url(url).map_err(de::Error::custom)?; - Ok(PackageId { - inner: Arc::new(PackageIdInner { + Ok(PackageId::wrap( + PackageIdInner { name: InternedString::new(name), version, source_id, - }), - }) - } -} - -impl Hash for PackageId { - fn hash(&self, state: &mut S) { - self.inner.name.hash(state); - self.inner.version.hash(state); - self.inner.source_id.hash(state); - } -} - -impl PartialEq for PackageId { - fn eq(&self, other: &PackageId) -> bool { - (*self.inner).eq(&*other.inner) - } -} -impl PartialOrd for PackageId { - fn partial_cmp(&self, other: &PackageId) -> Option { - (*self.inner).partial_cmp(&*other.inner) - } -} -impl Eq for PackageId {} -impl Ord for PackageId { - fn cmp(&self, other: &PackageId) -> Ordering { - (*self.inner).cmp(&*other.inner) + } + )) } } impl PackageId { pub fn new(name: &str, version: T, sid: SourceId) -> CargoResult { let v = version.to_semver()?; - Ok(PackageId { - inner: Arc::new(PackageIdInner { + + Ok(PackageId::wrap( + PackageIdInner { name: InternedString::new(name), version: v, source_id: sid, - }), - }) + } + )) + } + + fn wrap(inner: PackageIdInner) -> PackageId { + let mut cache = PACKAGE_ID_CACHE.lock().unwrap(); + let inner = cache.get(&inner).map(|&x| x).unwrap_or_else(|| { + let inner = Box::leak(Box::new(inner)); + cache.insert(inner); + inner + }); + PackageId { inner } } pub fn name(&self) -> InternedString { @@ -122,23 +130,23 @@ impl PackageId { } pub fn with_precise(&self, precise: Option) -> PackageId { - PackageId { - inner: Arc::new(PackageIdInner { + PackageId::wrap( + PackageIdInner { name: self.inner.name, version: self.inner.version.clone(), source_id: self.inner.source_id.with_precise(precise), - }), - } + } + ) } pub fn with_source_id(&self, source: SourceId) -> PackageId { - PackageId { - inner: Arc::new(PackageIdInner { + PackageId::wrap( + PackageIdInner { name: self.inner.name, version: self.inner.version.clone(), source_id: source, - }), - } + } + ) } pub fn stable_hash<'a>(&'a self, workspace: &'a Path) -> PackageIdStableHash<'a> { diff --git a/src/cargo/core/source/source_id.rs b/src/cargo/core/source/source_id.rs index ea29d39c863..c65ba4e63cd 100644 --- a/src/cargo/core/source/source_id.rs +++ b/src/cargo/core/source/source_id.rs @@ -335,6 +335,14 @@ impl SourceId { } self.hash(into) } + + pub fn full_eq(&self, other: &SourceId) -> bool { + self.inner == other.inner + } + + pub fn full_hash(&self, into: &mut S) { + self.inner.hash(into) + } } impl PartialOrd for SourceId { From 0abfcc0dd4515fe4add913a36f5c4adc3dcba42b Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 25 Nov 2018 14:18:36 +0000 Subject: [PATCH 100/128] Make PackageId derive Copy --- src/cargo/core/package_id.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cargo/core/package_id.rs b/src/cargo/core/package_id.rs index 4120f6779cc..7231c137251 100644 --- a/src/cargo/core/package_id.rs +++ b/src/cargo/core/package_id.rs @@ -18,7 +18,7 @@ lazy_static! { } /// Identifier for a specific version of a package in a specific source. -#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct PackageId { inner: &'static PackageIdInner, } From a73c5171f8a55fa698b38014f62bacdfcab0dea0 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Sun, 25 Nov 2018 14:20:42 +0000 Subject: [PATCH 101/128] Add pointer equality to PartialEq for PackageId --- src/cargo/core/package_id.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/cargo/core/package_id.rs b/src/cargo/core/package_id.rs index 7231c137251..885d2c61caf 100644 --- a/src/cargo/core/package_id.rs +++ b/src/cargo/core/package_id.rs @@ -3,6 +3,7 @@ use std::fmt::{self, Formatter}; use std::hash; use std::hash::Hash; use std::path::Path; +use std::ptr; use std::sync::Mutex; use semver; @@ -18,7 +19,7 @@ lazy_static! { } /// Identifier for a specific version of a package in a specific source. -#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Clone, Copy, Eq, Hash, PartialOrd, Ord)] pub struct PackageId { inner: &'static PackageIdInner, } @@ -96,6 +97,15 @@ impl<'de> de::Deserialize<'de> for PackageId { } } +impl PartialEq for PackageId { + fn eq(&self, other: &PackageId) -> bool { + if ptr::eq(self.inner, other.inner) { + return true; + } + (*self.inner).eq(&*other.inner) + } +} + impl PackageId { pub fn new(name: &str, version: T, sid: SourceId) -> CargoResult { let v = version.to_semver()?; From 41f788aac209db28d8408a7347b9840f63c2097b Mon Sep 17 00:00:00 2001 From: David Laehnemann Date: Mon, 26 Nov 2018 12:51:19 +0100 Subject: [PATCH 102/128] docs: specify profile usage for cargo test --release --- src/doc/src/reference/manifest.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/src/reference/manifest.md b/src/doc/src/reference/manifest.md index 8a024baf8be..85e77afa9e0 100644 --- a/src/doc/src/reference/manifest.md +++ b/src/doc/src/reference/manifest.md @@ -341,7 +341,7 @@ incremental = true # whether or not incremental compilation is enabled overflow-checks = true # use overflow checks for integer arithmetic. # Passes the `-C overflow-checks=...` flag to the compiler. -# The release profile, used for `cargo build --release` and `cargo test --release`. +# The release profile, used for `cargo build --release` (and the dependencies for `cargo test --release`, including the local lib/bin). [profile.release] opt-level = 3 debug = false @@ -353,7 +353,7 @@ panic = 'unwind' incremental = false overflow-checks = false -# The testing profile, used for `cargo test`. +# The testing profile, used for `cargo test` (for `cargo test --release` see the `release` and `bench` profiles). [profile.test] opt-level = 0 debug = 2 @@ -365,7 +365,7 @@ panic = 'unwind' incremental = true overflow-checks = true -# The benchmarking profile, used for `cargo bench`. +# The benchmarking profile, used for `cargo bench` (and the test targets and unit tests for `cargo test --release`). [profile.bench] opt-level = 3 debug = false From c5d0c34bc719ef04e42bbef3c774423012fd4af3 Mon Sep 17 00:00:00 2001 From: Collins Abitekaniza Date: Mon, 26 Nov 2018 15:07:05 +0300 Subject: [PATCH 103/128] only clean release artifacts if --release option is set --- src/cargo/ops/cargo_clean.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/cargo/ops/cargo_clean.rs b/src/cargo/ops/cargo_clean.rs index 10308cd8920..0f0f0adea6d 100644 --- a/src/cargo/ops/cargo_clean.rs +++ b/src/cargo/ops/cargo_clean.rs @@ -24,14 +24,18 @@ pub struct CleanOptions<'a> { /// Cleans the package's build artifacts. pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> { - let target_dir = ws.target_dir(); + let mut target_dir = ws.target_dir(); let config = ws.config(); // If the doc option is set, we just want to delete the doc directory. if opts.doc { - let target_dir = target_dir.join("doc"); - let target_dir = target_dir.into_path_unlocked(); - return rm_rf(&target_dir, config); + target_dir = target_dir.join("doc"); + return rm_rf(&target_dir.into_path_unlocked(), config); + } + + // If the release option is set, we set target to release directory + if opts.release { + target_dir = target_dir.join("release"); } // If we have a spec, then we need to delete some packages, otherwise, just @@ -40,8 +44,7 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> { // Note that we don't bother grabbing a lock here as we're just going to // blow it all away anyway. if opts.spec.is_empty() { - let target_dir = target_dir.into_path_unlocked(); - return rm_rf(&target_dir, config); + return rm_rf(&target_dir.into_path_unlocked(), config); } let (packages, resolve) = ops::resolve_ws(ws)?; From 84be123f791a6392f5897723d8c943bf42613936 Mon Sep 17 00:00:00 2001 From: Collins Abitekaniza Date: Mon, 26 Nov 2018 17:40:50 +0300 Subject: [PATCH 104/128] test cargo clean with --release option --- tests/testsuite/clean.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/testsuite/clean.rs b/tests/testsuite/clean.rs index ea62d062b8a..9e03bd11655 100644 --- a/tests/testsuite/clean.rs +++ b/tests/testsuite/clean.rs @@ -117,6 +117,9 @@ fn clean_release() { [FINISHED] release [optimized] target(s) in [..] ", ).run(); + + p.cargo("clean").arg("--release").run(); + assert!(!p.build_dir().join("release").is_dir()); } #[test] From f61966403abdbbb142bcf9263a7a46ae196c5fef Mon Sep 17 00:00:00 2001 From: Collins Abitekaniza Date: Mon, 26 Nov 2018 18:12:11 +0300 Subject: [PATCH 105/128] assert for non-release artifacts --- tests/testsuite/clean.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/testsuite/clean.rs b/tests/testsuite/clean.rs index 9e03bd11655..dc2ac57c4df 100644 --- a/tests/testsuite/clean.rs +++ b/tests/testsuite/clean.rs @@ -118,7 +118,11 @@ fn clean_release() { ", ).run(); + p.cargo("build").run(); + p.cargo("clean").arg("--release").run(); + assert!(p.build_dir().is_dir()); + assert!(p.build_dir().join("debug").is_dir()); assert!(!p.build_dir().join("release").is_dir()); } From ea87ca3e981eb5b05ef69eb1b052e9bc5ae9e6aa Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 26 Nov 2018 17:32:27 +0000 Subject: [PATCH 106/128] Use pointer eq/hash for SourceIdInner --- src/cargo/core/source/source_id.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cargo/core/source/source_id.rs b/src/cargo/core/source/source_id.rs index c65ba4e63cd..120816b864a 100644 --- a/src/cargo/core/source/source_id.rs +++ b/src/cargo/core/source/source_id.rs @@ -337,11 +337,11 @@ impl SourceId { } pub fn full_eq(&self, other: &SourceId) -> bool { - self.inner == other.inner + ptr::eq(self.inner, other.inner) } pub fn full_hash(&self, into: &mut S) { - self.inner.hash(into) + (self.inner as *const SourceIdInner).hash(into) } } From e269936633bb095bea75978cf5440570c228e287 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 26 Nov 2018 17:32:47 +0000 Subject: [PATCH 107/128] Re-expose custom SourceId equality in outer PackageId --- src/cargo/core/package_id.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/cargo/core/package_id.rs b/src/cargo/core/package_id.rs index 885d2c61caf..2f9f9f21497 100644 --- a/src/cargo/core/package_id.rs +++ b/src/cargo/core/package_id.rs @@ -19,7 +19,7 @@ lazy_static! { } /// Identifier for a specific version of a package in a specific source. -#[derive(Clone, Copy, Eq, Hash, PartialOrd, Ord)] +#[derive(Clone, Copy, Eq, PartialOrd, Ord)] pub struct PackageId { inner: &'static PackageIdInner, } @@ -102,7 +102,17 @@ impl PartialEq for PackageId { if ptr::eq(self.inner, other.inner) { return true; } - (*self.inner).eq(&*other.inner) + self.inner.name == other.inner.name + && self.inner.version == other.inner.version + && self.inner.source_id == other.inner.source_id + } +} + +impl<'a> Hash for PackageId { + fn hash(&self, state: &mut S) { + self.inner.name.hash(state); + self.inner.version.hash(state); + self.inner.source_id.hash(state); } } From efd03bdecfa108d649a6e0acc266bcdcbd2690c5 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 26 Nov 2018 17:45:52 +0000 Subject: [PATCH 108/128] A nicer way to hash a pointer --- src/cargo/core/source/source_id.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cargo/core/source/source_id.rs b/src/cargo/core/source/source_id.rs index 120816b864a..8a5557e6ce1 100644 --- a/src/cargo/core/source/source_id.rs +++ b/src/cargo/core/source/source_id.rs @@ -341,7 +341,7 @@ impl SourceId { } pub fn full_hash(&self, into: &mut S) { - (self.inner as *const SourceIdInner).hash(into) + ptr::NonNull::from(self.inner).hash(into) } } From a472e7c46f6df06f86bc3032181386087a1bb8c7 Mon Sep 17 00:00:00 2001 From: David Laehnemann Date: Tue, 27 Nov 2018 10:22:24 +0100 Subject: [PATCH 109/128] docs: requested clarification and word wrap for profiles doc --- src/doc/src/reference/manifest.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/doc/src/reference/manifest.md b/src/doc/src/reference/manifest.md index 85e77afa9e0..a5b40dc2b42 100644 --- a/src/doc/src/reference/manifest.md +++ b/src/doc/src/reference/manifest.md @@ -341,7 +341,8 @@ incremental = true # whether or not incremental compilation is enabled overflow-checks = true # use overflow checks for integer arithmetic. # Passes the `-C overflow-checks=...` flag to the compiler. -# The release profile, used for `cargo build --release` (and the dependencies for `cargo test --release`, including the local lib/bin). +# The release profile, used for `cargo build --release` (and the dependencies +# for `cargo test --release`, including the local library or binary). [profile.release] opt-level = 3 debug = false @@ -353,7 +354,8 @@ panic = 'unwind' incremental = false overflow-checks = false -# The testing profile, used for `cargo test` (for `cargo test --release` see the `release` and `bench` profiles). +# The testing profile, used for `cargo test` (for `cargo test --release` see +# the `release` and `bench` profiles). [profile.test] opt-level = 0 debug = 2 @@ -365,7 +367,8 @@ panic = 'unwind' incremental = true overflow-checks = true -# The benchmarking profile, used for `cargo bench` (and the test targets and unit tests for `cargo test --release`). +# The benchmarking profile, used for `cargo bench` (and the test targets and +# unit tests for `cargo test --release`). [profile.bench] opt-level = 3 debug = false From b738f486a4eee5bea622a876b2a12b8e771774bf Mon Sep 17 00:00:00 2001 From: Collins Abitekaniza Date: Tue, 27 Nov 2018 16:24:51 +0300 Subject: [PATCH 110/128] improve description for cargo install --- src/bin/cargo/cli.rs | 2 +- src/bin/cargo/commands/install.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/cargo/cli.rs b/src/bin/cargo/cli.rs index ad1ddd85297..1d6af33cad2 100644 --- a/src/bin/cargo/cli.rs +++ b/src/bin/cargo/cli.rs @@ -206,7 +206,7 @@ Some common cargo commands are (see all commands with --list): update Update dependencies listed in Cargo.lock search Search registry for crates publish Package and upload this package to the registry - install Install a Rust binary + install Install a Rust binary. Default location is $HOME/.cargo/bin uninstall Uninstall a Rust binary See 'cargo help ' for more information on a specific command.\n", diff --git a/src/bin/cargo/commands/install.rs b/src/bin/cargo/commands/install.rs index b6348d747d4..be7be8e21ed 100644 --- a/src/bin/cargo/commands/install.rs +++ b/src/bin/cargo/commands/install.rs @@ -6,7 +6,7 @@ use cargo::util::ToUrl; pub fn cli() -> App { subcommand("install") - .about("Install a Rust binary") + .about("Install a Rust binary. Default location is $HOME/.cargo/bin") .arg(Arg::with_name("crate").empty_values(false).multiple(true)) .arg( opt("version", "Specify a version to install from crates.io") From dae87a262428b8b0ec136ab02b52d773d80771ac Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Tue, 27 Nov 2018 17:05:31 -0500 Subject: [PATCH 111/128] PackageId is copy, clippy thinks we dont need &PackageId or PackageId.clone() --- src/cargo/core/compiler/build_config.rs | 10 +- src/cargo/core/compiler/build_context/mod.rs | 2 +- .../compiler/build_context/target_info.rs | 21 ++-- src/cargo/core/compiler/build_plan.rs | 24 ++--- src/cargo/core/compiler/compilation.rs | 10 +- .../compiler/context/compilation_files.rs | 48 +++++----- src/cargo/core/compiler/context/mod.rs | 95 ++++++++++--------- .../compiler/context/unit_dependencies.rs | 16 ++-- src/cargo/core/compiler/custom_build.rs | 58 ++++++----- src/cargo/core/compiler/fingerprint.rs | 35 ++++--- src/cargo/core/compiler/job.rs | 2 +- src/cargo/core/compiler/job_queue.rs | 20 ++-- src/cargo/core/compiler/layout.rs | 4 +- src/cargo/core/compiler/mod.rs | 78 ++++++++------- src/cargo/core/compiler/output_depinfo.rs | 5 +- src/cargo/core/dependency.rs | 10 +- src/cargo/core/manifest.rs | 4 +- src/cargo/core/package.rs | 33 +++---- src/cargo/core/package_id.rs | 72 +++++++------- src/cargo/core/package_id_spec.rs | 22 ++--- src/cargo/core/profiles.rs | 6 +- src/cargo/core/registry.rs | 20 ++-- src/cargo/core/resolver/conflict_cache.rs | 16 ++-- src/cargo/core/resolver/context.rs | 24 ++--- src/cargo/core/resolver/encode.rs | 10 +- src/cargo/core/resolver/errors.rs | 8 +- src/cargo/core/resolver/mod.rs | 54 +++++------ src/cargo/core/resolver/resolve.rs | 45 ++++----- src/cargo/core/resolver/types.rs | 12 +-- src/cargo/core/source/mod.rs | 20 ++-- src/cargo/core/source/source_id.rs | 4 +- src/cargo/core/summary.rs | 4 +- src/cargo/ops/cargo_clean.rs | 3 +- src/cargo/ops/cargo_compile.rs | 37 +++++--- src/cargo/ops/cargo_doc.rs | 3 +- src/cargo/ops/cargo_fetch.rs | 40 ++++---- src/cargo/ops/cargo_generate_lockfile.rs | 18 ++-- src/cargo/ops/cargo_install.rs | 32 +++---- src/cargo/ops/cargo_output_metadata.rs | 41 ++++---- src/cargo/ops/cargo_read_manifest.rs | 2 +- src/cargo/ops/cargo_test.rs | 10 +- src/cargo/ops/resolve.rs | 36 ++++--- src/cargo/sources/directory.rs | 12 +-- src/cargo/sources/git/source.rs | 4 +- src/cargo/sources/path.rs | 4 +- src/cargo/sources/registry/index.rs | 2 +- src/cargo/sources/registry/local.rs | 4 +- src/cargo/sources/registry/mod.rs | 14 +-- src/cargo/sources/registry/remote.rs | 8 +- src/cargo/sources/replaced.rs | 12 +-- src/cargo/util/machine_message.rs | 6 +- src/cargo/util/toml/mod.rs | 4 +- tests/testsuite/member_errors.rs | 4 +- tests/testsuite/resolve.rs | 8 +- tests/testsuite/support/resolver.rs | 2 +- 55 files changed, 566 insertions(+), 532 deletions(-) diff --git a/src/cargo/core/compiler/build_config.rs b/src/cargo/core/compiler/build_config.rs index 2de8fb575d9..7df16e4150a 100644 --- a/src/cargo/core/compiler/build_config.rs +++ b/src/cargo/core/compiler/build_config.rs @@ -1,5 +1,5 @@ -use std::path::Path; use std::cell::RefCell; +use std::path::Path; use serde::ser; @@ -51,9 +51,11 @@ impl BuildConfig { let path = Path::new(target) .canonicalize() .chain_err(|| format_err!("Target path {:?} is not a valid file", target))?; - Some(path.into_os_string() - .into_string() - .map_err(|_| format_err!("Target path is not valid unicode"))?) + Some( + path.into_os_string() + .into_string() + .map_err(|_| format_err!("Target path is not valid unicode"))?, + ) } other => other.clone(), }; diff --git a/src/cargo/core/compiler/build_context/mod.rs b/src/cargo/core/compiler/build_context/mod.rs index a6d8be47f35..6373a649a24 100644 --- a/src/cargo/core/compiler/build_context/mod.rs +++ b/src/cargo/core/compiler/build_context/mod.rs @@ -180,7 +180,7 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> { ) } - pub fn show_warnings(&self, pkg: &PackageId) -> bool { + pub fn show_warnings(&self, pkg: PackageId) -> bool { pkg.source_id().is_path() || self.config.extra_verbose() } diff --git a/src/cargo/core/compiler/build_context/target_info.rs b/src/cargo/core/compiler/build_context/target_info.rs index 84950bd0dd3..075c4e62213 100644 --- a/src/cargo/core/compiler/build_context/target_info.rs +++ b/src/cargo/core/compiler/build_context/target_info.rs @@ -4,9 +4,9 @@ use std::path::PathBuf; use std::str::{self, FromStr}; use super::env_args; -use util::{CargoResult, CargoResultExt, Cfg, Config, ProcessBuilder, Rustc}; -use core::TargetKind; use super::Kind; +use core::TargetKind; +use util::{CargoResult, CargoResultExt, Cfg, Config, ProcessBuilder, Rustc}; #[derive(Clone)] pub struct TargetInfo { @@ -173,17 +173,16 @@ impl TargetInfo { Some((ref prefix, ref suffix)) => (prefix, suffix), None => return Ok(None), }; - let mut ret = vec![ - FileType { - suffix: suffix.clone(), - prefix: prefix.clone(), - flavor, - should_replace_hyphens: false, - }, - ]; + let mut ret = vec![FileType { + suffix: suffix.clone(), + prefix: prefix.clone(), + flavor, + should_replace_hyphens: false, + }]; // rust-lang/cargo#4500 - if target_triple.ends_with("pc-windows-msvc") && crate_type.ends_with("dylib") + if target_triple.ends_with("pc-windows-msvc") + && crate_type.ends_with("dylib") && suffix == ".dll" { ret.push(FileType { diff --git a/src/cargo/core/compiler/build_plan.rs b/src/cargo/core/compiler/build_plan.rs index 28625c7de9e..3c4b624e801 100644 --- a/src/cargo/core/compiler/build_plan.rs +++ b/src/cargo/core/compiler/build_plan.rs @@ -8,13 +8,13 @@ use std::collections::BTreeMap; -use core::TargetKind; -use super::{CompileMode, Context, Kind, Unit}; use super::context::OutputFile; -use util::{internal, CargoResult, ProcessBuilder}; -use std::path::PathBuf; -use serde_json; +use super::{CompileMode, Context, Kind, Unit}; +use core::TargetKind; use semver; +use serde_json; +use std::path::PathBuf; +use util::{internal, CargoResult, ProcessBuilder}; #[derive(Debug, Serialize)] struct Invocation { @@ -71,7 +71,8 @@ impl Invocation { } pub fn update_cmd(&mut self, cmd: &ProcessBuilder) -> CargoResult<()> { - self.program = cmd.get_program() + self.program = cmd + .get_program() .to_str() .ok_or_else(|| format_err!("unicode program string required"))? .to_string(); @@ -111,7 +112,8 @@ impl BuildPlan { pub fn add(&mut self, cx: &Context, unit: &Unit) -> CargoResult<()> { let id = self.plan.invocations.len(); self.invocation_map.insert(unit.buildkey(), id); - let deps = cx.dep_targets(&unit) + let deps = cx + .dep_targets(&unit) .iter() .map(|dep| self.invocation_map[&dep.buildkey()]) .collect(); @@ -127,10 +129,10 @@ impl BuildPlan { outputs: &[OutputFile], ) -> CargoResult<()> { let id = self.invocation_map[invocation_name]; - let invocation = self.plan - .invocations - .get_mut(id) - .ok_or_else(|| internal(format!("couldn't find invocation for {}", invocation_name)))?; + let invocation = + self.plan.invocations.get_mut(id).ok_or_else(|| { + internal(format!("couldn't find invocation for {}", invocation_name)) + })?; invocation.update_cmd(cmd)?; for output in outputs.iter() { diff --git a/src/cargo/core/compiler/compilation.rs b/src/cargo/core/compiler/compilation.rs index 72dcbdc0d5c..556c302a9db 100644 --- a/src/cargo/core/compiler/compilation.rs +++ b/src/cargo/core/compiler/compilation.rs @@ -5,9 +5,9 @@ use std::path::PathBuf; use semver::Version; +use super::BuildContext; use core::{Edition, Package, PackageId, Target, TargetKind}; use util::{self, join_paths, process, CargoResult, CfgExpr, Config, ProcessBuilder}; -use super::BuildContext; pub struct Doctest { /// The package being doctested. @@ -196,7 +196,7 @@ impl<'cfg> Compilation<'cfg> { let search_path = join_paths(&search_path, util::dylib_path_envvar())?; cmd.env(util::dylib_path_envvar(), &search_path); - if let Some(env) = self.extra_env.get(pkg.package_id()) { + if let Some(env) = self.extra_env.get(&pkg.package_id()) { for &(ref k, ref v) in env { cmd.env(k, v); } @@ -276,8 +276,10 @@ fn target_runner(bcx: &BuildContext) -> CargoResult if let Some(runner) = bcx.config.get_path_and_args(&key)? { // more than one match, error out if matching_runner.is_some() { - bail!("several matching instances of `target.'cfg(..)'.runner` \ - in `.cargo/config`") + bail!( + "several matching instances of `target.'cfg(..)'.runner` \ + in `.cargo/config`" + ) } matching_runner = Some(runner.val); diff --git a/src/cargo/core/compiler/context/compilation_files.rs b/src/cargo/core/compiler/context/compilation_files.rs index 3a50fa418a1..276e053cf5e 100644 --- a/src/cargo/core/compiler/context/compilation_files.rs +++ b/src/cargo/core/compiler/context/compilation_files.rs @@ -271,27 +271,29 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> { )?; match file_types { - Some(types) => for file_type in types { - let path = out_dir.join(file_type.filename(&file_stem)); - let hardlink = link_stem - .as_ref() - .map(|&(ref ld, ref ls)| ld.join(file_type.filename(ls))); - let export_path = if unit.target.is_custom_build() { - None - } else { - self.export_dir.as_ref().and_then(|export_dir| { - hardlink.as_ref().and_then(|hardlink| { - Some(export_dir.join(hardlink.file_name().unwrap())) + Some(types) => { + for file_type in types { + let path = out_dir.join(file_type.filename(&file_stem)); + let hardlink = link_stem + .as_ref() + .map(|&(ref ld, ref ls)| ld.join(file_type.filename(ls))); + let export_path = if unit.target.is_custom_build() { + None + } else { + self.export_dir.as_ref().and_then(|export_dir| { + hardlink.as_ref().and_then(|hardlink| { + Some(export_dir.join(hardlink.file_name().unwrap())) + }) }) - }) - }; - ret.push(OutputFile { - path, - hardlink, - export_path, - flavor: file_type.flavor, - }); - }, + }; + ret.push(OutputFile { + path, + hardlink, + export_path, + flavor: file_type.flavor, + }); + } + } // not supported, don't worry about it None => { unsupported.push(crate_type.to_string()); @@ -392,7 +394,8 @@ fn compute_metadata<'a, 'cfg>( let bcx = &cx.bcx; let __cargo_default_lib_metadata = env::var("__CARGO_DEFAULT_LIB_METADATA"); if !(unit.mode.is_any_test() || unit.mode.is_check()) - && (unit.target.is_dylib() || unit.target.is_cdylib() + && (unit.target.is_dylib() + || unit.target.is_cdylib() || (unit.target.is_bin() && bcx.target_triple().starts_with("wasm32-"))) && unit.pkg.package_id().source_id().is_path() && __cargo_default_lib_metadata.is_err() @@ -433,7 +436,8 @@ fn compute_metadata<'a, 'cfg>( // Mix in the target-metadata of all the dependencies of this target { - let mut deps_metadata = cx.dep_targets(unit) + let mut deps_metadata = cx + .dep_targets(unit) .iter() .map(|dep| metadata_of(dep, cx, metas)) .collect::>(); diff --git a/src/cargo/core/compiler/context/mod.rs b/src/cargo/core/compiler/context/mod.rs index 3bc78fd8b38..8252af66f6b 100644 --- a/src/cargo/core/compiler/context/mod.rs +++ b/src/cargo/core/compiler/context/mod.rs @@ -7,25 +7,25 @@ use std::sync::Arc; use jobserver::Client; -use core::{Package, PackageId, Resolve, Target}; use core::compiler::compilation; use core::profiles::Profile; +use core::{Package, PackageId, Resolve, Target}; use util::errors::{CargoResult, CargoResultExt}; -use util::{internal, profile, Config, short_hash}; +use util::{internal, profile, short_hash, Config}; +use super::build_plan::BuildPlan; use super::custom_build::{self, BuildDeps, BuildScripts, BuildState}; use super::fingerprint::Fingerprint; use super::job_queue::JobQueue; use super::layout::Layout; use super::{BuildContext, Compilation, CompileMode, Executor, FileFlavor, Kind}; -use super::build_plan::BuildPlan; mod unit_dependencies; use self::unit_dependencies::build_unit_dependencies; mod compilation_files; -pub use self::compilation_files::{Metadata, OutputFile}; use self::compilation_files::CompilationFiles; +pub use self::compilation_files::{Metadata, OutputFile}; /// All information needed to define a Unit. /// @@ -68,7 +68,7 @@ pub struct Unit<'a> { impl<'a> Unit<'a> { pub fn buildkey(&self) -> String { format!("{}-{}", self.pkg.name(), short_hash(self)) - } + } } pub struct Context<'a, 'cfg: 'a> { @@ -80,12 +80,12 @@ pub struct Context<'a, 'cfg: 'a> { pub fingerprints: HashMap, Arc>, pub compiled: HashSet>, pub build_scripts: HashMap, Arc>, - pub links: Links<'a>, + pub links: Links, pub jobserver: Client, - primary_packages: HashSet<&'a PackageId>, + primary_packages: HashSet, unit_dependencies: HashMap, Vec>>, files: Option>, - package_cache: HashMap<&'a PackageId, &'a Package>, + package_cache: HashMap, } impl<'a, 'cfg> Context<'a, 'cfg> { @@ -189,7 +189,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> { let out_dir = self.files().build_script_out_dir(dep).display().to_string(); self.compilation .extra_env - .entry(dep.pkg.package_id().clone()) + .entry(dep.pkg.package_id()) .or_insert_with(Vec::new) .push(("OUT_DIR".to_string(), out_dir)); } @@ -235,7 +235,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> { if !feats.is_empty() { self.compilation .cfgs - .entry(unit.pkg.package_id().clone()) + .entry(unit.pkg.package_id()) .or_insert_with(|| { feats .iter() @@ -247,7 +247,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> { if !rustdocflags.is_empty() { self.compilation .rustdocflags - .entry(unit.pkg.package_id().clone()) + .entry(unit.pkg.package_id()) .or_insert(rustdocflags); } @@ -289,7 +289,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> { Some(target) => Some(Layout::new(self.bcx.ws, Some(target), dest)?), None => None, }; - self.primary_packages.extend(units.iter().map(|u| u.pkg.package_id())); + self.primary_packages + .extend(units.iter().map(|u| u.pkg.package_id())); build_unit_dependencies( units, @@ -361,7 +362,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> { // gets a full pre-filtered set of dependencies. This is not super // obvious, and clear, but it does work at the moment. if unit.target.is_custom_build() { - let key = (unit.pkg.package_id().clone(), unit.kind); + let key = (unit.pkg.package_id(), unit.kind); if self.build_script_overridden.contains(&key) { return Vec::new(); } @@ -393,7 +394,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> { // incremental compilation or not. Primarily development profiles // have it enabled by default while release profiles have it disabled // by default. - let global_cfg = self.bcx + let global_cfg = self + .bcx .config .get_bool("build.incremental")? .map(|c| c.val); @@ -426,12 +428,13 @@ impl<'a, 'cfg> Context<'a, 'cfg> { } pub fn is_primary_package(&self, unit: &Unit<'a>) -> bool { - self.primary_packages.contains(unit.pkg.package_id()) + self.primary_packages.contains(&unit.pkg.package_id()) } /// Gets a package for the given package id. - pub fn get_package(&self, id: &PackageId) -> CargoResult<&'a Package> { - self.package_cache.get(id) + pub fn get_package(&self, id: PackageId) -> CargoResult<&'a Package> { + self.package_cache + .get(&id) .cloned() .ok_or_else(|| format_err!("failed to find {}", id)) } @@ -457,8 +460,8 @@ impl<'a, 'cfg> Context<'a, 'cfg> { let describe_collision = |unit: &Unit, other_unit: &Unit, path: &PathBuf| -> String { format!( "The {} target `{}` in package `{}` has the same output \ - filename as the {} target `{}` in package `{}`.\n\ - Colliding filename is: {}\n", + filename as the {} target `{}` in package `{}`.\n\ + Colliding filename is: {}\n", unit.target.kind().description(), unit.target.name(), unit.pkg.package_id(), @@ -470,13 +473,16 @@ impl<'a, 'cfg> Context<'a, 'cfg> { }; let suggestion = "Consider changing their names to be unique or compiling them separately.\n\ This may become a hard error in the future, see https://github.com/rust-lang/cargo/issues/6313"; - let report_collision = |unit: &Unit, other_unit: &Unit, path: &PathBuf| -> CargoResult<()> { + let report_collision = |unit: &Unit, + other_unit: &Unit, + path: &PathBuf| + -> CargoResult<()> { if unit.target.name() == other_unit.target.name() { self.bcx.config.shell().warn(format!( "output filename collision.\n\ - {}\ - The targets should have unique names.\n\ - {}", + {}\ + The targets should have unique names.\n\ + {}", describe_collision(unit, other_unit, path), suggestion )) @@ -507,28 +513,24 @@ impl<'a, 'cfg> Context<'a, 'cfg> { keys.sort_unstable(); for unit in keys { for output in self.outputs(unit)?.iter() { - if let Some(other_unit) = - output_collisions.insert(output.path.clone(), unit) - { + if let Some(other_unit) = output_collisions.insert(output.path.clone(), unit) { report_collision(unit, &other_unit, &output.path)?; } if let Some(hardlink) = output.hardlink.as_ref() { - if let Some(other_unit) = output_collisions.insert(hardlink.clone(), unit) - { + if let Some(other_unit) = output_collisions.insert(hardlink.clone(), unit) { report_collision(unit, &other_unit, hardlink)?; } } if let Some(ref export_path) = output.export_path { - if let Some(other_unit) = - output_collisions.insert(export_path.clone(), unit) - { - self.bcx.config.shell().warn(format!("`--out-dir` filename collision.\n\ - {}\ - The exported filenames should be unique.\n\ - {}", + if let Some(other_unit) = output_collisions.insert(export_path.clone(), unit) { + self.bcx.config.shell().warn(format!( + "`--out-dir` filename collision.\n\ + {}\ + The exported filenames should be unique.\n\ + {}", describe_collision(unit, &other_unit, &export_path), suggestion - ))?; + ))?; } } } @@ -538,20 +540,20 @@ impl<'a, 'cfg> Context<'a, 'cfg> { } #[derive(Default)] -pub struct Links<'a> { - validated: HashSet<&'a PackageId>, - links: HashMap, +pub struct Links { + validated: HashSet, + links: HashMap, } -impl<'a> Links<'a> { - pub fn new() -> Links<'a> { +impl Links { + pub fn new() -> Links { Links { validated: HashSet::new(), links: HashMap::new(), } } - pub fn validate(&mut self, resolve: &Resolve, unit: &Unit<'a>) -> CargoResult<()> { + pub fn validate(&mut self, resolve: &Resolve, unit: &Unit) -> CargoResult<()> { if !self.validated.insert(unit.pkg.package_id()) { return Ok(()); } @@ -559,11 +561,11 @@ impl<'a> Links<'a> { Some(lib) => lib, None => return Ok(()), }; - if let Some(prev) = self.links.get(lib) { + if let Some(&prev) = self.links.get(lib) { let pkg = unit.pkg.package_id(); - let describe_path = |pkgid: &PackageId| -> String { - let dep_path = resolve.path_to_top(pkgid); + let describe_path = |pkgid: PackageId| -> String { + let dep_path = resolve.path_to_top(&pkgid); let mut dep_path_desc = format!("package `{}`", dep_path[0]); for dep in dep_path.iter().skip(1) { write!(dep_path_desc, "\n ... which is depended on by `{}`", dep).unwrap(); @@ -585,7 +587,8 @@ impl<'a> Links<'a> { lib ) } - if !unit.pkg + if !unit + .pkg .manifest() .targets() .iter() diff --git a/src/cargo/core/compiler/context/unit_dependencies.rs b/src/cargo/core/compiler/context/unit_dependencies.rs index 6c4d72976bd..22a4b5f9804 100644 --- a/src/cargo/core/compiler/context/unit_dependencies.rs +++ b/src/cargo/core/compiler/context/unit_dependencies.rs @@ -28,8 +28,8 @@ use CargoResult; struct State<'a: 'tmp, 'cfg: 'a, 'tmp> { bcx: &'tmp BuildContext<'a, 'cfg>, deps: &'tmp mut HashMap, Vec>>, - pkgs: RefCell<&'tmp mut HashMap<&'a PackageId, &'a Package>>, - waiting_on_download: HashSet<&'a PackageId>, + pkgs: RefCell<&'tmp mut HashMap>, + waiting_on_download: HashSet, downloads: Downloads<'a, 'cfg>, } @@ -37,7 +37,7 @@ pub fn build_unit_dependencies<'a, 'cfg>( roots: &[Unit<'a>], bcx: &BuildContext<'a, 'cfg>, deps: &mut HashMap, Vec>>, - pkgs: &mut HashMap<&'a PackageId, &'a Package>, + pkgs: &mut HashMap, ) -> CargoResult<()> { assert!(deps.is_empty(), "can only build unit deps once"); @@ -393,7 +393,7 @@ fn new_unit<'a>( mode: CompileMode, ) -> Unit<'a> { let profile = bcx.profiles.get_profile( - &pkg.package_id(), + pkg.package_id(), bcx.ws.is_member(pkg), unit_for, mode, @@ -482,9 +482,9 @@ fn connect_run_custom_build_deps(state: &mut State) { } impl<'a, 'cfg, 'tmp> State<'a, 'cfg, 'tmp> { - fn get(&mut self, id: &'a PackageId) -> CargoResult> { + fn get(&mut self, id: PackageId) -> CargoResult> { let mut pkgs = self.pkgs.borrow_mut(); - if let Some(pkg) = pkgs.get(id) { + if let Some(pkg) = pkgs.get(&id) { return Ok(Some(pkg)); } if !self.waiting_on_download.insert(id) { @@ -492,7 +492,7 @@ impl<'a, 'cfg, 'tmp> State<'a, 'cfg, 'tmp> { } if let Some(pkg) = self.downloads.start(id)? { pkgs.insert(id, pkg); - self.waiting_on_download.remove(id); + self.waiting_on_download.remove(&id); return Ok(Some(pkg)); } Ok(None) @@ -510,7 +510,7 @@ impl<'a, 'cfg, 'tmp> State<'a, 'cfg, 'tmp> { assert!(self.downloads.remaining() > 0); loop { let pkg = self.downloads.wait()?; - self.waiting_on_download.remove(pkg.package_id()); + self.waiting_on_download.remove(&pkg.package_id()); self.pkgs.borrow_mut().insert(pkg.package_id(), pkg); // Arbitrarily choose that 5 or more packages concurrently download diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index d2cab26b1c9..400bd4641e5 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -87,7 +87,7 @@ pub fn prepare<'a, 'cfg>( unit.target.name() )); - let key = (unit.pkg.package_id().clone(), unit.kind); + let key = (unit.pkg.package_id(), unit.kind); let overridden = cx.build_script_overridden.contains(&key); let (work_dirty, work_fresh) = if overridden { (Work::noop(), Work::noop()) @@ -106,7 +106,7 @@ pub fn prepare<'a, 'cfg>( } } -fn emit_build_output(output: &BuildOutput, id: &PackageId) { +fn emit_build_output(output: &BuildOutput, package_id: PackageId) { let library_paths = output .library_paths .iter() @@ -114,7 +114,7 @@ fn emit_build_output(output: &BuildOutput, id: &PackageId) { .collect::>(); machine_message::emit(&machine_message::BuildScript { - package_id: id, + package_id, linked_libs: &output.library_links, linked_paths: &library_paths, cfgs: &output.cfgs, @@ -230,7 +230,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes if unit.mode.is_run_custom_build() { Some(( unit.pkg.manifest().links().unwrap().to_string(), - unit.pkg.package_id().clone(), + unit.pkg.package_id(), )) } else { None @@ -240,7 +240,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes }; let pkg_name = unit.pkg.to_string(); let build_state = Arc::clone(&cx.build_state); - let id = unit.pkg.package_id().clone(); + let id = unit.pkg.package_id(); let (output_file, err_file, root_output_file) = { let build_output_parent = script_out_dir.parent().unwrap(); let output_file = build_output_parent.join("output"); @@ -250,7 +250,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes }; let host_target_root = cx.files().target_root().to_path_buf(); let all = ( - id.clone(), + id, pkg_name.clone(), Arc::clone(&build_state), output_file.clone(), @@ -267,8 +267,13 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes .and_then(|bytes| util::bytes2path(&bytes)) .unwrap_or_else(|_| script_out_dir.clone()); - let prev_output = - BuildOutput::parse_file(&output_file, &pkg_name, &prev_script_out_dir, &script_out_dir).ok(); + let prev_output = BuildOutput::parse_file( + &output_file, + &pkg_name, + &prev_script_out_dir, + &script_out_dir, + ) + .ok(); let deps = BuildDeps::new(&output_file, prev_output.as_ref()); cx.build_explicit_deps.insert(*unit, deps); @@ -301,7 +306,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes if !build_plan { let build_state = build_state.outputs.lock().unwrap(); for (name, id) in lib_deps { - let key = (id.clone(), kind); + let key = (id, kind); let state = build_state.get(&key).ok_or_else(|| { internal(format!( "failed to locate build state for env \ @@ -355,7 +360,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes BuildOutput::parse(&output.stdout, &pkg_name, &script_out_dir, &script_out_dir)?; if json_messages { - emit_build_output(&parsed_output, &id); + emit_build_output(&parsed_output, id); } build_state.insert(id, kind, parsed_output); } @@ -369,13 +374,16 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes let (id, pkg_name, build_state, output_file, script_out_dir) = all; let output = match prev_output { Some(output) => output, - None => { - BuildOutput::parse_file(&output_file, &pkg_name, &prev_script_out_dir, &script_out_dir)? - } + None => BuildOutput::parse_file( + &output_file, + &pkg_name, + &prev_script_out_dir, + &script_out_dir, + )?, }; if json_messages { - emit_build_output(&output, &id); + emit_build_output(&output, id); } build_state.insert(id, kind, output); @@ -412,7 +420,12 @@ impl BuildOutput { script_out_dir: &Path, ) -> CargoResult { let contents = paths::read_bytes(path)?; - BuildOutput::parse(&contents, pkg_name, script_out_dir_when_generated, script_out_dir) + BuildOutput::parse( + &contents, + pkg_name, + script_out_dir_when_generated, + script_out_dir, + ) } // Parses the output of a script. @@ -620,14 +633,15 @@ pub fn build_map<'b, 'cfg>(cx: &mut Context<'b, 'cfg>, units: &[Unit<'b>]) -> Ca } { - let key = unit.pkg + let key = unit + .pkg .manifest() .links() .map(|l| (l.to_string(), unit.kind)); let build_state = &cx.build_state; if let Some(output) = key.and_then(|k| build_state.overrides.get(&k)) { - let key = (unit.pkg.package_id().clone(), unit.kind); - cx.build_script_overridden.insert(key.clone()); + let key = (unit.pkg.package_id(), unit.kind); + cx.build_script_overridden.insert(key); build_state .outputs .lock() @@ -656,7 +670,7 @@ pub fn build_map<'b, 'cfg>(cx: &mut Context<'b, 'cfg>, units: &[Unit<'b>]) -> Ca ret.plugins .extend(dep_scripts.to_link.iter().map(|p| &p.0).cloned()); } else if unit.target.linkable() { - for &(ref pkg, kind) in dep_scripts.to_link.iter() { + for &(pkg, kind) in dep_scripts.to_link.iter() { add_to_link(&mut ret, pkg, kind); } } @@ -670,9 +684,9 @@ pub fn build_map<'b, 'cfg>(cx: &mut Context<'b, 'cfg>, units: &[Unit<'b>]) -> Ca // When adding an entry to 'to_link' we only actually push it on if the // script hasn't seen it yet (e.g. we don't push on duplicates). - fn add_to_link(scripts: &mut BuildScripts, pkg: &PackageId, kind: Kind) { - if scripts.seen_to_link.insert((pkg.clone(), kind)) { - scripts.to_link.push((pkg.clone(), kind)); + fn add_to_link(scripts: &mut BuildScripts, pkg: PackageId, kind: Kind) { + if scripts.seen_to_link.insert((pkg, kind)) { + scripts.to_link.push((pkg, kind)); } } } diff --git a/src/cargo/core/compiler/fingerprint.rs b/src/cargo/core/compiler/fingerprint.rs index c2ecec2c970..4a3d4fa4f95 100644 --- a/src/cargo/core/compiler/fingerprint.rs +++ b/src/cargo/core/compiler/fingerprint.rs @@ -15,9 +15,9 @@ use util::errors::{CargoResult, CargoResultExt}; use util::paths; use util::{internal, profile, Dirty, Fresh, Freshness}; -use super::{Context, BuildContext, FileFlavor, Unit}; use super::custom_build::BuildDeps; use super::job::Work; +use super::{BuildContext, Context, FileFlavor, Unit}; /// A tuple result of the `prepare_foo` functions in this module. /// @@ -88,11 +88,13 @@ pub fn prepare_target<'a, 'cfg>( let root = cx.files().out_dir(unit); let missing_outputs = { if unit.mode.is_doc() { - !root.join(unit.target.crate_name()) + !root + .join(unit.target.crate_name()) .join("index.html") .exists() } else { - match cx.outputs(unit)? + match cx + .outputs(unit)? .iter() .filter(|output| output.flavor != FileFlavor::DebugInfo) .find(|output| !output.path.exists()) @@ -159,7 +161,10 @@ pub struct Fingerprint { target: u64, profile: u64, path: u64, - #[serde(serialize_with = "serialize_deps", deserialize_with = "deserialize_deps")] + #[serde( + serialize_with = "serialize_deps", + deserialize_with = "deserialize_deps" + )] deps: Vec, local: Vec, #[serde(skip_serializing, skip_deserializing)] @@ -172,8 +177,7 @@ fn serialize_deps(deps: &[DepFingerprint], ser: S) -> Result where S: ser::Serializer, { - ser.collect_seq(deps.iter() - .map(|&(ref a, ref b, ref c)| (a, b, c.hash()))) + ser.collect_seq(deps.iter().map(|&(ref a, ref b, ref c)| (a, b, c.hash()))) } fn deserialize_deps<'de, D>(d: D) -> Result, D::Error> @@ -363,7 +367,8 @@ impl hash::Hash for Fingerprint { } = *self; ( rustc, features, target, path, profile, local, edition, rustflags, - ).hash(h); + ) + .hash(h); h.write_usize(deps.len()); for &(ref pkg_id, ref name, ref fingerprint) in deps { @@ -400,9 +405,9 @@ impl<'de> de::Deserialize<'de> for MtimeSlot { D: de::Deserializer<'de>, { let kind: Option<(i64, u32)> = de::Deserialize::deserialize(d)?; - Ok(MtimeSlot(Mutex::new(kind.map(|(s, n)| { - FileTime::from_unix_time(s, n) - })))) + Ok(MtimeSlot(Mutex::new( + kind.map(|(s, n)| FileTime::from_unix_time(s, n)), + ))) } } @@ -435,7 +440,8 @@ fn calculate<'a, 'cfg>( // induce a recompile, they're just dependencies in the sense that they need // to be built. let deps = cx.dep_targets(unit); - let deps = deps.iter() + let deps = deps + .iter() .filter(|u| !u.target.is_custom_build() && !u.target.is_bin()) .map(|dep| { calculate(cx, dep).and_then(|fingerprint| { @@ -548,7 +554,7 @@ pub fn prepare_build_cmd<'a, 'cfg>( // the kind of fingerprint by reinterpreting the dependencies output by the // build script. let state = Arc::clone(&cx.build_state); - let key = (unit.pkg.package_id().clone(), unit.kind); + let key = (unit.pkg.package_id(), unit.kind); let pkg_root = unit.pkg.root().to_path_buf(); let target_root = cx.files().target_root().to_path_buf(); let write_fingerprint = Work::new(move |_| { @@ -581,7 +587,7 @@ fn build_script_local_fingerprints<'a, 'cfg>( // // Note that the `None` here means that we don't want to update the local // fingerprint afterwards because this is all just overridden. - if let Some(output) = state.get(&(unit.pkg.package_id().clone(), unit.kind)) { + if let Some(output) = state.get(&(unit.pkg.package_id(), unit.kind)) { debug!("override local fingerprints deps"); let s = format!( "overridden build state with hash: {}", @@ -695,7 +701,8 @@ pub fn parse_dep_info(pkg: &Package, dep_info: &Path) -> CargoResult data, Err(_) => return Ok(None), }; - let paths = data.split(|&x| x == 0) + let paths = data + .split(|&x| x == 0) .filter(|x| !x.is_empty()) .map(|p| util::bytes2path(p).map(|p| pkg.root().join(p))) .collect::, _>>()?; diff --git a/src/cargo/core/compiler/job.rs b/src/cargo/core/compiler/job.rs index 61e979f1d55..f51288d4d03 100644 --- a/src/cargo/core/compiler/job.rs +++ b/src/cargo/core/compiler/job.rs @@ -1,7 +1,7 @@ use std::fmt; -use util::{CargoResult, Dirty, Fresh, Freshness}; use super::job_queue::JobState; +use util::{CargoResult, Dirty, Fresh, Freshness}; pub struct Job { dirty: Work, diff --git a/src/cargo/core/compiler/job_queue.rs b/src/cargo/core/compiler/job_queue.rs index 687f74d3ebf..aea810b5203 100644 --- a/src/cargo/core/compiler/job_queue.rs +++ b/src/cargo/core/compiler/job_queue.rs @@ -35,9 +35,9 @@ pub struct JobQueue<'a> { rx: Receiver>, active: Vec>, pending: HashMap, PendingBuild>, - compiled: HashSet<&'a PackageId>, - documented: HashSet<&'a PackageId>, - counts: HashMap<&'a PackageId, usize>, + compiled: HashSet, + documented: HashSet, + counts: HashMap, is_release: bool, } @@ -52,7 +52,7 @@ struct PendingBuild { #[derive(Clone, Copy, Eq, PartialEq, Hash)] struct Key<'a> { - pkg: &'a PackageId, + pkg: PackageId, target: &'a Target, profile: Profile, kind: Kind, @@ -398,7 +398,7 @@ impl<'a> JobQueue<'a> { info!("start: {:?}", key); self.active.push(key); - *self.counts.get_mut(key.pkg).unwrap() -= 1; + *self.counts.get_mut(&key.pkg).unwrap() -= 1; let my_tx = self.tx.clone(); let doit = move || { @@ -424,7 +424,7 @@ impl<'a> JobQueue<'a> { fn emit_warnings(&self, msg: Option<&str>, key: &Key<'a>, cx: &mut Context) -> CargoResult<()> { let output = cx.build_state.outputs.lock().unwrap(); let bcx = &mut cx.bcx; - if let Some(output) = output.get(&(key.pkg.clone(), key.kind)) { + if let Some(output) = output.get(&(key.pkg, key.kind)) { if let Some(msg) = msg { if !output.warnings.is_empty() { writeln!(bcx.config.shell().err(), "{}\n", msg)?; @@ -472,8 +472,8 @@ impl<'a> JobQueue<'a> { key: &Key<'a>, fresh: Freshness, ) -> CargoResult<()> { - if (self.compiled.contains(key.pkg) && !key.mode.is_doc()) - || (self.documented.contains(key.pkg) && key.mode.is_doc()) + if (self.compiled.contains(&key.pkg) && !key.mode.is_doc()) + || (self.documented.contains(&key.pkg) && key.mode.is_doc()) { return Ok(()); } @@ -499,8 +499,8 @@ impl<'a> JobQueue<'a> { } Fresh => { // If doctest is last, only print "Fresh" if nothing has been printed. - if self.counts[key.pkg] == 0 - && !(key.mode == CompileMode::Doctest && self.compiled.contains(key.pkg)) + if self.counts[&key.pkg] == 0 + && !(key.mode == CompileMode::Doctest && self.compiled.contains(&key.pkg)) { self.compiled.insert(key.pkg); config.shell().verbose(|c| c.status("Fresh", key.pkg))?; diff --git a/src/cargo/core/compiler/layout.rs b/src/cargo/core/compiler/layout.rs index 233c23d5e68..82784baf3fb 100644 --- a/src/cargo/core/compiler/layout.rs +++ b/src/cargo/core/compiler/layout.rs @@ -135,9 +135,9 @@ impl Layout { /// /// This is recommended to prevent derived/temporary files from bloating backups. fn exclude_from_backups(&self, path: &Path) { - use std::ptr; - use core_foundation::{number, string, url}; use core_foundation::base::TCFType; + use core_foundation::{number, string, url}; + use std::ptr; // For compatibility with 10.7 a string is used instead of global kCFURLIsExcludedFromBackupKey let is_excluded_key: Result = "NSURLIsExcludedFromBackupKey".parse(); diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index d371dc68216..d1f92ceb89a 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -14,7 +14,7 @@ use core::profiles::{Lto, Profile}; use core::{PackageId, Target}; use util::errors::{CargoResult, CargoResultExt, Internal, ProcessError}; use util::paths; -use util::{self, machine_message, Freshness, ProcessBuilder, process}; +use util::{self, machine_message, process, Freshness, ProcessBuilder}; use util::{internal, join_paths, profile}; use self::build_plan::BuildPlan; @@ -23,8 +23,8 @@ use self::job_queue::JobQueue; use self::output_depinfo::output_depinfo; -pub use self::build_context::{BuildContext, FileFlavor, TargetConfig, TargetInfo}; pub use self::build_config::{BuildConfig, CompileMode, MessageFormat}; +pub use self::build_context::{BuildContext, FileFlavor, TargetConfig, TargetInfo}; pub use self::compilation::{Compilation, Doctest}; pub use self::context::{Context, Unit}; pub use self::custom_build::{BuildMap, BuildOutput, BuildScripts}; @@ -65,9 +65,9 @@ pub trait Executor: Send + Sync + 'static { fn exec( &self, cmd: ProcessBuilder, - _id: &PackageId, + _id: PackageId, _target: &Target, - _mode: CompileMode + _mode: CompileMode, ) -> CargoResult<()> { cmd.exec()?; Ok(()) @@ -76,7 +76,7 @@ pub trait Executor: Send + Sync + 'static { fn exec_and_capture_output( &self, cmd: ProcessBuilder, - id: &PackageId, + id: PackageId, target: &Target, mode: CompileMode, _state: &job_queue::JobState<'_>, @@ -88,7 +88,7 @@ pub trait Executor: Send + Sync + 'static { fn exec_json( &self, cmd: ProcessBuilder, - _id: &PackageId, + _id: PackageId, _target: &Target, _mode: CompileMode, handle_stdout: &mut FnMut(&str) -> CargoResult<()>, @@ -114,7 +114,7 @@ impl Executor for DefaultExecutor { fn exec_and_capture_output( &self, cmd: ProcessBuilder, - _id: &PackageId, + _id: PackageId, _target: &Target, _mode: CompileMode, state: &job_queue::JobState<'_>, @@ -207,7 +207,7 @@ fn rustc<'a, 'cfg>( // Prepare the native lib state (extra -L and -l flags) let build_state = cx.build_state.clone(); - let current_id = unit.pkg.package_id().clone(); + let current_id = unit.pkg.package_id(); let build_deps = load_build_deps(cx, unit); // If we are a binary and the package also contains a library, then we @@ -222,12 +222,13 @@ fn rustc<'a, 'cfg>( root.join(&crate_name) } else { root.join(&cx.files().file_stem(unit)) - }.with_extension("d"); + } + .with_extension("d"); let dep_info_loc = fingerprint::dep_info_loc(cx, unit); rustc.args(&cx.bcx.rustflags_args(unit)?); let json_messages = cx.bcx.build_config.json_messages(); - let package_id = unit.pkg.package_id().clone(); + let package_id = unit.pkg.package_id(); let target = unit.target.clone(); let mode = unit.mode; @@ -257,11 +258,11 @@ fn rustc<'a, 'cfg>( &build_state, &build_deps, pass_l_flag, - ¤t_id, + current_id, )?; add_plugin_deps(&mut rustc, &build_state, &build_deps, &root_output)?; } - add_custom_env(&mut rustc, &build_state, ¤t_id, kind)?; + add_custom_env(&mut rustc, &build_state, current_id, kind)?; } for output in outputs.iter() { @@ -293,18 +294,18 @@ fn rustc<'a, 'cfg>( if json_messages { exec.exec_json( rustc, - &package_id, + package_id, &target, mode, &mut assert_is_empty, - &mut |line| json_stderr(line, &package_id, &target), + &mut |line| json_stderr(line, package_id, &target), ) .map_err(internal_if_simple_exit_code) .chain_err(|| format!("Could not compile `{}`.", name))?; } else if build_plan { state.build_plan(buildkey, rustc.clone(), outputs.clone()); } else { - exec.exec_and_capture_output(rustc, &package_id, &target, mode, state) + exec.exec_and_capture_output(rustc, package_id, &target, mode, state) .map_err(internal_if_simple_exit_code) .chain_err(|| format!("Could not compile `{}`.", name))?; } @@ -344,7 +345,7 @@ fn rustc<'a, 'cfg>( build_state: &BuildMap, build_scripts: &BuildScripts, pass_l_flag: bool, - current_id: &PackageId, + current_id: PackageId, ) -> CargoResult<()> { for key in build_scripts.to_link.iter() { let output = build_state.get(key).ok_or_else(|| { @@ -356,7 +357,7 @@ fn rustc<'a, 'cfg>( for path in output.library_paths.iter() { rustc.arg("-L").arg(path); } - if key.0 == *current_id { + if key.0 == current_id { for cfg in &output.cfgs { rustc.arg("--cfg").arg(cfg); } @@ -375,10 +376,10 @@ fn rustc<'a, 'cfg>( fn add_custom_env( rustc: &mut ProcessBuilder, build_state: &BuildMap, - current_id: &PackageId, + current_id: PackageId, kind: Kind, ) -> CargoResult<()> { - let key = (current_id.clone(), kind); + let key = (current_id, kind); if let Some(output) = build_state.get(&key) { for &(ref name, ref value) in output.env.iter() { rustc.env(name, value); @@ -398,11 +399,12 @@ fn link_targets<'a, 'cfg>( let bcx = cx.bcx; let outputs = cx.outputs(unit)?; let export_dir = cx.files().export_dir(); - let package_id = unit.pkg.package_id().clone(); + let package_id = unit.pkg.package_id(); let profile = unit.profile; let unit_mode = unit.mode; - let features = bcx.resolve - .features_sorted(&package_id) + let features = bcx + .resolve + .features_sorted(package_id) .into_iter() .map(|s| s.to_owned()) .collect(); @@ -456,7 +458,7 @@ fn link_targets<'a, 'cfg>( }; machine_message::emit(&machine_message::Artifact { - package_id: &package_id, + package_id, target: &target, profile: art_profile, features, @@ -526,10 +528,9 @@ fn add_plugin_deps( let var = util::dylib_path_envvar(); let search_path = rustc.get_env(var).unwrap_or_default(); let mut search_path = env::split_paths(&search_path).collect::>(); - for id in build_scripts.plugins.iter() { - let key = (id.clone(), Kind::Host); + for &id in build_scripts.plugins.iter() { let output = build_state - .get(&key) + .get(&(id, Kind::Host)) .ok_or_else(|| internal(format!("couldn't find libs for plugin dep {}", id)))?; search_path.append(&mut filter_dynamic_search_path( output.library_paths.iter(), @@ -637,9 +638,9 @@ fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult let name = unit.pkg.name().to_string(); let build_state = cx.build_state.clone(); - let key = (unit.pkg.package_id().clone(), unit.kind); + let key = (unit.pkg.package_id(), unit.kind); let json_messages = bcx.build_config.json_messages(); - let package_id = unit.pkg.package_id().clone(); + let package_id = unit.pkg.package_id(); let target = unit.target.clone(); Ok(Work::new(move |state| { @@ -657,9 +658,10 @@ fn rustdoc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult rustdoc .exec_with_streaming( &mut assert_is_empty, - &mut |line| json_stderr(line, &package_id, &target), + &mut |line| json_stderr(line, package_id, &target), false, - ).map(drop) + ) + .map(drop) } else { state.capture_output(&rustdoc, None, false).map(drop) }; @@ -719,15 +721,23 @@ fn add_cap_lints(bcx: &BuildContext, unit: &Unit, cmd: &mut ProcessBuilder) { fn add_color(bcx: &BuildContext, cmd: &mut ProcessBuilder) { let shell = bcx.config.shell(); - let color = if shell.supports_color() { "always" } else { "never" }; + let color = if shell.supports_color() { + "always" + } else { + "never" + }; cmd.args(&["--color", color]); } fn add_error_format(bcx: &BuildContext, cmd: &mut ProcessBuilder) { match bcx.build_config.message_format { MessageFormat::Human => (), - MessageFormat::Json => { cmd.arg("--error-format").arg("json"); }, - MessageFormat::Short => { cmd.arg("--error-format").arg("short"); }, + MessageFormat::Json => { + cmd.arg("--error-format").arg("json"); + } + MessageFormat::Short => { + cmd.arg("--error-format").arg("short"); + } } } @@ -1009,7 +1019,7 @@ fn assert_is_empty(line: &str) -> CargoResult<()> { } } -fn json_stderr(line: &str, package_id: &PackageId, target: &Target) -> CargoResult<()> { +fn json_stderr(line: &str, package_id: PackageId, target: &Target) -> CargoResult<()> { // stderr from rustc/rustdoc can have a mix of JSON and non-JSON output if line.starts_with('{') { // Handle JSON lines diff --git a/src/cargo/core/compiler/output_depinfo.rs b/src/cargo/core/compiler/output_depinfo.rs index df4f3d417a5..ab95ea6f001 100644 --- a/src/cargo/core/compiler/output_depinfo.rs +++ b/src/cargo/core/compiler/output_depinfo.rs @@ -52,7 +52,7 @@ fn add_deps_for_unit<'a, 'b>( } // Add rerun-if-changed dependencies - let key = (unit.pkg.package_id().clone(), unit.kind); + let key = (unit.pkg.package_id(), unit.kind); if let Some(output) = context.build_state.outputs.lock().unwrap().get(&key) { for path in &output.rerun_if_changed { deps.insert(path.into()); @@ -87,7 +87,8 @@ pub fn output_depinfo<'a, 'b>(cx: &mut Context<'a, 'b>, unit: &Unit<'a>) -> Carg } None => None, }; - let deps = deps.iter() + let deps = deps + .iter() .map(|f| render_filename(f, basedir)) .collect::>>()?; diff --git a/src/cargo/core/dependency.rs b/src/cargo/core/dependency.rs index bdb04e36a7a..85741138948 100644 --- a/src/cargo/core/dependency.rs +++ b/src/cargo/core/dependency.rs @@ -89,7 +89,7 @@ pub enum Kind { fn parse_req_with_deprecated( name: &str, req: &str, - extra: Option<(&PackageId, &Config)>, + extra: Option<(PackageId, &Config)>, ) -> CargoResult { match VersionReq::parse(req) { Err(ReqParseError::DeprecatedVersionRequirement(requirement)) => { @@ -152,7 +152,7 @@ impl Dependency { name: &str, version: Option<&str>, source_id: SourceId, - inside: &PackageId, + inside: PackageId, config: &Config, ) -> CargoResult { let arg = Some((inside, config)); @@ -349,7 +349,7 @@ impl Dependency { } /// Lock this dependency to depending on the specified package id - pub fn lock_to(&mut self, id: &PackageId) -> &mut Dependency { + pub fn lock_to(&mut self, id: PackageId) -> &mut Dependency { assert_eq!(self.inner.source_id, id.source_id()); assert!(self.inner.req.matches(id.version())); trace!( @@ -404,12 +404,12 @@ impl Dependency { } /// Returns true if the package (`sum`) can fulfill this dependency request. - pub fn matches_ignoring_source(&self, id: &PackageId) -> bool { + pub fn matches_ignoring_source(&self, id: PackageId) -> bool { self.package_name() == id.name() && self.version_req().matches(id.version()) } /// Returns true if the package (`id`) can fulfill this dependency request. - pub fn matches_id(&self, id: &PackageId) -> bool { + pub fn matches_id(&self, id: PackageId) -> bool { self.inner.name == id.name() && (self.inner.only_match_name || (self.inner.req.matches(id.version()) && self.inner.source_id == id.source_id())) diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 8763e4e628e..91eb9e00cac 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -413,7 +413,7 @@ impl Manifest { pub fn name(&self) -> InternedString { self.package_id().name() } - pub fn package_id(&self) -> &PackageId { + pub fn package_id(&self) -> PackageId { self.summary.package_id() } pub fn summary(&self) -> &Summary { @@ -519,7 +519,7 @@ impl Manifest { } pub fn metabuild_path(&self, target_dir: Filesystem) -> PathBuf { - let hash = short_hash(self.package_id()); + let hash = short_hash(&self.package_id()); target_dir .into_path_unlocked() .join(".metabuild") diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index bb85567bdfd..85064c1d531 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -41,7 +41,7 @@ pub struct Package { impl Ord for Package { fn cmp(&self, other: &Package) -> Ordering { - self.package_id().cmp(other.package_id()) + self.package_id().cmp(&other.package_id()) } } @@ -56,7 +56,7 @@ impl PartialOrd for Package { struct SerializedPackage<'a> { name: &'a str, version: &'a str, - id: &'a PackageId, + id: PackageId, license: Option<&'a str>, license_file: Option<&'a str>, description: Option<&'a str>, @@ -153,7 +153,7 @@ impl Package { self.package_id().name() } /// Get the PackageId object for the package (fully defines a package) - pub fn package_id(&self) -> &PackageId { + pub fn package_id(&self) -> PackageId { self.manifest.package_id() } /// Get the root folder of the package @@ -241,7 +241,7 @@ impl fmt::Display for Package { impl fmt::Debug for Package { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Package") - .field("id", self.summary().package_id()) + .field("id", &self.summary().package_id()) .field("..", &"..") .finish() } @@ -354,7 +354,7 @@ impl<'cfg> PackageSet<'cfg> { Ok(PackageSet { packages: package_ids .iter() - .map(|id| (id.clone(), LazyCell::new())) + .map(|&id| (id, LazyCell::new())) .collect(), sources: RefCell::new(sources), config, @@ -364,8 +364,8 @@ impl<'cfg> PackageSet<'cfg> { }) } - pub fn package_ids<'a>(&'a self) -> Box + 'a> { - Box::new(self.packages.keys()) + pub fn package_ids<'a>(&'a self) -> impl Iterator + 'a { + self.packages.keys().cloned() } pub fn enable_download<'a>(&'a self) -> CargoResult> { @@ -394,14 +394,11 @@ impl<'cfg> PackageSet<'cfg> { }) } - pub fn get_one(&self, id: &PackageId) -> CargoResult<&Package> { + pub fn get_one(&self, id: PackageId) -> CargoResult<&Package> { Ok(self.get_many(Some(id))?.remove(0)) } - pub fn get_many<'a>( - &self, - ids: impl IntoIterator, - ) -> CargoResult> { + pub fn get_many(&self, ids: impl IntoIterator) -> CargoResult> { let mut pkgs = Vec::new(); let mut downloads = self.enable_download()?; for id in ids { @@ -425,13 +422,13 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { /// Returns `None` if the package is queued up for download and will /// eventually be returned from `wait_for_download`. Returns `Some(pkg)` if /// the package is ready and doesn't need to be downloaded. - pub fn start(&mut self, id: &PackageId) -> CargoResult> { + pub fn start(&mut self, id: PackageId) -> CargoResult> { // First up see if we've already cached this package, in which case // there's nothing to do. let slot = self .set .packages - .get(id) + .get(&id) .ok_or_else(|| internal(format!("couldn't find `{}` in package set", id)))?; if let Some(pkg) = slot.borrow() { return Ok(Some(pkg)); @@ -463,7 +460,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { let token = self.next; self.next += 1; debug!("downloading {} as {}", id, token); - assert!(self.pending_ids.insert(id.clone())); + assert!(self.pending_ids.insert(id)); let (mut handle, _timeout) = ops::http_handle_and_timeout(self.set.config)?; handle.get(true)?; @@ -542,7 +539,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { let dl = Download { token, data: RefCell::new(Vec::new()), - id: id.clone(), + id, url, descriptor, total: Cell::new(0), @@ -632,7 +629,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { match ret { Some(()) => break (dl, data), None => { - self.pending_ids.insert(dl.id.clone()); + self.pending_ids.insert(dl.id); self.enqueue(dl, handle)? } } @@ -671,7 +668,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { .get_mut(dl.id.source_id()) .ok_or_else(|| internal(format!("couldn't find source for `{}`", dl.id)))?; let start = Instant::now(); - let pkg = source.finish_download(&dl.id, data)?; + let pkg = source.finish_download(dl.id, data)?; // Assume that no time has passed while we were calling // `finish_download`, update all speed checks and timeout limits of all diff --git a/src/cargo/core/package_id.rs b/src/cargo/core/package_id.rs index 2f9f9f21497..6574e51b221 100644 --- a/src/cargo/core/package_id.rs +++ b/src/cargo/core/package_id.rs @@ -15,7 +15,8 @@ use core::source::SourceId; use util::{CargoResult, ToSemver}; lazy_static! { - static ref PACKAGE_ID_CACHE: Mutex> = Mutex::new(HashSet::new()); + static ref PACKAGE_ID_CACHE: Mutex> = + Mutex::new(HashSet::new()); } /// Identifier for a specific version of a package in a specific source. @@ -36,7 +37,7 @@ impl PartialEq for PackageIdInner { fn eq(&self, other: &Self) -> bool { self.name == other.name && self.version == other.version - && self.source_id.full_eq(&other.source_id) + && self.source_id.full_eq(other.source_id) } } @@ -87,13 +88,11 @@ impl<'de> de::Deserialize<'de> for PackageId { }; let source_id = SourceId::from_url(url).map_err(de::Error::custom)?; - Ok(PackageId::wrap( - PackageIdInner { - name: InternedString::new(name), - version, - source_id, - } - )) + Ok(PackageId::wrap(PackageIdInner { + name: InternedString::new(name), + version, + source_id, + })) } } @@ -120,18 +119,16 @@ impl PackageId { pub fn new(name: &str, version: T, sid: SourceId) -> CargoResult { let v = version.to_semver()?; - Ok(PackageId::wrap( - PackageIdInner { - name: InternedString::new(name), - version: v, - source_id: sid, - } - )) + Ok(PackageId::wrap(PackageIdInner { + name: InternedString::new(name), + version: v, + source_id: sid, + })) } fn wrap(inner: PackageIdInner) -> PackageId { let mut cache = PACKAGE_ID_CACHE.lock().unwrap(); - let inner = cache.get(&inner).map(|&x| x).unwrap_or_else(|| { + let inner = cache.get(&inner).cloned().unwrap_or_else(|| { let inner = Box::leak(Box::new(inner)); cache.insert(inner); inner @@ -139,42 +136,38 @@ impl PackageId { PackageId { inner } } - pub fn name(&self) -> InternedString { + pub fn name(self) -> InternedString { self.inner.name } - pub fn version(&self) -> &semver::Version { + pub fn version(self) -> &'static semver::Version { &self.inner.version } - pub fn source_id(&self) -> SourceId { + pub fn source_id(self) -> SourceId { self.inner.source_id } - pub fn with_precise(&self, precise: Option) -> PackageId { - PackageId::wrap( - PackageIdInner { - name: self.inner.name, - version: self.inner.version.clone(), - source_id: self.inner.source_id.with_precise(precise), - } - ) + pub fn with_precise(self, precise: Option) -> PackageId { + PackageId::wrap(PackageIdInner { + name: self.inner.name, + version: self.inner.version.clone(), + source_id: self.inner.source_id.with_precise(precise), + }) } - pub fn with_source_id(&self, source: SourceId) -> PackageId { - PackageId::wrap( - PackageIdInner { - name: self.inner.name, - version: self.inner.version.clone(), - source_id: source, - } - ) + pub fn with_source_id(self, source: SourceId) -> PackageId { + PackageId::wrap(PackageIdInner { + name: self.inner.name, + version: self.inner.version.clone(), + source_id: source, + }) } - pub fn stable_hash<'a>(&'a self, workspace: &'a Path) -> PackageIdStableHash<'a> { + pub fn stable_hash(self, workspace: &Path) -> PackageIdStableHash { PackageIdStableHash(self, workspace) } } -pub struct PackageIdStableHash<'a>(&'a PackageId, &'a Path); +pub struct PackageIdStableHash<'a>(PackageId, &'a Path); impl<'a> Hash for PackageIdStableHash<'a> { fn hash(&self, state: &mut S) { @@ -236,7 +229,8 @@ PackageId { version: "1.0.0", source: "registry `https://github.com/rust-lang/crates.io-index`" } -"#.trim(); +"# + .trim(); assert_eq!(pretty, format!("{:#?}", pkg_id)); } diff --git a/src/cargo/core/package_id_spec.rs b/src/cargo/core/package_id_spec.rs index 64312f0812a..5597e6c0d35 100644 --- a/src/cargo/core/package_id_spec.rs +++ b/src/cargo/core/package_id_spec.rs @@ -77,9 +77,9 @@ impl PackageIdSpec { } /// Roughly equivalent to `PackageIdSpec::parse(spec)?.query(i)` - pub fn query_str<'a, I>(spec: &str, i: I) -> CargoResult<&'a PackageId> + pub fn query_str(spec: &str, i: I) -> CargoResult where - I: IntoIterator, + I: IntoIterator, { let spec = PackageIdSpec::parse(spec) .chain_err(|| format_err!("invalid package id specification: `{}`", spec))?; @@ -88,7 +88,7 @@ impl PackageIdSpec { /// Convert a `PackageId` to a `PackageIdSpec`, which will have both the `Version` and `Url` /// fields filled in. - pub fn from_package_id(package_id: &PackageId) -> PackageIdSpec { + pub fn from_package_id(package_id: PackageId) -> PackageIdSpec { PackageIdSpec { name: package_id.name().to_string(), version: Some(package_id.version().clone()), @@ -160,7 +160,7 @@ impl PackageIdSpec { } /// Checks whether the given `PackageId` matches the `PackageIdSpec`. - pub fn matches(&self, package_id: &PackageId) -> bool { + pub fn matches(&self, package_id: PackageId) -> bool { if self.name() != &*package_id.name() { return false; } @@ -179,9 +179,9 @@ impl PackageIdSpec { /// Checks a list of `PackageId`s to find 1 that matches this `PackageIdSpec`. If 0, 2, or /// more are found, then this returns an error. - pub fn query<'a, I>(&self, i: I) -> CargoResult<&'a PackageId> + pub fn query(&self, i: I) -> CargoResult where - I: IntoIterator, + I: IntoIterator, { let mut ids = i.into_iter().filter(|p| self.matches(*p)); let ret = match ids.next() { @@ -212,7 +212,7 @@ impl PackageIdSpec { None => Ok(ret), }; - fn minimize(msg: &mut String, ids: &[&PackageId], spec: &PackageIdSpec) { + fn minimize(msg: &mut String, ids: &[PackageId], spec: &PackageIdSpec) { let mut version_cnt = HashMap::new(); for id in ids { *version_cnt.entry(id.version()).or_insert(0) += 1; @@ -371,9 +371,9 @@ mod tests { let foo = PackageId::new("foo", "1.2.3", sid).unwrap(); let bar = PackageId::new("bar", "1.2.3", sid).unwrap(); - assert!(PackageIdSpec::parse("foo").unwrap().matches(&foo)); - assert!(!PackageIdSpec::parse("foo").unwrap().matches(&bar)); - assert!(PackageIdSpec::parse("foo:1.2.3").unwrap().matches(&foo)); - assert!(!PackageIdSpec::parse("foo:1.2.2").unwrap().matches(&foo)); + assert!(PackageIdSpec::parse("foo").unwrap().matches(foo)); + assert!(!PackageIdSpec::parse("foo").unwrap().matches(bar)); + assert!(PackageIdSpec::parse("foo:1.2.3").unwrap().matches(foo)); + assert!(!PackageIdSpec::parse("foo:1.2.2").unwrap().matches(foo)); } } diff --git a/src/cargo/core/profiles.rs b/src/cargo/core/profiles.rs index beeabac6f01..b7c3f360696 100644 --- a/src/cargo/core/profiles.rs +++ b/src/cargo/core/profiles.rs @@ -67,7 +67,7 @@ impl Profiles { /// workspace. pub fn get_profile( &self, - pkg_id: &PackageId, + pkg_id: PackageId, is_member: bool, unit_for: UnitFor, mode: CompileMode, @@ -163,7 +163,7 @@ struct ProfileMaker { impl ProfileMaker { fn get_profile( &self, - pkg_id: Option<&PackageId>, + pkg_id: Option, is_member: bool, unit_for: UnitFor, ) -> Profile { @@ -292,7 +292,7 @@ impl ProfileMaker { } fn merge_toml( - pkg_id: Option<&PackageId>, + pkg_id: Option, is_member: bool, unit_for: UnitFor, profile: &mut Profile, diff --git a/src/cargo/core/registry.rs b/src/cargo/core/registry.rs index cc2cb1a81ea..97fae9f7a56 100644 --- a/src/cargo/core/registry.rs +++ b/src/cargo/core/registry.rs @@ -264,11 +264,7 @@ impl<'cfg> PackageRegistry<'cfg> { // we want to fill in the `patches_available` map (later used in the // `lock` method) and otherwise store the unlocked summaries in // `patches` to get locked in a future call to `lock_patches`. - let ids = unlocked_summaries - .iter() - .map(|s| s.package_id()) - .cloned() - .collect(); + let ids = unlocked_summaries.iter().map(|s| s.package_id()).collect(); self.patches_available.insert(url.clone(), ids); self.patches.insert(url.clone(), unlocked_summaries); @@ -558,7 +554,7 @@ fn lock(locked: &LockedMap, patches: &HashMap>, summary: Sum let pair = locked .get(&summary.source_id()) .and_then(|map| map.get(&*summary.name())) - .and_then(|vec| vec.iter().find(|&&(ref id, _)| id == summary.package_id())); + .and_then(|vec| vec.iter().find(|&&(id, _)| id == summary.package_id())); trace!("locking summary of {}", summary.package_id()); @@ -595,8 +591,8 @@ fn lock(locked: &LockedMap, patches: &HashMap>, summary: Sum // Cases 1/2 are handled by `matches_id` and case 3 is handled by // falling through to the logic below. if let Some(&(_, ref locked_deps)) = pair { - let locked = locked_deps.iter().find(|id| dep.matches_id(id)); - if let Some(locked) = locked { + let locked = locked_deps.iter().find(|&&id| dep.matches_id(id)); + if let Some(&locked) = locked { trace!("\tfirst hit on {}", locked); let mut dep = dep.clone(); dep.lock_to(locked); @@ -610,8 +606,8 @@ fn lock(locked: &LockedMap, patches: &HashMap>, summary: Sum let v = locked .get(&dep.source_id()) .and_then(|map| map.get(&*dep.package_name())) - .and_then(|vec| vec.iter().find(|&&(ref id, _)| dep.matches_id(id))); - if let Some(&(ref id, _)) = v { + .and_then(|vec| vec.iter().find(|&&(id, _)| dep.matches_id(id))); + if let Some(&(id, _)) = v { trace!("\tsecond hit on {}", id); let mut dep = dep.clone(); dep.lock_to(id); @@ -622,7 +618,9 @@ fn lock(locked: &LockedMap, patches: &HashMap>, summary: Sum // this dependency. let v = patches.get(dep.source_id().url()).map(|vec| { let dep2 = dep.clone(); - let mut iter = vec.iter().filter(move |p| dep2.matches_ignoring_source(p)); + let mut iter = vec + .iter() + .filter(move |&&p| dep2.matches_ignoring_source(p)); (iter.next(), iter) }); if let Some((Some(patch_id), mut remaining)) = v { diff --git a/src/cargo/core/resolver/conflict_cache.rs b/src/cargo/core/resolver/conflict_cache.rs index 670bf48b362..29aac8fd2ed 100644 --- a/src/cargo/core/resolver/conflict_cache.rs +++ b/src/cargo/core/resolver/conflict_cache.rs @@ -37,28 +37,28 @@ impl ConflictStoreTrie { } } ConflictStoreTrie::Node(m) => { - for (pid, store) in m { + for (&pid, store) in m { // if the key is active then we need to check all of the corresponding subTrie. if cx.is_active(pid) { if let Some(o) = store.find_conflicting(cx, filter) { return Some(o); } } // else, if it is not active then there is no way any of the corresponding - // subTrie will be conflicting. + // subTrie will be conflicting. } None } } } - fn insert<'a>( + fn insert( &mut self, - mut iter: impl Iterator, + mut iter: impl Iterator, con: BTreeMap, ) { if let Some(pid) = iter.next() { if let ConflictStoreTrie::Node(p) = self { - p.entry(pid.clone()) + p.entry(pid) .or_insert_with(|| ConflictStoreTrie::Node(HashMap::new())) .insert(iter, con); } // else, We already have a subset of this in the ConflictStore @@ -160,7 +160,7 @@ impl ConflictCache { self.con_from_dep .entry(dep.clone()) .or_insert_with(|| ConflictStoreTrie::Node(HashMap::new())) - .insert(con.keys(), con.clone()); + .insert(con.keys().cloned(), con.clone()); trace!( "{} = \"{}\" adding a skip {:?}", @@ -176,7 +176,7 @@ impl ConflictCache { .insert(dep.clone()); } } - pub fn dependencies_conflicting_with(&self, pid: &PackageId) -> Option<&HashSet> { - self.dep_from_pid.get(pid) + pub fn dependencies_conflicting_with(&self, pid: PackageId) -> Option<&HashSet> { + self.dep_from_pid.get(&pid) } } diff --git a/src/cargo/core/resolver/context.rs b/src/cargo/core/resolver/context.rs index c1dd7e22e96..f49b6301fb4 100644 --- a/src/cargo/core/resolver/context.rs +++ b/src/cargo/core/resolver/context.rs @@ -58,10 +58,10 @@ impl Context { .entry((id.name(), id.source_id())) .or_insert_with(|| Rc::new(Vec::new())); if !prev.iter().any(|c| c == summary) { - self.resolve_graph.push(GraphNode::Add(id.clone())); + self.resolve_graph.push(GraphNode::Add(id)); if let Some(link) = summary.links() { ensure!( - self.links.insert(link, id.clone()).is_none(), + self.links.insert(link, id).is_none(), "Attempting to resolve a with more then one crate with the links={}. \n\ This will not build as is. Consider rebuilding the .lock file.", &*link @@ -84,7 +84,7 @@ impl Context { }; let has_default_feature = summary.features().contains_key("default"); - Ok(match self.resolve_features.get(id) { + Ok(match self.resolve_features.get(&id) { Some(prev) => { features.iter().all(|f| prev.contains(f)) && (!use_default || prev.contains("default") || !has_default_feature) @@ -131,7 +131,7 @@ impl Context { .unwrap_or(&[]) } - pub fn is_active(&self, id: &PackageId) -> bool { + pub fn is_active(&self, id: PackageId) -> bool { self.activations .get(&(id.name(), id.source_id())) .map(|v| v.iter().any(|s| s.package_id() == id)) @@ -142,13 +142,13 @@ impl Context { /// are still active pub fn is_conflicting( &self, - parent: Option<&PackageId>, + parent: Option, conflicting_activations: &BTreeMap, ) -> bool { conflicting_activations .keys() - .chain(parent) - .all(|id| self.is_active(id)) + .chain(parent.as_ref()) + .all(|&id| self.is_active(id)) } /// Return all dependencies and the features we want from them. @@ -230,11 +230,7 @@ impl Context { features ) .into(), - Some(p) => ( - p.package_id().clone(), - ConflictReason::MissingFeatures(features), - ) - .into(), + Some(p) => (p.package_id(), ConflictReason::MissingFeatures(features)).into(), }); } @@ -244,7 +240,7 @@ impl Context { let set = Rc::make_mut( self.resolve_features - .entry(pkgid.clone()) + .entry(pkgid) .or_insert_with(|| Rc::new(HashSet::new())), ); @@ -260,7 +256,7 @@ impl Context { let mut replacements = HashMap::new(); let mut cur = &self.resolve_replacements; while let Some(ref node) = cur.head { - let (k, v) = node.0.clone(); + let (k, v) = node.0; replacements.insert(k, v); cur = &node.1; } diff --git a/src/cargo/core/resolver/encode.rs b/src/cargo/core/resolver/encode.rs index c4e682da3d5..84c04f48327 100644 --- a/src/cargo/core/resolver/encode.rs +++ b/src/cargo/core/resolver/encode.rs @@ -72,7 +72,7 @@ impl EncodableResolve { }; let lookup_id = |enc_id: &EncodablePackageId| -> Option { - live_pkgs.get(enc_id).map(|&(ref id, _)| id.clone()) + live_pkgs.get(enc_id).map(|&(id, _)| id) }; let g = { @@ -343,8 +343,8 @@ impl<'a, 'cfg> ser::Serialize for WorkspaceResolve<'a, 'cfg> { let mut metadata = self.resolve.metadata().clone(); - for id in ids.iter().filter(|id| !id.source_id().is_path()) { - let checksum = match self.resolve.checksums()[*id] { + for &id in ids.iter().filter(|id| !id.source_id().is_path()) { + let checksum = match self.resolve.checksums()[&id] { Some(ref s) => &s[..], None => "", }; @@ -382,7 +382,7 @@ impl<'a, 'cfg> ser::Serialize for WorkspaceResolve<'a, 'cfg> { } } -fn encodable_resolve_node(id: &PackageId, resolve: &Resolve) -> EncodableDependency { +fn encodable_resolve_node(id: PackageId, resolve: &Resolve) -> EncodableDependency { let (replace, deps) = match resolve.replacement(id) { Some(id) => (Some(encodable_package_id(id)), None), None => { @@ -404,7 +404,7 @@ fn encodable_resolve_node(id: &PackageId, resolve: &Resolve) -> EncodableDepende } } -pub fn encodable_package_id(id: &PackageId) -> EncodablePackageId { +pub fn encodable_package_id(id: PackageId) -> EncodablePackageId { EncodablePackageId { name: id.name().to_string(), version: id.version().to_string(), diff --git a/src/cargo/core/resolver/errors.rs b/src/cargo/core/resolver/errors.rs index 5111abbb6be..cb5679e7ac9 100644 --- a/src/cargo/core/resolver/errors.rs +++ b/src/cargo/core/resolver/errors.rs @@ -82,7 +82,7 @@ pub(super) fn activation_error( ResolveError::new( err, graph - .path_to_top(parent.package_id()) + .path_to_top(&parent.package_id()) .into_iter() .cloned() .collect(), @@ -92,7 +92,7 @@ pub(super) fn activation_error( if !candidates.is_empty() { let mut msg = format!("failed to select a version for `{}`.", dep.package_name()); msg.push_str("\n ... required by "); - msg.push_str(&describe_path(&graph.path_to_top(parent.package_id()))); + msg.push_str(&describe_path(&graph.path_to_top(&parent.package_id()))); msg.push_str("\nversions that meet the requirements `"); msg.push_str(&dep.version_req().to_string()); @@ -204,7 +204,7 @@ pub(super) fn activation_error( registry.describe_source(dep.source_id()), ); msg.push_str("required by "); - msg.push_str(&describe_path(&graph.path_to_top(parent.package_id()))); + msg.push_str(&describe_path(&graph.path_to_top(&parent.package_id()))); // If we have a path dependency with a locked version, then this may // indicate that we updated a sub-package and forgot to run `cargo @@ -258,7 +258,7 @@ pub(super) fn activation_error( msg.push_str("\n"); } msg.push_str("required by "); - msg.push_str(&describe_path(&graph.path_to_top(parent.package_id()))); + msg.push_str(&describe_path(&graph.path_to_top(&parent.package_id()))); msg }; diff --git a/src/cargo/core/resolver/mod.rs b/src/cargo/core/resolver/mod.rs index 9b22202608b..afe289f7d06 100644 --- a/src/cargo/core/resolver/mod.rs +++ b/src/cargo/core/resolver/mod.rs @@ -111,7 +111,7 @@ pub fn resolve( summaries: &[(Summary, Method)], replacements: &[(PackageIdSpec, Dependency)], registry: &mut Registry, - try_to_use: &HashSet<&PackageId>, + try_to_use: &HashSet, config: Option<&Config>, print_warnings: bool, ) -> CargoResult { @@ -127,14 +127,14 @@ pub fn resolve( let mut cksums = HashMap::new(); for summary in cx.activations.values().flat_map(|v| v.iter()) { let cksum = summary.checksum().map(|s| s.to_string()); - cksums.insert(summary.package_id().clone(), cksum); + cksums.insert(summary.package_id(), cksum); } let resolve = Resolve::new( cx.graph(), cx.resolve_replacements(), cx.resolve_features .iter() - .map(|(k, v)| (k.clone(), v.iter().map(|x| x.to_string()).collect())) + .map(|(k, v)| (*k, v.iter().map(|x| x.to_string()).collect())) .collect(), cksums, BTreeMap::new(), @@ -358,7 +358,7 @@ fn activate_deps_loop( None }; - let pid = candidate.summary.package_id().clone(); + let pid = candidate.summary.package_id(); let method = Method::Required { dev_deps: false, features: &features, @@ -417,7 +417,7 @@ fn activate_deps_loop( conflicting .iter() .filter(|&(p, _)| p != &pid) - .map(|(p, r)| (p.clone(), r.clone())), + .map(|(&p, r)| (p, r.clone())), ); has_past_conflicting_dep = true; @@ -432,7 +432,7 @@ fn activate_deps_loop( // parent conflict with us. if !has_past_conflicting_dep { if let Some(known_related_bad_deps) = - past_conflicting_activations.dependencies_conflicting_with(&pid) + past_conflicting_activations.dependencies_conflicting_with(pid) { if let Some((other_parent, conflict)) = remaining_deps .iter() @@ -462,9 +462,9 @@ fn activate_deps_loop( conflict .iter() .filter(|&(p, _)| p != &pid) - .map(|(p, r)| (p.clone(), r.clone())), + .map(|(&p, r)| (p, r.clone())), ); - conflicting_activations.insert(other_parent.clone(), rel); + conflicting_activations.insert(other_parent, rel); has_past_conflicting_dep = true; } } @@ -589,8 +589,8 @@ fn activate( ) -> ActivateResult> { if let Some((parent, dep)) = parent { cx.resolve_graph.push(GraphNode::Link( - parent.package_id().clone(), - candidate.summary.package_id().clone(), + parent.package_id(), + candidate.summary.package_id(), dep.clone(), )); } @@ -599,10 +599,8 @@ fn activate( let candidate = match candidate.replace { Some(replace) => { - cx.resolve_replacements.push(( - candidate.summary.package_id().clone(), - replace.package_id().clone(), - )); + cx.resolve_replacements + .push((candidate.summary.package_id(), replace.package_id())); if cx.flag_activated(&replace, method)? && activated { return Ok(None); } @@ -700,10 +698,10 @@ impl RemainingCandidates { // `links` key. If this candidate links to something that's already // linked to by a different package then we've gotta skip this. if let Some(link) = b.summary.links() { - if let Some(a) = cx.links.get(&link) { + if let Some(&a) = cx.links.get(&link) { if a != b.summary.package_id() { conflicting_prev_active - .entry(a.clone()) + .entry(a) .or_insert_with(|| ConflictReason::Links(link)); continue; } @@ -724,7 +722,7 @@ impl RemainingCandidates { { if *a != b.summary { conflicting_prev_active - .entry(a.package_id().clone()) + .entry(a.package_id()) .or_insert(ConflictReason::Semver); continue; } @@ -823,7 +821,7 @@ fn find_candidate( } fn check_cycles(resolve: &Resolve, activations: &Activations) -> CargoResult<()> { - let summaries: HashMap<&PackageId, &Summary> = activations + let summaries: HashMap = activations .values() .flat_map(|v| v.iter()) .map(|s| (s.package_id(), s)) @@ -834,25 +832,25 @@ fn check_cycles(resolve: &Resolve, activations: &Activations) -> CargoResult<()> all_packages.sort_unstable(); let mut checked = HashSet::new(); for pkg in all_packages { - if !checked.contains(pkg) { + if !checked.contains(&pkg) { visit(resolve, pkg, &summaries, &mut HashSet::new(), &mut checked)? } } return Ok(()); - fn visit<'a>( - resolve: &'a Resolve, - id: &'a PackageId, - summaries: &HashMap<&'a PackageId, &Summary>, - visited: &mut HashSet<&'a PackageId>, - checked: &mut HashSet<&'a PackageId>, + fn visit( + resolve: &Resolve, + id: PackageId, + summaries: &HashMap, + visited: &mut HashSet, + checked: &mut HashSet, ) -> CargoResult<()> { // See if we visited ourselves if !visited.insert(id) { bail!( "cyclic package dependency: package `{}` depends on itself. Cycle:\n{}", id, - errors::describe_path(&resolve.path_to_top(id)) + errors::describe_path(&resolve.path_to_top(&id)) ); } @@ -864,7 +862,7 @@ fn check_cycles(resolve: &Resolve, activations: &Activations) -> CargoResult<()> // visitation list as we can't induce a cycle through transitive // dependencies. if checked.insert(id) { - let summary = summaries[id]; + let summary = summaries[&id]; for dep in resolve.deps_not_replaced(id) { let is_transitive = summary .dependencies() @@ -885,7 +883,7 @@ fn check_cycles(resolve: &Resolve, activations: &Activations) -> CargoResult<()> } // Ok, we're done, no longer visiting our node any more - visited.remove(id); + visited.remove(&id); Ok(()) } } diff --git a/src/cargo/core/resolver/resolve.rs b/src/cargo/core/resolver/resolve.rs index 9b77065f9e5..1b2e8dcb928 100644 --- a/src/cargo/core/resolver/resolve.rs +++ b/src/cargo/core/resolver/resolve.rs @@ -41,10 +41,7 @@ impl Resolve { metadata: Metadata, unused_patches: Vec, ) -> Resolve { - let reverse_replacements = replacements - .iter() - .map(|p| (p.1.clone(), p.0.clone())) - .collect(); + let reverse_replacements = replacements.iter().map(|(&p, &r)| (r, p)).collect(); Resolve { graph, replacements, @@ -68,7 +65,7 @@ impl Resolve { if self.iter().any(|id| id == summary.package_id()) { continue; } - self.unused_patches.push(summary.package_id().clone()); + self.unused_patches.push(summary.package_id()); } } @@ -175,39 +172,39 @@ unable to verify that `{0}` is the same as when the lockfile was generated self.graph.sort() } - pub fn iter(&self) -> impl Iterator { - self.graph.iter() + pub fn iter<'a>(&'a self) -> impl Iterator + 'a { + self.graph.iter().cloned() } - pub fn deps(&self, pkg: &PackageId) -> impl Iterator { + pub fn deps(&self, pkg: PackageId) -> impl Iterator { self.graph - .edges(pkg) - .map(move |(id, deps)| (self.replacement(id).unwrap_or(id), deps.as_slice())) + .edges(&pkg) + .map(move |(&id, deps)| (self.replacement(id).unwrap_or(id), deps.as_slice())) } - pub fn deps_not_replaced(&self, pkg: &PackageId) -> impl Iterator { - self.graph.edges(pkg).map(|(id, _)| id) + pub fn deps_not_replaced<'a>(&'a self, pkg: PackageId) -> impl Iterator + 'a { + self.graph.edges(&pkg).map(|(&id, _)| id) } - pub fn replacement(&self, pkg: &PackageId) -> Option<&PackageId> { - self.replacements.get(pkg) + pub fn replacement(&self, pkg: PackageId) -> Option { + self.replacements.get(&pkg).cloned() } pub fn replacements(&self) -> &HashMap { &self.replacements } - pub fn features(&self, pkg: &PackageId) -> &HashSet { - self.features.get(pkg).unwrap_or(&self.empty_features) + pub fn features(&self, pkg: PackageId) -> &HashSet { + self.features.get(&pkg).unwrap_or(&self.empty_features) } - pub fn features_sorted(&self, pkg: &PackageId) -> Vec<&str> { + pub fn features_sorted(&self, pkg: PackageId) -> Vec<&str> { let mut v = Vec::from_iter(self.features(pkg).iter().map(|s| s.as_ref())); v.sort_unstable(); v } - pub fn query(&self, spec: &str) -> CargoResult<&PackageId> { + pub fn query(&self, spec: &str) -> CargoResult { PackageIdSpec::query_str(spec, self.iter()) } @@ -225,8 +222,8 @@ unable to verify that `{0}` is the same as when the lockfile was generated pub fn extern_crate_name( &self, - from: &PackageId, - to: &PackageId, + from: PackageId, + to: PackageId, to_target: &Target, ) -> CargoResult { let deps = if from == to { @@ -256,7 +253,7 @@ unable to verify that `{0}` is the same as when the lockfile was generated Ok(name.to_string()) } - fn dependencies_listed(&self, from: &PackageId, to: &PackageId) -> &[Dependency] { + fn dependencies_listed(&self, from: PackageId, to: PackageId) -> &[Dependency] { // We've got a dependency on `from` to `to`, but this dependency edge // may be affected by [replace]. If the `to` package is listed as the // target of a replacement (aka the key of a reverse replacement map) @@ -266,12 +263,12 @@ unable to verify that `{0}` is the same as when the lockfile was generated // Note that we don't treat `from` as if it's been replaced because // that's where the dependency originates from, and we only replace // targets of dependencies not the originator. - if let Some(replace) = self.reverse_replacements.get(to) { - if let Some(deps) = self.graph.edge(from, replace) { + if let Some(replace) = self.reverse_replacements.get(&to) { + if let Some(deps) = self.graph.edge(&from, replace) { return deps; } } - match self.graph.edge(from, to) { + match self.graph.edge(&from, &to) { Some(ret) => ret, None => panic!("no Dependency listed for `{}` => `{}`", from, to), } diff --git a/src/cargo/core/resolver/types.rs b/src/cargo/core/resolver/types.rs index 6f940afbc3d..b9923bf7775 100644 --- a/src/cargo/core/resolver/types.rs +++ b/src/cargo/core/resolver/types.rs @@ -76,7 +76,7 @@ impl ResolverProgress { pub struct RegistryQueryer<'a> { pub registry: &'a mut (Registry + 'a), replacements: &'a [(PackageIdSpec, Dependency)], - try_to_use: &'a HashSet<&'a PackageId>, + try_to_use: &'a HashSet, cache: HashMap>>, // If set the list of dependency candidates will be sorted by minimal // versions first. That allows `cargo update -Z minimal-versions` which will @@ -88,7 +88,7 @@ impl<'a> RegistryQueryer<'a> { pub fn new( registry: &'a mut Registry, replacements: &'a [(PackageIdSpec, Dependency)], - try_to_use: &'a HashSet<&'a PackageId>, + try_to_use: &'a HashSet, minimal_versions: bool, ) -> Self { RegistryQueryer { @@ -203,8 +203,8 @@ impl<'a> RegistryQueryer<'a> { // prioritized summaries (those in `try_to_use`) and failing that we // list everything from the maximum version to the lowest version. ret.sort_unstable_by(|a, b| { - let a_in_previous = self.try_to_use.contains(a.summary.package_id()); - let b_in_previous = self.try_to_use.contains(b.summary.package_id()); + let a_in_previous = self.try_to_use.contains(&a.summary.package_id()); + let b_in_previous = self.try_to_use.contains(&b.summary.package_id()); let previous_cmp = a_in_previous.cmp(&b_in_previous).reverse(); match previous_cmp { Ordering::Equal => { @@ -279,7 +279,7 @@ impl DepsFrame { .unwrap_or(0) } - pub fn flatten(&self) -> impl Iterator { + pub fn flatten<'a>(&'a self) -> impl Iterator + 'a { self.remaining_siblings .clone() .map(move |(_, (d, _, _))| (self.parent.package_id(), d)) @@ -353,7 +353,7 @@ impl RemainingDeps { } None } - pub fn iter(&mut self) -> impl Iterator { + pub fn iter<'a>(&'a mut self) -> impl Iterator + 'a { self.data.iter().flat_map(|(other, _)| other.flatten()) } } diff --git a/src/cargo/core/source/mod.rs b/src/cargo/core/source/mod.rs index a6dc8aa0955..5617fe65ec0 100644 --- a/src/cargo/core/source/mod.rs +++ b/src/cargo/core/source/mod.rs @@ -49,9 +49,9 @@ pub trait Source { /// The download method fetches the full package for each name and /// version specified. - fn download(&mut self, package: &PackageId) -> CargoResult; + fn download(&mut self, package: PackageId) -> CargoResult; - fn finish_download(&mut self, package: &PackageId, contents: Vec) -> CargoResult; + fn finish_download(&mut self, package: PackageId, contents: Vec) -> CargoResult; /// Generates a unique string which represents the fingerprint of the /// current state of the source. @@ -71,7 +71,7 @@ pub trait Source { /// verification during the `download` step, but this is intended to be run /// just before a crate is compiled so it may perform more expensive checks /// which may not be cacheable. - fn verify(&self, _pkg: &PackageId) -> CargoResult<()> { + fn verify(&self, _pkg: PackageId) -> CargoResult<()> { Ok(()) } @@ -127,11 +127,11 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box { } /// Forwards to `Source::download` - fn download(&mut self, id: &PackageId) -> CargoResult { + fn download(&mut self, id: PackageId) -> CargoResult { (**self).download(id) } - fn finish_download(&mut self, id: &PackageId, data: Vec) -> CargoResult { + fn finish_download(&mut self, id: PackageId, data: Vec) -> CargoResult { (**self).finish_download(id, data) } @@ -141,7 +141,7 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box { } /// Forwards to `Source::verify` - fn verify(&self, pkg: &PackageId) -> CargoResult<()> { + fn verify(&self, pkg: PackageId) -> CargoResult<()> { (**self).verify(pkg) } @@ -183,11 +183,11 @@ impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T { (**self).update() } - fn download(&mut self, id: &PackageId) -> CargoResult { + fn download(&mut self, id: PackageId) -> CargoResult { (**self).download(id) } - fn finish_download(&mut self, id: &PackageId, data: Vec) -> CargoResult { + fn finish_download(&mut self, id: PackageId, data: Vec) -> CargoResult { (**self).finish_download(id, data) } @@ -195,7 +195,7 @@ impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T { (**self).fingerprint(pkg) } - fn verify(&self, pkg: &PackageId) -> CargoResult<()> { + fn verify(&self, pkg: PackageId) -> CargoResult<()> { (**self).verify(pkg) } @@ -255,7 +255,7 @@ impl<'src> SourceMap<'src> { /// Like `HashMap::get`, but first calculates the `SourceId` from a /// `PackageId` - pub fn get_by_package_id(&self, pkg_id: &PackageId) -> Option<&(Source + 'src)> { + pub fn get_by_package_id(&self, pkg_id: PackageId) -> Option<&(Source + 'src)> { self.get(pkg_id.source_id()) } diff --git a/src/cargo/core/source/source_id.rs b/src/cargo/core/source/source_id.rs index 8a5557e6ce1..93766c4b0ba 100644 --- a/src/cargo/core/source/source_id.rs +++ b/src/cargo/core/source/source_id.rs @@ -336,11 +336,11 @@ impl SourceId { self.hash(into) } - pub fn full_eq(&self, other: &SourceId) -> bool { + pub fn full_eq(self, other: SourceId) -> bool { ptr::eq(self.inner, other.inner) } - pub fn full_hash(&self, into: &mut S) { + pub fn full_hash(self, into: &mut S) { ptr::NonNull::from(self.inner).hash(into) } } diff --git a/src/cargo/core/summary.rs b/src/cargo/core/summary.rs index 8610f500e97..087903107d3 100644 --- a/src/cargo/core/summary.rs +++ b/src/cargo/core/summary.rs @@ -71,8 +71,8 @@ impl Summary { }) } - pub fn package_id(&self) -> &PackageId { - &self.inner.package_id + pub fn package_id(&self) -> PackageId { + self.inner.package_id } pub fn name(&self) -> InternedString { self.package_id().name() diff --git a/src/cargo/ops/cargo_clean.rs b/src/cargo/ops/cargo_clean.rs index 0f0f0adea6d..b42c2cb4a8d 100644 --- a/src/cargo/ops/cargo_clean.rs +++ b/src/cargo/ops/cargo_clean.rs @@ -134,7 +134,8 @@ fn rm_rf(path: &Path, config: &Config) -> CargoResult<()> { config .shell() .verbose(|shell| shell.status("Removing", path.display()))?; - paths::remove_dir_all(path).chain_err(|| format_err!("could not remove build directory"))?; + paths::remove_dir_all(path) + .chain_err(|| format_err!("could not remove build directory"))?; } else if m.is_ok() { config .shell() diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 7b188507112..c1abb9348f2 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -28,7 +28,7 @@ use std::sync::Arc; use core::compiler::{BuildConfig, BuildContext, Compilation, Context, DefaultExecutor, Executor}; use core::compiler::{CompileMode, Kind, Unit}; -use core::profiles::{UnitFor, Profiles}; +use core::profiles::{Profiles, UnitFor}; use core::resolver::{Method, Resolve}; use core::{Package, Source, Target}; use core::{PackageId, PackageIdSpec, TargetKind, Workspace}; @@ -109,11 +109,13 @@ impl Packages { pub fn to_package_id_specs(&self, ws: &Workspace) -> CargoResult> { let specs = match *self { - Packages::All => ws.members() + Packages::All => ws + .members() .map(Package::package_id) .map(PackageIdSpec::from_package_id) .collect(), - Packages::OptOut(ref opt_out) => ws.members() + Packages::OptOut(ref opt_out) => ws + .members() .map(Package::package_id) .map(PackageIdSpec::from_package_id) .filter(|p| opt_out.iter().position(|x| *x == p.name()).is_none()) @@ -125,7 +127,8 @@ impl Packages { .iter() .map(|p| PackageIdSpec::parse(p)) .collect::>>()?, - Packages::Default => ws.default_members() + Packages::Default => ws + .default_members() .map(Package::package_id) .map(PackageIdSpec::from_package_id) .collect(), @@ -159,7 +162,8 @@ impl Packages { .ok_or_else(|| { format_err!("package `{}` is not a member of the workspace", name) }) - }).collect::>>()?, + }) + .collect::>>()?, }; Ok(packages) } @@ -243,7 +247,8 @@ pub fn compile_ws<'a>( let resolve = ops::resolve_ws_with_method(ws, source, method, &specs)?; let (packages, resolve_with_overrides) = resolve; - let to_build_ids = specs.iter() + let to_build_ids = specs + .iter() .map(|s| s.query(resolve_with_overrides.iter())) .collect::>>()?; let mut to_builds = packages.get_many(to_build_ids)?; @@ -390,8 +395,11 @@ impl CompileFilter { benches: FilterRule::All, tests: FilterRule::All, } - } else if lib_only || rule_bins.is_specific() || rule_tsts.is_specific() - || rule_exms.is_specific() || rule_bens.is_specific() + } else if lib_only + || rule_bins.is_specific() + || rule_tsts.is_specific() + || rule_exms.is_specific() + || rule_bens.is_specific() { CompileFilter::Only { all_targets: false, @@ -695,7 +703,13 @@ fn generate_targets<'a>( // features available. let mut features_map = HashMap::new(); let mut units = HashSet::new(); - for Proposal { pkg, target, requires_features, mode} in proposals { + for Proposal { + pkg, + target, + requires_features, + mode, + } in proposals + { let unavailable_features = match target.required_features() { Some(rf) => { let features = features_map @@ -730,7 +744,7 @@ fn generate_targets<'a>( fn resolve_all_features( resolve_with_overrides: &Resolve, - package_id: &PackageId, + package_id: PackageId, ) -> HashSet { let mut features = resolve_with_overrides.features(package_id).clone(); @@ -843,7 +857,8 @@ fn find_named_targets<'a>( pkg.targets() .iter() .filter(|target| is_expected_kind(target)) - }).map(|target| (lev_distance(target_name, target.name()), target)) + }) + .map(|target| (lev_distance(target_name, target.name()), target)) .filter(|&(d, _)| d < 4) .min_by_key(|t| t.0) .map(|t| t.1); diff --git a/src/cargo/ops/cargo_doc.rs b/src/cargo/ops/cargo_doc.rs index 3e84120f504..c6d5daff9b0 100644 --- a/src/cargo/ops/cargo_doc.rs +++ b/src/cargo/ops/cargo_doc.rs @@ -31,7 +31,8 @@ pub fn doc(ws: &Workspace, options: &DocOptions) -> CargoResult<()> { )?; let (packages, resolve_with_overrides) = resolve; - let ids = specs.iter() + let ids = specs + .iter() .map(|s| s.query(resolve_with_overrides.iter())) .collect::>>()?; let pkgs = packages.get_many(ids)?; diff --git a/src/cargo/ops/cargo_fetch.rs b/src/cargo/ops/cargo_fetch.rs index c9d25534f8a..de0df384713 100644 --- a/src/cargo/ops/cargo_fetch.rs +++ b/src/cargo/ops/cargo_fetch.rs @@ -34,31 +34,31 @@ pub fn fetch<'a>( continue; } - to_download.push(id.clone()); - let deps = resolve.deps(id) + to_download.push(id); + let deps = resolve + .deps(id) .filter(|&(_id, deps)| { - deps.iter() - .any(|d| { - // If no target was specified then all dependencies can - // be fetched. - let target = match options.target { - Some(ref t) => t, - None => return true, - }; - // If this dependency is only available for certain - // platforms, make sure we're only fetching it for that - // platform. - let platform = match d.platform() { - Some(p) => p, - None => return true, - }; - platform.matches(target, target_info.cfg()) - }) + deps.iter().any(|d| { + // If no target was specified then all dependencies can + // be fetched. + let target = match options.target { + Some(ref t) => t, + None => return true, + }; + // If this dependency is only available for certain + // platforms, make sure we're only fetching it for that + // platform. + let platform = match d.platform() { + Some(p) => p, + None => return true, + }; + platform.matches(target, target_info.cfg()) + }) }) .map(|(id, _deps)| id); deps_to_fetch.extend(deps); } - packages.get_many(&to_download)?; + packages.get_many(to_download)?; } Ok((resolve, packages)) diff --git a/src/cargo/ops/cargo_generate_lockfile.rs b/src/cargo/ops/cargo_generate_lockfile.rs index f25b05e78ea..5ea5fb4d651 100644 --- a/src/cargo/ops/cargo_generate_lockfile.rs +++ b/src/cargo/ops/cargo_generate_lockfile.rs @@ -124,9 +124,9 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions) -> CargoResult<()> fn fill_with_deps<'a>( resolve: &'a Resolve, - dep: &'a PackageId, - set: &mut HashSet<&'a PackageId>, - visited: &mut HashSet<&'a PackageId>, + dep: PackageId, + set: &mut HashSet, + visited: &mut HashSet, ) { if !visited.insert(dep) { return; @@ -137,11 +137,11 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions) -> CargoResult<()> } } - fn compare_dependency_graphs<'a>( - previous_resolve: &'a Resolve, - resolve: &'a Resolve, - ) -> Vec<(Vec<&'a PackageId>, Vec<&'a PackageId>)> { - fn key(dep: &PackageId) -> (&str, SourceId) { + fn compare_dependency_graphs( + previous_resolve: &Resolve, + resolve: &Resolve, + ) -> Vec<(Vec, Vec)> { + fn key(dep: PackageId) -> (&'static str, SourceId) { (dep.name().as_str(), dep.source_id()) } @@ -149,7 +149,7 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions) -> CargoResult<()> // more complicated because the equality for source ids does not take // precise versions into account (e.g. git shas), but we want to take // that into account here. - fn vec_subtract<'a>(a: &[&'a PackageId], b: &[&'a PackageId]) -> Vec<&'a PackageId> { + fn vec_subtract(a: &[PackageId], b: &[PackageId]) -> Vec { a.iter() .filter(|a| { // If this package id is not found in `b`, then it's definitely diff --git a/src/cargo/ops/cargo_install.rs b/src/cargo/ops/cargo_install.rs index 0b0dd026863..815ae44f698 100644 --- a/src/cargo/ops/cargo_install.rs +++ b/src/cargo/ops/cargo_install.rs @@ -359,11 +359,11 @@ fn install_one( } // Failsafe to force replacing metadata for git packages // https://github.com/rust-lang/cargo/issues/4582 - if let Some(set) = list.v1.remove(&pkg.package_id().clone()) { - list.v1.insert(pkg.package_id().clone(), set); + if let Some(set) = list.v1.remove(&pkg.package_id()) { + list.v1.insert(pkg.package_id(), set); } list.v1 - .entry(pkg.package_id().clone()) + .entry(pkg.package_id()) .or_insert_with(BTreeSet::new) .insert(bin.to_string()); } @@ -372,13 +372,7 @@ fn install_one( let pkgs = list .v1 .iter() - .filter_map(|(p, set)| { - if set.is_empty() { - Some(p.clone()) - } else { - None - } - }) + .filter_map(|(&p, set)| if set.is_empty() { Some(p) } else { None }) .collect::>(); for p in pkgs.iter() { list.v1.remove(p); @@ -387,7 +381,7 @@ fn install_one( // If installation was successful record newly installed binaries. if result.is_ok() { list.v1 - .entry(pkg.package_id().clone()) + .entry(pkg.package_id()) .or_insert_with(BTreeSet::new) .extend(to_install.iter().map(|s| s.to_string())); } @@ -518,8 +512,8 @@ where let pkg = { let mut map = SourceMap::new(); map.insert(Box::new(&mut source)); - PackageSet::new(&[pkgid.clone()], map, config)? - .get_one(&pkgid)? + PackageSet::new(&[pkgid], map, config)? + .get_one(pkgid)? .clone() }; Ok((pkg, Box::new(source))) @@ -617,8 +611,8 @@ fn find_duplicates( let name = format!("{}{}", name, env::consts::EXE_SUFFIX); if fs::metadata(dst.join(&name)).is_err() { None - } else if let Some((p, _)) = prev.v1.iter().find(|&(_, v)| v.contains(&name)) { - Some((name, Some(p.clone()))) + } else if let Some((&p, _)) = prev.v1.iter().find(|&(_, v)| v.contains(&name)) { + Some((name, Some(p))) } else { Some((name, None)) } @@ -779,8 +773,8 @@ pub fn uninstall_one( ) -> CargoResult<()> { let crate_metadata = metadata(config, root)?; let metadata = read_crate_list(&crate_metadata)?; - let pkgid = PackageIdSpec::query_str(spec, metadata.v1.keys())?.clone(); - uninstall_pkgid(&crate_metadata, metadata, &pkgid, bins, config) + let pkgid = PackageIdSpec::query_str(spec, metadata.v1.keys().cloned())?; + uninstall_pkgid(&crate_metadata, metadata, pkgid, bins, config) } fn uninstall_cwd(root: &Filesystem, bins: &[String], config: &Config) -> CargoResult<()> { @@ -798,13 +792,13 @@ fn uninstall_cwd(root: &Filesystem, bins: &[String], config: &Config) -> CargoRe fn uninstall_pkgid( crate_metadata: &FileLock, mut metadata: CrateListingV1, - pkgid: &PackageId, + pkgid: PackageId, bins: &[String], config: &Config, ) -> CargoResult<()> { let mut to_remove = Vec::new(); { - let mut installed = match metadata.v1.entry(pkgid.clone()) { + let mut installed = match metadata.v1.entry(pkgid) { Entry::Occupied(e) => e, Entry::Vacant(..) => bail!("package `{}` is not installed", pkgid), }; diff --git a/src/cargo/ops/cargo_output_metadata.rs b/src/cargo/ops/cargo_output_metadata.rs index da6462bb6f0..7f9970d4369 100644 --- a/src/cargo/ops/cargo_output_metadata.rs +++ b/src/cargo/ops/cargo_output_metadata.rs @@ -38,7 +38,7 @@ pub fn output_metadata(ws: &Workspace, opt: &OutputMetadataOptions) -> CargoResu fn metadata_no_deps(ws: &Workspace, _opt: &OutputMetadataOptions) -> CargoResult { Ok(ExportInfo { packages: ws.members().cloned().collect(), - workspace_members: ws.members().map(|pkg| pkg.package_id().clone()).collect(), + workspace_members: ws.members().map(|pkg| pkg.package_id()).collect(), resolve: None, target_directory: ws.target_dir().display().to_string(), version: VERSION, @@ -58,15 +58,15 @@ fn metadata_full(ws: &Workspace, opt: &OutputMetadataOptions) -> CargoResult, } -fn serialize_resolve((packages, resolve): &(HashMap, Resolve), s: S) -> Result +fn serialize_resolve( + (packages, resolve): &(HashMap, Resolve), + s: S, +) -> Result where S: ser::Serializer, { #[derive(Serialize)] - struct Dep<'a> { + struct Dep { name: Option, - pkg: &'a PackageId + pkg: PackageId, } #[derive(Serialize)] struct Node<'a> { - id: &'a PackageId, - dependencies: Vec<&'a PackageId>, - deps: Vec>, + id: PackageId, + dependencies: Vec, + deps: Vec, features: Vec<&'a str>, } - s.collect_seq(resolve - .iter() - .map(|id| Node { + s.collect_seq(resolve.iter().map(|id| { + Node { id, dependencies: resolve.deps(id).map(|(pkg, _deps)| pkg).collect(), - deps: resolve.deps(id) + deps: resolve + .deps(id) .map(|(pkg, _deps)| { - let name = packages.get(pkg) + let name = packages + .get(&pkg) .and_then(|pkg| pkg.targets().iter().find(|t| t.is_lib())) - .and_then(|lib_target| { - resolve.extern_crate_name(id, pkg, lib_target).ok() - }); + .and_then(|lib_target| resolve.extern_crate_name(id, pkg, lib_target).ok()); Dep { name, pkg } }) .collect(), features: resolve.features_sorted(id), - })) + } + })) } diff --git a/src/cargo/ops/cargo_read_manifest.rs b/src/cargo/ops/cargo_read_manifest.rs index 540552b89bd..0e1913e05fd 100644 --- a/src/cargo/ops/cargo_read_manifest.rs +++ b/src/cargo/ops/cargo_read_manifest.rs @@ -165,7 +165,7 @@ fn read_nested_packages( }; let pkg = Package::new(manifest, &manifest_path); - let pkg_id = pkg.package_id().clone(); + let pkg_id = pkg.package_id(); use std::collections::hash_map::Entry; match all_packages.entry(pkg_id) { Entry::Vacant(v) => { diff --git a/src/cargo/ops/cargo_test.rs b/src/cargo/ops/cargo_test.rs index fe410ccde32..2b7f8f57c24 100644 --- a/src/cargo/ops/cargo_test.rs +++ b/src/cargo/ops/cargo_test.rs @@ -1,10 +1,10 @@ use std::ffi::OsString; -use ops; use core::compiler::{Compilation, Doctest}; -use util::{self, CargoTestError, ProcessError, Test}; -use util::errors::CargoResult; use core::Workspace; +use ops; +use util::errors::CargoResult; +use util::{self, CargoTestError, ProcessError, Test}; pub struct TestOptions<'a> { pub compile_opts: ops::CompileOptions<'a>, @@ -172,7 +172,7 @@ fn run_doc_tests( p.arg("--test-args").arg(arg); } - if let Some(cfgs) = compilation.cfgs.get(package.package_id()) { + if let Some(cfgs) = compilation.cfgs.get(&package.package_id()) { for cfg in cfgs.iter() { p.arg("--cfg").arg(cfg); } @@ -185,7 +185,7 @@ fn run_doc_tests( p.arg("--extern").arg(&arg); } - if let Some(flags) = compilation.rustdocflags.get(package.package_id()) { + if let Some(flags) = compilation.rustdocflags.get(&package.package_id()) { p.args(flags); } diff --git a/src/cargo/ops/resolve.rs b/src/cargo/ops/resolve.rs index e0a8aaf3d81..84a9e6511c6 100644 --- a/src/cargo/ops/resolve.rs +++ b/src/cargo/ops/resolve.rs @@ -133,12 +133,12 @@ fn resolve_with_registry<'cfg>( /// /// The previous resolve normally comes from a lockfile. This function does not /// read or write lockfiles from the filesystem. -pub fn resolve_with_previous<'a, 'cfg>( +pub fn resolve_with_previous<'cfg>( registry: &mut PackageRegistry<'cfg>, ws: &Workspace<'cfg>, method: Method, - previous: Option<&'a Resolve>, - to_avoid: Option<&HashSet<&'a PackageId>>, + previous: Option<&Resolve>, + to_avoid: Option<&HashSet>, specs: &[PackageIdSpec], register_patches: bool, warn: bool, @@ -160,7 +160,7 @@ pub fn resolve_with_previous<'a, 'cfg>( ); } - let keep = |p: &&'a PackageId| { + let keep = |p: &PackageId| { !to_avoid_sources.contains(&p.source_id()) && match to_avoid { Some(set) => !set.contains(p), @@ -196,9 +196,9 @@ pub fn resolve_with_previous<'a, 'cfg>( let patches = patches .iter() .map(|dep| { - let unused = previous.unused_patches(); + let unused = previous.unused_patches().iter().cloned(); let candidates = previous.iter().chain(unused); - match candidates.filter(keep).find(|id| dep.matches_id(id)) { + match candidates.filter(keep).find(|&id| dep.matches_id(id)) { Some(id) => { let mut dep = dep.clone(); dep.lock_to(id); @@ -309,7 +309,7 @@ pub fn resolve_with_previous<'a, 'cfg>( Some(r) => root_replace .iter() .map(|&(ref spec, ref dep)| { - for (key, val) in r.replacements().iter() { + for (&key, &val) in r.replacements().iter() { if spec.matches(key) && dep.matches_id(val) && keep(&val) { let mut dep = dep.clone(); dep.lock_to(val); @@ -376,7 +376,7 @@ pub fn get_resolved_packages<'a>( resolve: &Resolve, registry: PackageRegistry<'a>, ) -> CargoResult> { - let ids: Vec = resolve.iter().cloned().collect(); + let ids: Vec = resolve.iter().collect(); registry.get(&ids) } @@ -396,11 +396,11 @@ pub fn get_resolved_packages<'a>( /// /// Note that this function, at the time of this writing, is basically the /// entire fix for #4127 -fn register_previous_locks<'a>( +fn register_previous_locks( ws: &Workspace, registry: &mut PackageRegistry, - resolve: &'a Resolve, - keep: &Fn(&&'a PackageId) -> bool, + resolve: &Resolve, + keep: &Fn(&PackageId) -> bool, ) { let path_pkg = |id: SourceId| { if !id.is_path() { @@ -489,7 +489,7 @@ fn register_previous_locks<'a>( let mut path_deps = ws.members().cloned().collect::>(); let mut visited = HashSet::new(); while let Some(member) = path_deps.pop() { - if !visited.insert(member.package_id().clone()) { + if !visited.insert(member.package_id()) { continue; } for dep in member.dependencies() { @@ -547,19 +547,15 @@ fn register_previous_locks<'a>( // function let's put it to action. Take a look at the previous lockfile, // filter everything by this callback, and then shove everything else into // the registry as a locked dependency. - let keep = |id: &&'a PackageId| keep(id) && !avoid_locking.contains(id); + let keep = |id: &PackageId| keep(id) && !avoid_locking.contains(id); for node in resolve.iter().filter(keep) { - let deps = resolve - .deps_not_replaced(node) - .filter(keep) - .cloned() - .collect(); - registry.register_lock(node.clone(), deps); + let deps = resolve.deps_not_replaced(node).filter(keep).collect(); + registry.register_lock(node, deps); } /// recursively add `node` and all its transitive dependencies to `set` - fn add_deps<'a>(resolve: &'a Resolve, node: &'a PackageId, set: &mut HashSet<&'a PackageId>) { + fn add_deps(resolve: &Resolve, node: PackageId, set: &mut HashSet) { if !set.insert(node) { return; } diff --git a/src/cargo/sources/directory.rs b/src/cargo/sources/directory.rs index 649ffaf4f19..00ffe893179 100644 --- a/src/cargo/sources/directory.rs +++ b/src/cargo/sources/directory.rs @@ -145,22 +145,22 @@ impl<'cfg> Source for DirectorySource<'cfg> { } manifest.set_summary(summary); let pkg = Package::new(manifest, pkg.manifest_path()); - self.packages.insert(pkg.package_id().clone(), (pkg, cksum)); + self.packages.insert(pkg.package_id(), (pkg, cksum)); } Ok(()) } - fn download(&mut self, id: &PackageId) -> CargoResult { + fn download(&mut self, id: PackageId) -> CargoResult { self.packages - .get(id) + .get(&id) .map(|p| &p.0) .cloned() .map(MaybePackage::Ready) .ok_or_else(|| format_err!("failed to find package with id: {}", id)) } - fn finish_download(&mut self, _id: &PackageId, _data: Vec) -> CargoResult { + fn finish_download(&mut self, _id: PackageId, _data: Vec) -> CargoResult { panic!("no downloads to do") } @@ -168,8 +168,8 @@ impl<'cfg> Source for DirectorySource<'cfg> { Ok(pkg.package_id().version().to_string()) } - fn verify(&self, id: &PackageId) -> CargoResult<()> { - let (pkg, cksum) = match self.packages.get(id) { + fn verify(&self, id: PackageId) -> CargoResult<()> { + let (pkg, cksum) = match self.packages.get(&id) { Some(&(ref pkg, ref cksum)) => (pkg, cksum), None => bail!("failed to find entry for `{}` in directory source", id), }; diff --git a/src/cargo/sources/git/source.rs b/src/cargo/sources/git/source.rs index ccd5d9e82d1..49001dd9066 100644 --- a/src/cargo/sources/git/source.rs +++ b/src/cargo/sources/git/source.rs @@ -214,7 +214,7 @@ impl<'cfg> Source for GitSource<'cfg> { self.path_source.as_mut().unwrap().update() } - fn download(&mut self, id: &PackageId) -> CargoResult { + fn download(&mut self, id: PackageId) -> CargoResult { trace!( "getting packages for package id `{}` from `{:?}`", id, @@ -226,7 +226,7 @@ impl<'cfg> Source for GitSource<'cfg> { .download(id) } - fn finish_download(&mut self, _id: &PackageId, _data: Vec) -> CargoResult { + fn finish_download(&mut self, _id: PackageId, _data: Vec) -> CargoResult { panic!("no download should have started") } diff --git a/src/cargo/sources/path.rs b/src/cargo/sources/path.rs index 170162359b2..7a6823c3eda 100644 --- a/src/cargo/sources/path.rs +++ b/src/cargo/sources/path.rs @@ -545,7 +545,7 @@ impl<'cfg> Source for PathSource<'cfg> { Ok(()) } - fn download(&mut self, id: &PackageId) -> CargoResult { + fn download(&mut self, id: PackageId) -> CargoResult { trace!("getting packages; id={}", id); let pkg = self.packages.iter().find(|pkg| pkg.package_id() == id); @@ -554,7 +554,7 @@ impl<'cfg> Source for PathSource<'cfg> { .ok_or_else(|| internal(format!("failed to find {} in path source", id))) } - fn finish_download(&mut self, _id: &PackageId, _data: Vec) -> CargoResult { + fn finish_download(&mut self, _id: PackageId, _data: Vec) -> CargoResult { panic!("no download should have started") } diff --git a/src/cargo/sources/registry/index.rs b/src/cargo/sources/registry/index.rs index c2556d3f9aa..9fdf9eee1b2 100644 --- a/src/cargo/sources/registry/index.rs +++ b/src/cargo/sources/registry/index.rs @@ -124,7 +124,7 @@ impl<'cfg> RegistryIndex<'cfg> { } /// Return the hash listed for a specified PackageId. - pub fn hash(&mut self, pkg: &PackageId, load: &mut RegistryData) -> CargoResult { + pub fn hash(&mut self, pkg: PackageId, load: &mut RegistryData) -> CargoResult { let name = pkg.name().as_str(); let version = pkg.version(); if let Some(s) = self.hashes.get(name).and_then(|v| v.get(version)) { diff --git a/src/cargo/sources/registry/local.rs b/src/cargo/sources/registry/local.rs index 82c95052ee8..cea6690f3c1 100644 --- a/src/cargo/sources/registry/local.rs +++ b/src/cargo/sources/registry/local.rs @@ -69,7 +69,7 @@ impl<'cfg> RegistryData for LocalRegistry<'cfg> { Ok(()) } - fn download(&mut self, pkg: &PackageId, checksum: &str) -> CargoResult { + fn download(&mut self, pkg: PackageId, checksum: &str) -> CargoResult { let crate_file = format!("{}-{}.crate", pkg.name(), pkg.version()); let mut crate_file = self.root.open_ro(&crate_file, self.config, "crate file")?; @@ -106,7 +106,7 @@ impl<'cfg> RegistryData for LocalRegistry<'cfg> { fn finish_download( &mut self, - _pkg: &PackageId, + _pkg: PackageId, _checksum: &str, _data: &[u8], ) -> CargoResult { diff --git a/src/cargo/sources/registry/mod.rs b/src/cargo/sources/registry/mod.rs index 7aa2fbf7dfd..d0e3fc32c99 100644 --- a/src/cargo/sources/registry/mod.rs +++ b/src/cargo/sources/registry/mod.rs @@ -348,15 +348,15 @@ pub trait RegistryData { ) -> CargoResult<()>; fn config(&mut self) -> CargoResult>; fn update_index(&mut self) -> CargoResult<()>; - fn download(&mut self, pkg: &PackageId, checksum: &str) -> CargoResult; + fn download(&mut self, pkg: PackageId, checksum: &str) -> CargoResult; fn finish_download( &mut self, - pkg: &PackageId, + pkg: PackageId, checksum: &str, data: &[u8], ) -> CargoResult; - fn is_crate_downloaded(&self, _pkg: &PackageId) -> bool { + fn is_crate_downloaded(&self, _pkg: PackageId) -> bool { true } } @@ -418,7 +418,7 @@ impl<'cfg> RegistrySource<'cfg> { /// compiled. /// /// No action is taken if the source looks like it's already unpacked. - fn unpack_package(&self, pkg: &PackageId, tarball: &FileLock) -> CargoResult { + fn unpack_package(&self, pkg: PackageId, tarball: &FileLock) -> CargoResult { let dst = self .src_path .join(&format!("{}-{}", pkg.name(), pkg.version())); @@ -475,7 +475,7 @@ impl<'cfg> RegistrySource<'cfg> { Ok(()) } - fn get_pkg(&mut self, package: &PackageId, path: &FileLock) -> CargoResult { + fn get_pkg(&mut self, package: PackageId, path: &FileLock) -> CargoResult { let path = self .unpack_package(package, path) .chain_err(|| internal(format!("failed to unpack package `{}`", package)))?; @@ -566,7 +566,7 @@ impl<'cfg> Source for RegistrySource<'cfg> { Ok(()) } - fn download(&mut self, package: &PackageId) -> CargoResult { + fn download(&mut self, package: PackageId) -> CargoResult { let hash = self.index.hash(package, &mut *self.ops)?; match self.ops.download(package, &hash)? { MaybeLock::Ready(file) => self.get_pkg(package, &file).map(MaybePackage::Ready), @@ -576,7 +576,7 @@ impl<'cfg> Source for RegistrySource<'cfg> { } } - fn finish_download(&mut self, package: &PackageId, data: Vec) -> CargoResult { + fn finish_download(&mut self, package: PackageId, data: Vec) -> CargoResult { let hash = self.index.hash(package, &mut *self.ops)?; let file = self.ops.finish_download(package, &hash, &data)?; self.get_pkg(package, &file) diff --git a/src/cargo/sources/registry/remote.rs b/src/cargo/sources/registry/remote.rs index 9c1bf4557a4..6f9c2b61f39 100644 --- a/src/cargo/sources/registry/remote.rs +++ b/src/cargo/sources/registry/remote.rs @@ -126,7 +126,7 @@ impl<'cfg> RemoteRegistry<'cfg> { Ok(Ref::map(self.tree.borrow(), |s| s.as_ref().unwrap())) } - fn filename(&self, pkg: &PackageId) -> String { + fn filename(&self, pkg: PackageId) -> String { format!("{}-{}.crate", pkg.name(), pkg.version()) } } @@ -213,7 +213,7 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> { Ok(()) } - fn download(&mut self, pkg: &PackageId, _checksum: &str) -> CargoResult { + fn download(&mut self, pkg: PackageId, _checksum: &str) -> CargoResult { let filename = self.filename(pkg); // Attempt to open an read-only copy first to avoid an exclusive write @@ -246,7 +246,7 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> { fn finish_download( &mut self, - pkg: &PackageId, + pkg: PackageId, checksum: &str, data: &[u8], ) -> CargoResult { @@ -269,7 +269,7 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> { Ok(dst) } - fn is_crate_downloaded(&self, pkg: &PackageId) -> bool { + fn is_crate_downloaded(&self, pkg: PackageId) -> bool { let filename = format!("{}-{}.crate", pkg.name(), pkg.version()); let path = Path::new(&filename); diff --git a/src/cargo/sources/replaced.rs b/src/cargo/sources/replaced.rs index 006e514de0f..128a8529df9 100644 --- a/src/cargo/sources/replaced.rs +++ b/src/cargo/sources/replaced.rs @@ -70,11 +70,11 @@ impl<'cfg> Source for ReplacedSource<'cfg> { Ok(()) } - fn download(&mut self, id: &PackageId) -> CargoResult { + fn download(&mut self, id: PackageId) -> CargoResult { let id = id.with_source_id(self.replace_with); let pkg = self .inner - .download(&id) + .download(id) .chain_err(|| format!("failed to download replaced source {}", self.to_replace))?; Ok(match pkg { MaybePackage::Ready(pkg) => { @@ -84,11 +84,11 @@ impl<'cfg> Source for ReplacedSource<'cfg> { }) } - fn finish_download(&mut self, id: &PackageId, data: Vec) -> CargoResult { + fn finish_download(&mut self, id: PackageId, data: Vec) -> CargoResult { let id = id.with_source_id(self.replace_with); let pkg = self .inner - .finish_download(&id, data) + .finish_download(id, data) .chain_err(|| format!("failed to download replaced source {}", self.to_replace))?; Ok(pkg.map_source(self.replace_with, self.to_replace)) } @@ -97,9 +97,9 @@ impl<'cfg> Source for ReplacedSource<'cfg> { self.inner.fingerprint(id) } - fn verify(&self, id: &PackageId) -> CargoResult<()> { + fn verify(&self, id: PackageId) -> CargoResult<()> { let id = id.with_source_id(self.replace_with); - self.inner.verify(&id) + self.inner.verify(id) } fn describe(&self) -> String { diff --git a/src/cargo/util/machine_message.rs b/src/cargo/util/machine_message.rs index 1c683934a08..993c00521fa 100644 --- a/src/cargo/util/machine_message.rs +++ b/src/cargo/util/machine_message.rs @@ -16,7 +16,7 @@ pub fn emit(t: &T) { #[derive(Serialize)] pub struct FromCompiler<'a> { - pub package_id: &'a PackageId, + pub package_id: PackageId, pub target: &'a Target, pub message: Box, } @@ -29,7 +29,7 @@ impl<'a> Message for FromCompiler<'a> { #[derive(Serialize)] pub struct Artifact<'a> { - pub package_id: &'a PackageId, + pub package_id: PackageId, pub target: &'a Target, pub profile: ArtifactProfile, pub features: Vec, @@ -57,7 +57,7 @@ pub struct ArtifactProfile { #[derive(Serialize)] pub struct BuildScript<'a> { - pub package_id: &'a PackageId, + pub package_id: PackageId, pub linked_libs: &'a [String], pub linked_paths: &'a [String], pub cfgs: &'a [String], diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index d85219cc883..e14fdd4f241 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -666,7 +666,7 @@ impl TomlProject { } struct Context<'a, 'b> { - pkgid: Option<&'a PackageId>, + pkgid: Option, deps: &'a mut Vec, source_id: SourceId, nested_paths: &'a mut Vec, @@ -873,7 +873,7 @@ impl TomlManifest { { let mut cx = Context { - pkgid: Some(&pkgid), + pkgid: Some(pkgid), deps: &mut deps, source_id, nested_paths: &mut nested_paths, diff --git a/tests/testsuite/member_errors.rs b/tests/testsuite/member_errors.rs index a4f82cff8b0..17d8da56d97 100644 --- a/tests/testsuite/member_errors.rs +++ b/tests/testsuite/member_errors.rs @@ -1,7 +1,7 @@ +use cargo::core::resolver::ResolveError; use cargo::core::{compiler::CompileMode, Workspace}; use cargo::ops::{self, CompileOptions}; use cargo::util::{config::Config, errors::ManifestError}; -use cargo::core::resolver::ResolveError; use support::project; @@ -150,5 +150,5 @@ fn member_manifest_version_error() { let resolve_err: &ResolveError = error.downcast_ref().expect("Not a ResolveError"); let package_path = resolve_err.package_path(); assert_eq!(package_path.len(), 1, "package_path: {:?}", package_path); - assert_eq!(&package_path[0], member_bar.package_id()); + assert_eq!(package_path[0], member_bar.package_id()); } diff --git a/tests/testsuite/resolve.rs b/tests/testsuite/resolve.rs index 3cae07b282c..e9644e628d5 100644 --- a/tests/testsuite/resolve.rs +++ b/tests/testsuite/resolve.rs @@ -133,7 +133,7 @@ proptest! { let not_selected: Vec<_> = input .iter() .cloned() - .filter(|x| !r.contains(x.package_id())) + .filter(|x| !r.contains(&x.package_id())) .collect(); if !not_selected.is_empty() { let indexs_to_unpublish: Vec<_> = indexs_to_unpublish.iter().map(|x| x.get(¬_selected)).collect(); @@ -1001,7 +1001,7 @@ fn incomplete_information_skiping() { input .iter() .cloned() - .filter(|x| &package_to_yank != x.package_id()) + .filter(|x| package_to_yank != x.package_id()) .collect(), ); assert_eq!(input.len(), new_reg.len() + 1); @@ -1070,7 +1070,7 @@ fn incomplete_information_skiping_2() { input .iter() .cloned() - .filter(|x| &package_to_yank != x.package_id()) + .filter(|x| package_to_yank != x.package_id()) .collect(), ); assert_eq!(input.len(), new_reg.len() + 1); @@ -1120,7 +1120,7 @@ fn incomplete_information_skiping_3() { input .iter() .cloned() - .filter(|x| &package_to_yank != x.package_id()) + .filter(|x| package_to_yank != x.package_id()) .collect(), ); assert_eq!(input.len(), new_reg.len() + 1); diff --git a/tests/testsuite/support/resolver.rs b/tests/testsuite/support/resolver.rs index a1544e30441..758db0ec2f6 100644 --- a/tests/testsuite/support/resolver.rs +++ b/tests/testsuite/support/resolver.rs @@ -42,7 +42,7 @@ pub fn resolve_and_validated( if p.name().ends_with("-sys") { assert!(links.insert(p.name())); } - stack.extend(resolve.deps(&p).map(|(dp, deps)| { + stack.extend(resolve.deps(p).map(|(dp, deps)| { for d in deps { assert!(d.matches_id(dp)); } From 09cc2f2cb636f4c37cb4850d5acbd0b19b65ff85 Mon Sep 17 00:00:00 2001 From: Zach Reizner Date: Wed, 7 Nov 2018 13:01:15 -0800 Subject: [PATCH 112/128] add --no-vcs option to `cargo package` If `cargo package` is run for a crate that is not version controlled in a way that cargo expects, git2 will overreach upwards and grab a irrelevant .git repo. This change adds `--no-vcs` as an option to `cargo package` to prevent this. --- src/bin/cargo/commands/package.rs | 5 +++++ src/cargo/ops/cargo_package.rs | 9 +++++++-- src/cargo/ops/registry.rs | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/bin/cargo/commands/package.rs b/src/bin/cargo/commands/package.rs index f5e9d918462..1da90841c15 100644 --- a/src/bin/cargo/commands/package.rs +++ b/src/bin/cargo/commands/package.rs @@ -23,6 +23,10 @@ pub fn cli() -> App { "allow-dirty", "Allow dirty working directories to be packaged", )) + .arg(opt( + "no-vcs", + "Ignore version control for packaging", + )) .arg_target_triple("Build for the target triple") .arg_target_dir() .arg_manifest_path() @@ -39,6 +43,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { list: args.is_present("list"), check_metadata: !args.is_present("no-metadata"), allow_dirty: args.is_present("allow-dirty"), + use_vcs: !args.is_present("no-vcs"), target: args.target(), jobs: args.jobs()?, registry: None, diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index 37c82238ad5..f6da49935a7 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -24,6 +24,7 @@ pub struct PackageOpts<'cfg> { pub check_metadata: bool, pub allow_dirty: bool, pub verify: bool, + pub use_vcs: bool, pub jobs: Option, pub target: Option, pub registry: Option, @@ -55,8 +56,12 @@ pub fn package(ws: &Workspace, opts: &PackageOpts) -> CargoResult CargoResult<()> { list: false, check_metadata: true, allow_dirty: opts.allow_dirty, + use_vcs: true, target: opts.target.clone(), jobs: opts.jobs, registry: opts.registry.clone(), From fd5fb6e2dc4c6b06402d4c14df270edf6cd56b57 Mon Sep 17 00:00:00 2001 From: Zach Reizner Date: Tue, 27 Nov 2018 17:09:46 -0800 Subject: [PATCH 113/128] use allow-dirty option in `cargo package` to skip vcs checks To avoid introducing another flag, this change uses the `--allow-dirty` flag to skip checking for vcs information. This is logical because a user that passes that flag is indicating to `cargo package` that they do not care about the state of vcs at that time. --- src/bin/cargo/commands/package.rs | 5 ----- src/cargo/ops/cargo_package.rs | 3 +-- src/cargo/ops/registry.rs | 1 - 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/bin/cargo/commands/package.rs b/src/bin/cargo/commands/package.rs index 1da90841c15..f5e9d918462 100644 --- a/src/bin/cargo/commands/package.rs +++ b/src/bin/cargo/commands/package.rs @@ -23,10 +23,6 @@ pub fn cli() -> App { "allow-dirty", "Allow dirty working directories to be packaged", )) - .arg(opt( - "no-vcs", - "Ignore version control for packaging", - )) .arg_target_triple("Build for the target triple") .arg_target_dir() .arg_manifest_path() @@ -43,7 +39,6 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { list: args.is_present("list"), check_metadata: !args.is_present("no-metadata"), allow_dirty: args.is_present("allow-dirty"), - use_vcs: !args.is_present("no-vcs"), target: args.target(), jobs: args.jobs()?, registry: None, diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index f6da49935a7..e33961c1498 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -24,7 +24,6 @@ pub struct PackageOpts<'cfg> { pub check_metadata: bool, pub allow_dirty: bool, pub verify: bool, - pub use_vcs: bool, pub jobs: Option, pub target: Option, pub registry: Option, @@ -56,7 +55,7 @@ pub fn package(ws: &Workspace, opts: &PackageOpts) -> CargoResult CargoResult<()> { list: false, check_metadata: true, allow_dirty: opts.allow_dirty, - use_vcs: true, target: opts.target.clone(), jobs: opts.jobs, registry: opts.registry.clone(), From aa8eff88a96169b5737a2276b5c50766e71ed4ec Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 30 Nov 2018 14:13:30 +0000 Subject: [PATCH 114/128] Switch to pretty_env_logger, under --features pretty-env-logger --- Cargo.toml | 2 ++ src/bin/cargo/main.rs | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 2eb0a7d5894..d2d48ff7671 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ crypto-hash = "0.3.1" curl = { version = "0.4.19", features = ['http2'] } curl-sys = "0.4.15" env_logger = "0.6.0" +pretty_env_logger = { version = "0.2", optional = true } failure = "0.1.2" filetime = "0.2" flate2 = { version = "1.0.3", features = ['zlib'] } @@ -105,3 +106,4 @@ doc = false [features] vendored-openssl = ['openssl/vendored'] +pretty-env-logger = ['pretty_env_logger'] diff --git a/src/bin/cargo/main.rs b/src/bin/cargo/main.rs index 4dd90777f72..8839fdd41b7 100644 --- a/src/bin/cargo/main.rs +++ b/src/bin/cargo/main.rs @@ -3,6 +3,9 @@ extern crate cargo; extern crate clap; +#[cfg(feature = "pretty-env-logger")] +extern crate pretty_env_logger; +#[cfg(not(feature = "pretty-env-logger"))] extern crate env_logger; #[macro_use] extern crate failure; @@ -28,6 +31,9 @@ mod commands; use command_prelude::*; fn main() { + #[cfg(feature = "pretty-env-logger")] + pretty_env_logger::init(); + #[cfg(not(feature = "pretty-env-logger"))] env_logger::init(); cargo::core::maybe_allow_nightly_features(); From b93863789356e2cc926d78f1e516030f4964bbdb Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 30 Nov 2018 16:48:22 +0000 Subject: [PATCH 115/128] Use expect over unwrap, for panic-in-panic aborts ... doesn't help, but it can't hurt either, right? --- tests/testsuite/support/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testsuite/support/mod.rs b/tests/testsuite/support/mod.rs index 9c8fbec795c..2c7c25e7f52 100644 --- a/tests/testsuite/support/mod.rs +++ b/tests/testsuite/support/mod.rs @@ -682,7 +682,7 @@ impl Execs { self.expect_json = Some( expected .split("\n\n") - .map(|obj| obj.parse().unwrap()) + .map(|line| line.parse().expect("line to be a valid JSON value")) .collect(), ); self From 8c7f6af4e8d2dec25474d0ac9c7916a4796faedf Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Wed, 14 Nov 2018 17:31:49 -0500 Subject: [PATCH 116/128] I think this shrinks better. --- tests/testsuite/support/resolver.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/testsuite/support/resolver.rs b/tests/testsuite/support/resolver.rs index 758db0ec2f6..9dca8fcfd8e 100644 --- a/tests/testsuite/support/resolver.rs +++ b/tests/testsuite/support/resolver.rs @@ -355,8 +355,13 @@ pub fn registry_strategy( ) -> impl Strategy { let name = string_regex("[A-Za-z][A-Za-z0-9_-]*(-sys)?").unwrap(); - let raw_version = [..max_versions; 3]; - let version_from_raw = |v: &[usize; 3]| format!("{}.{}.{}", v[0], v[1], v[2]); + let raw_version = ..max_versions.pow(3); + let version_from_raw = move |r: usize| { + let major = ((r / max_versions) / max_versions) % max_versions; + let minor = (r / max_versions) % max_versions; + let patch = r % max_versions; + format!("{}.{}.{}", major, minor, patch) + }; // If this is false than the crate will depend on the nonexistent "bad" // instead of the complex set we generated for it. @@ -365,7 +370,7 @@ pub fn registry_strategy( let list_of_versions = btree_map(raw_version, allow_deps, 1..=max_versions).prop_map(move |ver| { ver.into_iter() - .map(|a| (version_from_raw(&a.0), a.1)) + .map(|a| (version_from_raw(a.0), a.1)) .collect::>() }); From 3bd1005c0da0bab2d0be3e43f5587b0a0123a87b Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Sat, 1 Dec 2018 10:04:03 -0500 Subject: [PATCH 117/128] regain determinism --- src/cargo/core/resolver/conflict_cache.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cargo/core/resolver/conflict_cache.rs b/src/cargo/core/resolver/conflict_cache.rs index 29aac8fd2ed..479c3029d93 100644 --- a/src/cargo/core/resolver/conflict_cache.rs +++ b/src/cargo/core/resolver/conflict_cache.rs @@ -11,7 +11,7 @@ enum ConflictStoreTrie { Leaf(BTreeMap), /// a Node is a map from an element to a subTrie where /// all the Sets in the subTrie contains that element. - Node(HashMap), + Node(BTreeMap), } impl ConflictStoreTrie { @@ -59,7 +59,7 @@ impl ConflictStoreTrie { if let Some(pid) = iter.next() { if let ConflictStoreTrie::Node(p) = self { p.entry(pid) - .or_insert_with(|| ConflictStoreTrie::Node(HashMap::new())) + .or_insert_with(|| ConflictStoreTrie::Node(BTreeMap::new())) .insert(iter, con); } // else, We already have a subset of this in the ConflictStore } else { @@ -159,7 +159,7 @@ impl ConflictCache { pub fn insert(&mut self, dep: &Dependency, con: &BTreeMap) { self.con_from_dep .entry(dep.clone()) - .or_insert_with(|| ConflictStoreTrie::Node(HashMap::new())) + .or_insert_with(|| ConflictStoreTrie::Node(BTreeMap::new())) .insert(con.keys().cloned(), con.clone()); trace!( From b5453f391235b889e853ed30eb427c804be1d592 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Sat, 1 Dec 2018 10:17:26 -0500 Subject: [PATCH 118/128] inline the filter --- src/cargo/core/resolver/conflict_cache.rs | 28 ++++++++++------------- src/cargo/core/resolver/mod.rs | 4 +--- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/cargo/core/resolver/conflict_cache.rs b/src/cargo/core/resolver/conflict_cache.rs index 479c3029d93..04424dfc420 100644 --- a/src/cargo/core/resolver/conflict_cache.rs +++ b/src/cargo/core/resolver/conflict_cache.rs @@ -17,17 +17,14 @@ enum ConflictStoreTrie { impl ConflictStoreTrie { /// Finds any known set of conflicts, if any, /// which are activated in `cx` and pass the `filter` specified? - fn find_conflicting( + fn find_conflicting( &self, cx: &Context, - filter: &F, - ) -> Option<&BTreeMap> - where - for<'r> F: Fn(&'r &BTreeMap) -> bool, - { + must_contain: Option, + ) -> Option<&BTreeMap> { match self { ConflictStoreTrie::Leaf(c) => { - if filter(&c) { + if must_contain.map(|f| c.contains_key(&f)).unwrap_or(true) { // is_conflicting checks that all the elements are active, // but we have checked each one by the recursion of this function. debug_assert!(cx.is_conflicting(None, c)); @@ -40,7 +37,7 @@ impl ConflictStoreTrie { for (&pid, store) in m { // if the key is active then we need to check all of the corresponding subTrie. if cx.is_active(pid) { - if let Some(o) = store.find_conflicting(cx, filter) { + if let Some(o) = store.find_conflicting(cx, must_contain) { return Some(o); } } // else, if it is not active then there is no way any of the corresponding @@ -134,23 +131,22 @@ impl ConflictCache { } /// Finds any known set of conflicts, if any, /// which are activated in `cx` and pass the `filter` specified? - pub fn find_conflicting( + pub fn find_conflicting( &self, cx: &Context, dep: &Dependency, - filter: F, - ) -> Option<&BTreeMap> - where - for<'r> F: Fn(&'r &BTreeMap) -> bool, - { - self.con_from_dep.get(dep)?.find_conflicting(cx, &filter) + must_contain: Option, + ) -> Option<&BTreeMap> { + self.con_from_dep + .get(dep)? + .find_conflicting(cx, must_contain) } pub fn conflicting( &self, cx: &Context, dep: &Dependency, ) -> Option<&BTreeMap> { - self.find_conflicting(cx, dep, |_| true) + self.find_conflicting(cx, dep, None) } /// Add to the cache a conflict of the form: diff --git a/src/cargo/core/resolver/mod.rs b/src/cargo/core/resolver/mod.rs index afe289f7d06..6df605cb1b7 100644 --- a/src/cargo/core/resolver/mod.rs +++ b/src/cargo/core/resolver/mod.rs @@ -442,9 +442,7 @@ fn activate_deps_loop( }) .filter_map(|(other_parent, other_dep)| { past_conflicting_activations - .find_conflicting(&cx, &other_dep, |con| { - con.contains_key(&pid) - }) + .find_conflicting(&cx, &other_dep, Some(pid)) .map(|con| (other_parent, con)) }) .next() From 50af11758740ac87e1eda0c1192369b5f978ef61 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Sat, 1 Dec 2018 10:42:56 -0500 Subject: [PATCH 119/128] we only need to search the part of the Trie that may contain the filler --- src/cargo/core/resolver/conflict_cache.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/cargo/core/resolver/conflict_cache.rs b/src/cargo/core/resolver/conflict_cache.rs index 04424dfc420..79173202ba0 100644 --- a/src/cargo/core/resolver/conflict_cache.rs +++ b/src/cargo/core/resolver/conflict_cache.rs @@ -24,20 +24,21 @@ impl ConflictStoreTrie { ) -> Option<&BTreeMap> { match self { ConflictStoreTrie::Leaf(c) => { - if must_contain.map(|f| c.contains_key(&f)).unwrap_or(true) { - // is_conflicting checks that all the elements are active, - // but we have checked each one by the recursion of this function. - debug_assert!(cx.is_conflicting(None, c)); - Some(c) - } else { - None - } + // is_conflicting checks that all the elements are active, + // but we have checked each one by the recursion of this function. + debug_assert!(cx.is_conflicting(None, c)); + Some(c) } ConflictStoreTrie::Node(m) => { - for (&pid, store) in m { + for (&pid, store) in must_contain + .map(|f| m.range(..=f)) + .unwrap_or_else(|| m.range(..)) + { // if the key is active then we need to check all of the corresponding subTrie. if cx.is_active(pid) { - if let Some(o) = store.find_conflicting(cx, must_contain) { + if let Some(o) = + store.find_conflicting(cx, must_contain.filter(|&f| f == pid)) + { return Some(o); } } // else, if it is not active then there is no way any of the corresponding From 2814ca2b191e7480435171503c6bd72e236f402a Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Sat, 1 Dec 2018 15:01:34 -0500 Subject: [PATCH 120/128] fuzzer found a bad case --- tests/testsuite/resolve.rs | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/testsuite/resolve.rs b/tests/testsuite/resolve.rs index e9644e628d5..ce66ce06288 100644 --- a/tests/testsuite/resolve.rs +++ b/tests/testsuite/resolve.rs @@ -1201,3 +1201,43 @@ fn large_conflict_cache() { let reg = registry(input); let _ = resolve(&pkg_id("root"), root_deps, ®); } + +#[test] +fn conflict_store_bug() { + let input = vec![ + pkg!(("A", "0.0.3")), + pkg!(("A", "0.0.5")), + pkg!(("A", "0.0.9") => [dep("bad"),]), + pkg!(("A", "0.0.10") => [dep("bad"),]), + pkg!(("L-sys", "0.0.1") => [dep("bad"),]), + pkg!(("L-sys", "0.0.5")), + pkg!(("R", "0.0.4") => [ + dep_req("L-sys", "= 0.0.5"), + ]), + pkg!(("R", "0.0.6")), + pkg!(("a-sys", "0.0.5")), + pkg!(("a-sys", "0.0.11")), + pkg!(("c", "0.0.12") => [ + dep_req("R", ">= 0.0.3, <= 0.0.4"), + ]), + pkg!(("c", "0.0.13") => [ + dep_req("a-sys", ">= 0.0.8, <= 0.0.11"), + ]), + pkg!(("c0", "0.0.6") => [ + dep_req("L-sys", "<= 0.0.2"), + ]), + pkg!(("c0", "0.0.10") => [ + dep_req("A", ">= 0.0.9, <= 0.0.10"), + dep_req("a-sys", "= 0.0.5"), + ]), + pkg!("j" => [ + dep_req("A", ">= 0.0.3, <= 0.0.5"), + dep_req("R", ">=0.0.4, <= 0.0.6"), + dep_req("c", ">= 0.0.9"), + dep_req("c0", ">= 0.0.6"), + ]), + ]; + + let reg = registry(input.clone()); + let _ = resolve_and_validated(&pkg_id("root"), vec![dep("j")], ®); +} From eeaebfcdfce39d1701d27015cca8b717996d0047 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Sat, 1 Dec 2018 19:08:12 -0500 Subject: [PATCH 121/128] oops... --- src/cargo/core/resolver/conflict_cache.rs | 28 +++++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/cargo/core/resolver/conflict_cache.rs b/src/cargo/core/resolver/conflict_cache.rs index 79173202ba0..aacab60be18 100644 --- a/src/cargo/core/resolver/conflict_cache.rs +++ b/src/cargo/core/resolver/conflict_cache.rs @@ -24,10 +24,15 @@ impl ConflictStoreTrie { ) -> Option<&BTreeMap> { match self { ConflictStoreTrie::Leaf(c) => { - // is_conflicting checks that all the elements are active, - // but we have checked each one by the recursion of this function. - debug_assert!(cx.is_conflicting(None, c)); - Some(c) + if must_contain.is_none() { + // is_conflicting checks that all the elements are active, + // but we have checked each one by the recursion of this function. + debug_assert!(cx.is_conflicting(None, c)); + Some(c) + } else { + // we did not find `must_contain` so we need to keep looking. + None + } } ConflictStoreTrie::Node(m) => { for (&pid, store) in must_contain @@ -37,7 +42,7 @@ impl ConflictStoreTrie { // if the key is active then we need to check all of the corresponding subTrie. if cx.is_active(pid) { if let Some(o) = - store.find_conflicting(cx, must_contain.filter(|&f| f == pid)) + store.find_conflicting(cx, must_contain.filter(|&f| f != pid)) { return Some(o); } @@ -138,9 +143,18 @@ impl ConflictCache { dep: &Dependency, must_contain: Option, ) -> Option<&BTreeMap> { - self.con_from_dep + let out = self + .con_from_dep .get(dep)? - .find_conflicting(cx, must_contain) + .find_conflicting(cx, must_contain); + if cfg!(debug_assertions) { + if let Some(f) = must_contain { + if let Some(c) = &out { + assert!(c.contains_key(&f)); + } + } + } + out } pub fn conflicting( &self, From 3b0f31e2d7095b265d88cd1b089997862c15833d Mon Sep 17 00:00:00 2001 From: Edwin Amsler Date: Sun, 2 Dec 2018 01:36:12 -0600 Subject: [PATCH 122/128] Remove `cmake` as a requirement No longer needed as outlined in https://github.com/rust-lang/cargo/issues/6367 --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ed8ca979102..404c7e73712 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@ Cargo requires the following tools and packages to build: * `python` * `curl` (on Unix) -* `cmake` * OpenSSL headers (only for Unix, this is the `libssl-dev` package on ubuntu) * `cargo` and `rustc` From ebced4acc6edbda7396b4223c2960ea75c6f3745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 2 Dec 2018 12:28:56 +0100 Subject: [PATCH 123/128] progress: display "Downloading 1 crate" instead of "Downloading 1 crates" --- src/cargo/core/package.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 85064c1d531..e52d4124bf1 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -816,7 +816,12 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { return Ok(()); } } - let mut msg = format!("{} crates", self.pending.len()); + let pending = self.pending.len(); + let mut msg = if pending == 1 { + format!("{} crate", pending) + } else { + format!("{} crates", pending) + }; match why { WhyTick::Extracting(krate) => { msg.push_str(&format!(", extracting {} ...", krate)); From 31f9a5cac5831f89c4d2fca3cb58aa7b2658fe42 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 5 Dec 2018 09:29:10 -0800 Subject: [PATCH 124/128] Fix built-in aliases taking arguments. --- src/bin/cargo/cli.rs | 18 ++++------- src/bin/cargo/commands/build.rs | 2 +- src/bin/cargo/commands/check.rs | 2 +- src/bin/cargo/commands/mod.rs | 28 +++++------------ src/bin/cargo/commands/run.rs | 2 +- src/bin/cargo/commands/test.rs | 2 +- src/bin/cargo/main.rs | 43 +++++++++++++-------------- tests/testsuite/cargo_alias_config.rs | 14 +++++++++ 8 files changed, 52 insertions(+), 59 deletions(-) diff --git a/src/bin/cargo/cli.rs b/src/bin/cargo/cli.rs index 1d6af33cad2..246a1544515 100644 --- a/src/bin/cargo/cli.rs +++ b/src/bin/cargo/cli.rs @@ -4,7 +4,7 @@ use clap::{AppSettings, Arg, ArgMatches}; use cargo::{self, CliResult, Config}; -use super::commands::{self, BuiltinExec}; +use super::commands; use super::list_commands; use command_prelude::*; @@ -107,28 +107,22 @@ fn expand_aliases( commands::builtin_exec(cmd), super::aliased_command(config, cmd)?, ) { - ( - Some(BuiltinExec { - alias_for: None, .. - }), - Some(_), - ) => { + (Some(_), Some(_)) => { // User alias conflicts with a built-in subcommand config.shell().warn(format!( "user-defined alias `{}` is ignored, because it is shadowed by a built-in command", cmd, ))?; } - (_, Some(mut user_alias)) => { - // User alias takes precedence over built-in aliases - user_alias.extend( + (_, Some(mut alias)) => { + alias.extend( args.values_of("") .unwrap_or_default() .map(|s| s.to_string()), ); let args = cli() .setting(AppSettings::NoBinaryName) - .get_matches_from_safe(user_alias)?; + .get_matches_from_safe(alias)?; return expand_aliases(config, args); } (_, None) => {} @@ -165,7 +159,7 @@ fn execute_subcommand(config: &mut Config, args: &ArgMatches) -> CliResult { .unwrap_or_default(), )?; - if let Some(BuiltinExec { exec, .. }) = commands::builtin_exec(cmd) { + if let Some(exec) = commands::builtin_exec(cmd) { return exec(config, subcommand_args); } diff --git a/src/bin/cargo/commands/build.rs b/src/bin/cargo/commands/build.rs index d919936c9b0..eac4ae3c095 100644 --- a/src/bin/cargo/commands/build.rs +++ b/src/bin/cargo/commands/build.rs @@ -4,7 +4,7 @@ use cargo::ops; pub fn cli() -> App { subcommand("build") - // subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases() + // subcommand aliases are handled in aliased_command() // .alias("b") .about("Compile a local package and all of its dependencies") .arg_package_spec( diff --git a/src/bin/cargo/commands/check.rs b/src/bin/cargo/commands/check.rs index 2edb6089c1b..c8715cdfa01 100644 --- a/src/bin/cargo/commands/check.rs +++ b/src/bin/cargo/commands/check.rs @@ -4,7 +4,7 @@ use cargo::ops; pub fn cli() -> App { subcommand("check") - // subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases() + // subcommand aliases are handled in aliased_command() // .alias("c") .about("Check a local package and all of its dependencies for errors") .arg_package_spec( diff --git a/src/bin/cargo/commands/mod.rs b/src/bin/cargo/commands/mod.rs index 3f7e4bf26e2..d7d8bc70886 100644 --- a/src/bin/cargo/commands/mod.rs +++ b/src/bin/cargo/commands/mod.rs @@ -35,16 +35,11 @@ pub fn builtin() -> Vec { ] } -pub struct BuiltinExec<'a> { - pub exec: fn(&'a mut Config, &'a ArgMatches) -> CliResult, - pub alias_for: Option<&'static str>, -} - -pub fn builtin_exec(cmd: &str) -> Option { - let exec = match cmd { + pub fn builtin_exec(cmd: &str) -> Option CliResult> { + let f = match cmd { "bench" => bench::exec, - "build" | "b" => build::exec, - "check" | "c" => check::exec, + "build" => build::exec, + "check" => check::exec, "clean" => clean::exec, "doc" => doc::exec, "fetch" => fetch::exec, @@ -62,11 +57,11 @@ pub fn builtin_exec(cmd: &str) -> Option { "pkgid" => pkgid::exec, "publish" => publish::exec, "read-manifest" => read_manifest::exec, - "run" | "r" => run::exec, + "run" => run::exec, "rustc" => rustc::exec, "rustdoc" => rustdoc::exec, "search" => search::exec, - "test" | "t" => test::exec, + "test" => test::exec, "uninstall" => uninstall::exec, "update" => update::exec, "verify-project" => verify_project::exec, @@ -74,16 +69,7 @@ pub fn builtin_exec(cmd: &str) -> Option { "yank" => yank::exec, _ => return None, }; - - let alias_for = match cmd { - "b" => Some("build"), - "c" => Some("check"), - "r" => Some("run"), - "t" => Some("test"), - _ => None, - }; - - Some(BuiltinExec { exec, alias_for }) + Some(f) } pub mod bench; diff --git a/src/bin/cargo/commands/run.rs b/src/bin/cargo/commands/run.rs index 6b1b8d06914..ca55fc6f3f0 100644 --- a/src/bin/cargo/commands/run.rs +++ b/src/bin/cargo/commands/run.rs @@ -5,7 +5,7 @@ use cargo::ops::{self, CompileFilter}; pub fn cli() -> App { subcommand("run") - // subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases() + // subcommand aliases are handled in aliased_command() // .alias("r") .setting(AppSettings::TrailingVarArg) .about("Run the main binary of the local package (src/main.rs)") diff --git a/src/bin/cargo/commands/test.rs b/src/bin/cargo/commands/test.rs index 19c50e854f6..d581bf61a06 100644 --- a/src/bin/cargo/commands/test.rs +++ b/src/bin/cargo/commands/test.rs @@ -4,7 +4,7 @@ use cargo::ops::{self, CompileFilter}; pub fn cli() -> App { subcommand("test") - // subcommand aliases are handled in commands::builtin_exec() and cli::expand_aliases() + // subcommand aliases are handled in aliased_command() // .alias("t") .setting(AppSettings::TrailingVarArg) .about("Execute all unit and integration tests of a local package") diff --git a/src/bin/cargo/main.rs b/src/bin/cargo/main.rs index 8839fdd41b7..da2b439c725 100644 --- a/src/bin/cargo/main.rs +++ b/src/bin/cargo/main.rs @@ -63,28 +63,27 @@ fn main() { fn aliased_command(config: &Config, command: &str) -> CargoResult>> { let alias_name = format!("alias.{}", command); - let mut result = Ok(None); - match config.get_string(&alias_name) { - Ok(value) => { - if let Some(record) = value { - let alias_commands = record - .val - .split_whitespace() - .map(|s| s.to_string()) - .collect(); - result = Ok(Some(alias_commands)); - } - } - Err(_) => { - let value = config.get_list(&alias_name)?; - if let Some(record) = value { - let alias_commands: Vec = - record.val.iter().map(|s| s.0.to_string()).collect(); - result = Ok(Some(alias_commands)); - } - } - } - result + let user_alias = match config.get_string(&alias_name) { + Ok(Some(record)) => Some( + record + .val + .split_whitespace() + .map(|s| s.to_string()) + .collect(), + ), + Ok(None) => None, + Err(_) => config + .get_list(&alias_name)? + .map(|record| record.val.iter().map(|s| s.0.to_string()).collect()), + }; + let result = user_alias.or_else(|| match command { + "b" => Some(vec!["build".to_string()]), + "c" => Some(vec!["check".to_string()]), + "r" => Some(vec!["run".to_string()]), + "t" => Some(vec!["test".to_string()]), + _ => None, + }); + Ok(result) } /// List all runnable commands diff --git a/tests/testsuite/cargo_alias_config.rs b/tests/testsuite/cargo_alias_config.rs index c1893d1609f..8867c8cdaa7 100644 --- a/tests/testsuite/cargo_alias_config.rs +++ b/tests/testsuite/cargo_alias_config.rs @@ -148,3 +148,17 @@ fn alias_override_builtin_alias() { ", ).run(); } + +#[test] +fn builtin_alias_takes_options() { + // #6381 + let p = project() + .file("src/lib.rs", "") + .file( + "examples/ex1.rs", + r#"fn main() { println!("{}", std::env::args().skip(1).next().unwrap()) }"#, + ) + .build(); + + p.cargo("r --example ex1 -- asdf").with_stdout("asdf").run(); +} From df1bf8e80a8d1653c023b5fb8f7c5b3044638b39 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 6 Dec 2018 00:14:37 -0800 Subject: [PATCH 125/128] Fix fetching crates on old versions of libcurl. --- src/cargo/core/package.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index e52d4124bf1..c700db6ddd4 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -416,6 +416,23 @@ impl<'cfg> PackageSet<'cfg> { } } +// When dynamically linked against libcurl, we want to ignore some failures +// when using old versions that don't support certain features. +macro_rules! try_old_curl { + ($e:expr, $msg:expr) => { + let result = $e; + if cfg!(target_os = "macos") { + if let Err(e) = result { + warn!("ignoring libcurl {} error: {}", $msg, e); + } + } else { + result.with_context(|_| { + format_err!("failed to enable {}, is curl not built right?", $msg) + })?; + } + }; +} + impl<'a, 'cfg> Downloads<'a, 'cfg> { /// Starts to download the package for the `id` specified. /// @@ -480,14 +497,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { // errors here on OSX, but consider this a fatal error to not activate // HTTP/2 on all other platforms. if self.set.multiplexing { - let result = handle.http_version(HttpVersion::V2); - if cfg!(target_os = "macos") { - if let Err(e) = result { - warn!("ignoring HTTP/2 activation error: {}", e) - } - } else { - result.with_context(|_| "failed to enable HTTP2, is curl not built right?")?; - } + try_old_curl!(handle.http_version(HttpVersion::V2), "HTTP2"); } else { handle.http_version(HttpVersion::V11)?; } @@ -499,7 +509,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> { // Once the main one is opened we realized that pipelining is possible // and multiplexing is possible with static.crates.io. All in all this // reduces the number of connections done to a more manageable state. - handle.pipewait(true)?; + try_old_curl!(handle.pipewait(true), "pipewait"); handle.write_function(move |buf| { debug!("{} - {} bytes of data", token, buf.len()); From 8f9114a4cbc7903e9f0e60a44e46b7f4ddf77313 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 27 Dec 2018 15:47:09 -0800 Subject: [PATCH 126/128] Fix fingerprint calculation for patched deps. --- src/cargo/core/compiler/fingerprint.rs | 6 +-- tests/testsuite/freshness.rs | 59 +++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/cargo/core/compiler/fingerprint.rs b/src/cargo/core/compiler/fingerprint.rs index 4a3d4fa4f95..0ec6274b830 100644 --- a/src/cargo/core/compiler/fingerprint.rs +++ b/src/cargo/core/compiler/fingerprint.rs @@ -228,7 +228,6 @@ struct MtimeSlot(Mutex>); impl Fingerprint { fn update_local(&self, root: &Path) -> CargoResult<()> { - let mut hash_busted = false; for local in self.local.iter() { match *local { LocalFingerprint::MtimeBased(ref slot, ref path) => { @@ -238,12 +237,9 @@ impl Fingerprint { } LocalFingerprint::EnvBased(..) | LocalFingerprint::Precalculated(..) => continue, } - hash_busted = true; } - if hash_busted { - *self.memoized_hash.lock().unwrap() = None; - } + *self.memoized_hash.lock().unwrap() = None; Ok(()) } diff --git a/tests/testsuite/freshness.rs b/tests/testsuite/freshness.rs index 00c50e69053..0537a6b5ed2 100644 --- a/tests/testsuite/freshness.rs +++ b/tests/testsuite/freshness.rs @@ -4,7 +4,7 @@ use std::io::prelude::*; use support::paths::CargoPathExt; use support::registry::Package; use support::sleep_ms; -use support::{basic_manifest, project}; +use support::{basic_manifest, is_coarse_mtime, project}; #[test] fn modifying_and_moving() { @@ -1177,3 +1177,60 @@ fn reuse_panic_pm() { ) .run(); } + +#[test] +fn bust_patched_dep() { + Package::new("registry1", "0.1.0").publish(); + Package::new("registry2", "0.1.0") + .dep("registry1", "0.1.0") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + + [dependencies] + registry2 = "0.1.0" + + [patch.crates-io] + registry1 = { path = "reg1new" } + "#, + ) + .file("src/lib.rs", "") + .file("reg1new/Cargo.toml", &basic_manifest("registry1", "0.1.0")) + .file("reg1new/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + + File::create(&p.root().join("reg1new/src/lib.rs")).unwrap(); + if is_coarse_mtime() { + sleep_ms(1000); + } + + p.cargo("build") + .with_stderr( + "\ +[COMPILING] registry1 v0.1.0 ([..]) +[COMPILING] registry2 v0.1.0 +[COMPILING] foo v0.0.1 ([..]) +[FINISHED] [..] +", + ) + .run(); + + p.cargo("build -v") + .with_stderr( + "\ +[FRESH] registry1 v0.1.0 ([..]) +[FRESH] registry2 v0.1.0 +[FRESH] foo v0.0.1 ([..]) +[FINISHED] [..] +", + ) + .run(); +} From eef5fa31f844a689b8dbac8c35754ab9e5c7cbbe Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 10 Dec 2018 18:00:43 -0800 Subject: [PATCH 127/128] Migrate from trim_right to trim_end The `trim_right` method is soon to be deprecated! --- src/cargo/core/compiler/custom_build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index 400bd4641e5..a4ec2cc73e8 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -466,7 +466,7 @@ impl BuildOutput { let key = iter.next(); let value = iter.next(); let (key, value) = match (key, value) { - (Some(a), Some(b)) => (a, b.trim_right()), + (Some(a), Some(b)) => (a, b.trim_end()), // line started with `cargo:` but didn't match `key=value` _ => bail!("Wrong output in {}: `{}`", whence, line), }; From 0b55e9e560059870e8635f6ad5134ffeee449d8a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 2 Jan 2019 12:11:42 -0800 Subject: [PATCH 128/128] Bump CI minimum version to 1.31 so that `trim_end` is available. --- .travis.yml | 2 +- appveyor.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index a421a7b9334..49b35327950 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ matrix: # increased every 6 weeks or so when the first PR to use a new feature. - env: TARGET=x86_64-unknown-linux-gnu ALT=i686-unknown-linux-gnu - rust: 1.28.0 + rust: 1.31.0 script: - rustup toolchain install nightly - cargo +nightly generate-lockfile -Z minimal-versions diff --git a/appveyor.yml b/appveyor.yml index 282633ee071..6a2e257850b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,7 +11,7 @@ install: - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - - if defined MINIMAL_VERSIONS rustup toolchain install 1.28.0 + - if defined MINIMAL_VERSIONS rustup toolchain install 1.31.0 - if defined OTHER_TARGET rustup target add %OTHER_TARGET% - rustc -V - cargo -V @@ -25,5 +25,5 @@ test_script: # we don't have ci time to run the full `cargo test` with `minimal-versions` like # - if defined MINIMAL_VERSIONS cargo +nightly generate-lockfile -Z minimal-versions && cargo +stable test # so we just run `cargo check --tests` like - - if defined MINIMAL_VERSIONS cargo +nightly generate-lockfile -Z minimal-versions && cargo +1.28.0 check --tests + - if defined MINIMAL_VERSIONS cargo +nightly generate-lockfile -Z minimal-versions && cargo +1.31.0 check --tests - if NOT defined MINIMAL_VERSIONS cargo test