shell_compose/justfile.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
use serde::Deserialize;
use std::collections::HashMap;
use std::process::Command;
use thiserror::Error;
pub struct Justfile {
justfile: JustfileDump,
}
/// Output of `just --dump --dump-format json`
#[derive(Deserialize, Debug)]
struct JustfileDump {
// aliases: {},
// assignments: {},
// doc: null,
// first: Option<String>,
// groups: [],
// modules: {},
recipes: HashMap<String, JustfileRecipe>,
// settings: HashMap<String, serde_json::Value>,
// "allow_duplicate_recipes": false,
// "allow_duplicate_variables": false,
// "dotenv_filename": null,
// "dotenv_load": false,
// "dotenv_path": null,
// "dotenv_required": false,
// "export": false,
// "fallback": false,
// "ignore_comments": false,
// "positional_arguments": false,
// "quiet": false,
// "shell": null,
// "tempdir": null,
// "unstable": false,
// "windows_powershell": false,
// "windows_shell": null,
// "working_directory": null
// unexports: [],
// warnings: []
}
#[derive(Deserialize, Debug)]
struct JustfileRecipe {
attributes: Vec<HashMap<String, String>>,
// "group": "autostart"
// body: [...],
// dependencies: [],
// doc: null,
name: String,
// namepath: String,
// parameters: [],
// priors: 0,
// private: false,
// quiet: false,
// shebang: true
}
#[derive(Error, Debug)]
pub enum JustfileError {
#[error("Error in calling just executable: {0}")]
SpawnError(#[from] std::io::Error),
#[error("Invalid characters in justfile: {0}")]
Utf8Error(#[from] std::string::FromUtf8Error),
#[error("justfile version mismatch: {0}")]
JsonError(#[from] serde_json::error::Error),
}
impl Justfile {
pub fn parse() -> Result<Self, JustfileError> {
let output = Command::new("just")
.args(["--dump", "--dump-format", "json"])
.output()?;
let jsonstr = String::from_utf8(output.stdout)?;
let justfile = serde_json::from_str(&jsonstr)?;
let just = Justfile { justfile };
Ok(just)
}
pub fn group_recipes(&self, group: &str) -> Vec<String> {
let recipes = self.justfile.recipes.values().filter(|recipe| {
recipe
.attributes
.iter()
.any(|attr| attr.get("group").map(|g| g == group).unwrap_or(false))
});
recipes.map(|recipe| recipe.name.clone()).collect()
}
}