jannie

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

commit b48ba649f0349b6a4bd60f5aba8ba2ac00d5f9f9
parent 6d684d1c56f5ff14f07ff3dc0c2c9e8dafad0098
Author: Andy Khramtsov <>
Date:   Sat,  7 Feb 2026 13:18:34 +0300

feat: add inventory

Diffstat:
MCargo.lock | 1+
MCargo.toml | 1+
Mconfig.yaml | 2++
Minventory.json | 7+++++++
Asrc/inventory.rs | 11+++++++++++
Msrc/lib.rs | 61+++++++++++++++++++++++++++++++++++++------------------------
Msrc/state.rs | 31+++++++++++++++++++++++++------
7 files changed, 84 insertions(+), 30 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -471,6 +471,7 @@ dependencies = [ "dialoguer", "indexmap", "serde", + "serde_json", "test-log", "thiserror", "tokio", diff --git a/Cargo.toml b/Cargo.toml @@ -9,6 +9,7 @@ config = "0.15.19" dialoguer = "0.12.0" indexmap = "2.13.0" serde = { version = "1.0.228", features = ["derive"] } +serde_json = "1.0.149" test-log = { version = "0.2.19", features = ["trace"] } thiserror = "2.0.17" tokio = { version = "1.49.0", features = ["rt-multi-thread", "fs"] } diff --git a/config.yaml b/config.yaml @@ -13,6 +13,8 @@ filters: type: blacklist - path: my-space/projects/rust type: whitelist + - path: my-space/projects/openscad + type: whitelist - path: my-space/projects/rust/jannie type: blacklist - path: my-space/projects/rust/jannie/log diff --git a/inventory.json b/inventory.json @@ -0,0 +1,7 @@ +{ + "items": [ + { + "path": "/home/andy/my-space/projects/openscad/cable-holder" + } + ] +} diff --git a/src/inventory.rs b/src/inventory.rs @@ -0,0 +1,11 @@ +use std::path::PathBuf; + +#[derive(serde::Deserialize, Debug)] +pub struct Inventory { + pub items: Vec<Item>, +} + +#[derive(serde::Deserialize, Debug)] +pub struct Item { + pub path: PathBuf, +} diff --git a/src/lib.rs b/src/lib.rs @@ -12,6 +12,7 @@ use crate::{ pub mod args; pub mod config; pub mod filetree; +pub mod inventory; pub mod logging; pub mod state; @@ -34,11 +35,18 @@ pub fn result_main() -> Result<(), Error> { #[derive(Clone, Debug)] struct Meta { + inventory: Option<bool>, blacklist: Option<bool>, } async fn read(state: &State) { - let root = Node::new(state.config.root.clone(), Meta { blacklist: None }); + let root = Node::new( + state.config.root.clone(), + Meta { + blacklist: None, + inventory: None, + }, + ); let mut filetree = Filetree::new(root); let mut buffer = Vec::new(); @@ -68,6 +76,10 @@ async fn read(state: &State) { } let allowed = allowed(state, &dir); + let in_inventory = state + .inventory_tree + .node_by_path(&dir) + .is_some_and(|node| node.borrow().is_leaf()); if base != dir { let mut suffix = dir.strip_prefix(&base).unwrap().to_owned(); @@ -76,7 +88,13 @@ async fn read(state: &State) { for component in suffix.components() { base.push(component); filetree - .insert(Node::new(base.clone(), Meta { blacklist: None })) + .insert(Node::new( + base.clone(), + Meta { + blacklist: None, + inventory: None, + }, + )) .unwrap(); } filetree @@ -84,6 +102,7 @@ async fn read(state: &State) { dir.clone(), Meta { blacklist: Some(!allowed), + inventory: Some(in_inventory), }, )) .unwrap(); @@ -158,28 +177,22 @@ fn print(tree: &Filetree<Meta>) -> Result<(), Error> { print_buffer.push((0, tree.root().borrow().id())); while let Some((offset, node_id)) = print_buffer.pop() { let node = tree.node(node_id).expect("Shold have the node"); - match node.borrow().meta().blacklist { - Some(true) => println!( - "{}| {}, BL", - " ".repeat(offset), - node.borrow() - .path() - .file_name() - .map(|name| name.to_str()) - .flatten() - .unwrap_or("UNKNOWN") - ), - _ => println!( - "{}| {}", - " ".repeat(offset), - node.borrow() - .path() - .file_name() - .map(|name| name.to_str()) - .flatten() - .unwrap_or("UNKNOWN") - ), - }; + let name = node + .borrow() + .path() + .file_name() + .map(|name| name.to_str()) + .flatten() + .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); + } else if let Some(true) = node.borrow().meta().blacklist { + println!("{}\x1b[2m|\x1b[0m \x1b[2;9m{}\x1b[0m", offset_text, name); + } else { + println!("{}\x1b[2m|\x1b[0m {}", offset_text, name); + } print_buffer.extend( node.borrow() .children() diff --git a/src/state.rs b/src/state.rs @@ -5,12 +5,14 @@ use tokio::runtime::Runtime; use crate::{ config::Config, filetree::{self, Filetree, node::Node}, + inventory::Inventory, }; pub struct State { pub config_dir: PathBuf, pub config: Config, pub runtime: Runtime, + pub inventory: Inventory, pub blacklist_tree: Filetree<()>, pub whitelist_tree: Filetree<()>, pub inventory_tree: Filetree<()>, @@ -18,7 +20,19 @@ pub struct State { impl State { pub fn new(config_dir: &Path, config: Config) -> Result<Self, Error> { - // todo: read inventory + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .map_err(Error::Runtime)?; + + let inventory_path = config_dir.join("inventory.json"); + + let inventory = runtime + .block_on(tokio::fs::read(inventory_path)) + .map_err(Error::ReadFile)?; + let inventory: Inventory = + serde_json::from_slice(inventory.as_slice()).map_err(Error::Json)?; + let mut blacklist_tree = Filetree::new(Node::new("/".into(), ())); let mut whitelist_tree = Filetree::new(Node::new("/".into(), ())); @@ -47,14 +61,15 @@ impl State { } } - let inventory_tree = Filetree::new(Node::new("/".into(), ())); + let mut inventory_tree = Filetree::new(Node::new("/".into(), ())); + for item in &inventory.items { + add_to_tree(&mut inventory_tree, &item.path)? + } Ok(Self { config_dir: config_dir.into(), config, - runtime: tokio::runtime::Builder::new_current_thread() - .enable_all() - .build() - .map_err(Error::Runtime)?, + runtime, + inventory, blacklist_tree, whitelist_tree, inventory_tree, @@ -87,6 +102,10 @@ fn add_to_tree(tree: &mut Filetree<()>, path: &Path) -> Result<(), Error> { pub enum Error { #[error("Error building runtime: {0}")] Runtime(tokio::io::Error), + #[error("Error reading file: {0}")] + ReadFile(std::io::Error), + #[error("Error parsing json: {0}")] + Json(serde_json::Error), #[error("Error building filetree: {0}")] Filetree(#[from] filetree::Error), }