use super::directory::analyze_directory;
use crate::mcp::helpers::validate_and_convert_path;
use crate::mcp::McpContext;
use anyhow::Result;
use serde_json::{json, Value};
use std::path::Path;
use std::sync::Arc;
use std::time::SystemTime;
pub async fn get_git_context(path: &str) -> Result<String> {
let repo_path = Path::new(path);
let Ok(repo) = gix::discover(repo_path) else {
return Ok(String::new()); };
let mut git_info = Vec::new();
git_info.push("GIT CONTEXT:".to_string());
if let Ok(head) = repo.head_ref() {
match head {
Some(reference) => {
let branch_name = reference.name().as_bstr().to_string();
git_info.push(format!(
"Branch: {}",
branch_name
.strip_prefix("refs/heads/")
.unwrap_or(&branch_name)
));
}
None => {
if let Ok(head_id) = repo.head_id() {
git_info.push(format!("HEAD: {} (detached)", &head_id.to_string()[..8]));
}
}
}
}
if let Ok(head_commit) = repo.head_commit() {
let commit_id = head_commit.id().to_string();
let message = head_commit
.message_raw_sloppy()
.to_string()
.lines()
.next()
.unwrap_or("No commit message")
.to_string();
git_info.push(format!("Last commit: {} - {}", &commit_id[..8], message));
if let Ok(time) = head_commit.time() {
let seconds_ago = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap_or_default()
.as_secs() as i64
- time.seconds;
let time_str = if seconds_ago < 60 {
format!("{} seconds ago", seconds_ago)
} else if seconds_ago < 3600 {
format!("{} minutes ago", seconds_ago / 60)
} else if seconds_ago < 86400 {
format!("{} hours ago", seconds_ago / 3600)
} else {
format!("{} days ago", seconds_ago / 86400)
};
git_info.push(format!("Committed: {}", time_str));
}
}
git_info.push("Status: Repository detected ✓".to_string());
if git_info.len() > 1 {
Ok(git_info.join("\n") + "\n")
} else {
Ok(String::new())
}
}
pub async fn get_git_status(args: Value, ctx: Arc<McpContext>) -> Result<Value> {
let path_str = args["path"]
.as_str()
.ok_or_else(|| anyhow::anyhow!("Missing path"))?;
let path = validate_and_convert_path(path_str, &ctx)?;
let git_dir = path.join(".git");
if !git_dir.exists() {
return Ok(json!({
"content": [{
"type": "text",
"text": "Not a git repository"
}]
}));
}
let tree_result = analyze_directory(
json!({
"path": path.display().to_string(),
"mode": "ai",
"max_depth": 5,
"show_ignored": true
}),
ctx.clone(),
)
.await?;
Ok(json!({
"content": [{
"type": "text",
"text": format!(
"GIT REPOSITORY STRUCTURE\nPath: {}\n\n{}",
path.display(),
tree_result["content"][0]["text"].as_str().unwrap_or("")
)
}]
}))
}