From 11ecd0ac8911ae0e3e0b4ee8d38263d31b5a21dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Jane=C5=BEi=C4=8D?= Date: Tue, 8 Sep 2026 09:54:58 +0000 Subject: [PATCH] refactor: return an exit code from main --- src/main.rs | 71 +++++++++++++++++++++++++++++++-------------- src/scripts/link.rs | 10 +++---- 2 files changed, 54 insertions(+), 27 deletions(-) diff --git a/src/main.rs b/src/main.rs index 892bdd9..a8cd413 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,11 @@ +use std::process::ExitCode; + use ahab::{cli, command_builder, scripts}; use anyhow::Result; use clap::Parser; -fn main() -> Result<()> { +fn main() -> ExitCode { let args = cli::Ahab::parse(); command_builder::set_options(command_builder::Options { @@ -11,26 +13,49 @@ fn main() -> Result<()> { dry_run: args.dry_run, }); - match args.command { - cli::Commands::Django { command } => match command { - cli::Django::Bash => scripts::django::bash(), - cli::Django::Run { rest } => scripts::django::run(&rest), - cli::Django::MakeCommand { app, name } => scripts::django::make_command(&app, &name), - cli::Django::Makemigrations => scripts::django::makemigrations(), - cli::Django::Manage { rest } => scripts::django::manage(&rest), - cli::Django::Migrate { rest } => scripts::django::migrate(&rest), - cli::Django::Shell => scripts::django::shell(), - cli::Django::Test => scripts::django::test(), - }, - cli::Commands::Postgres { command } => match command { - cli::Postgres::Import { path } => scripts::postgres::import(&path), - cli::Postgres::Dump { path, format, gzip } => { - scripts::postgres::dump(&path, format, gzip) - } - }, + match run(args.command) { + Ok(code) => code, + Err(e) => { + eprintln!("Error: {e:#}"); + ExitCode::FAILURE + } + } +} + +fn run(command: cli::Commands) -> Result { + let done = ExitCode::SUCCESS; + + match command { + cli::Commands::Django { command } => { + match command { + cli::Django::Bash => scripts::django::bash(), + cli::Django::Run { rest } => scripts::django::run(&rest), + cli::Django::MakeCommand { app, name } => { + scripts::django::make_command(&app, &name) + } + cli::Django::Makemigrations => scripts::django::makemigrations(), + cli::Django::Manage { rest } => scripts::django::manage(&rest), + cli::Django::Migrate { rest } => scripts::django::migrate(&rest), + cli::Django::Shell => scripts::django::shell(), + cli::Django::Test => scripts::django::test(), + }?; + + Ok(done) + } + cli::Commands::Postgres { command } => { + match command { + cli::Postgres::Import { path } => scripts::postgres::import(&path), + cli::Postgres::Dump { path, format, gzip } => { + scripts::postgres::dump(&path, format, gzip) + } + }?; + + Ok(done) + } cli::Commands::Link { command } => match command { - cli::Link::Add { paths, force } => scripts::link::add(&paths, force), - cli::Link::Restore { paths, all } => scripts::link::restore(&paths, all), + cli::Link::Add { paths, force } => scripts::link::add(&paths, force).map(|()| done), + cli::Link::Restore { paths, all } => scripts::link::restore(&paths, all).map(|()| done), + // the one command with something to say through its exit code cli::Link::Check { paths, porcelain, @@ -38,6 +63,10 @@ fn main() -> Result<()> { exit_code, } => scripts::link::check(&paths, porcelain, null, exit_code), }, - cli::Commands::Completions { shell } => scripts::completions::completions(shell), + cli::Commands::Completions { shell } => { + scripts::completions::completions(shell)?; + + Ok(done) + } } } diff --git a/src/scripts/link.rs b/src/scripts/link.rs index 504da76..6e0ef51 100644 --- a/src/scripts/link.rs +++ b/src/scripts/link.rs @@ -2,11 +2,10 @@ use std::cell::Cell; use std::env; use std::ffi::OsString; use std::fs; -use std::io::{self, Write}; use std::os::unix::fs::symlink; use std::path::{Path, PathBuf}; -use std::process; use std::process::Command; +use std::process::ExitCode; use anyhow::{Context, Result, anyhow, bail}; @@ -179,7 +178,7 @@ fn warn(msg: impl std::fmt::Display) { } // list untracked paths not in the store, i.e. what a sandbox can still read -pub fn check(paths: &[PathBuf], porcelain: bool, null: bool, exit_code: bool) -> Result<()> { +pub fn check(paths: &[PathBuf], porcelain: bool, null: bool, exit_code: bool) -> Result { let repo = Repo::discover()?; let pathspecs = relative_pathspecs(&repo, paths)?; @@ -208,11 +207,10 @@ pub fn check(paths: &[PathBuf], porcelain: bool, null: bool, exit_code: bool) -> // git's --exit-code convention: nothing to report is 0, anything is 1 if exit_code && !exposed.is_empty() { - io::stdout().flush().context("writing the listing")?; - process::exit(1); + return Ok(ExitCode::FAILURE); } - Ok(()) + Ok(ExitCode::SUCCESS) } fn print_porcelain(exposed: &[Exposed], null: bool) {