use std::path::PathBuf;
use std::process::{Command, Output};
use crate::error::VcsError;
use crate::vcs::{Vcs, VcsType};
pub struct SaplingVcs {
root: PathBuf,
}
impl SaplingVcs {
pub fn new(root: PathBuf) -> Self {
Self { root }
}
fn run_sl(&self, args: &[&str]) -> Result<Output, VcsError> {
Command::new("sl")
.args(args)
.current_dir(&self.root)
.output()
.map_err(|e| VcsError::CommandFailed {
command: format!("sl {}", args.join(" ")),
error: e.to_string(),
})
}
}
impl Vcs for SaplingVcs {
fn vcs_type(&self) -> VcsType {
VcsType::Sapling
}
fn has_changes(&self) -> Result<bool, VcsError> {
let output = self.run_sl(&["status"])?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(VcsError::CommandFailed {
command: "sl status".to_string(),
error: stderr.to_string(),
});
}
Ok(!output.stdout.is_empty())
}
fn stage_all(&self) -> Result<(), VcsError> {
let output = self.run_sl(&["addremove"])?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(VcsError::CommandFailed {
command: "sl addremove".to_string(),
error: stderr.to_string(),
});
}
Ok(())
}
fn commit(&self, message: &str) -> Result<String, VcsError> {
let output = self.run_sl(&["commit", "-m", message])?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
if stdout.contains("nothing changed") || stderr.contains("nothing changed") {
return Err(VcsError::NothingToCommit);
}
return Err(VcsError::CommitFailed(stderr.to_string()));
}
let log_output = self.run_sl(&["log", "-l", "1", "--template", "{node|short}"])?;
if log_output.status.success() {
let hash = String::from_utf8_lossy(&log_output.stdout)
.trim()
.to_string();
if !hash.is_empty() {
return Ok(hash);
}
}
Ok("unknown".to_string())
}
}