feat: add basic plan support

This commit is contained in:
2025-02-13 22:57:04 +01:00
parent a4565c7c12
commit 040f1a8a56
8 changed files with 204 additions and 79 deletions

View File

@@ -0,0 +1,84 @@
use std::path::Path;
use anyhow::Context;
use crate::model::Project;
pub mod local {
use std::path::Path;
use anyhow::Context;
pub async fn reconcile(source: &Path, dest: &Path) -> anyhow::Result<()> {
for entry in walkdir::WalkDir::new(source) {
let entry = entry?;
let rel = entry.path().strip_prefix(source)?;
let metadata = entry.metadata()?;
if metadata.is_file() {
tracing::trace!("copying file: {}", rel.display());
let dest_path = dest.join(rel);
tokio::fs::copy(entry.path(), &dest_path)
.await
.context(anyhow::anyhow!(
"failed to file directory at: {}",
dest_path.display()
))?;
} else if metadata.is_dir() {
let dest_path = dest.join(rel);
tracing::trace!("creating directory: {}", dest_path.display());
tokio::fs::create_dir_all(&dest_path)
.await
.context(anyhow::anyhow!(
"failed to create directory at: {}",
dest_path.display()
))?;
}
}
Ok(())
}
}
#[derive(Default)]
pub struct PlanReconciler {}
impl PlanReconciler {
pub fn new() -> Self {
Self {}
}
pub async fn reconcile(&self, project: &Project, destination: &Path) -> anyhow::Result<()> {
tracing::info!("reconciling project");
if project.plan.is_none() {
tracing::debug!("no plan, returning");
return Ok(());
}
// prepare the plan dir
// TODO: We're always deleting, consider some form of caching
let plan_dir = destination.join(".forest").join("plan");
if plan_dir.exists() {
tokio::fs::remove_dir_all(&plan_dir).await?;
}
tokio::fs::create_dir_all(&plan_dir)
.await
.context(anyhow::anyhow!(
"failed to create plan dir: {}",
plan_dir.display()
))?;
match project.plan.as_ref().unwrap() {
crate::model::ProjectPlan::Local { path } => {
let source = &destination.join(path);
local::reconcile(source, &plan_dir).await?;
}
crate::model::ProjectPlan::NoPlan => {
tracing::debug!("no plan, returning")
}
}
Ok(())
}
}