-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[wip] Download crates in parallel #5161
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,8 @@ use std::fs::{self, File}; | |
use std::iter::repeat; | ||
use std::time::Duration; | ||
|
||
use curl::easy::{Easy, SslOpt}; | ||
use curl::easy::{Easy, Easy2, Handler, SslOpt, HttpVersion}; | ||
use curl::multi::Multi; | ||
use git2; | ||
use registry::{Registry, NewCrate, NewCrateDependency}; | ||
|
||
|
@@ -291,6 +292,60 @@ pub fn http_handle(config: &Config) -> CargoResult<Easy> { | |
Ok(handle) | ||
} | ||
|
||
pub fn http_multi_handle(config: &Config) -> CargoResult<Multi> { | ||
if config.frozen() { | ||
bail!("attempting to make an HTTP request, but --frozen was \ | ||
specified") | ||
} | ||
if !config.network_allowed() { | ||
bail!("can't make HTTP request in the offline mode") | ||
} | ||
|
||
let mut handle = Multi::new(); | ||
let pipelining = config.get_bool("http.pipelining")?.map(|x| x.val).unwrap_or(true); | ||
let multiplexing = config.get_bool("http.multiplexing")?.map(|x| x.val).unwrap_or(true); | ||
handle.pipelining(pipelining, multiplexing)?; | ||
Ok(handle) | ||
} | ||
|
||
/// Create a curl Easy2 handle with default options | ||
pub fn http_easy2_handle<H: Handler>(config: &Config, handler: H) -> CargoResult<Easy2<H>> { | ||
let mut handle = Easy2::new(handler); | ||
configure_http_easy2_handle(config, &mut handle)?; | ||
Ok(handle) | ||
} | ||
|
||
pub fn configure_http_easy2_handle<H: Handler>(config: &Config, handle: &mut Easy2<H>) -> CargoResult<()> { | ||
// This is a duplicate of configure_http_handle, due to Easy and Easy2 | ||
// being completely different types. | ||
// 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_limit(10 /* bytes per second */)?; | ||
handle.low_speed_time(Duration::new(30, 0))?; | ||
handle.useragent(&version().to_string())?; | ||
// Not all cURL builds support HTTP/2, ignore any errors. | ||
if config.get_bool("http.http2")?.map(|x| x.val).unwrap_or(true) { | ||
let _ = handle.http_version(HttpVersion::V2TLS); | ||
} | ||
if let Some(proxy) = http_proxy(config)? { | ||
handle.proxy(&proxy)?; | ||
} | ||
if let Some(cainfo) = config.get_path("http.cainfo")? { | ||
handle.cainfo(&cainfo.val)?; | ||
} | ||
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))?; | ||
} | ||
Ok(()) | ||
} | ||
|
||
pub fn needs_custom_http_transport(config: &Config) -> CargoResult<bool> { | ||
let proxy_exists = http_proxy_exists(config)?; | ||
let timeout = http_timeout(config)?; | ||
|
@@ -310,6 +365,10 @@ pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult< | |
handle.low_speed_limit(10 /* bytes per second */)?; | ||
handle.low_speed_time(Duration::new(30, 0))?; | ||
handle.useragent(&version().to_string())?; | ||
// Not all cURL builds support HTTP/2, ignore any errors. | ||
if config.get_bool("http.http2")?.map(|x| x.val).unwrap_or(true) { | ||
let _ = handle.http_version(HttpVersion::V2TLS); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this perhaps emit a warning if an error happens? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have this option turned on by default, so it could be annoying and confusing to those using old libcurl. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh good point yeah, I was thinking that if you explicitly configured |
||
} | ||
if let Some(proxy) = http_proxy(config)? { | ||
handle.proxy(&proxy)?; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this method is pretty interesting. Long ago Cargo had the signature:
but we then changed to lazily download packages in order to close #2394. That was the easiest fix to do at the time but I think is causing issues with this patch.
I think to get the most benefit out of the scheme (downloading in parallel) we'll want to probably implement a separate pass over
Context
to collect a list of packages that we're gonna want to download. Perhaps that could be deferred to a future PR, though? (just want to make sure we don't lose track of this)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm willing to do some refactor, thanks for the reference!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW I've been thinking recently that the end-state here may be to "future-ify" everything where we just create a gob of futures and throw them at tokio to do the whole build, although that's certainly not a refactoring required for this PR!