difftreelog
feat print errors to stderr, exit 1 on failure
in: master
1 file changed
cmds/jrsonnet/src/main.rsdiffbeforeafterboth1use clap::AppSettings;2use clap::Clap;3use jrsonnet_cli::{ConfigureState, GeneralOpts, InputOpts, ManifestOpts, OutputOpts};4use jrsonnet_evaluator::{error::LocError, EvaluationState, ManifestFormat};5use std::{6 fs::{create_dir_all, File},7 io::Read,8 io::Write,9 path::PathBuf,10 rc::Rc,11};1213#[cfg(feature = "mimalloc")]14#[global_allocator]15static GLOBAL: mimallocator::Mimalloc = mimallocator::Mimalloc;1617#[derive(Clap)]18#[clap(help_heading = "DEBUG")]19struct DebugOpts {20 /// Required OS stack size.21 /// This shouldn't be changed unless jrsonnet is failing with stack overflow error.22 #[clap(long, name = "size")]23 pub os_stack: Option<usize>,24}2526#[derive(Clap)]27#[clap(28 global_setting = AppSettings::ColoredHelp,29 global_setting = AppSettings::DeriveDisplayOrder,30)]31struct Opts {32 #[clap(flatten)]33 input: InputOpts,34 #[clap(flatten)]35 general: GeneralOpts,36 #[clap(flatten)]37 manifest: ManifestOpts,38 #[clap(flatten)]39 output: OutputOpts,40 #[clap(flatten)]41 debug: DebugOpts,42}4344fn main() {45 let opts: Opts = Opts::parse();46 if let Some(size) = opts.debug.os_stack {47 std::thread::Builder::new()48 .stack_size(size * 1024 * 1024)49 .spawn(|| main_catch(opts))50 .expect("new thread spawned")51 .join()52 .expect("thread finished successfully");53 } else {54 main_catch(opts)55 }56}5758#[derive(thiserror::Error, Debug)]59enum Error {60 // Handled differently61 #[error("evaluation error")]62 Evaluation(jrsonnet_evaluator::error::LocError),63 #[error("io error")]64 Io(#[from] std::io::Error),65 #[error("input is not utf8 encoded")]66 Utf8(#[from] std::str::Utf8Error),67}68impl From<LocError> for Error {69 fn from(e: LocError) -> Self {70 Self::Evaluation(e)71 }72}7374fn main_catch(opts: Opts) {75 let state = EvaluationState::default();76 if let Err(e) = main_real(&state, opts) {77 if let Error::Evaluation(e) = e {78 println!("{}", state.stringify_err(&e));79 } else {80 println!("{}", e);81 }82 }83}8485fn main_real(state: &EvaluationState, opts: Opts) -> Result<(), Error> {86 opts.general.configure(&state)?;87 opts.manifest.configure(&state)?;8889 let val = if opts.input.exec {90 state.set_manifest_format(ManifestFormat::ToString);91 state.evaluate_snippet_raw(92 Rc::new(PathBuf::from("args")),93 (&opts.input.input as &str).into(),94 )?95 } else if opts.input.input == "-" {96 let mut input = Vec::new();97 std::io::stdin().read_to_end(&mut input)?;98 let input_str = std::str::from_utf8(&input)?.into();99 state.evaluate_snippet_raw(Rc::new(PathBuf::from("<stdin>")), input_str)?100 } else {101 state.evaluate_file_raw(&PathBuf::from(opts.input.input))?102 };103104 let val = state.with_tla(val)?;105106 if let Some(multi) = opts.output.multi {107 if opts.output.create_output_dirs {108 let mut dir = multi.clone();109 dir.pop();110 create_dir_all(dir)?;111 }112 for (file, data) in state.manifest_multi(val)?.iter() {113 let mut path = multi.clone();114 path.push(&file as &str);115 if opts.output.create_output_dirs {116 let mut dir = path.clone();117 dir.pop();118 create_dir_all(dir)?;119 }120 println!("{}", path.to_str().expect("path"));121 let mut file = File::create(path)?;122 writeln!(file, "{}", data)?;123 }124 } else if let Some(path) = opts.output.output_file {125 if opts.output.create_output_dirs {126 let mut dir = path.clone();127 dir.pop();128 create_dir_all(dir)?;129 }130 let mut file = File::create(path)?;131 writeln!(file, "{}", state.manifest(val)?)?;132 } else {133 println!("{}", state.manifest(val)?);134 }135136 Ok(())137}1use clap::AppSettings;2use clap::Clap;3use jrsonnet_cli::{ConfigureState, GeneralOpts, InputOpts, ManifestOpts, OutputOpts};4use jrsonnet_evaluator::{error::LocError, EvaluationState, ManifestFormat};5use std::{6 fs::{create_dir_all, File},7 io::Read,8 io::Write,9 path::PathBuf,10 rc::Rc,11};1213#[cfg(feature = "mimalloc")]14#[global_allocator]15static GLOBAL: mimallocator::Mimalloc = mimallocator::Mimalloc;1617#[derive(Clap)]18#[clap(help_heading = "DEBUG")]19struct DebugOpts {20 /// Required OS stack size.21 /// This shouldn't be changed unless jrsonnet is failing with stack overflow error.22 #[clap(long, name = "size")]23 pub os_stack: Option<usize>,24}2526#[derive(Clap)]27#[clap(28 global_setting = AppSettings::ColoredHelp,29 global_setting = AppSettings::DeriveDisplayOrder,30)]31struct Opts {32 #[clap(flatten)]33 input: InputOpts,34 #[clap(flatten)]35 general: GeneralOpts,36 #[clap(flatten)]37 manifest: ManifestOpts,38 #[clap(flatten)]39 output: OutputOpts,40 #[clap(flatten)]41 debug: DebugOpts,42}4344fn main() {45 let opts: Opts = Opts::parse();46 let success;47 if let Some(size) = opts.debug.os_stack {48 success = std::thread::Builder::new()49 .stack_size(size * 1024 * 1024)50 .spawn(|| main_catch(opts))51 .expect("new thread spawned")52 .join()53 .expect("thread finished successfully");54 } else {55 success = main_catch(opts)56 }57 if !success {58 std::process::exit(1);59 }60}6162#[derive(thiserror::Error, Debug)]63enum Error {64 // Handled differently65 #[error("evaluation error")]66 Evaluation(jrsonnet_evaluator::error::LocError),67 #[error("io error")]68 Io(#[from] std::io::Error),69 #[error("input is not utf8 encoded")]70 Utf8(#[from] std::str::Utf8Error),71}72impl From<LocError> for Error {73 fn from(e: LocError) -> Self {74 Self::Evaluation(e)75 }76}7778fn main_catch(opts: Opts) -> bool {79 let state = EvaluationState::default();80 if let Err(e) = main_real(&state, opts) {81 if let Error::Evaluation(e) = e {82 eprintln!("{}", state.stringify_err(&e));83 } else {84 eprintln!("{}", e);85 }86 return false;87 }88 true89}9091fn main_real(state: &EvaluationState, opts: Opts) -> Result<(), Error> {92 opts.general.configure(&state)?;93 opts.manifest.configure(&state)?;9495 let val = if opts.input.exec {96 state.set_manifest_format(ManifestFormat::ToString);97 state.evaluate_snippet_raw(98 Rc::new(PathBuf::from("args")),99 (&opts.input.input as &str).into(),100 )?101 } else if opts.input.input == "-" {102 let mut input = Vec::new();103 std::io::stdin().read_to_end(&mut input)?;104 let input_str = std::str::from_utf8(&input)?.into();105 state.evaluate_snippet_raw(Rc::new(PathBuf::from("<stdin>")), input_str)?106 } else {107 state.evaluate_file_raw(&PathBuf::from(opts.input.input))?108 };109110 let val = state.with_tla(val)?;111112 if let Some(multi) = opts.output.multi {113 if opts.output.create_output_dirs {114 let mut dir = multi.clone();115 dir.pop();116 create_dir_all(dir)?;117 }118 for (file, data) in state.manifest_multi(val)?.iter() {119 let mut path = multi.clone();120 path.push(&file as &str);121 if opts.output.create_output_dirs {122 let mut dir = path.clone();123 dir.pop();124 create_dir_all(dir)?;125 }126 println!("{}", path.to_str().expect("path"));127 let mut file = File::create(path)?;128 writeln!(file, "{}", data)?;129 }130 } else if let Some(path) = opts.output.output_file {131 if opts.output.create_output_dirs {132 let mut dir = path.clone();133 dir.pop();134 create_dir_all(dir)?;135 }136 let mut file = File::create(path)?;137 writeln!(file, "{}", state.manifest(val)?)?;138 } else {139 println!("{}", state.manifest(val)?);140 }141142 Ok(())143}