hive-forge: rewrite bash CLI helper as a rust binary (closes #280)
This commit is contained in:
parent
560360d2e3
commit
595e3c040c
28 changed files with 1434 additions and 612 deletions
56
hive-forge/src/body.rs
Normal file
56
hive-forge/src/body.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
//! Body-input resolution shared by every verb that posts a body.
|
||||
//! Matches the bash `resolve_body` helper (#382): exactly one source
|
||||
//! between `--body`, `--body-file`, and piped stdin. Passing both
|
||||
//! `--body` and `--body-file` is a clear error.
|
||||
|
||||
use std::io::{IsTerminal, Read};
|
||||
|
||||
use anyhow::{Context, Result, bail};
|
||||
|
||||
/// Resolve the body to send, given the user's explicit flags and the
|
||||
/// current stdin state. Returns `None` when none of the sources are
|
||||
/// available (the caller decides whether that's allowed — e.g.
|
||||
/// `issue-edit` treats absent body as "leave unchanged", while
|
||||
/// `comment` treats absent body as a hard error).
|
||||
pub fn resolve(body: Option<&str>, file: Option<&str>) -> Result<Option<String>> {
|
||||
if body.is_some() && file.is_some() {
|
||||
bail!("hive-forge: --body and --body-file are mutually exclusive");
|
||||
}
|
||||
if let Some(b) = body {
|
||||
return Ok(Some(b.to_owned()));
|
||||
}
|
||||
if let Some(path) = file {
|
||||
if path == "-" {
|
||||
return Ok(Some(read_stdin().context("read stdin for --body-file -")?));
|
||||
}
|
||||
let s = std::fs::read_to_string(path)
|
||||
.with_context(|| format!("read --body-file {path}"))?;
|
||||
return Ok(Some(s));
|
||||
}
|
||||
if !std::io::stdin().is_terminal() {
|
||||
return Ok(Some(read_stdin().context("read piped stdin")?));
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Resolve, then require a non-empty result (whitespace-trimmed).
|
||||
/// Used by `comment` / `comment-edit` which refuse to post empty
|
||||
/// bodies.
|
||||
pub fn resolve_required(body: Option<&str>, file: Option<&str>, verb: &str) -> Result<String> {
|
||||
let resolved = resolve(body, file)?;
|
||||
let Some(s) = resolved else {
|
||||
bail!(
|
||||
"hive-forge {verb}: no body — pass --body <text>, --body-file <path>, or pipe via stdin"
|
||||
);
|
||||
};
|
||||
if s.trim().is_empty() {
|
||||
bail!("hive-forge {verb}: refusing to post empty body");
|
||||
}
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
fn read_stdin() -> std::io::Result<String> {
|
||||
let mut s = String::new();
|
||||
std::io::stdin().read_to_string(&mut s)?;
|
||||
Ok(s)
|
||||
}
|
||||
Loading…
Reference in a new issue