|
1 | 1 | use std::ffi::OsString; |
2 | 2 | use std::fmt::Write; |
3 | 3 | use std::io::Read; |
| 4 | +use std::ops::RangeInclusive; |
4 | 5 | use std::path::PathBuf; |
5 | 6 |
|
6 | 7 | use anstream::eprintln; |
7 | 8 | use anyhow::Result; |
| 9 | +use itertools::Itertools; |
8 | 10 | use owo_colors::OwoColorize; |
9 | 11 |
|
10 | 12 | use prek_consts::env_vars::EnvVars; |
@@ -99,8 +101,13 @@ pub(crate) async fn hook_impl( |
99 | 101 | } |
100 | 102 |
|
101 | 103 | if !hook_type.num_args().contains(&args.len()) { |
102 | | - eprintln!("Invalid number of arguments for hook: {}", hook_type); |
103 | | - return Ok(ExitStatus::Failure); |
| 104 | + anyhow::bail!( |
| 105 | + "hook `{}` expects {} but received {}{}", |
| 106 | + hook_type.to_string().cyan(), |
| 107 | + format_expected_args(hook_type.num_args()), |
| 108 | + format_received_args(args.len()), |
| 109 | + format_argument_dump(&args) |
| 110 | + ); |
104 | 111 | } |
105 | 112 |
|
106 | 113 | let Some(run_args) = to_run_args(hook_type, &args).await else { |
@@ -267,3 +274,31 @@ async fn parse_pre_push_info(remote_name: &str) -> Option<PushInfo> { |
267 | 274 | // Nothing to push |
268 | 275 | None |
269 | 276 | } |
| 277 | + |
| 278 | +fn format_expected_args(range: RangeInclusive<usize>) -> String { |
| 279 | + let (start, end) = (*range.start(), *range.end()); |
| 280 | + match (start, end) { |
| 281 | + (0, 0) => "no arguments".to_string(), |
| 282 | + (1, 1) => "exactly 1 argument".to_string(), |
| 283 | + (s, e) if s == e => format!("exactly {s} arguments"), |
| 284 | + (0, e) => format!("up to {e} arguments"), |
| 285 | + (s, usize::MAX) => format!("at least {s} arguments"), |
| 286 | + (s, e) => format!("between {s} and {e} arguments"), |
| 287 | + } |
| 288 | +} |
| 289 | + |
| 290 | +fn format_received_args(received: usize) -> String { |
| 291 | + match received { |
| 292 | + 0 => "no arguments".to_string(), |
| 293 | + 1 => "1 argument".to_string(), |
| 294 | + n => format!("{n} arguments"), |
| 295 | + } |
| 296 | +} |
| 297 | + |
| 298 | +fn format_argument_dump(args: &[OsString]) -> String { |
| 299 | + if args.is_empty() { |
| 300 | + String::new() |
| 301 | + } else { |
| 302 | + format!(": `{}`", args.iter().map(|s| s.to_string_lossy()).join(" ")) |
| 303 | + } |
| 304 | +} |
0 commit comments