//! Context wrapper for git tool handlers. //! //! Provides `GitToolCtx` which wraps `ToolContext` and adds git-domain operations. use agent::ToolContext; use git::GitDomain; use models::projects::project; use models::repos::repo; use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; /// Wrapper around `ToolContext` providing git-domain operations for tool handlers. #[derive(Clone)] pub struct GitToolCtx { pub ctx: ToolContext, } impl GitToolCtx { pub fn new(ctx: ToolContext) -> Self { Self { ctx } } /// Opens a git repository by project name and repo name. pub async fn open_repo(&self, project_name: &str, repo_name: &str) -> Result { let db = self.ctx.db(); resolve_project_and_repo(db, project_name, repo_name) .await .and_then(|(_, path)| GitDomain::open(&path).map_err(|e| e.to_string())) } } /// Free helper to resolve project_id + storage_path from names. Used by registry. async fn resolve_project_and_repo( db: &db::database::AppDatabase, project_name: &str, repo_name: &str, ) -> Result<(uuid::Uuid, String), String> { let project = project::Entity::find() .filter(project::Column::Name.eq(project_name)) .one(db) .await .map_err(|e| format!("DB error looking up project '{}': {}", project_name, e))? .ok_or_else(|| format!("project '{}' not found", project_name))?; let repo_model = repo::Entity::find() .filter(repo::Column::Project.eq(project.id)) .filter(repo::Column::RepoName.eq(repo_name)) .one(db) .await .map_err(|e| format!("DB error looking up repo '{}/{}': {}", project_name, repo_name, e))? .ok_or_else(|| format!("repo '{}/{}' not found", project_name, repo_name))?; Ok((project.id, repo_model.storage_path)) }