From 120d650b1d7dc9eeabcc287d6d27c564e818834f Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 8 Jun 2020 00:27:33 +0200 Subject: add --check to check a single file The --check flag will check the given file and set the exit status accordingly. --- src/main.rs | 102 ++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 33 deletions(-) (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs index 2b2aeb7..96a8539 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,6 +79,15 @@ pub struct Opt { #[structopt(short = "d", long = "dir", default_value = ".", parse(from_os_str))] path: PathBuf, + /// Check the given file only. + #[structopt( + short = "c", + long = "check", + value_name = "file", + conflicts_with = "path" + )] + check: Option, + /// Only show the name of matching files. #[structopt(short = "l", long = "files-with-matches")] file_name_only: bool, @@ -116,6 +125,30 @@ pub struct Opt { expression: Vec, } +impl Opt { + fn build_filter(&self) -> Result> { + // As a shortcut, we allow only the regular expression to be given, to retain the behaviour + // before the filter changes. + if self.expression.len() == 1 { + let line = &self.expression[0]; + let maybe_filter = build_filter(line); + if maybe_filter.is_err() && !line.starts_with('-') { + let maybe_regex = Regex::new(line); + if let Ok(rgx) = maybe_regex { + let filter = filters::player::any( + filters::player::account(rgx.clone()) | filters::player::character(rgx), + ); + return Ok(filter); + } + } + return Ok(maybe_filter?); + } + + let expr_string = fexpr::requote(&self.expression); + Ok(build_filter(&expr_string)?) + } +} + /// A log that matches the search criteria. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct LogResult { @@ -302,26 +335,17 @@ fn run() -> Result { } fn single(opt: &Opt) -> Result { - // As a shortcut, we allow only the regular expression to be given, to retain the behaviour - // before the filter changes. - if opt.expression.len() == 1 { - let line = &opt.expression[0]; - let maybe_filter = build_filter(line); - if maybe_filter.is_err() && !line.starts_with('-') { - let maybe_regex = Regex::new(line); - if let Ok(rgx) = maybe_regex { - let filter = filters::player::any( - filters::player::account(rgx.clone()) | filters::player::character(rgx), - ); - return grep(opt, &*filter); - } - } - return grep(opt, &*maybe_filter?); + let filter = opt.build_filter()?; + if let Some(ref path) = opt.check { + let is_zip = path + .file_name() + .and_then(|f| f.to_str()) + .map(is_zip_file_name) + .unwrap_or(false); + search_file(path, is_zip, &*filter).map(|r| r.is_some()) + } else { + grep(&opt, &*filter) } - - let expr_string = fexpr::requote(&opt.expression); - let filter = build_filter(&expr_string)?; - grep(&opt, &*filter) } fn repl(opt: &Opt) -> Result<()> { @@ -417,7 +441,7 @@ fn grep(opt: &Opt, filter: &dyn LogFilter) -> Result { return; } if is_log_file(&entry) { - let search = search_log(&entry, filter); + let search = search_entry(&entry, filter); match search { Ok(None) => (), Ok(Some(result)) => { @@ -438,18 +462,30 @@ fn grep(opt: &Opt, filter: &dyn LogFilter) -> Result { Ok(found_something.load(Ordering::Relaxed)) } -/// Search the given single log. +fn is_zip_file_name(file_name: &str) -> bool { + file_name.ends_with(".zip") || file_name.ends_with(".zevtc") +} + +/// Search the given directory entry. /// -/// If the log matches, returns `Ok(Some(..))`. -/// If the log doesn't match, returns `Ok(None)`. -/// If there was a fatal error, returns `Err(..)`. -fn search_log(entry: &DirEntry, filter: &dyn LogFilter) -> Result> { - let file_stream = BufReader::new(File::open(entry.path())?); +/// This forwards to [`search_file`][search_file] with the right parameters, and as such has the +/// same return possibilities. +fn search_entry(entry: &DirEntry, filter: &dyn LogFilter) -> Result> { let is_zip = entry .file_name() .to_str() - .map(|n| n.ends_with(".zip") || n.ends_with(".zevtc")) + .map(is_zip_file_name) .unwrap_or(false); + search_file(entry.path(), is_zip, filter) +} + +/// Search the given single log.. +/// +/// If the log matches, returns `Ok(Some(..))`. +/// If the log doesn't match, returns `Ok(None)`. +/// If there was a fatal error, returns `Err(..)`. +fn search_file(path: &Path, is_zip: bool, filter: &dyn LogFilter) -> Result> { + let file_stream = BufReader::new(File::open(path)?); let mut wrapper = if is_zip { ZipWrapper::zipped(file_stream) } else { @@ -459,7 +495,7 @@ fn search_log(entry: &DirEntry, filter: &dyn LogFilter) -> Result Result Result LogResult { +fn extract_info(path: &Path, log: &Log) -> LogResult { let boss = log.encounter(); if boss.is_none() { debug!( "log file has unknown boss: {:?} (id: {:#x})", - entry.path(), + path, log.encounter_id() ); } @@ -515,7 +551,7 @@ fn extract_info(entry: &DirEntry, log: &Log) -> LogResult { players.sort(); LogResult { - log_file: entry.path().to_path_buf(), + log_file: path.to_path_buf(), time: Utc.timestamp(i64::from(log.local_end_timestamp().unwrap_or(0)), 0), boss, players, -- cgit v1.2.3