use std::io::Read;
use std::path::Path;
use std::process::{Command, Stdio};
use crate::error::{CwError, Result};
#[derive(serde::Deserialize)]
struct CreatePayload {
branch_name: String,
base_path: Option<String>,
#[serde(flatten)]
_other: serde_json::Value,
}
#[derive(serde::Deserialize)]
struct RemovePayload {
worktree_path: String,
#[serde(flatten)]
_other: serde_json::Value,
}
pub fn run_create() -> Result<()> {
let mut buf = String::new();
std::io::stdin().read_to_string(&mut buf)?;
let payload: CreatePayload = serde_json::from_str(&buf)
.map_err(|e| CwError::Other(format!("invalid WorktreeCreate hook payload: {e}")))?;
if let Some(ref bp) = payload.base_path {
std::env::set_current_dir(bp)?;
}
let exe = std::env::current_exe()?;
let output = Command::new(&exe)
.args([
"new",
&payload.branch_name,
"--emit",
"json",
"--term",
"skip",
])
.env("CW_NON_INTERACTIVE", "1")
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::inherit())
.output()?;
if !output.status.success() {
return Err(CwError::Other(format!(
"gw new failed (exit {})",
output.status.code().unwrap_or(-1)
)));
}
let stdout = String::from_utf8_lossy(&output.stdout);
let parsed: serde_json::Value = serde_json::from_str(stdout.trim())
.map_err(|e| CwError::Other(format!("could not parse `gw new --emit json` output: {e}")))?;
let wt_path = parsed["worktree_path"]
.as_str()
.ok_or_else(|| CwError::Other("`worktree_path` missing in `gw new` JSON output".into()))?;
println!("{}", wt_path);
Ok(())
}
pub fn run_remove() -> Result<()> {
let mut buf = String::new();
std::io::stdin().read_to_string(&mut buf)?;
let payload: RemovePayload = serde_json::from_str(&buf)
.map_err(|e| CwError::Other(format!("invalid WorktreeRemove hook payload: {e}")))?;
let wt_path = Path::new(&payload.worktree_path);
if let Err(e) = crate::hooks::run_event("pre_rm", wt_path) {
eprintln!(
"warning: pre_rm hook failed for '{}' (advisory, removal proceeds): {}",
wt_path.display(),
e
);
}
Ok(())
}