mirror of
https://github.com/nushell/nushell.git
synced 2024-12-23 07:30:13 +01:00
Unwrap cleanup mitigation.
This commit is contained in:
parent
8b79b28971
commit
8d5fd6f379
@ -238,6 +238,7 @@ pub struct RunnableContext {
|
||||
}
|
||||
|
||||
impl RunnableContext {
|
||||
#[allow(unused)]
|
||||
pub fn cwd(&self) -> PathBuf {
|
||||
PathBuf::from(self.shell_manager.path())
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ pub struct Cpy;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CopyArgs {
|
||||
source: Tagged<PathBuf>,
|
||||
destination: Tagged<PathBuf>,
|
||||
src: Tagged<PathBuf>,
|
||||
dst: Tagged<PathBuf>,
|
||||
recursive: Tagged<bool>,
|
||||
}
|
||||
|
||||
@ -32,44 +32,43 @@ impl PerItemCommand for Cpy {
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("cp")
|
||||
.required("source", SyntaxType::Path)
|
||||
.required("destination", SyntaxType::Path)
|
||||
.required("src", SyntaxType::Path)
|
||||
.required("dst", SyntaxType::Path)
|
||||
.named("file", SyntaxType::Any)
|
||||
.switch("recursive")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cp(
|
||||
args: CopyArgs,
|
||||
context: &RunnablePerItemContext,
|
||||
fn cp(
|
||||
CopyArgs {
|
||||
src,
|
||||
dst,
|
||||
recursive,
|
||||
}: CopyArgs,
|
||||
RunnablePerItemContext { name, .. }: &RunnablePerItemContext,
|
||||
) -> Result<VecDeque<ReturnValue>, ShellError> {
|
||||
let mut source = PathBuf::from(context.shell_manager.path());
|
||||
let mut destination = PathBuf::from(context.shell_manager.path());
|
||||
let name_span = context.name;
|
||||
let source = src.item.clone();
|
||||
let mut destination = dst.item.clone();
|
||||
let name_span = name;
|
||||
|
||||
source.push(&args.source.item);
|
||||
|
||||
destination.push(&args.destination.item);
|
||||
|
||||
let sources = glob::glob(&source.to_string_lossy());
|
||||
|
||||
if sources.is_err() {
|
||||
let sources: Vec<_> = match glob::glob(&source.to_string_lossy()) {
|
||||
Ok(files) => files.collect(),
|
||||
Err(_) => {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Invalid pattern.",
|
||||
"Invalid pattern.",
|
||||
args.source.tag,
|
||||
));
|
||||
src.tag,
|
||||
))
|
||||
}
|
||||
|
||||
let sources: Vec<_> = sources.unwrap().collect();
|
||||
};
|
||||
|
||||
if sources.len() == 1 {
|
||||
if let Ok(entry) = &sources[0] {
|
||||
if entry.is_dir() && !args.recursive.item {
|
||||
if entry.is_dir() && !recursive.item {
|
||||
return Err(ShellError::labeled_error(
|
||||
"is a directory (not copied). Try using \"--recursive\".",
|
||||
"is a directory (not copied). Try using \"--recursive\".",
|
||||
args.source.tag,
|
||||
src.tag,
|
||||
));
|
||||
}
|
||||
|
||||
@ -167,7 +166,16 @@ pub fn cp(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
destination.push(entry.file_name().unwrap());
|
||||
match entry.file_name() {
|
||||
Some(name) => destination.push(name),
|
||||
None => {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Copy aborted. Not a valid path",
|
||||
"Copy aborted. Not a valid path",
|
||||
name_span,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
match std::fs::create_dir_all(&destination) {
|
||||
Err(e) => {
|
||||
@ -234,18 +242,31 @@ pub fn cp(
|
||||
}
|
||||
} else {
|
||||
if destination.exists() {
|
||||
if !sources.iter().all(|x| (x.as_ref().unwrap()).is_file()) {
|
||||
if !sources.iter().all(|x| match x {
|
||||
Ok(f) => f.is_file(),
|
||||
Err(_) => false,
|
||||
}) {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Copy aborted (directories found). Recursive copying in patterns not supported yet (try copying the directory directly)",
|
||||
"Copy aborted (directories found). Recursive copying in patterns not supported yet (try copying the directory directly)",
|
||||
args.source.tag,
|
||||
src.tag,
|
||||
));
|
||||
}
|
||||
|
||||
for entry in sources {
|
||||
if let Ok(entry) = entry {
|
||||
let mut to = PathBuf::from(&destination);
|
||||
to.push(&entry.file_name().unwrap());
|
||||
|
||||
match entry.file_name() {
|
||||
Some(name) => to.push(name),
|
||||
None => {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Copy aborted. Not a valid path",
|
||||
"Copy aborted. Not a valid path",
|
||||
name_span,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
if entry.is_file() {
|
||||
match std::fs::copy(&entry, &to) {
|
||||
@ -253,7 +274,7 @@ pub fn cp(
|
||||
return Err(ShellError::labeled_error(
|
||||
e.to_string(),
|
||||
e.to_string(),
|
||||
args.source.tag,
|
||||
src.tag,
|
||||
));
|
||||
}
|
||||
Ok(o) => o,
|
||||
@ -262,16 +283,23 @@ pub fn cp(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let destination_file_name = {
|
||||
match destination.file_name() {
|
||||
Some(name) => PathBuf::from(name),
|
||||
None => {
|
||||
return Err(ShellError::labeled_error(
|
||||
format!(
|
||||
"Copy aborted. (Does {:?} exist?)",
|
||||
&destination.file_name().unwrap()
|
||||
),
|
||||
format!(
|
||||
"Copy aborted. (Does {:?} exist?)",
|
||||
&destination.file_name().unwrap()
|
||||
),
|
||||
args.destination.span(),
|
||||
"Copy aborted. Not a valid destination",
|
||||
"Copy aborted. Not a valid destination",
|
||||
name_span,
|
||||
))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return Err(ShellError::labeled_error(
|
||||
format!("Copy aborted. (Does {:?} exist?)", destination_file_name),
|
||||
format!("Copy aborted. (Does {:?} exist?)", destination_file_name),
|
||||
&dst.span(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -5,15 +5,12 @@ use crate::parser::registry::{CommandRegistry, Signature};
|
||||
use crate::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg(windows)]
|
||||
use crate::utils::FileStructure;
|
||||
|
||||
pub struct Move;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct MoveArgs {
|
||||
source: Tagged<PathBuf>,
|
||||
destination: Tagged<PathBuf>,
|
||||
src: Tagged<PathBuf>,
|
||||
dst: Tagged<PathBuf>,
|
||||
}
|
||||
|
||||
impl PerItemCommand for Move {
|
||||
@ -39,17 +36,16 @@ impl PerItemCommand for Move {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mv(
|
||||
args: MoveArgs,
|
||||
context: &RunnablePerItemContext,
|
||||
fn mv(
|
||||
MoveArgs { src, dst }: MoveArgs,
|
||||
RunnablePerItemContext {
|
||||
name,
|
||||
shell_manager,
|
||||
}: &RunnablePerItemContext,
|
||||
) -> Result<VecDeque<ReturnValue>, ShellError> {
|
||||
let mut source = PathBuf::from(context.shell_manager.path());
|
||||
let mut destination = PathBuf::from(context.shell_manager.path());
|
||||
let name_span = context.name;
|
||||
|
||||
source.push(&args.source.item);
|
||||
|
||||
destination.push(&args.destination.item);
|
||||
let source = src.item.clone();
|
||||
let mut destination = dst.item.clone();
|
||||
let name_span = name;
|
||||
|
||||
let sources: Vec<_> = match glob::glob(&source.to_string_lossy()) {
|
||||
Ok(files) => files.collect(),
|
||||
@ -57,21 +53,23 @@ pub fn mv(
|
||||
return Err(ShellError::labeled_error(
|
||||
"Invalid pattern.",
|
||||
"Invalid pattern.",
|
||||
args.source.tag,
|
||||
src.tag,
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
let destination_file_name = {
|
||||
let path = &destination;
|
||||
if "." == destination.to_string_lossy() {
|
||||
destination = PathBuf::from(shell_manager.path());
|
||||
}
|
||||
|
||||
match path.file_name() {
|
||||
let destination_file_name = {
|
||||
match destination.file_name() {
|
||||
Some(name) => PathBuf::from(name),
|
||||
None => {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Rename aborted. Not a valid destination",
|
||||
"Rename aborted. Not a valid destination",
|
||||
name_span,
|
||||
dst.span(),
|
||||
))
|
||||
}
|
||||
}
|
||||
@ -174,6 +172,8 @@ pub fn mv(
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
use crate::utils::FileStructure;
|
||||
|
||||
let mut sources: FileStructure = FileStructure::new();
|
||||
|
||||
sources.walk_decorate(&entry)?;
|
||||
@ -284,7 +284,7 @@ pub fn mv(
|
||||
return Err(ShellError::labeled_error(
|
||||
"Rename aborted (directories found). Renaming in patterns not supported yet (try moving the directory directly)",
|
||||
"Rename aborted (directories found). Renaming in patterns not supported yet (try moving the directory directly)",
|
||||
args.source.tag,
|
||||
src.tag,
|
||||
));
|
||||
}
|
||||
|
||||
@ -332,7 +332,7 @@ pub fn mv(
|
||||
return Err(ShellError::labeled_error(
|
||||
format!("Rename aborted. (Does {:?} exist?)", destination_file_name),
|
||||
format!("Rename aborted. (Does {:?} exist?)", destination_file_name),
|
||||
args.destination.span(),
|
||||
dst.span(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -12,14 +12,6 @@ struct PickArgs {
|
||||
pub struct Pick;
|
||||
|
||||
impl WholeStreamCommand for Pick {
|
||||
fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
args.process(registry, pick)?.run()
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
"pick"
|
||||
}
|
||||
@ -27,6 +19,14 @@ impl WholeStreamCommand for Pick {
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("pick").rest()
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
args.process(registry, pick)?.run()
|
||||
}
|
||||
}
|
||||
|
||||
fn pick(
|
||||
|
@ -10,7 +10,7 @@ pub struct Remove;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct RemoveArgs {
|
||||
path: Tagged<PathBuf>,
|
||||
target: Tagged<PathBuf>,
|
||||
recursive: Tagged<bool>,
|
||||
}
|
||||
|
||||
@ -36,32 +36,30 @@ impl PerItemCommand for Remove {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rm(
|
||||
args: RemoveArgs,
|
||||
context: &RunnablePerItemContext,
|
||||
fn rm(
|
||||
RemoveArgs { target, recursive }: RemoveArgs,
|
||||
RunnablePerItemContext { name, .. }: &RunnablePerItemContext,
|
||||
) -> Result<VecDeque<ReturnValue>, ShellError> {
|
||||
let mut path = PathBuf::from(context.shell_manager.path());
|
||||
let name_span = context.name;
|
||||
let path = target.item.clone();
|
||||
let name_span = name;
|
||||
|
||||
let file = &args.path.item.to_string_lossy();
|
||||
let file = path.to_string_lossy();
|
||||
|
||||
if file == "." || file == ".." {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Remove aborted. \".\" or \"..\" may not be removed.",
|
||||
"Remove aborted. \".\" or \"..\" may not be removed.",
|
||||
args.path.span(),
|
||||
target.span(),
|
||||
));
|
||||
}
|
||||
|
||||
path.push(&args.path.item);
|
||||
|
||||
let entries: Vec<_> = match glob::glob(&path.to_string_lossy()) {
|
||||
Ok(files) => files.collect(),
|
||||
Err(_) => {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Invalid pattern.",
|
||||
"Invalid pattern.",
|
||||
args.path.tag,
|
||||
target.tag,
|
||||
))
|
||||
}
|
||||
};
|
||||
@ -73,17 +71,11 @@ pub fn rm(
|
||||
|
||||
source_dir.walk_decorate(&entry)?;
|
||||
|
||||
if source_dir.contains_files() && !args.recursive.item {
|
||||
if source_dir.contains_files() && !recursive.item {
|
||||
return Err(ShellError::labeled_error(
|
||||
format!(
|
||||
"{:?} is a directory. Try using \"--recursive\".",
|
||||
&args.path.item.to_string_lossy()
|
||||
),
|
||||
format!(
|
||||
"{:?} is a directory. Try using \"--recursive\".",
|
||||
&args.path.item.to_string_lossy()
|
||||
),
|
||||
args.path.span(),
|
||||
format!("{:?} is a directory. Try using \"--recursive\".", file),
|
||||
format!("{:?} is a directory. Try using \"--recursive\".", file),
|
||||
target.span(),
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -94,9 +86,7 @@ pub fn rm(
|
||||
match entry {
|
||||
Ok(path) => {
|
||||
let path_file_name = {
|
||||
let p = &path;
|
||||
|
||||
match p.file_name() {
|
||||
match path.file_name() {
|
||||
Some(name) => PathBuf::from(name),
|
||||
None => {
|
||||
return Err(ShellError::labeled_error(
|
||||
@ -112,7 +102,7 @@ pub fn rm(
|
||||
|
||||
source_dir.walk_decorate(&path)?;
|
||||
|
||||
if source_dir.contains_more_than_one_file() && !args.recursive.item {
|
||||
if source_dir.contains_more_than_one_file() && !recursive.item {
|
||||
return Err(ShellError::labeled_error(
|
||||
format!(
|
||||
"Directory {:?} found somewhere inside. Try using \"--recursive\".",
|
||||
@ -122,7 +112,7 @@ pub fn rm(
|
||||
"Directory {:?} found somewhere inside. Try using \"--recursive\".",
|
||||
path_file_name
|
||||
),
|
||||
args.path.span(),
|
||||
target.span(),
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -36,19 +36,26 @@ impl WholeStreamCommand for Save {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save(
|
||||
fn save(
|
||||
SaveArgs {
|
||||
path,
|
||||
raw: save_raw,
|
||||
}: SaveArgs,
|
||||
context: RunnableContext,
|
||||
RunnableContext {
|
||||
input,
|
||||
name,
|
||||
shell_manager,
|
||||
source_map,
|
||||
..
|
||||
}: RunnableContext,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let mut full_path = context.cwd();
|
||||
let mut full_path = PathBuf::from(shell_manager.path());
|
||||
let name_span = name;
|
||||
|
||||
if path.is_none() {
|
||||
let source_map = context.source_map.clone();
|
||||
let source_map = source_map.clone();
|
||||
let stream = async_stream_block! {
|
||||
let input: Vec<Tagged<Value>> = context.input.values.collect().await;
|
||||
let input: Vec<Tagged<Value>> = input.values.collect().await;
|
||||
// If there is no filename, check the metadata for the origin filename
|
||||
if input.len() > 0 {
|
||||
let origin = input[0].origin();
|
||||
@ -61,7 +68,7 @@ pub fn save(
|
||||
yield Err(ShellError::labeled_error(
|
||||
"Save requires a filepath",
|
||||
"needs path",
|
||||
context.name,
|
||||
name_span,
|
||||
));
|
||||
}
|
||||
},
|
||||
@ -69,7 +76,7 @@ pub fn save(
|
||||
yield Err(ShellError::labeled_error(
|
||||
"Save requires a filepath",
|
||||
"needs path",
|
||||
context.name,
|
||||
name_span,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -77,139 +84,126 @@ pub fn save(
|
||||
yield Err(ShellError::labeled_error(
|
||||
"Save requires a filepath",
|
||||
"needs path",
|
||||
context.name,
|
||||
name_span,
|
||||
));
|
||||
}
|
||||
|
||||
let contents = match full_path.extension() {
|
||||
Some(x) if x == "csv" && !save_raw => {
|
||||
if input.len() != 1 {
|
||||
yield Err(ShellError::string(
|
||||
"saving to csv requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
to_csv_to_string(&value_to_csv_value(&input[0])).unwrap()
|
||||
}
|
||||
Some(x) if x == "toml" && !save_raw => {
|
||||
if input.len() != 1 {
|
||||
yield Err(ShellError::string(
|
||||
"saving to toml requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
toml::to_string(&value_to_toml_value(&input[0])).unwrap()
|
||||
}
|
||||
Some(x) if x == "json" && !save_raw => {
|
||||
if input.len() != 1 {
|
||||
yield Err(ShellError::string(
|
||||
"saving to json requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
serde_json::to_string(&value_to_json_value(&input[0])).unwrap()
|
||||
}
|
||||
Some(x) if x == "yml" && !save_raw => {
|
||||
if input.len() != 1 {
|
||||
yield Err(ShellError::string(
|
||||
"saving to yml requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
serde_yaml::to_string(&value_to_yaml_value(&input[0])).unwrap()
|
||||
}
|
||||
Some(x) if x == "yaml" && !save_raw => {
|
||||
if input.len() != 1 {
|
||||
yield Err(ShellError::string(
|
||||
"saving to yaml requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
serde_yaml::to_string(&value_to_yaml_value(&input[0])).unwrap()
|
||||
}
|
||||
_ => {
|
||||
let mut save_data = String::new();
|
||||
if input.len() > 0 {
|
||||
let mut first = true;
|
||||
for i in input.iter() {
|
||||
if !first {
|
||||
save_data.push_str("\n");
|
||||
let content = if !save_raw {
|
||||
to_string_for(full_path.extension(), &input)
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
save_data.push_str(&i.as_string().unwrap());
|
||||
}
|
||||
}
|
||||
save_data
|
||||
}
|
||||
string_from(&input)
|
||||
};
|
||||
|
||||
let _ = std::fs::write(full_path, contents);
|
||||
match content {
|
||||
Ok(save_data) => match std::fs::write(full_path, save_data) {
|
||||
Ok(o) => o,
|
||||
Err(e) => yield Err(ShellError::string(e.to_string())),
|
||||
},
|
||||
Err(e) => yield Err(ShellError::string(e.to_string())),
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Ok(OutputStream::new(stream))
|
||||
} else {
|
||||
full_path.push(path.unwrap().item());
|
||||
if let Some(file) = path {
|
||||
full_path.push(file.item());
|
||||
}
|
||||
|
||||
let stream = async_stream_block! {
|
||||
let input: Vec<Tagged<Value>> = context.input.values.collect().await;
|
||||
let input: Vec<Tagged<Value>> = input.values.collect().await;
|
||||
|
||||
let contents = match full_path.extension() {
|
||||
Some(x) if x == "csv" && !save_raw => {
|
||||
if input.len() != 1 {
|
||||
yield Err(ShellError::string(
|
||||
"saving to csv requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
to_csv_to_string(&value_to_csv_value(&input[0])).unwrap()
|
||||
}
|
||||
Some(x) if x == "toml" && !save_raw => {
|
||||
if input.len() != 1 {
|
||||
yield Err(ShellError::string(
|
||||
"saving to toml requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
toml::to_string(&value_to_toml_value(&input[0])).unwrap()
|
||||
}
|
||||
Some(x) if x == "json" && !save_raw => {
|
||||
if input.len() != 1 {
|
||||
yield Err(ShellError::string(
|
||||
"saving to json requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
serde_json::to_string(&value_to_json_value(&input[0])).unwrap()
|
||||
}
|
||||
Some(x) if x == "yml" && !save_raw => {
|
||||
if input.len() != 1 {
|
||||
yield Err(ShellError::string(
|
||||
"saving to yml requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
serde_yaml::to_string(&value_to_yaml_value(&input[0])).unwrap()
|
||||
}
|
||||
Some(x) if x == "yaml" && !save_raw => {
|
||||
if input.len() != 1 {
|
||||
yield Err(ShellError::string(
|
||||
"saving to yaml requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
serde_yaml::to_string(&value_to_yaml_value(&input[0])).unwrap()
|
||||
}
|
||||
_ => {
|
||||
let mut save_data = String::new();
|
||||
if input.len() > 0 {
|
||||
let mut first = true;
|
||||
for i in input.iter() {
|
||||
if !first {
|
||||
save_data.push_str("\n");
|
||||
let content = if !save_raw {
|
||||
to_string_for(full_path.extension(), &input)
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
save_data.push_str(&i.as_string().unwrap());
|
||||
}
|
||||
}
|
||||
save_data
|
||||
}
|
||||
string_from(&input)
|
||||
};
|
||||
|
||||
let _ = std::fs::write(full_path, contents);
|
||||
match content {
|
||||
Ok(save_data) => match std::fs::write(full_path, save_data) {
|
||||
Ok(o) => o,
|
||||
Err(e) => yield Err(ShellError::string(e.to_string())),
|
||||
},
|
||||
Err(e) => yield Err(ShellError::string(e.to_string())),
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Ok(OutputStream::new(stream))
|
||||
}
|
||||
}
|
||||
|
||||
fn string_from(input: &Vec<Tagged<Value>>) -> Result<String, ShellError> {
|
||||
let mut save_data = String::new();
|
||||
|
||||
if input.len() > 0 {
|
||||
let mut first = true;
|
||||
for i in input.iter() {
|
||||
if !first {
|
||||
save_data.push_str("\n");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
if let Ok(data) = &i.as_string() {
|
||||
save_data.push_str(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(save_data)
|
||||
}
|
||||
|
||||
fn to_string_for(
|
||||
ext: Option<&std::ffi::OsStr>,
|
||||
input: &Vec<Tagged<Value>>,
|
||||
) -> Result<String, ShellError> {
|
||||
let contents = match ext {
|
||||
Some(x) if x == "csv" => {
|
||||
if input.len() != 1 {
|
||||
return Err(ShellError::string(
|
||||
"saving to csv requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
to_csv_to_string(&value_to_csv_value(&input[0]))?
|
||||
}
|
||||
Some(x) if x == "toml" => {
|
||||
if input.len() != 1 {
|
||||
return Err(ShellError::string(
|
||||
"saving to toml requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
toml::to_string(&value_to_toml_value(&input[0]))?
|
||||
}
|
||||
Some(x) if x == "json" => {
|
||||
if input.len() != 1 {
|
||||
return Err(ShellError::string(
|
||||
"saving to json requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
serde_json::to_string(&value_to_json_value(&input[0]))?
|
||||
}
|
||||
Some(x) if x == "yml" => {
|
||||
if input.len() != 1 {
|
||||
return Err(ShellError::string(
|
||||
"saving to yml requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
serde_yaml::to_string(&value_to_yaml_value(&input[0]))?
|
||||
}
|
||||
Some(x) if x == "yaml" => {
|
||||
if input.len() != 1 {
|
||||
return Err(ShellError::string(
|
||||
"saving to yaml requires a single object (or use --raw)",
|
||||
));
|
||||
}
|
||||
serde_yaml::to_string(&value_to_yaml_value(&input[0]))?
|
||||
}
|
||||
_ => {
|
||||
return Err(ShellError::string(
|
||||
"tried saving a single object with an unrecognized format.",
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
Ok(contents)
|
||||
}
|
||||
|
@ -411,6 +411,16 @@ impl std::fmt::Display for ShellError {
|
||||
|
||||
impl std::error::Error for ShellError {}
|
||||
|
||||
impl std::convert::From<Box<dyn std::error::Error>> for ShellError {
|
||||
fn from(input: Box<dyn std::error::Error>) -> ShellError {
|
||||
ProximateShellError::String(StringError {
|
||||
title: format!("{}", input),
|
||||
error: Value::nothing(),
|
||||
})
|
||||
.start()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<std::io::Error> for ShellError {
|
||||
fn from(input: std::io::Error) -> ShellError {
|
||||
ProximateShellError::String(StringError {
|
||||
@ -431,6 +441,17 @@ impl std::convert::From<subprocess::PopenError> for ShellError {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<serde_yaml::Error> for ShellError {
|
||||
fn from(input: serde_yaml::Error) -> ShellError {
|
||||
ProximateShellError::String(StringError {
|
||||
title: format!("{:?}", input),
|
||||
error: Value::nothing(),
|
||||
})
|
||||
.start()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl std::convert::From<toml::ser::Error> for ShellError {
|
||||
fn from(input: toml::ser::Error) -> ShellError {
|
||||
ProximateShellError::String(StringError {
|
||||
|
Loading…
Reference in New Issue
Block a user