Merge pull request #397 from jonathandturner/surf

switch from reqwest to surf
This commit is contained in:
Jonathan Turner 2019-08-25 18:20:19 +12:00 committed by GitHub
commit 5a355683ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 430 additions and 761 deletions

View File

@ -6,7 +6,7 @@ strategy:
linux-nightly:
image: ubuntu-16.04
macos-nightly:
image: macos-10.13
image: macos-10.14
windows-nightly:
image: vs2017-win2016

867
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -28,8 +28,8 @@ chrono-humanize = "0.0.11"
byte-unit = "3.0.1"
ordered-float = {version = "1.0.2", features = ["serde"]}
prettyprint = "0.7.0"
futures-preview = { version = "=0.3.0-alpha.18", features = ["compat", "io-compat"] }
futures-sink-preview = "=0.3.0-alpha.18"
futures-preview = { version = "=0.3.0-alpha.17", features = ["compat", "io-compat"] }
futures-sink-preview = "=0.3.0-alpha.17"
futures-async-stream = "0.1.0-alpha.1"
futures_codec = "0.2.5"
term = "0.5.2"
@ -52,7 +52,8 @@ dirs = "2.0.2"
glob = "0.3.0"
ctrlc = "3.1.3"
ptree = "0.2"
reqwest = "0.9"
surf = "1.0"
url = "2.1.0"
roxmltree = "0.7.0"
nom5_locate = "0.1.1"
enum-utils = "0.1.1"

View File

