git.delta.rocks / jrsonnet / refs/commits / 3943cce16e87

difftreelog

refactor extract shared CLI code to jrsonnet-cli

Лач2020-07-19parent: #3100b67.patch.diff
in: master

8 files changed

modifiedcmds/jrsonnet/Cargo.tomldiffbeforeafterboth
11[dependencies]11[dependencies]
12jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "1.0.0" }12jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "1.0.0" }
13jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "1.0.0" }13jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "1.0.0" }
14jrsonnet-trace = { path = "../../crates/jrsonnet-trace", version = "1.0.0" }14jrsonnet-cli = { path = "../../crates/jrsonnet-cli", version = "0.1.0" }
15# TODO: Fix mimalloc compile errors, and use them15# TODO: Fix mimalloc compile errors, and use them
16mimallocator = "0.1.3"16mimallocator = "0.1.3"
1717
18[dependencies.clap]18[dependencies.clap]
19git = "https://github.com/clap-rs/clap"
19version = "3.0.0-beta.1"20rev = "48d308a8ab9e96d4b21336e428feee420dbac51d"
2021
modifiedcmds/jrsonnet/src/main.rsdiffbeforeafterboth
1use clap::Clap;1use clap::Clap;
2use jrsonnet_evaluator::Val;
3use jrsonnet_parser::{el, Arg, ArgsDesc, Expr, LocExpr, ParserSettings};2use jrsonnet_cli::{ConfigureState, GeneralOpts, InputOpts, ManifestOpts};
4use jrsonnet_trace::{CompactFormat, ExplainingFormat, PathResolver, TraceFormat};3use jrsonnet_evaluator::{EvaluationState, Result};
5use std::env::current_dir;
6use std::{collections::HashMap, path::PathBuf, rc::Rc, str::FromStr};4use std::{path::PathBuf, rc::Rc};
75
8#[global_allocator]6#[global_allocator]
9static GLOBAL: mimallocator::Mimalloc = mimallocator::Mimalloc;7static GLOBAL: mimallocator::Mimalloc = mimallocator::Mimalloc;
10
11enum Format {
12 None,
13 Json,
14 Yaml,
15}
16
17impl FromStr for Format {
18 type Err = &'static str;
19 fn from_str(s: &str) -> Result<Self, Self::Err> {
20 Ok(match s {
21 "none" => Format::None,
22 "json" => Format::Json,
23 "yaml" => Format::Yaml,
24 _ => return Err("no such format"),
25 })
26 }
27}
28
29#[derive(PartialEq)]
30enum TraceFormatName {
31 Compact,
32 Explaining,
33}
34impl FromStr for TraceFormatName {
35 type Err = &'static str;
36 fn from_str(s: &str) -> Result<Self, Self::Err> {
37 Ok(match s {
38 "compact" => TraceFormatName::Compact,
39 "explaining" => TraceFormatName::Explaining,
40 _ => return Err("no such format"),
41 })
42 }
43}
448
45#[derive(Clone)]9#[derive(Clap)]
10// #[clap(help_heading = "DEBUG")]
46struct ExtStr {11struct DebugOpts {
12 /// Required OS stack size, probally you shouldn't change it, unless jrsonnet is failing with stack overflow
47 name: String,13 #[clap(long, name = "size")]
48 value: String,14 pub os_stack: Option<usize>,
49}15}
50impl FromStr for ExtStr {
51 type Err = &'static str;
52 fn from_str(s: &str) -> Result<Self, Self::Err> {
53 let out: Vec<_> = s.split('=').collect();
54 match out.len() {
55 1 => Ok(ExtStr {
56 name: out[0].to_owned(),
57 value: std::env::var(out[0]).or(Err("missing env var"))?,
58 }),
59 2 => Ok(ExtStr {
60 name: out[0].to_owned(),
61 value: out[1].to_owned(),
62 }),
63 _ => Err("bad ext-str syntax"),
64 }
65 }
66}
6716
68#[derive(Clap)]17#[derive(Clap)]
69#[clap(name = "jrsonnet", version, author)]
70pub struct Opts {18struct Opts {
71 #[clap(long, about = "Disable global std variable")]19 #[clap(flatten)]
72 no_stdlib: bool,20 input: InputOpts,
73 #[clap(long, about = "Add external string", number_of_values = 1)]21 #[clap(flatten)]
74 ext_str: Vec<ExtStr>,22 general: GeneralOpts,
75 #[clap(long, about = "Add external string from code", number_of_values = 1)]23 #[clap(flatten)]
76 ext_code: Vec<ExtStr>,24 manifest: ManifestOpts,
77 #[clap(long, about = "Add TLA", number_of_values = 1)]25 #[clap(flatten)]
78 tla_str: Vec<ExtStr>,26 debug: DebugOpts,
79 #[clap(long, about = "Add TLA from code", number_of_values = 1)]
80 tla_code: Vec<ExtStr>,
81 #[clap(long, short = "f", default_value = "json", possible_values = &["none", "json", "yaml"], about = "Output format, wraps resulting value to corresponding std.manifest call")]
82 format: Format,
83 #[clap(long, default_value = "compact", possible_values = &["compact", "explaining"], about = "Choose format of displayed stacktraces")]
84 trace_format: TraceFormatName,
85
86 #[clap(
87 long,
88 short = "s",
89 default_value = "200",
90 about = "Number of allowed stack frames"
91 )]
92 max_stack: usize,
93 #[clap(
94 long,
95 short = "t",
96 default_value = "20",
97 about = "Max length of stack trace before cropping"
98 )]
99 max_trace: usize,
100
101 #[clap(
102 long,
103 about = "Required os stack size, probally you shouldn't change it"
104 )]
105 thread_stack_size: Option<usize>,
106
107 #[clap(long, short = "J", about = "Library search dir")]
108 jpath: Vec<PathBuf>,
109
110 #[clap(
111 long,
112 default_value = "3",
113 about = "When using --format, this option specifies string to pad output with"
114 )]
115 line_padding: usize,
116
117 #[clap(about = "File to compile")]
118 input: String,
119}27}
12028
121fn main() {29fn main() {
122 let opts: Opts = Opts::parse();30 let opts: Opts = Opts::parse();
123 if let Some(size) = opts.thread_stack_size {31 if let Some(size) = opts.debug.os_stack {
124 std::thread::Builder::new()32 std::thread::Builder::new()
125 .stack_size(size * 1024 * 1024)33 .stack_size(size * 1024 * 1024)
126 .spawn(|| main_real(opts))34 .spawn(|| main_catch(opts))
127 .unwrap()35 .expect("new thread spawned")
128 .join()36 .join()
129 .unwrap();37 .expect("thread finished successfully");
130 } else {38 } else {
131 main_real(opts)39 main_catch(opts)
132 }40 }
133}41}
13442
135fn main_real(opts: Opts) {43fn main_catch(opts: Opts) {
44 let state = EvaluationState::default();
45 if let Err(e) = main_real(&state, opts) {
46 println!("{}", state.stringify_err(&e));
47 }
48}
49
136 let evaluator = jrsonnet_evaluator::EvaluationState::default();50fn main_real(state: &EvaluationState, opts: Opts) -> Result<()> {
137 {
138 let mut settings = evaluator.settings_mut();
139 settings.max_stack = opts.max_stack;
140 settings.max_trace = opts.max_trace;
141 settings.import_resolver = Box::new(jrsonnet_evaluator::FileImportResolver {
142 library_paths: opts.jpath.clone(),
143 });
144 }
145 if !opts.no_stdlib {
146 evaluator.with_stdlib();
147 }
148 for ExtStr { name, value } in opts.ext_str.iter().cloned() {51 opts.general.configure(&state)?;
149 evaluator
150 .settings_mut()
151 .ext_vars
152 .insert(name.into(), Val::Str(value.into()));
153 }
154 for ExtStr { name, value } in opts.ext_code.iter().cloned() {
155 evaluator.settings_mut().ext_vars.insert(52 opts.manifest.configure(&state)?;
156 name.clone().into(),
157 evaluator
158 .parse_evaluate_raw(PathBuf::from(format!("ext_code {}", name)).into(), &value)
159 .unwrap(),
160 );
161 }
16253
163 let resolver = PathResolver::Relative(std::env::current_dir().unwrap());54 let val = if opts.input.evaluate {
164 let trace_format: Box<dyn TraceFormat> = match opts.trace_format {
165 TraceFormatName::Compact => Box::new(CompactFormat { resolver }),
166 TraceFormatName::Explaining => Box::new(ExplainingFormat { resolver }),
167 };
168
169 let mut input = current_dir().unwrap();
170 input.push(opts.input.clone());55 state.evaluate_snippet_raw(
56 Rc::new(PathBuf::from("args")),
57 (&opts.input.input as &str).into(),
58 )?
59 } else {
171 let code_string = String::from_utf8(std::fs::read(opts.input.clone()).unwrap()).unwrap();60 state.evaluate_file_raw(&PathBuf::from(opts.input.input))?
61 };
62
172 if let Err(e) = evaluator.add_file(Rc::new(input.clone()), code_string.into()) {63 let val = state.with_tla(val)?;
173 trace_format.print_trace(&evaluator, &e).unwrap();64
174 std::process::exit(1);
175 }
176 let result = evaluator.evaluate_file(&input);65 println!("{}", state.manifest(val)?);
177 match result {66
178 Ok(v) => {67 Ok(())
179 let v = match v {68}
180 Val::Func(f) => {
181 let mut desc_map = HashMap::new();
182 for ExtStr { name, value } in opts.tla_str.iter().cloned() {
183 desc_map.insert(name, el!(Expr::Str(value.into())));
184 }
185 for ExtStr { name, value } in opts.tla_code.iter().cloned() {
186 desc_map.insert(
187 name,
188 jrsonnet_parser::parse(
189 &value,
190 &ParserSettings {
191 file_name: Rc::new(PathBuf::new()),
192 loc_data: false,
193 },
194 )
195 .unwrap(),
196 );
197 }
198 evaluator
199 .settings_mut()
200 .globals
201 .insert("__tmp__tlf__".into(), Val::Func(f));
202 evaluator
203 .evaluate_raw(el!(Expr::Apply(
204 el!(Expr::Var("__tmp__tlf__".into())),
205 ArgsDesc(desc_map.into_iter().map(|(k, v)| Arg(Some(k), v)).collect()),
206 false,
207 )))
208 .unwrap()
209 }
210 v => v,
211 };
212 let v = evaluator.run_in_state(|| match opts.format {
213 Format::Json => Ok(Val::Str(v.into_json(opts.line_padding)?)),
214 Format::Yaml => Ok(Val::Str(v.into_yaml(opts.line_padding)?)),
215 _ => Ok(v),
216 });
217 let v = match v {
218 Ok(v) => v,
219 Err(err) => {
220 trace_format.print_trace(&evaluator, &err).unwrap();
221 std::process::exit(1);
222 }
223 };
224 match v {
225 Val::Str(s) => println!("{}", s),
226 Val::Num(n) => println!("{}", n),
227 _v => eprintln!(
228 "jsonnet output is not a string.\nDid you forgot to set --format, or wrap your data with std.manifestJson?"
229 ),
230 }
231 }
232 Err(err) => {
233 trace_format.print_trace(&evaluator, &err).unwrap();
234 std::process::exit(1);
235 }
236 }
237}
23869
addedcrates/jrsonnet-cli/Cargo.tomldiffbeforeafterboth

no changes

addedcrates/jrsonnet-cli/src/ext.rsdiffbeforeafterboth

no changes

addedcrates/jrsonnet-cli/src/lib.rsdiffbeforeafterboth

no changes

addedcrates/jrsonnet-cli/src/manifest.rsdiffbeforeafterboth

no changes

addedcrates/jrsonnet-cli/src/tla.rsdiffbeforeafterboth

no changes

addedcrates/jrsonnet-cli/src/trace.rsdiffbeforeafterboth

no changes