cli: add acquire_cli (#179837)

* cli: add acquire_cli

As given in my draft document, pipes a CLI of the given platform to the
specified process, for example:

```js
const cmd = await rpc.call('acquire_cli', {
	command: 'node',
	args: [
		'-e',
		'process.stdin.pipe(fs.createWriteStream("c:/users/conno/downloads/hello-cli"))',
	],
	platform: Platform.LinuxX64,
	quality: 'insider',
});
```

It genericizes caching so that the CLI is also cached on the host, just
like servers.

* fix bug
This commit is contained in:
Connor Peet
2023-04-13 11:18:48 -07:00
committed by GitHub
parent 24c44070ae
commit f743297aa1
15 changed files with 489 additions and 405 deletions

View File

@@ -477,9 +477,11 @@ pub enum CodeError {
UnsupportedPlatform(String),
#[error("This machine not meet {name}'s prerequisites, expected either...: {bullets}")]
PrerequisitesFailed { name: &'static str, bullets: String },
#[error("failed to spawn process: {0:?}")]
ProcessSpawnFailed(std::io::Error)
ProcessSpawnFailed(std::io::Error),
#[error("download appears corrupted, please retry ({0})")]
CorruptDownload(&'static str),
}
makeAnyError!(

View File

@@ -59,14 +59,23 @@ pub struct SimpleResponse {
pub status_code: StatusCode,
pub headers: HeaderMap,
pub read: Pin<Box<dyn Send + AsyncRead + 'static>>,
pub url: String,
pub url: Option<url::Url>,
}
impl SimpleResponse {
pub fn generic_error(url: String) -> Self {
pub fn url_path_basename(&self) -> Option<String> {
self.url.as_ref().and_then(|u| {
u.path_segments()
.and_then(|s| s.last().map(|s| s.to_owned()))
})
}
}
impl SimpleResponse {
pub fn generic_error(url: &str) -> Self {
let (_, rx) = mpsc::unbounded_channel();
SimpleResponse {
url,
url: url::Url::parse(url).ok(),
status_code: StatusCode::INTERNAL_SERVER_ERROR,
headers: HeaderMap::new(),
read: Box::pin(DelegatedReader::new(rx)),
@@ -79,7 +88,10 @@ impl SimpleResponse {
self.read.read_to_string(&mut body).await.ok();
StatusError {
url: self.url,
url: self
.url
.map(|u| u.to_string())
.unwrap_or_else(|| "<invalid url>".to_owned()),
status_code: self.status_code.as_u16(),
body,
}
@@ -97,7 +109,7 @@ impl SimpleResponse {
.map_err(|e| wrap(e, "error reading response"))?;
let t = serde_json::from_slice(&buf)
.map_err(|e| wrap(e, format!("error decoding json from {}", self.url)))?;
.map_err(|e| wrap(e, format!("error decoding json from {:?}", self.url)))?;
Ok(t)
}
@@ -161,7 +173,7 @@ impl SimpleHttp for ReqwestSimpleHttp {
Ok(SimpleResponse {
status_code: res.status(),
headers: res.headers().clone(),
url,
url: Some(res.url().clone()),
read: Box::pin(
res.bytes_stream()
.map_err(|e| futures::io::Error::new(futures::io::ErrorKind::Other, e))
@@ -250,7 +262,7 @@ impl SimpleHttp for DelegatedSimpleHttp {
.await;
if sent.is_err() {
return Ok(SimpleResponse::generic_error(url)); // sender shut down
return Ok(SimpleResponse::generic_error(&url)); // sender shut down
}
match rx.recv().await {
@@ -275,16 +287,16 @@ impl SimpleHttp for DelegatedSimpleHttp {
}
Ok(SimpleResponse {
url,
url: url::Url::parse(&url).ok(),
status_code: StatusCode::from_u16(status_code)
.unwrap_or(StatusCode::INTERNAL_SERVER_ERROR),
headers: headers_map,
read: Box::pin(DelegatedReader::new(rx)),
})
}
Some(DelegatedHttpEvent::End) => Ok(SimpleResponse::generic_error(url)),
Some(DelegatedHttpEvent::End) => Ok(SimpleResponse::generic_error(&url)),
Some(_) => panic!("expected initresponse as first message from delegated http"),
None => Ok(SimpleResponse::generic_error(url)), // sender shut down
None => Ok(SimpleResponse::generic_error(&url)), // sender shut down
}
}
}