@ -166,7 +166,8 @@ impl InternalCommand {
&full_path,
&location,
Span::unknown(),
)?;
)
.await?;
if let Some(uuid) = contents_tag.origin {
// If we have loaded something, track its source

View File

@ -81,7 +81,7 @@ impl CallInfo {
pub fn process<'de, T: Deserialize<'de>>(
&self,
shell_manager: &ShellManager,
callback: fn(T, &RunnablePerItemContext) -> Result<VecDeque<ReturnValue>, ShellError>,
callback: fn(T, &RunnablePerItemContext) -> Result<OutputStream, ShellError>,
) -> Result<RunnablePerItemArgs<T>, ShellError> {
let mut deserializer = ConfigDeserializer::from_call_info(self.clone());
@ -250,11 +250,11 @@ impl RunnableContext {
pub struct RunnablePerItemArgs<T> {
args: T,
context: RunnablePerItemContext,
callback: fn(T, &RunnablePerItemContext) -> Result<VecDeque<ReturnValue>, ShellError>,
callback: fn(T, &RunnablePerItemContext) -> Result<OutputStream, ShellError>,
}
impl<T> RunnablePerItemArgs<T> {
pub fn run(self) -> Result<VecDeque<ReturnValue>, ShellError> {
pub fn run(self) -> Result<OutputStream, ShellError> {
(self.callback)(self.args, &self.context)
}
}
@ -485,7 +485,7 @@ pub trait PerItemCommand: Send + Sync {
registry: &CommandRegistry,
shell_manager: &ShellManager,
input: Tagged<Value>,
) -> Result<VecDeque<ReturnValue>, ShellError>;
) -> Result<OutputStream, ShellError>;
fn signature(&self) -> Signature {
Signature {
@ -552,7 +552,7 @@ impl Command {
.unwrap();
match command.run(&call_info, &registry, &raw_args.shell_manager, x) {
Ok(o) => o,
Err(e) => VecDeque::from(vec![ReturnValue::Err(e)]),
Err(e) => VecDeque::from(vec![ReturnValue::Err(e)]).to_output_stream(),
}
})
.flatten();

View File

@ -21,7 +21,7 @@ impl PerItemCommand for Cpy {
_registry: &CommandRegistry,
shell_manager: &ShellManager,
_input: Tagged<Value>,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
call_info.process(shell_manager, cp)?.run()
}
@ -38,10 +38,7 @@ impl PerItemCommand for Cpy {
}
}
fn cp(
args: CopyArgs,
context: &RunnablePerItemContext,
) -> Result<VecDeque<ReturnValue>, ShellError> {
fn cp(args: CopyArgs, context: &RunnablePerItemContext) -> Result<OutputStream, ShellError> {
let shell_manager = context.shell_manager.clone();
shell_manager.cp(args, context)
}

View File

@ -21,7 +21,7 @@ impl PerItemCommand for Enter {
_registry: &registry::CommandRegistry,
_shell_manager: &ShellManager,
_input: Tagged<Value>,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
match call_info.args.expect_nth(0)? {
Tagged {
item: Value::Primitive(Primitive::String(location)),

View File

@ -18,7 +18,7 @@ impl PerItemCommand for Mkdir {
_registry: &CommandRegistry,
shell_manager: &ShellManager,
_input: Tagged<Value>,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
call_info.process(shell_manager, mkdir)?.run()
}
@ -31,10 +31,7 @@ impl PerItemCommand for Mkdir {
}
}
fn mkdir(
args: MkdirArgs,
context: &RunnablePerItemContext,
) -> Result<VecDeque<ReturnValue>, ShellError> {
fn mkdir(args: MkdirArgs, context: &RunnablePerItemContext) -> Result<OutputStream, ShellError> {
let shell_manager = context.shell_manager.clone();
shell_manager.mkdir(args, context)
}

View File

@ -31,15 +31,12 @@ impl PerItemCommand for Move {
_registry: &CommandRegistry,
shell_manager: &ShellManager,
_input: Tagged<Value>,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
call_info.process(shell_manager, mv)?.run()
}
}
fn mv(
args: MoveArgs,
context: &RunnablePerItemContext,
) -> Result<VecDeque<ReturnValue>, ShellError> {
fn mv(args: MoveArgs, context: &RunnablePerItemContext) -> Result<OutputStream, ShellError> {
let shell_manager = context.shell_manager.clone();
shell_manager.mv(args, context)
}

View File

@ -7,6 +7,7 @@ use crate::prelude::*;
use mime::Mime;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use surf::mime;
use uuid::Uuid;
pub struct Open;
@ -27,15 +28,12 @@ impl PerItemCommand for Open {
_registry: &CommandRegistry,
shell_manager: &ShellManager,
_input: Tagged<Value>,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
run(call_info, shell_manager)
}
}
fn run(
call_info: &CallInfo,
shell_manager: &ShellManager,
) -> Result<VecDeque<ReturnValue>, ShellError> {
fn run(call_info: &CallInfo, shell_manager: &ShellManager) -> Result<OutputStream, ShellError> {
let cwd = PathBuf::from(shell_manager.path());
let full_path = PathBuf::from(cwd);
@ -46,85 +44,101 @@ fn run(
{
file => file,
};
let path_str = path.as_string()?;
let path_span = path.span();
let name_span = call_info.name_span;
let has_raw = call_info.args.has("raw");
let (file_extension, contents, contents_tag, span_source) =
fetch(&full_path, &path_str, path.span())?;
let stream = async_stream_block! {
let file_extension = if call_info.args.has("raw") {
None
} else {
file_extension
};
//FIXME: unwraps
let mut stream = VecDeque::new();
let (file_extension, contents, contents_tag, span_source) =
fetch(&full_path, &path_str, path_span).await.unwrap();
if let Some(uuid) = contents_tag.origin {
// If we have loaded something, track its source
stream.push_back(ReturnSuccess::action(CommandAction::AddSpanSource(
uuid,
span_source,
)))
}
let file_extension = if has_raw {
None
} else {
file_extension
};
match contents {
Value::Primitive(Primitive::String(string)) => {
let value = parse_as_value(file_extension, string, contents_tag, call_info.name_span)?;
match value {
Tagged {
item: Value::List(list),
..
} => {
for elem in list {
stream.push_back(ReturnSuccess::value(elem));
}
}
x => stream.push_back(ReturnSuccess::value(x)),
}
if let Some(uuid) = contents_tag.origin {
// If we have loaded something, track its source
yield ReturnSuccess::action(CommandAction::AddSpanSource(
uuid,
span_source,
));
}
other => stream.push_back(ReturnSuccess::value(other.tagged(contents_tag))),
match contents {
Value::Primitive(Primitive::String(string)) => {
let value = parse_as_value(file_extension, string, contents_tag, name_span).unwrap();
match value {
Tagged {
item: Value::List(list),
..
} => {
for elem in list {
yield ReturnSuccess::value(elem);
}
}
x => yield ReturnSuccess::value(x),
}
}
other => yield ReturnSuccess::value(other.tagged(contents_tag)),
};
};
Ok(stream)
Ok(stream.to_output_stream())
}
pub fn fetch(
pub async fn fetch(
cwd: &PathBuf,
location: &str,
span: Span,
) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> {
let mut cwd = cwd.clone();
if location.starts_with("http:") || location.starts_with("https:") {
let response = reqwest::get(location);
let response = surf::get(location).await;
match response {
Ok(mut r) => match r.headers().get("content-type") {
Some(content_type) => {
let content_type = Mime::from_str(content_type.to_str().unwrap()).unwrap();
let content_type = Mime::from_str(content_type).unwrap();
match (content_type.type_(), content_type.subtype()) {
(mime::APPLICATION, mime::XML) => Ok((
Some("xml".to_string()),
Value::string(r.text().unwrap()),
Value::string(r.body_string().await.map_err(|_| {
ShellError::labeled_error(
"Could not load text from remote url",
"could not load",
span,
)
})?),
Tag {
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()),
SpanSource::Url(location.to_string()),
)),
(mime::APPLICATION, mime::JSON) => Ok((
Some("json".to_string()),
Value::string(r.text().unwrap()),
Value::string(r.body_string().await.map_err(|_| {
ShellError::labeled_error(
"Could not load text from remote url",
"could not load",
span,
)
})?),
Tag {
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()),
SpanSource::Url(location.to_string()),
)),
(mime::APPLICATION, mime::OCTET_STREAM) => {
let mut buf: Vec<u8> = vec![];
r.copy_to(&mut buf).map_err(|_| {
let buf: Vec<u8> = r.body_bytes().await.map_err(|_| {
ShellError::labeled_error(
"Could not load binary file",
"could not load",
@ -138,12 +152,11 @@ pub fn fetch(
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()),
SpanSource::Url(location.to_string()),
))
}
(mime::IMAGE, image_ty) => {
let mut buf: Vec<u8> = vec![];
r.copy_to(&mut buf).map_err(|_| {
let buf: Vec<u8> = r.body_bytes().await.map_err(|_| {
ShellError::labeled_error(
"Could not load image file",
"could not load",
@ -157,21 +170,27 @@ pub fn fetch(
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()),
SpanSource::Url(location.to_string()),
))
}
(mime::TEXT, mime::HTML) => Ok((
Some("html".to_string()),
Value::string(r.text().unwrap()),
Value::string(r.body_string().await.map_err(|_| {
ShellError::labeled_error(
"Could not load text from remote url",
"could not load",
span,
)
})?),
Tag {
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()),
SpanSource::Url(location.to_string()),
)),
(mime::TEXT, mime::PLAIN) => {
let path_extension = r
.url()
let path_extension = url::Url::parse(location)
.unwrap()
.path_segments()
.and_then(|segments| segments.last())
.and_then(|name| if name.is_empty() { None } else { Some(name) })
@ -183,12 +202,18 @@ pub fn fetch(
Ok((
path_extension,
Value::string(r.text().unwrap()),
Value::string(r.body_string().await.map_err(|_| {
ShellError::labeled_error(
"Could not load text from remote url",
"could not load",
span,
)
})?),
Tag {
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()),
SpanSource::Url(location.to_string()),
))
}
(ty, sub_ty) => Ok((
@ -201,7 +226,7 @@ pub fn fetch(
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()),
SpanSource::Url(location.to_string()),
)),
}
}
@ -212,7 +237,7 @@ pub fn fetch(
span,
origin: Some(Uuid::new_v4()),
},
SpanSource::Url(r.url().to_string()),
SpanSource::Url(location.to_string()),
)),
},
Err(_) => {

View File

@ -30,15 +30,12 @@ impl PerItemCommand for Remove {
_registry: &CommandRegistry,
shell_manager: &ShellManager,
_input: Tagged<Value>,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
call_info.process(shell_manager, rm)?.run()
}
}
fn rm(
args: RemoveArgs,
context: &RunnablePerItemContext,
) -> Result<VecDeque<ReturnValue>, ShellError> {
fn rm(args: RemoveArgs, context: &RunnablePerItemContext) -> Result<OutputStream, ShellError> {
let shell_manager = context.shell_manager.clone();
shell_manager.rm(args, context)
}

View File

@ -21,10 +21,10 @@ impl PerItemCommand for Where {
_registry: &registry::CommandRegistry,
_shell_manager: &ShellManager,
input: Tagged<Value>,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
let input_clone = input.clone();
let condition = call_info.args.expect_nth(0)?;
match condition {
let stream = match condition {
Tagged {
item: Value::Block(block),
tag,
@ -33,23 +33,29 @@ impl PerItemCommand for Where {
match result {
Ok(v) => {
if v.is_true() {
Ok(VecDeque::from(vec![Ok(ReturnSuccess::Value(input_clone))]))
VecDeque::from(vec![Ok(ReturnSuccess::Value(input_clone))])
} else {
Ok(VecDeque::new())
VecDeque::new()
}
}
Err(e) => Err(ShellError::labeled_error(
format!("Could not evaluate ({})", e.to_string()),
"could not evaluate",
tag.span,
)),
Err(e) => {
return Err(ShellError::labeled_error(
format!("Could not evaluate ({})", e.to_string()),
"could not evaluate",
tag.span,
))
}
}
}
Tagged { tag, .. } => Err(ShellError::labeled_error(
"Expected a condition",
"where needs a condition",
tag.span,
)),
}
Tagged { tag, .. } => {
return Err(ShellError::labeled_error(
"Expected a condition",
"where needs a condition",
tag.span,
))
}
};
Ok(stream.to_output_stream())
}
}

View File

@ -451,7 +451,6 @@ impl std::convert::From<serde_yaml::Error> for ShellError {
}
}
impl std::convert::From<toml::ser::Error> for ShellError {
fn from(input: toml::ser::Error) -> ShellError {
ProximateShellError::String(StringError {
@ -482,6 +481,16 @@ impl std::convert::From<regex::Error> for ShellError {
}
}
impl std::convert::From<Box<dyn std::error::Error + Send + Sync>> for ShellError {
fn from(input: Box<dyn std::error::Error + Send + Sync>) -> ShellError {
ProximateShellError::String(StringError {
title: format!("{:?}", input),
error: Value::nothing(),
})
.start()
}
}
pub trait ShellErrorUtils<T> {
fn unwrap_error(self, desc: impl Into<String>) -> Result<T, ShellError>;
}

View File

@ -308,7 +308,7 @@ fn view_text_value(value: &Tagged<Value>, source_map: &SourceMap) {
path.extension().map(|x| x.to_string_lossy().to_string())
}
SpanSource::Url(url) => {
let url = reqwest::Url::parse(url);
let url = url::Url::parse(url);
if let Ok(url) = url {
let url = url.clone();
if let Some(mut segments) = url.path_segments() {

View File

@ -221,7 +221,7 @@ impl Shell for FilesystemShell {
}: CopyArgs,
name: Span,
path: &str,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
let name_span = name;
let mut source = PathBuf::from(path);
@ -491,7 +491,7 @@ impl Shell for FilesystemShell {
}
}
Ok(VecDeque::new())
Ok(OutputStream::empty())
}
fn mkdir(
@ -504,7 +504,7 @@ impl Shell for FilesystemShell {
// }: &RunnablePerItemContext,
name: Span,
path: &str,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
let full_path = PathBuf::from(path);
if directories.len() == 0 {
@ -534,7 +534,7 @@ impl Shell for FilesystemShell {
}
}
Ok(VecDeque::new())
Ok(OutputStream::empty())
}
fn mv(
@ -542,7 +542,7 @@ impl Shell for FilesystemShell {
MoveArgs { src, dst }: MoveArgs,
name: Span,
path: &str,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
let name_span = name;
let mut source = PathBuf::from(path);
@ -837,7 +837,7 @@ impl Shell for FilesystemShell {
}
}
Ok(VecDeque::new())
Ok(OutputStream::empty())
}
fn rm(
@ -845,7 +845,7 @@ impl Shell for FilesystemShell {
RemoveArgs { target, recursive }: RemoveArgs,
name: Span,
path: &str,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
let name_span = name;
if target.item.to_str() == Some(".") || target.item.to_str() == Some("..") {
@ -941,7 +941,7 @@ impl Shell for FilesystemShell {
}
}
Ok(VecDeque::new())
Ok(OutputStream::empty())
}
fn path(&self) -> String {

View File

@ -12,30 +12,10 @@ pub trait Shell: std::fmt::Debug {
fn name(&self, source_map: &SourceMap) -> String;
fn ls(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
fn cd(&self, args: EvaluatedWholeStreamCommandArgs) -> Result<OutputStream, ShellError>;
fn cp(
&self,
args: CopyArgs,
name: Span,
path: &str,
) -> Result<VecDeque<ReturnValue>, ShellError>;
fn mkdir(
&self,
args: MkdirArgs,
name: Span,
path: &str,
) -> Result<VecDeque<ReturnValue>, ShellError>;
fn mv(
&self,
args: MoveArgs,
name: Span,
path: &str,
) -> Result<VecDeque<ReturnValue>, ShellError>;
fn rm(
&self,
args: RemoveArgs,
name: Span,
path: &str,
) -> Result<VecDeque<ReturnValue>, ShellError>;
fn cp(&self, args: CopyArgs, name: Span, path: &str) -> Result<OutputStream, ShellError>;
fn mkdir(&self, args: MkdirArgs, name: Span, path: &str) -> Result<OutputStream, ShellError>;
fn mv(&self, args: MoveArgs, name: Span, path: &str) -> Result<OutputStream, ShellError>;
fn rm(&self, args: RemoveArgs, name: Span, path: &str) -> Result<OutputStream, ShellError>;
fn path(&self) -> String;
fn set_path(&mut self, path: String);

View File

@ -116,7 +116,7 @@ impl ShellManager {
&self,
args: CopyArgs,
context: &RunnablePerItemContext,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
let env = self.shells.lock();
match env {
@ -136,7 +136,7 @@ impl ShellManager {
&self,
args: RemoveArgs,
context: &RunnablePerItemContext,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
let env = self.shells.lock();
match env {
@ -156,7 +156,7 @@ impl ShellManager {
&self,
args: MkdirArgs,
context: &RunnablePerItemContext,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
let env = self.shells.lock();
match env {
@ -176,7 +176,7 @@ impl ShellManager {
&self,
args: MoveArgs,
context: &RunnablePerItemContext,
) -> Result<VecDeque<ReturnValue>, ShellError> {
) -> Result<OutputStream, ShellError> {
let env = self.shells.lock();
match env {

View File

@ -103,12 +103,7 @@ impl Shell for ValueShell {
Ok(stream.into())
}
fn cp(
&self,
_args: CopyArgs,
name: Span,
_path: &str,
) -> Result<VecDeque<ReturnValue>, ShellError> {
fn cp(&self, _args: CopyArgs, name: Span, _path: &str) -> Result<OutputStream, ShellError> {
Err(ShellError::labeled_error(
"cp not currently supported on values",
"not currently supported",
@ -116,12 +111,7 @@ impl Shell for ValueShell {
))
}
fn mv(
&self,
_args: MoveArgs,
name: Span,
_path: &str,
) -> Result<VecDeque<ReturnValue>, ShellError> {
fn mv(&self, _args: MoveArgs, name: Span, _path: &str) -> Result<OutputStream, ShellError> {
Err(ShellError::labeled_error(
"mv not currently supported on values",
"not currently supported",
@ -129,12 +119,7 @@ impl Shell for ValueShell {
))
}
fn mkdir(
&self,
_args: MkdirArgs,
name: Span,
_path: &str,
) -> Result<VecDeque<ReturnValue>, ShellError> {
fn mkdir(&self, _args: MkdirArgs, name: Span, _path: &str) -> Result<OutputStream, ShellError> {
Err(ShellError::labeled_error(
"mkdir not currently supported on values",
"not currently supported",
@ -142,12 +127,7 @@ impl Shell for ValueShell {
))
}
fn rm(
&self,
_args: RemoveArgs,
name: Span,
_path: &str,
) -> Result<VecDeque<ReturnValue>, ShellError> {
fn rm(&self, _args: RemoveArgs, name: Span, _path: &str) -> Result<OutputStream, ShellError> {
Err(ShellError::labeled_error(
"rm not currently supported on values",
"not currently supported",