difftreelog
feat jrsonnet-deps command
in: master
3 files changed
Cargo.lockdiffbeforeafterboth621 "jrsonnet-stdlib",621 "jrsonnet-stdlib",622]622]623624[[package]]625name = "jrsonnet-deps"626version = "0.5.0-pre97"627dependencies = [628 "clap",629 "jrsonnet-cli",630 "jrsonnet-evaluator",631 "jrsonnet-ir",632 "jrsonnet-ir-parser",633]623634624[[package]]635[[package]]625name = "jrsonnet-evaluator"636name = "jrsonnet-evaluator"cmds/jrsonnet-deps/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/cmds/jrsonnet-deps/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "jrsonnet-deps"
+description = "List dependencies of a jsonnet file"
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+repository.workspace = true
+version.workspace = true
+
+[lints]
+workspace = true
+
+[dependencies]
+jrsonnet-evaluator.workspace = true
+jrsonnet-ir.workspace = true
+jrsonnet-ir-parser.workspace = true
+jrsonnet-cli.workspace = true
+
+clap = { workspace = true, features = ["derive"] }
cmds/jrsonnet-deps/src/main.rsdiffbeforeafterboth--- /dev/null
+++ b/cmds/jrsonnet-deps/src/main.rs
@@ -0,0 +1,80 @@
+use std::collections::BTreeSet;
+use std::process::exit;
+
+use clap::Parser;
+use jrsonnet_evaluator::{FileImportResolver, ImportResolver};
+use jrsonnet_ir::{visit::Visitor, IStr, Source, SourcePath};
+use jrsonnet_ir_parser::ParserSettings;
+
+use jrsonnet_cli::MiscOpts;
+
+#[derive(Parser)]
+struct Opts {
+ /// Path to the file to start dependency search from
+ input: String,
+ #[clap(flatten)]
+ misc: MiscOpts,
+}
+
+struct FoundImports(Vec<(IStr, bool)>);
+impl Visitor for FoundImports {
+ fn visit_import(&mut self, expression: bool, value: IStr) {
+ self.0.push((value, expression));
+ }
+}
+
+fn collect_deps(
+ resolver: &FileImportResolver,
+ source: &SourcePath,
+ deps: &mut BTreeSet<String>,
+) -> Result<(), String> {
+ let contents = resolver
+ .load_file_contents(source)
+ .map_err(|e| format!("{e}"))?;
+ let code = std::str::from_utf8(&contents).map_err(|e| format!("{source}: {e}"))?;
+ let code: IStr = code.into();
+ let parsed = jrsonnet_ir_parser::parse(
+ &code,
+ &ParserSettings {
+ source: Source::new(source.clone(), code.clone()),
+ },
+ )
+ .map_err(|e| format!("{source}: {e}"))?;
+
+ let mut imports = FoundImports(vec![]);
+ imports.visit_expr(&parsed);
+
+ for (path, expression) in imports.0 {
+ let resolved = resolver
+ .resolve_from(source, &&*path)
+ .map_err(|e| format!("{e}"))?;
+ let path_str = format!("{resolved}");
+ if deps.insert(path_str) && expression {
+ collect_deps(resolver, &resolved, deps)?;
+ }
+ }
+
+ Ok(())
+}
+
+fn main() {
+ let opts = Opts::parse();
+ let resolver = opts.misc.import_resolver();
+
+ let source = resolver
+ .resolve_from_default(&opts.input.as_str())
+ .unwrap_or_else(|e| {
+ eprintln!("{e}");
+ exit(1);
+ });
+
+ let mut deps = BTreeSet::new();
+ if let Err(e) = collect_deps(&resolver, &source, &mut deps) {
+ eprintln!("{e}");
+ exit(1);
+ }
+
+ for dep in &deps {
+ println!("{dep}");
+ }
+}