git.delta.rocks / jrsonnet / refs/commits / 252cf3bfebf5

difftreelog

fix remove unimplemented deps subcommand

Yaroslav Bolyukin2023-04-17parent: #b61a6d8.patch.diff
in: master

1 file changed

modifiedcmds/jrsonnet/src/main.rsdiffbeforeafterboth
before · cmds/jrsonnet/src/main.rs
1use std::{2	fs::{create_dir_all, File},3	io::{Read, Write},4};56use clap::{CommandFactory, Parser};7use clap_complete::Shell;8use jrsonnet_cli::{GcOpts, ManifestOpts, MiscOpts, OutputOpts, StdOpts, TlaOpts, TraceOpts};9use jrsonnet_evaluator::{10	apply_tla,11	error::{Error as JrError, ErrorKind},12	throw, ResultExt, State, Val,13};1415#[cfg(feature = "mimalloc")]16#[global_allocator]17static GLOBAL: mimallocator::Mimalloc = mimallocator::Mimalloc;1819#[derive(Parser)]20enum SubOpts {21	/// Generate completions for specified shell22	Generate {23		/// Target shell name24		shell: Shell,25	},26	Deps {27		path: String,28	},29}3031#[derive(Parser)]32#[clap(next_help_heading = "DEBUG")]33struct DebugOpts {34	/// Required OS stack size.35	/// This shouldn't be changed unless jrsonnet is failing with stack overflow error.36	#[clap(long, name = "size")]37	pub os_stack: Option<usize>,38}3940#[derive(Parser)]41#[clap(next_help_heading = "INPUT")]42struct InputOpts {43	/// Treat input as code, evaluate them instead of reading file44	#[clap(long, short = 'e')]45	pub exec: bool,4647	/// Path to the file to be compiled if `--evaluate` is unset, otherwise code itself48	pub input: Option<String>,49}5051/// Jsonnet commandline interpreter (Rust implementation)52#[derive(Parser)]53#[clap(54	args_conflicts_with_subcommands = true,55	disable_version_flag = true,56	version,57	author58)]59struct Opts {60	#[clap(subcommand)]61	sub: Option<SubOpts>,6263	#[clap(flatten)]64	input: InputOpts,65	#[clap(flatten)]66	misc: MiscOpts,67	#[clap(flatten)]68	tla: TlaOpts,69	#[clap(flatten)]70	std: StdOpts,71	#[clap(flatten)]72	gc: GcOpts,7374	#[clap(flatten)]75	trace: TraceOpts,76	#[clap(flatten)]77	manifest: ManifestOpts,78	#[clap(flatten)]79	output: OutputOpts,80	#[clap(flatten)]81	debug: DebugOpts,82}8384fn main() {85	let opts: Opts = Opts::parse();8687	if let Some(sub) = opts.sub {88		match sub {89			SubOpts::Deps { path } => todo!(),90			SubOpts::Generate { shell } => {91				use clap_complete::generate;92				let app = &mut Opts::command();93				let buf = &mut std::io::stdout();94				generate(shell, app, "jrsonnet", buf);95				std::process::exit(0)96			}97		}98	}99100	let success = if let Some(size) = opts.debug.os_stack {101		std::thread::Builder::new()102			.stack_size(size * 1024 * 1024)103			.spawn(|| main_catch(opts))104			.expect("new thread spawned")105			.join()106			.expect("thread finished successfully")107	} else {108		main_catch(opts)109	};110	if !success {111		std::process::exit(1);112	}113}114115#[derive(thiserror::Error, Debug)]116enum Error {117	// Handled differently118	#[error("evaluation error")]119	Evaluation(JrError),120	#[error("io error")]121	Io(#[from] std::io::Error),122	#[error("input is not utf8 encoded")]123	Utf8(#[from] std::str::Utf8Error),124	#[error("missing input argument")]125	MissingInputArgument,126}127impl From<JrError> for Error {128	fn from(e: JrError) -> Self {129		Self::Evaluation(e)130	}131}132impl From<ErrorKind> for Error {133	fn from(e: ErrorKind) -> Self {134		Self::from(JrError::from(e))135	}136}137138fn main_catch(opts: Opts) -> bool {139	let s = State::default();140	let trace = opts.trace.trace_format();141	if let Err(e) = main_real(&s, opts) {142		if let Error::Evaluation(e) = e {143			let mut out = String::new();144			trace.write_trace(&mut out, &e).expect("format error");145			eprintln!("{out}")146		} else {147			eprintln!("{e}");148		}149		return false;150	}151	true152}153154fn main_real(s: &State, opts: Opts) -> Result<(), Error> {155	let _gc_leak_guard = opts.gc.leak_on_exit();156	let _gc_print_stats = opts.gc.stats_printer();157	let _stack_depth_override = opts.misc.stack_size_override();158159	let import_resolver = opts.misc.import_resolver();160	s.set_import_resolver(import_resolver);161162	let std = opts.std.context_initializer(s)?;163	if let Some(std) = std {164		s.set_context_initializer(std);165	}166167	let input = opts.input.input.ok_or(Error::MissingInputArgument)?;168	let val = if opts.input.exec {169		s.evaluate_snippet("<cmdline>".to_owned(), &input as &str)?170	} else if input == "-" {171		let mut input = Vec::new();172		std::io::stdin().read_to_end(&mut input)?;173		let input_str = std::str::from_utf8(&input)?;174		s.evaluate_snippet("<stdin>".to_owned(), input_str)?175	} else {176		s.import(&input)?177	};178179	let tla = opts.tla.tla_opts()?;180	let val = apply_tla(s.clone(), &tla, val)?;181182	let manifest_format = opts.manifest.manifest_format();183	if let Some(multi) = opts.output.multi {184		if opts.output.create_output_dirs {185			let mut dir = multi.clone();186			dir.pop();187			create_dir_all(dir)?;188		}189		let Val::Obj(obj) = val else {190			throw!("value should be object for --multi manifest, got {}", val.value_type())191		};192		for (field, data) in obj.iter(193			#[cfg(feature = "exp-preserve-order")]194			opts.manifest.preserve_order,195		) {196			let data = data.with_description(|| format!("getting field {field} for manifest"))?;197198			let mut path = multi.clone();199			path.push(&field as &str);200			if opts.output.create_output_dirs {201				let mut dir = path.clone();202				dir.pop();203				create_dir_all(dir)?;204			}205			println!("{}", path.to_str().expect("path"));206			let mut file = File::create(path)?;207			writeln!(208				file,209				"{}",210				data.manifest(&manifest_format)211					.with_description(|| format!("manifesting {field}"))?212			)?;213		}214	} else if let Some(path) = opts.output.output_file {215		if opts.output.create_output_dirs {216			let mut dir = path.clone();217			dir.pop();218			create_dir_all(dir)?;219		}220		let mut file = File::create(path)?;221		writeln!(file, "{}", val.manifest(manifest_format)?)?;222	} else {223		let output = val.manifest(manifest_format)?;224		if !output.is_empty() {225			println!("{output}");226		}227	}228229	Ok(())230}
after · cmds/jrsonnet/src/main.rs
1use std::{2	fs::{create_dir_all, File},3	io::{Read, Write},4};56use clap::{CommandFactory, Parser};7use clap_complete::Shell;8use jrsonnet_cli::{GcOpts, ManifestOpts, MiscOpts, OutputOpts, StdOpts, TlaOpts, TraceOpts};9use jrsonnet_evaluator::{10	apply_tla,11	error::{Error as JrError, ErrorKind},12	throw, ResultExt, State, Val,13};1415#[cfg(feature = "mimalloc")]16#[global_allocator]17static GLOBAL: mimallocator::Mimalloc = mimallocator::Mimalloc;1819#[derive(Parser)]20enum SubOpts {21	/// Generate completions for specified shell22	Generate {23		/// Target shell name24		shell: Shell,25	},26}2728#[derive(Parser)]29#[clap(next_help_heading = "DEBUG")]30struct DebugOpts {31	/// Required OS stack size.32	/// This shouldn't be changed unless jrsonnet is failing with stack overflow error.33	#[clap(long, name = "size")]34	pub os_stack: Option<usize>,35}3637#[derive(Parser)]38#[clap(next_help_heading = "INPUT")]39struct InputOpts {40	/// Treat input as code, evaluate them instead of reading file41	#[clap(long, short = 'e')]42	pub exec: bool,4344	/// Path to the file to be compiled if `--evaluate` is unset, otherwise code itself45	pub input: Option<String>,46}4748/// Jsonnet commandline interpreter (Rust implementation)49#[derive(Parser)]50#[clap(51	args_conflicts_with_subcommands = true,52	disable_version_flag = true,53	version,54	author55)]56struct Opts {57	#[clap(subcommand)]58	sub: Option<SubOpts>,5960	#[clap(flatten)]61	input: InputOpts,62	#[clap(flatten)]63	misc: MiscOpts,64	#[clap(flatten)]65	tla: TlaOpts,66	#[clap(flatten)]67	std: StdOpts,68	#[clap(flatten)]69	gc: GcOpts,7071	#[clap(flatten)]72	trace: TraceOpts,73	#[clap(flatten)]74	manifest: ManifestOpts,75	#[clap(flatten)]76	output: OutputOpts,77	#[clap(flatten)]78	debug: DebugOpts,79}8081fn main() {82	let opts: Opts = Opts::parse();8384	if let Some(sub) = opts.sub {85		match sub {86			SubOpts::Generate { shell } => {87				use clap_complete::generate;88				let app = &mut Opts::command();89				let buf = &mut std::io::stdout();90				generate(shell, app, "jrsonnet", buf);91				std::process::exit(0)92			}93		}94	}9596	let success = if let Some(size) = opts.debug.os_stack {97		std::thread::Builder::new()98			.stack_size(size * 1024 * 1024)99			.spawn(|| main_catch(opts))100			.expect("new thread spawned")101			.join()102			.expect("thread finished successfully")103	} else {104		main_catch(opts)105	};106	if !success {107		std::process::exit(1);108	}109}110111#[derive(thiserror::Error, Debug)]112enum Error {113	// Handled differently114	#[error("evaluation error")]115	Evaluation(JrError),116	#[error("io error")]117	Io(#[from] std::io::Error),118	#[error("input is not utf8 encoded")]119	Utf8(#[from] std::str::Utf8Error),120	#[error("missing input argument")]121	MissingInputArgument,122}123impl From<JrError> for Error {124	fn from(e: JrError) -> Self {125		Self::Evaluation(e)126	}127}128impl From<ErrorKind> for Error {129	fn from(e: ErrorKind) -> Self {130		Self::from(JrError::from(e))131	}132}133134fn main_catch(opts: Opts) -> bool {135	let s = State::default();136	let trace = opts.trace.trace_format();137	if let Err(e) = main_real(&s, opts) {138		if let Error::Evaluation(e) = e {139			let mut out = String::new();140			trace.write_trace(&mut out, &e).expect("format error");141			eprintln!("{out}")142		} else {143			eprintln!("{e}");144		}145		return false;146	}147	true148}149150fn main_real(s: &State, opts: Opts) -> Result<(), Error> {151	let _gc_leak_guard = opts.gc.leak_on_exit();152	let _gc_print_stats = opts.gc.stats_printer();153	let _stack_depth_override = opts.misc.stack_size_override();154155	let import_resolver = opts.misc.import_resolver();156	s.set_import_resolver(import_resolver);157158	let std = opts.std.context_initializer(s)?;159	if let Some(std) = std {160		s.set_context_initializer(std);161	}162163	let input = opts.input.input.ok_or(Error::MissingInputArgument)?;164	let val = if opts.input.exec {165		s.evaluate_snippet("<cmdline>".to_owned(), &input as &str)?166	} else if input == "-" {167		let mut input = Vec::new();168		std::io::stdin().read_to_end(&mut input)?;169		let input_str = std::str::from_utf8(&input)?;170		s.evaluate_snippet("<stdin>".to_owned(), input_str)?171	} else {172		s.import(&input)?173	};174175	let tla = opts.tla.tla_opts()?;176	let val = apply_tla(s.clone(), &tla, val)?;177178	let manifest_format = opts.manifest.manifest_format();179	if let Some(multi) = opts.output.multi {180		if opts.output.create_output_dirs {181			let mut dir = multi.clone();182			dir.pop();183			create_dir_all(dir)?;184		}185		let Val::Obj(obj) = val else {186			throw!("value should be object for --multi manifest, got {}", val.value_type())187		};188		for (field, data) in obj.iter(189			#[cfg(feature = "exp-preserve-order")]190			opts.manifest.preserve_order,191		) {192			let data = data.with_description(|| format!("getting field {field} for manifest"))?;193194			let mut path = multi.clone();195			path.push(&field as &str);196			if opts.output.create_output_dirs {197				let mut dir = path.clone();198				dir.pop();199				create_dir_all(dir)?;200			}201			println!("{}", path.to_str().expect("path"));202			let mut file = File::create(path)?;203			writeln!(204				file,205				"{}",206				data.manifest(&manifest_format)207					.with_description(|| format!("manifesting {field}"))?208			)?;209		}210	} else if let Some(path) = opts.output.output_file {211		if opts.output.create_output_dirs {212			let mut dir = path.clone();213			dir.pop();214			create_dir_all(dir)?;215		}216		let mut file = File::create(path)?;217		writeln!(file, "{}", val.manifest(manifest_format)?)?;218	} else {219		let output = val.manifest(manifest_format)?;220		if !output.is_empty() {221			println!("{output}");222		}223	}224225	Ok(())226}