sandlot/rust-sandlot/src/commands/diff.rs
2026-04-10 11:13:00 -07:00

64 lines
2.0 KiB
Rust

use anyhow::Result;
use crate::git;
use super::helpers::require_session;
pub async fn action(branch: &str) -> Result<()> {
let (_, session) = require_session(branch).await;
// Check for uncommitted changes (staged + unstaged)
let status = tokio::process::Command::new("git")
.args(["-C", &session.worktree, "status", "--porcelain"])
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.output()
.await;
let status = match status {
Ok(o) if o.status.success() => String::from_utf8_lossy(&o.stdout).to_string(),
_ => {
eprintln!("\u{2716} git status failed");
std::process::exit(1);
}
};
let args: Vec<String> = if !status.trim().is_empty() {
// Show uncommitted changes
let has_head = tokio::process::Command::new("git")
.args(["-C", &session.worktree, "rev-parse", "--verify", "HEAD"])
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.status()
.await;
if has_head.is_ok_and(|s| s.success()) {
vec!["diff".into(), "HEAD".into()]
} else {
vec!["diff".into()]
}
} else {
// No uncommitted changes — show full branch diff vs main
let main = git::main_branch(Some(&session.worktree)).await?;
vec!["diff".into(), format!("{main}...{branch}")]
};
// Run git diff with inherited stdio
let status = std::process::Command::new("git")
.args(
std::iter::once("-C".to_string())
.chain(std::iter::once(session.worktree.clone()))
.chain(args),
)
.stdin(std::process::Stdio::inherit())
.stdout(std::process::Stdio::inherit())
.stderr(std::process::Stdio::inherit())
.spawn()?
.wait()?;
if !status.success() {
std::process::exit(status.code().unwrap_or(1));
}
Ok(())
}