cuddle-v2/crates/cuddle/src/plan.rs
kjuulh 531ea225f3
feat: add basic plan and project clone
Signed-off-by: kjuulh <contact@kjuulh.io>
2024-08-24 00:45:16 +02:00

121 lines
3.4 KiB
Rust

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<Option<ClonedPlan>> {
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<ClonedPlan> {
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<ClonedPlan> {
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 {}