Skip to content

Commit 6af6789

Browse files
committed
Make crates.io timeout error specific to crates.io
1 parent 35cb079 commit 6af6789

File tree

2 files changed

+60
-57
lines changed

2 files changed

+60
-57
lines changed

src/cargo/ops/registry.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,7 @@ fn verify_dependencies(
129129
// This extra hostname check is mostly to assist with testing,
130130
// but also prevents someone using `--index` to specify
131131
// something that points to crates.io.
132-
let is_crates_io = registry
133-
.host()
134-
.to_url()
135-
.map(|u| u.host_str() == Some("crates.io"))
136-
.unwrap_or(false);
137-
if registry_src.is_default_registry() || is_crates_io {
132+
if registry_src.is_default_registry() || registry.host_is_crates_io() {
138133
bail!("crates cannot be published to crates.io with dependencies sourced from other\n\
139134
registries either publish `{}` on crates.io or pull it into this repository\n\
140135
and specify it with a path and version\n\

src/crates-io/lib.rs

Lines changed: 59 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use http::status::StatusCode;
1313
use serde::{Deserialize, Serialize};
1414
use serde_json;
1515
use url::percent_encoding::{percent_encode, QUERY_ENCODE_SET};
16+
use url::Url;
1617

1718
pub type Result<T> = std::result::Result<T, failure::Error>;
1819

@@ -142,6 +143,12 @@ impl Registry {
142143
&self.host
143144
}
144145

146+
pub fn host_is_crates_io(&self) -> bool {
147+
Url::parse(self.host())
148+
.map(|u| u.host_str() == Some("crates.io"))
149+
.unwrap_or(false)
150+
}
151+
145152
pub fn add_owners(&mut self, krate: &str, owners: &[&str]) -> Result<String> {
146153
let body = serde_json::to_string(&OwnersReq { users: owners })?;
147154
let body = self.put(&format!("/crates/{}/owners", krate), body.as_bytes())?;
@@ -208,7 +215,7 @@ impl Registry {
208215
headers.append(&format!("Authorization: {}", token))?;
209216
self.handle.http_headers(headers)?;
210217

211-
let body = handle(&mut self.handle, &mut |buf| body.read(buf).unwrap_or(0))?;
218+
let body = self.handle(&mut |buf| body.read(buf).unwrap_or(0))?;
212219

213220
let response = if body.is_empty() {
214221
"{}".parse()?
@@ -301,61 +308,62 @@ impl Registry {
301308
Some(mut body) => {
302309
self.handle.upload(true)?;
303310
self.handle.in_filesize(body.len() as u64)?;
304-
handle(&mut self.handle, &mut |buf| body.read(buf).unwrap_or(0))
311+
self.handle(&mut |buf| body.read(buf).unwrap_or(0))
305312
}
306-
None => handle(&mut self.handle, &mut |_| 0),
313+
None => self.handle(&mut |_| 0),
307314
}
308315
}
309-
}
310-
311-
fn handle(handle: &mut Easy, read: &mut dyn FnMut(&mut [u8]) -> usize) -> Result<String> {
312-
let mut headers = Vec::new();
313-
let mut body = Vec::new();
314-
let started;
315-
{
316-
let mut handle = handle.transfer();
317-
handle.read_function(|buf| Ok(read(buf)))?;
318-
handle.write_function(|data| {
319-
body.extend_from_slice(data);
320-
Ok(data.len())
321-
})?;
322-
handle.header_function(|data| {
323-
headers.push(String::from_utf8_lossy(data).into_owned());
324-
true
325-
})?;
326-
started = Instant::now();
327-
handle.perform()?;
328-
}
329316

330-
let body = match String::from_utf8(body) {
331-
Ok(body) => body,
332-
Err(..) => bail!("response body was not valid utf-8"),
333-
};
334-
let errors = serde_json::from_str::<ApiErrorList>(&body).ok().map(|s| {
335-
s.errors.into_iter().map(|s| s.detail).collect::<Vec<_>>()
336-
});
337-
338-
match (handle.response_code()?, errors) {
339-
(0, None) | (200, None) => {},
340-
(503, _) if started.elapsed().as_secs() >= 29 => {
341-
bail!("Request took more than 30 seconds to complete. If you're\
342-
trying to upload a crate it may be too large")
317+
fn handle(&mut self, read: &mut dyn FnMut(&mut [u8]) -> usize) -> Result<String> {
318+
let mut headers = Vec::new();
319+
let mut body = Vec::new();
320+
let started;
321+
{
322+
let mut handle = self.handle.transfer();
323+
handle.read_function(|buf| Ok(read(buf)))?;
324+
handle.write_function(|data| {
325+
body.extend_from_slice(data);
326+
Ok(data.len())
327+
})?;
328+
handle.header_function(|data| {
329+
headers.push(String::from_utf8_lossy(data).into_owned());
330+
true
331+
})?;
332+
started = Instant::now();
333+
handle.perform()?;
343334
}
344-
(code, Some(errors)) => {
345-
let code = StatusCode::from_u16(code as _)?;
346-
bail!("api errors (status {}): {}", code, errors.join(", "))
335+
336+
let body = match String::from_utf8(body) {
337+
Ok(body) => body,
338+
Err(..) => bail!("response body was not valid utf-8"),
339+
};
340+
let errors = serde_json::from_str::<ApiErrorList>(&body).ok().map(|s| {
341+
s.errors.into_iter().map(|s| s.detail).collect::<Vec<_>>()
342+
});
343+
344+
match (self.handle.response_code()?, errors) {
345+
(0, None) | (200, None) => {},
346+
(503, _) if started.elapsed().as_secs() >= 29 && self.host_is_crates_io() => {
347+
bail!("Request timed out after 30 seconds. If you're trying to \
348+
upload a crate it may be too large. If the crate is under \
349+
10MB in size, you can email help@crates.io for assistance.")
350+
}
351+
(code, Some(errors)) => {
352+
let code = StatusCode::from_u16(code as _)?;
353+
bail!("api errors (status {}): {}", code, errors.join(", "))
354+
}
355+
(code, None) => bail!(
356+
"failed to get a 200 OK response, got {}\n\
357+
headers:\n\
358+
\t{}\n\
359+
body:\n\
360+
{}",
361+
code,
362+
headers.join("\n\t"),
363+
body,
364+
),
347365
}
348-
(code, None) => bail!(
349-
"failed to get a 200 OK response, got {}\n\
350-
headers:\n\
351-
\t{}\n\
352-
body:\n\
353-
{}",
354-
code,
355-
headers.join("\n\t"),
356-
body,
357-
),
358-
}
359366

360-
Ok(body)
367+
Ok(body)
368+
}
361369
}

0 commit comments

Comments
 (0)