use std::path::{Path, PathBuf}; use fs_extra::dir::CopyOptions; use crate::project::{self, ProjectPlan}; pub const CUDDLE_PLAN_FOLDER: &str = "plan"; pub const CUDDLE_PROJECT_WORKSPACE: &str = ".cuddle"; pub trait PlanPathExt { fn plan_path(&self) -> PathBuf; } impl PlanPathExt for project::ProjectPlan { fn plan_path(&self) -> PathBuf { self.root .join(CUDDLE_PROJECT_WORKSPACE) .join(CUDDLE_PLAN_FOLDER) } } pub struct Plan {} impl Plan { pub fn new() -> Self { Self {} } pub async fn clone_from_project( &self, project: &ProjectPlan, ) -> anyhow::Result> { if !project.plan_path().exists() { if project.has_plan() { self.prepare_plan(project).await?; } match project.get_plan() { project::Plan::None => Ok(None), project::Plan::Git(url) => Ok(Some(self.git_plan(project, url).await?)), project::Plan::Folder(folder) => { Ok(Some(self.folder_plan(project, &folder).await?)) } } } else { match project.get_plan() { project::Plan::Folder(folder) => { self.clean_plan(project).await?; self.prepare_plan(project).await?; Ok(Some(self.folder_plan(project, &folder).await?)) } project::Plan::Git(_git) => Ok(Some(ClonedPlan {})), project::Plan::None => Ok(None), } } } async fn prepare_plan(&self, project: &ProjectPlan) -> anyhow::Result<()> { tracing::trace!("preparing workspace"); tokio::fs::create_dir_all(project.plan_path()).await?; Ok(()) } async fn clean_plan(&self, project: &ProjectPlan) -> anyhow::Result<()> { tracing::trace!("clean plan"); tokio::fs::remove_dir_all(project.plan_path()).await?; Ok(()) } async fn git_plan(&self, project: &ProjectPlan, url: String) -> anyhow::Result { let mut cmd = tokio::process::Command::new("git"); cmd.args(["clone", &url, &project.plan_path().display().to_string()]); tracing::debug!(url = url, "cloning git plan"); let output = cmd.output().await?; if !output.status.success() { anyhow::bail!( "failed to clone: {}, output: {} {}", url, std::str::from_utf8(&output.stdout)?, std::str::from_utf8(&output.stderr)?, ) } Ok(ClonedPlan {}) } async fn folder_plan(&self, project: &ProjectPlan, path: &Path) -> anyhow::Result { tracing::trace!( src = path.display().to_string(), dest = project.plan_path().display().to_string(), "copying src into plan dest" ); let mut items_stream = tokio::fs::read_dir(path).await?; let mut items = Vec::new(); while let Some(item) = items_stream.next_entry().await? { items.push(item.path()); } fs_extra::copy_items( &items, project.plan_path(), &CopyOptions::default() .overwrite(true) .depth(0) .copy_inside(false), )?; todo!() } } pub struct ClonedPlan {}