Fix undefined error for various I/O error using --output.

This commit is contained in:
jcamiel 2023-11-14 10:50:34 +01:00
parent 06b2e19ad0
commit 0b86a70d43
No known key found for this signature in database
GPG Key ID: 07FF11CFD55356CC
15 changed files with 84 additions and 41 deletions

View File

@ -0,0 +1 @@
error: Error ~~~: ~~~ (os error ~~~)

View File

@ -0,0 +1 @@
3

View File

@ -0,0 +1,4 @@
Set-StrictMode -Version latest
$ErrorActionPreference = 'Stop'
New-Item -Path build\tmp -Force -ItemType Directory
hurl --output build/tmp tests_ok/hello.hurl

View File

@ -0,0 +1,4 @@
#!/bin/bash
set -Eeuo pipefail
mkdir -p build/tmp
hurl --output build/tmp tests_ok/hello.hurl

View File

@ -0,0 +1 @@
error: Error ~~~foo~bar~baz: ~~~ (os error ~~~)

View File

@ -0,0 +1 @@
3

View File

@ -0,0 +1,3 @@
Set-StrictMode -Version latest
$ErrorActionPreference = 'Stop'
hurl --output C:\foo\bar\baz tests_ok/hello.hurl

View File

@ -0,0 +1,3 @@
#!/bin/bash
set -Eeuo pipefail
hurl --output /foo/bar/baz tests_ok/hello.hurl

View File

@ -0,0 +1 @@
Hello World!

View File

@ -62,7 +62,9 @@ impl From<report::Error> for CliError {
impl From<output::Error> for CliError {
fn from(e: output::Error) -> Self {
Self { message: e.message }
Self {
message: e.to_string(),
}
}
}

View File

@ -0,0 +1,44 @@
/*
* Hurl (https://hurl.dev)
* Copyright (C) 2023 Orange
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
use std::fmt;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Error(String);
impl Error {
pub fn new(message: &str) -> Error {
Error(message.to_string())
}
pub fn from_path(error: std::io::Error, path: &str) -> Error {
let message = format!("Error {path}: {error}");
Error::new(&message)
}
}
impl From<std::io::Error> for Error {
fn from(value: std::io::Error) -> Self {
Error::new(&value.to_string())
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}

View File

@ -16,7 +16,7 @@
*
*/
use crate::output;
use crate::output::Error;
use crate::output::error::Error;
use crate::runner::HurlResult;
/// Writes the `hurl_result` JSON representation to the file `filename_out`.

View File

@ -21,45 +21,32 @@
//! - JSON: the whole run is serialized to JSON (like the [HAR](https://en.wikipedia.org/wiki/HAR_(file_format)) format)
//! - raw: the last response of a run is serialized to a file. The body can be automatically uncompress
//! or written as it.
mod error;
mod json;
mod raw;
mod stdout;
use std::fmt;
use std::io::Write;
use std::path::Path;
pub use self::error::Error;
pub use self::json::write_json;
pub use self::raw::write_body;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Error {
pub message: String,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.message)
}
}
/// Writes `bytes` to the file `filename` or stdout by default.
fn write_output(bytes: &Vec<u8>, filename: &Option<String>) -> Result<(), Error> {
match filename {
None => stdout::write_stdout(bytes.as_slice()),
None => stdout::write_stdout(bytes.as_slice())?,
Some(filename) => {
let path = Path::new(filename.as_str());
let mut file = match std::fs::File::create(path) {
Err(why) => {
return Err(Error {
message: format!("Issue writing to {}: {:?}", path.display(), why),
});
}
Ok(file) => file,
Err(e) => return Err(Error::from_path(e, filename)),
};
file.write_all(bytes.as_slice())
.expect("writing bytes to file");
Ok(())
if let Err(e) = file.write_all(bytes.as_slice()) {
return Err(Error::from_path(e, filename));
}
}
}
Ok(())
}

View File

@ -33,7 +33,7 @@ pub fn write_body(
color: bool,
filename_out: &Option<String>,
logger: &Logger,
) -> Result<(), output::Error> {
) -> Result<(), output::error::Error> {
// By default, we output the body response bytes of the last entry
if let Some(entry_result) = hurl_result.entries.last() {
if let Some(call) = entry_result.calls.last() {
@ -60,19 +60,14 @@ pub fn write_body(
assert: false,
};
let message = error.fixme();
return Err(output::Error { message });
return Err(output::error::Error::new(&message));
}
}
} else {
response.body.clone()
};
output.append(&mut body);
let result = output::write_output(&output, filename_out);
if result.is_err() {
return Err(output::Error {
message: "Undefined error".to_string(),
});
}
output::write_output(&output, filename_out)?;
} else {
logger.info("No response has been received");
}

View File

@ -21,26 +21,22 @@ use std::io::Write;
#[cfg(target_family = "windows")]
use std::io::IsTerminal;
use crate::output::Error;
use crate::output::error::Error;
#[cfg(target_family = "unix")]
pub(crate) fn write_stdout(buf: &[u8]) -> Result<(), Error> {
let stdout = io::stdout();
let mut handle = stdout.lock();
handle.write_all(buf).map_err(|_| Error {
message: "Error writing output".to_string(),
})
let mut handle = io::stdout().lock();
handle.write_all(buf)?;
Ok(())
}
#[cfg(target_family = "windows")]
pub(crate) fn write_stdout(buf: &[u8]) -> Result<(), Error> {
if io::stdout().is_terminal() {
println!("{}", String::from_utf8_lossy(buf));
Ok(())
} else {
let mut handle = io::stdout().lock();
handle.write_all(buf).map_err(|_| Error {
message: "Error writing output".to_string(),
})
handle.write_all(buf)?;
}
Ok(())
}