commit 42e504ae010254d3c4861dd0d4a06fc9de7d4f93
parent 541a82a1b76b0a3c34eda1eb4ebfb24c4be328b9
Author: Andy Khramtsov <>
Date: Sat, 7 Feb 2026 21:28:42 +0300
feat: check inventory
Diffstat:
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(),