feat!: report findings with exit code 4, not the code for failure
This commit is contained in:
@@ -45,7 +45,7 @@ pub enum Link {
|
|||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
porcelain: bool,
|
porcelain: bool,
|
||||||
|
|
||||||
/// Exit with 1 when anything is outside the store, for scripts
|
/// Exit with 4 when anything is outside the store, for scripts
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
exit_code: bool,
|
exit_code: bool,
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use fs_err::{read_dir, read_link};
|
use fs_err::{read_dir, read_link};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::ExitCode;
|
|
||||||
|
|
||||||
use anyhow::{Result, anyhow};
|
use anyhow::{Result, anyhow};
|
||||||
|
|
||||||
@@ -9,14 +8,14 @@ use crate::cmd::{Cmd, LsFiles};
|
|||||||
use crate::ctx::Ctx;
|
use crate::ctx::Ctx;
|
||||||
use crate::output::{line, text};
|
use crate::output::{line, text};
|
||||||
|
|
||||||
|
// whether anything is outside the store, which main turns into an exit code
|
||||||
pub fn check(
|
pub fn check(
|
||||||
ctx: &Ctx,
|
ctx: &Ctx,
|
||||||
paths: &[PathBuf],
|
paths: &[PathBuf],
|
||||||
porcelain: bool,
|
porcelain: bool,
|
||||||
null: bool,
|
null: bool,
|
||||||
exit_code: bool,
|
|
||||||
store: Option<&Path>,
|
store: Option<&Path>,
|
||||||
) -> Result<ExitCode> {
|
) -> Result<bool> {
|
||||||
let repo = Repo::discover(ctx, store)?;
|
let repo = Repo::discover(ctx, store)?;
|
||||||
let pathspecs = relative_pathspecs(&repo, paths)?;
|
let pathspecs = relative_pathspecs(&repo, paths)?;
|
||||||
|
|
||||||
@@ -43,19 +42,12 @@ pub fn check(
|
|||||||
print_listing(&repo, &exposed);
|
print_listing(&repo, &exposed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// git's --exit-code convention: nothing to report is 0, anything is 1
|
Ok(!exposed.is_empty())
|
||||||
if exit_code && !exposed.is_empty() {
|
|
||||||
return Ok(ExitCode::FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(ExitCode::SUCCESS)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_porcelain(exposed: &[Exposed], null: bool) {
|
fn print_porcelain(exposed: &[Exposed], null: bool) {
|
||||||
let end = if null { '\0' } else { '\n' };
|
let end = if null { '\0' } else { '\n' };
|
||||||
// a filename can hold an arrow but not a NUL, so -z separates the two paths
|
// a filename can hold an arrow but not a NUL, as `git status -z` also assumes
|
||||||
// with one the way `git status -z` does for a rename. the two character code
|
|
||||||
// stays where it is: it cannot be mistaken for part of a path
|
|
||||||
let between = if null { "\0" } else { " -> " };
|
let between = if null { "\0" } else { " -> " };
|
||||||
|
|
||||||
for item in exposed {
|
for item in exposed {
|
||||||
|
|||||||
20
src/main.rs
20
src/main.rs
@@ -14,6 +14,9 @@ use clap::Parser;
|
|||||||
use crate::ctx::Ctx;
|
use crate::ctx::Ctx;
|
||||||
use crate::output::note;
|
use crate::output::note;
|
||||||
|
|
||||||
|
// 0 ran with nothing to report, 1 could not finish, 2 bad arguments, 4 found something
|
||||||
|
const FINDINGS: u8 = 4;
|
||||||
|
|
||||||
fn main() -> ExitCode {
|
fn main() -> ExitCode {
|
||||||
let args = cli::Ahab::parse();
|
let args = cli::Ahab::parse();
|
||||||
|
|
||||||
@@ -87,14 +90,15 @@ fn run(ctx: &Ctx, command: cli::Commands) -> Result<ExitCode> {
|
|||||||
null,
|
null,
|
||||||
exit_code,
|
exit_code,
|
||||||
store,
|
store,
|
||||||
} => commands::link::check(
|
} => {
|
||||||
ctx,
|
let exposed =
|
||||||
&paths,
|
commands::link::check(ctx, &paths, porcelain, null, store.root.as_deref())?;
|
||||||
porcelain,
|
|
||||||
null,
|
match exit_code && exposed {
|
||||||
exit_code,
|
true => Ok(ExitCode::from(FINDINGS)),
|
||||||
store.root.as_deref(),
|
false => Ok(done),
|
||||||
),
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
cli::Commands::Status { store } => {
|
cli::Commands::Status { store } => {
|
||||||
commands::status::status(ctx, store.root.as_deref())?;
|
commands::status::status(ctx, store.root.as_deref())?;
|
||||||
|
|||||||
Reference in New Issue
Block a user