jannie

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 42e504ae010254d3c4861dd0d4a06fc9de7d4f93
parent 541a82a1b76b0a3c34eda1eb4ebfb24c4be328b9
Author: Andy Khramtsov <>
Date:   Sat,  7 Feb 2026 21:28:42 +0300

feat: check inventory

Diffstat:
Msrc/inventory.rs | 10++++++++++
Msrc/lib.rs | 33+++++++++++++++++++++++++++------
Msrc/state.rs | 30++++++++++++++++++++++++++----
3 files changed, 63 insertions(+), 10 deletions(-)

diff --git a/src/inventory.rs b/src/inventory.rs @@ -8,4 +8,14 @@ pub struct Inventory { #[derive(serde::Deserialize, Debug)] pub struct Item { pub path: PathBuf, + #[serde(default)] + pub check: Check, +} + +#[derive(serde::Deserialize, Clone, Debug, Default)] +#[serde(rename_all = "snake_case")] +pub enum Check { + #[default] + None, + Shell(String), } diff --git a/src/lib.rs b/src/lib.rs @@ -38,7 +38,7 @@ pub fn result_main() -> Result<(), Error> { #[derive(Clone, Debug)] struct Meta { - inventory: Option<bool>, + inventory: Option<String>, blacklist: Option<bool>, } @@ -85,7 +85,21 @@ async fn read(state: &State) { let in_inventory = state .inventory_tree .node_by_path(&dir) - .is_some_and(|node| node.borrow().is_leaf()); + .filter(|node| node.borrow().is_leaf()) + .map(|node| node.borrow().meta().clone()) + .flatten() + .map(|check| match check { + inventory::Check::None => "".to_string(), + inventory::Check::Shell(cmd) => String::from_utf8( + std::process::Command::new("sh") + .arg("-c") + .arg(cmd) + .output() + .expect("Should finish command") + .stdout, + ) + .expect("Should be utf8 string"), + }); if base != dir { let mut suffix = dir.strip_prefix(&base).unwrap().to_owned(); @@ -108,7 +122,7 @@ async fn read(state: &State) { dir.clone(), Meta { blacklist: Some(!allowed), - inventory: Some(in_inventory), + inventory: in_inventory, }, )) .unwrap(); @@ -214,12 +228,19 @@ fn print(tree: &Filetree<Meta>) -> Result<(), Error> { .unwrap_or("UNKNOWN") .to_owned(); let offset_text = " ".repeat(offset); - if let Some(true) = node.borrow().meta().inventory { - println!("{}\x1b[2m|\x1b[0m \x1b[32m/{}\x1b[0m", offset_text, name); + if let Some(msg) = node.borrow().meta().inventory.as_ref() { + println!( + "{}\x1b[2m|\x1b[0m \x1b[32m/{}\x1b[0m {}", + offset_text, + name, + msg.trim() + ); } else if let Some(true) = node.borrow().meta().blacklist { println!("{}\x1b[2m|\x1b[0m \x1b[2;9m/{}\x1b[0m", offset_text, name); - } else { + } else if node.borrow().is_leaf() { println!("{}\x1b[2m|\x1b[0m \x1b[31m/{}\x1b[0m", offset_text, name); + } else { + println!("{}\x1b[2m|\x1b[0m /{}", offset_text, name); } for child in node .borrow() diff --git a/src/state.rs b/src/state.rs @@ -5,7 +5,7 @@ use tokio::runtime::Runtime; use crate::{ config::Config, filetree::{self, Filetree, node::Node}, - inventory::Inventory, + inventory::{self, Inventory}, }; pub struct State { @@ -15,7 +15,7 @@ pub struct State { pub inventory: Inventory, pub blacklist_tree: Filetree<()>, pub whitelist_tree: Filetree<()>, - pub inventory_tree: Filetree<()>, + pub inventory_tree: Filetree<Option<inventory::Check>>, } impl State { @@ -61,9 +61,31 @@ impl State { } } - let mut inventory_tree = Filetree::new(Node::new("/".into(), ())); + let mut inventory_tree = Filetree::new(Node::new("/".into(), None)); for item in &inventory.items { - add_to_tree(&mut inventory_tree, &item.path)? + let path = &item.path; + let mut components = path.components(); + let mut path_buf = PathBuf::new(); + loop { + let component = components.next(); + match component { + Some(component) => { + path_buf.push(component); + if inventory_tree.node_by_path(&path_buf).is_none() { + inventory_tree.insert(Node::new(path_buf.clone(), None))?; + } + } + None => { + inventory_tree + .node_by_path(path) + .expect("Should have added inventory item") + .borrow_mut() + .meta_mut() + .replace(item.check.clone()); + break; + } + } + } } Ok(Self { config_dir: config_dir.into(),