aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs47
1 files changed, 35 insertions, 12 deletions
diff --git a/src/main.rs b/src/main.rs
index 84d1063..d048cb0 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -33,6 +33,13 @@ use playerclass::PlayerClass;
/// Application name, as it should be used in configuration directory paths.
const APP_NAME: &str = "raidgrep";
+/// Process exit code for when everything went right.
+const RETCODE_SUCCESS: i32 = 0;
+/// Process exit code for when no results are found.
+const RETCODE_NO_RESULTS: i32 = 1;
+/// Process exit code for when an error occurred.
+const RETCODE_ERROR: i32 = 2;
+
/// A program that allows you to search through all your evtc logs for specific people.
///
/// raidgrep supports different predicates that determine whether a log is included or not.
@@ -241,8 +248,12 @@ static INTERRUPTED: AtomicBool = AtomicBool::new(false);
fn main() {
let result = run();
- if let Err(err) = result {
- display_error(&err);
+ match result {
+ Ok(retcode) => std::process::exit(retcode),
+ Err(err) => {
+ display_error(&err);
+ std::process::exit(RETCODE_ERROR);
+ }
}
}
@@ -254,7 +265,7 @@ fn display_error(err: &Error) {
}
}
-fn run() -> Result<()> {
+fn run() -> Result<i32> {
let opt = Opt::from_args();
if opt.no_color {
@@ -271,20 +282,26 @@ fn run() -> Result<()> {
guilds::prepare_cache();
}
+ let retcode;
if !opt.repl {
- single(&opt)?;
+ if single(&opt)? {
+ retcode = RETCODE_SUCCESS;
+ } else {
+ retcode = RETCODE_NO_RESULTS;
+ }
} else {
repl(&opt)?;
+ retcode = RETCODE_SUCCESS;
}
if opt.guilds {
guilds::save_cache();
}
- Ok(())
+ Ok(retcode)
}
-fn single(opt: &Opt) -> Result<()> {
+fn single(opt: &Opt) -> Result<bool> {
// 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 {
@@ -304,8 +321,7 @@ fn single(opt: &Opt) -> Result<()> {
let expr_string = fexpr::requote(&opt.expression);
let filter = build_filter(&expr_string)?;
- grep(&opt, &*filter)?;
- Ok(())
+ grep(&opt, &*filter)
}
fn repl(opt: &Opt) -> Result<()> {
@@ -328,7 +344,7 @@ fn repl(opt: &Opt) -> Result<()> {
let parsed = build_filter(&line);
INTERRUPTED.store(false, Ordering::Relaxed);
match parsed {
- Ok(filter) => grep(&opt, &*filter)?,
+ Ok(filter) => grep(&opt, &*filter).map(|_| ())?,
Err(err) => display_error(&err),
}
}
@@ -384,9 +400,13 @@ fn build_filter(expr_string: &str) -> Result<Box<dyn LogFilter>> {
}
/// Run the grep search with the given options.
-fn grep(opt: &Opt, filter: &dyn LogFilter) -> Result<()> {
+///
+/// This function returns `false` if no log has been found, and `true` if at least one log matched
+/// the filter.
+fn grep(opt: &Opt, filter: &dyn LogFilter) -> Result<bool> {
let pipeline = output::build_pipeline(opt);
let pipeline_ref = &pipeline;
+ let found_something = &AtomicBool::new(false);
let result: Result<()> = rayon::scope(|s| {
let walker = WalkDir::new(&opt.path);
for entry in walker {
@@ -400,7 +420,10 @@ fn grep(opt: &Opt, filter: &dyn LogFilter) -> Result<()> {
let search = search_log(&entry, filter);
match search {
Ok(None) => (),
- Ok(Some(result)) => pipeline_ref.push_item(result),
+ Ok(Some(result)) => {
+ found_something.store(true, Ordering::Relaxed);
+ pipeline_ref.push_item(result);
+ },
Err(err) => {
debug!("Runtime error while scanning {:?}: {}", entry.path(), err);
}
@@ -412,7 +435,7 @@ fn grep(opt: &Opt, filter: &dyn LogFilter) -> Result<()> {
});
result?;
pipeline.finish();
- Ok(())
+ Ok(found_something.load(Ordering::Relaxed))
}
/// Search the given single log.