use clap::Parser;
use anyhow::Result;
use log::{info, LevelFilter};
use std::ops::Add;
use std::path::PathBuf;
use std::time;
use crate::{setup, simplelog};
#[derive(Debug, Parser)]
#[command(version, about, long_about = None)]
struct Options {
#[arg(value_name = "path")]
pub inputs: Vec<PathBuf>,
#[arg(long)]
pub brp: bool,
#[arg(short, long, action = clap::ArgAction::Count)]
pub verbose: u8,
#[arg(short = 'n', long)]
pub dry_run: bool,
#[arg(long)]
pub ignore_mtime: bool,
#[arg(long)]
pub ignore_mode: bool,
#[arg(long)]
pub ignore_owner: bool,
#[arg(long)]
pub ignore_selinux_context: bool,
#[arg(long)]
pub print_selinux_contexts: bool,
}
pub struct Config {
#[allow(dead_code)]
pub root: Option<PathBuf>,
pub inputs: Vec<PathBuf>,
pub brp: bool,
pub fatal_errors: bool,
pub _verbose: u8,
pub dry_run: bool,
pub ignore_mtime: bool,
pub ignore_mode: bool,
pub ignore_owner: bool,
pub source_date_epoch: Option<time::SystemTime>,
pub print_selinux_contexts: bool,
#[cfg(feature = "selinux")]
pub selinux_labels: Option<selinux::label::Labeler<selinux::label::back_end::File>>,
}
impl Config {
pub fn make() -> Result<Self> {
let mut root = None;
let options = Options::parse();
let log_level = match options.verbose {
0 => LevelFilter::Warn,
1 => LevelFilter::Info,
2 => LevelFilter::Debug,
3.. => LevelFilter::Trace,
};
simplelog::init(log_level, false)?;
let source_date_epoch = setup::source_date_epoch()?.map(
|s| time::UNIX_EPOCH.add(time::Duration::new(s as u64, 0))
);
if options.brp {
root = Some(setup::brp_check(None, &options.inputs)?);
}
#[cfg(feature = "selinux")]
let selinux_labels = if options.ignore_selinux_context {
None
} else {
Some(selinux::label::Labeler::new(&[], false)?)
};
if options.inputs.is_empty() && !options.brp {
info!("No arguments specified, nothing to do. 😎");
}
Ok(Self {
root,
inputs: options.inputs,
brp: options.brp,
fatal_errors: options.brp,
_verbose: options.verbose,
dry_run: options.dry_run,
ignore_mtime: options.ignore_mtime,
ignore_mode: options.ignore_mode,
ignore_owner: options.ignore_owner,
source_date_epoch,
print_selinux_contexts: options.print_selinux_contexts,
#[cfg(feature = "selinux")]
selinux_labels,
})
}
#[allow(dead_code)]
pub const fn empty() -> Self {
Self {
root: None,
inputs: vec![],
brp: false,
fatal_errors: false,
_verbose: 0,
dry_run: false,
ignore_mtime: false,
ignore_mode: false,
ignore_owner: false,
source_date_epoch: None,
print_selinux_contexts: false,
#[cfg(feature = "selinux")]
selinux_labels: None,
}
}
}