use std::env;
use std::path::PathBuf;
use colored::Colorize;
use crate::cli::auto_commit::{print_push_summary, sync_and_push_current_branch};
use crate::utils::command_exists;
pub async fn run_push() -> Result<(), String> {
if !command_exists("git") {
return Err("Git is not installed on this machine.".to_string());
}
let cwd = env::current_dir().map_err(|error| format!("Failed to read cwd: {error}"))?;
let repo_root = resolve_git_root(&cwd).await?;
println!(
"{} {}",
"Push".bright_cyan().bold(),
format!("syncing and pushing from {}", repo_root.display()).bright_white()
);
match sync_and_push_current_branch(&repo_root).await? {
Some(outcome) => {
print_push_summary(&outcome);
if outcome.rebased {
println!(
"{}",
"Integrated remote commits with stash-safe rebase before push."
.dimmed()
);
}
Ok(())
}
None => Err(
"Push skipped: HEAD is detached or no branch name is available. Checkout a branch first."
.to_string(),
),
}
}
async fn resolve_git_root(start: &std::path::Path) -> Result<PathBuf, String> {
let output = tokio::process::Command::new("git")
.current_dir(start)
.args(["rev-parse", "--show-toplevel"])
.output()
.await
.map_err(|error| format!("Failed to run git: {error}"))?;
if !output.status.success() {
return Err(
"Current directory is not inside a git repository. `cd` into the repo and retry."
.to_string(),
);
}
let root = String::from_utf8_lossy(&output.stdout).trim().to_string();
if root.is_empty() {
return Err("Could not resolve git repository root.".to_string());
}
Ok(PathBuf::from(root))
}