From fa9f318cdfd00b603c8a6352683ca8d3730ac3c6 Mon Sep 17 00:00:00 2001 From: amy null Date: Mon, 10 Jul 2023 15:05:01 -0400 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feature:=200.8.0:=20--no-config,=20?= =?UTF-8?q?--rule=20(closes=20#70)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 2 ++ src/config/mod.rs | 56 +++++++++++++++++++++++++++++++++++-------- src/enclosure/rule.rs | 13 ++++++++++ src/main.rs | 29 ++++++++++++---------- 6 files changed, 80 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0800ccc..327f2c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -165,7 +165,7 @@ dependencies = [ [[package]] name = "boxxy" -version = "0.7.2" +version = "0.8.0" dependencies = [ "atty", "bat", diff --git a/Cargo.toml b/Cargo.toml index f49e412..2652796 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "boxxy" -version = "0.7.2" +version = "0.8.0" edition = "2021" repository = "https://github.com/queer/boxxy" diff --git a/README.md b/README.md index 4aade3d..8814f2b 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,8 @@ force it to puts its data somewhere nice and proper. - `0.6.1`: boxxy rules can inject env vars: ![image of 0.6.1 features](https://cdn.mewna.xyz/2023/03/29/ukcWuiYdtI8yq.png) - `0.7.2`: boxxy can fork the boxxed process into the background with the `--daemon` flag. +- `0.8.0`: boxxy can pass rules at the command line with `--rule`, and disable + loading config files with `--no-config`. ### potential drawbacks diff --git a/src/config/mod.rs b/src/config/mod.rs index 06a1881..0a0c984 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,10 +1,11 @@ +use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::process::Command; use color_eyre::Result; use log::*; -use crate::enclosure::rule::BoxxyRules; +use crate::enclosure::rule::{BoxxyRules, Rule}; pub struct BoxxyConfig { pub rules: BoxxyRules, @@ -101,6 +102,39 @@ impl BoxxyConfig { Ok(rules) } + pub fn load_rules_from_cli_flag(rules: &[String]) -> Result { + let rules = rules + .iter() + .map(|s| { + let parts: Vec<&str> = s.split(':').collect(); + match parts.as_slice() { + [src, dest] => Rule { + name: format!("cli-loaded rule: {src} -> {dest}"), + target: src.to_string(), + rewrite: dest.to_string(), + mode: crate::enclosure::rule::RuleMode::File, + context: vec![], + only: vec![], + env: HashMap::new(), + }, + + [src, dest, mode] => Rule { + name: format!("cli-loaded rule: {src} -> {dest} ({mode})"), + target: src.to_string(), + rewrite: dest.to_string(), + mode: mode.parse().unwrap(), + context: vec![], + only: vec![], + env: HashMap::new(), + }, + + _ => panic!("invalid format for cli rule: {s}"), + } + }) + .collect(); + Ok(BoxxyRules { rules }) + } + pub fn merge(configs: Vec) -> BoxxyRules { let mut merged = BoxxyRules { rules: vec![] }; for config in configs { @@ -111,18 +145,20 @@ impl BoxxyConfig { } pub fn load_config(args: crate::Args) -> Result { + // Load rules let rules = { - let paths = Self::rule_paths()?; - let mut configs = vec![]; - for path in paths { - debug!("loading rules from {}", path.display()); - let config = Self::load_rules_from_path(&path)?; - debug!("loaded {} rules", config.rules.len()); - configs.push(config); + let mut rules = vec![]; + if !args.no_config { + debug!("loading rules (not asked not to!)"); + for config in BoxxyConfig::rule_paths()? { + info!("loading rules from {}", config.display()); + rules.push(BoxxyConfig::load_rules_from_path(&config)?); + } } - - Self::merge(configs) + rules.push(BoxxyConfig::load_rules_from_cli_flag(&args.arg_rules)?); + BoxxyConfig::merge(rules) }; + info!("loaded {} total rule(s)", rules.rules.len()); let (cmd, cmd_args) = (&args.command_with_args[0], &args.command_with_args[1..]); diff --git a/src/enclosure/rule.rs b/src/enclosure/rule.rs index bbf088c..7e736af 100644 --- a/src/enclosure/rule.rs +++ b/src/enclosure/rule.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use std::ffi::OsStr; use std::path::{Path, PathBuf}; +use std::str::FromStr; use color_eyre::Result; use log::*; @@ -198,3 +199,15 @@ pub enum RuleMode { File, Directory, } + +impl FromStr for RuleMode { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "file" => Ok(RuleMode::File), + "directory" => Ok(RuleMode::Directory), + _ => Err(format!("invalid rule mode: {}", s)), + } + } +} diff --git a/src/main.rs b/src/main.rs index 0eb19ca..83a5031 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::path::PathBuf; use atty::Stream; -use clap::{Parser, Subcommand}; +use clap::{ArgAction, Parser, Subcommand}; use color_eyre::Result; use log::*; use scanner::App; @@ -76,6 +76,22 @@ pub struct Args { )] pub daemon: bool, + #[arg( + long = "no-config", + default_value = "false", + help = "Disable loading config files entirely.", + action = ArgAction::SetTrue + )] + pub no_config: bool, + + #[arg( + short = 'r', + long = "rule", + help = "Pass rules via CLI. -r/--rule `/remount/this:/to/this:`", + action = ArgAction::Append + )] + pub arg_rules: Vec, + #[command(subcommand)] pub command: Option, } @@ -119,17 +135,6 @@ fn main() -> Result<()> { } } - // Load rules - let rules = { - let mut rules = vec![]; - for config in BoxxyConfig::rule_paths()? { - info!("loading rules from {}", config.display()); - rules.push(BoxxyConfig::load_rules_from_path(&config)?); - } - BoxxyConfig::merge(rules) - }; - info!("loaded {} total rule(s)", rules.rules.len()); - // Do the thing! enclosure::Enclosure::new(BoxxyConfig::load_config(cfg)?).run()?;