use crate::domain::build_system::services::BuildSystemDetector;
use crate::domain::gradle::aggregates::GradleProject;
use crate::domain::gradle::services::TaskExecutor;
use crate::domain::maven::aggregates::MavenProject;
use crate::domain::maven::services::LifecycleExecutor;
use crate::domain::maven::value_objects::LifecyclePhase;
use anyhow::{anyhow, Result};
use std::path::Path;
use std::str::FromStr;
pub struct BuildOrchestrationService;
impl BuildOrchestrationService {
pub fn execute_build(project_dir: &Path, goals: Vec<String>) -> Result<BuildResult> {
let build_system = BuildSystemDetector::get_build_type(project_dir)
.ok_or_else(|| anyhow!("No build system detected in {project_dir:?}"))?;
match build_system {
crate::domain::build_system::value_objects::BuildSystemType::Maven => {
Self::execute_maven_build(project_dir, goals)
}
crate::domain::build_system::value_objects::BuildSystemType::Gradle => {
Self::execute_gradle_build(project_dir, goals)
}
crate::domain::build_system::value_objects::BuildSystemType::JBuild => {
Self::execute_jbuild_build(project_dir, goals)
}
}
}
fn execute_maven_build(project_dir: &Path, goals: Vec<String>) -> Result<BuildResult> {
let coords = crate::domain::artifact::value_objects::ArtifactCoordinates::from_gav(
"temp:temp:1.0.0",
)?;
let project = MavenProject::new(coords, project_dir)?;
let executor = LifecycleExecutor::new();
let mut steps = Vec::new();
for goal in goals {
if let Ok(phase) = LifecyclePhase::from_str(&goal) {
let plan = executor.execute_phase(&project, phase)?;
steps.push(format!("Executed phase: {goal}"));
steps.extend(plan.steps().iter().map(|s| format!(" - {}", s.goal)));
} else {
executor.execute_goal(&project, &goal)?;
steps.push(format!("Executed goal: {goal}"));
}
}
Ok(BuildResult {
success: true,
build_system: "Maven".to_string(),
steps,
})
}
fn execute_gradle_build(project_dir: &Path, tasks: Vec<String>) -> Result<BuildResult> {
let project = GradleProject::new("temp", "temp", "1.0.0", project_dir.to_str().unwrap())?;
let mut steps = Vec::new();
for task_name in tasks {
let plan = TaskExecutor::execute_task(&project, &task_name)?;
steps.push(format!("Executed task: {task_name}"));
steps.extend(plan.tasks().iter().map(|t| format!(" - {}", t.name())));
}
Ok(BuildResult {
success: true,
build_system: "Gradle".to_string(),
steps,
})
}
fn execute_jbuild_build(_project_dir: &Path, goals: Vec<String>) -> Result<BuildResult> {
Ok(BuildResult {
success: true,
build_system: "JBuild".to_string(),
steps: goals.iter().map(|g| format!("Executed: {g}")).collect(),
})
}
pub fn clean(project_dir: &Path) -> Result<()> {
let build_system = BuildSystemDetector::get_build_type(project_dir)
.ok_or_else(|| anyhow!("No build system detected"))?;
let dir_name = match build_system {
crate::domain::build_system::value_objects::BuildSystemType::Maven => "target",
crate::domain::build_system::value_objects::BuildSystemType::Gradle => "build",
crate::domain::build_system::value_objects::BuildSystemType::JBuild => "target",
};
Self::remove_dir_if_exists(&project_dir.join(dir_name))
}
fn remove_dir_if_exists(dir: &Path) -> Result<()> {
if dir.exists() {
std::fs::remove_dir_all(dir)?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct BuildResult {
pub success: bool,
pub build_system: String,
pub steps: Vec<String>,
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use tempfile::TempDir;
#[test]
fn test_execute_maven_build() {
let temp_dir = TempDir::new().unwrap();
let pom_path = temp_dir.path().join("pom.xml");
fs::write(&pom_path, "<project></project>").unwrap();
let result =
BuildOrchestrationService::execute_build(temp_dir.path(), vec!["compile".to_string()]);
assert!(result.is_ok());
let result = result.unwrap();
assert!(result.success);
assert_eq!(result.build_system, "Maven");
}
#[test]
fn test_execute_gradle_build() {
let temp_dir = TempDir::new().unwrap();
let build_path = temp_dir.path().join("build.gradle");
fs::write(&build_path, "").unwrap();
let result =
BuildOrchestrationService::execute_build(temp_dir.path(), vec!["compile".to_string()]);
assert!(BuildSystemDetector::get_build_type(temp_dir.path()).is_some());
}
#[test]
fn test_clean_maven_project() {
let temp_dir = TempDir::new().unwrap();
let pom_path = temp_dir.path().join("pom.xml");
fs::write(&pom_path, "<project></project>").unwrap();
let target_dir = temp_dir.path().join("target");
fs::create_dir(&target_dir).unwrap();
assert!(target_dir.exists());
let result = BuildOrchestrationService::clean(temp_dir.path());
assert!(result.is_ok());
assert!(!target_dir.exists());
}
#[test]
fn test_clean_gradle_project() {
let temp_dir = TempDir::new().unwrap();
let build_path = temp_dir.path().join("build.gradle");
fs::write(&build_path, "").unwrap();
let build_dir = temp_dir.path().join("build");
fs::create_dir(&build_dir).unwrap();
assert!(build_dir.exists());
let result = BuildOrchestrationService::clean(temp_dir.path());
assert!(result.is_ok());
assert!(!build_dir.exists());
}
#[test]
fn test_no_build_system_detected() {
let temp_dir = TempDir::new().unwrap();
let result =
BuildOrchestrationService::execute_build(temp_dir.path(), vec!["build".to_string()]);
assert!(result.is_err());
}
}