56 lines
2 KiB
Rust
56 lines
2 KiB
Rust
//! 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)
|
|
}
|