feat: can clone using git
This commit is contained in:
parent
f10a1c0ac5
commit
dfe2ac62e3
@ -1,5 +1,6 @@
|
||||
use std::{collections::BTreeMap, fmt::Debug, path::PathBuf};
|
||||
|
||||
use colored_json::Paint;
|
||||
use kdl::{KdlDocument, KdlNode, KdlValue};
|
||||
use serde::Serialize;
|
||||
|
||||
@ -53,6 +54,7 @@ impl TryFrom<KdlDocument> for Plan {
|
||||
#[serde(untagged)]
|
||||
pub enum ProjectPlan {
|
||||
Local { path: PathBuf },
|
||||
Git { url: String, path: Option<PathBuf> },
|
||||
NoPlan,
|
||||
}
|
||||
|
||||
@ -74,6 +76,24 @@ impl TryFrom<&KdlNode> for ProjectPlan {
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(git) = children.get_arg("git") {
|
||||
return Ok(Self::Git {
|
||||
url: git
|
||||
.as_string()
|
||||
.map(|l| l.to_string())
|
||||
.ok_or(anyhow::anyhow!("a git url is required"))?,
|
||||
path: children
|
||||
.get("git")
|
||||
.and_then(|git| {
|
||||
git.entries()
|
||||
.iter()
|
||||
.filter(|i| i.name().is_some())
|
||||
.find(|i| i.name().expect("to have a value").to_string() == "path")
|
||||
})
|
||||
.and_then(|i| i.value().as_string().map(|p| p.to_string().into())),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(Self::NoPlan)
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,65 @@ use anyhow::Context;
|
||||
use crate::model::Project;
|
||||
|
||||
pub mod local;
|
||||
pub mod git {
|
||||
use std::{
|
||||
env::temp_dir,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use super::local;
|
||||
|
||||
pub async fn reconcile(
|
||||
url: &str,
|
||||
path: &Option<PathBuf>,
|
||||
plan_dir: &Path,
|
||||
) -> anyhow::Result<()> {
|
||||
let temp = TempDir::new();
|
||||
tokio::fs::create_dir_all(&temp.0).await?;
|
||||
|
||||
let mut cmd = tokio::process::Command::new("git");
|
||||
cmd.args(["clone", url, &temp.0.display().to_string(), "--depth=1"]);
|
||||
|
||||
tracing::info!("cloning plan: {}", url);
|
||||
let out = cmd.output().await?;
|
||||
if !out.status.success() {
|
||||
let stdout = std::str::from_utf8(&out.stdout).unwrap_or_default();
|
||||
let stderr = std::str::from_utf8(&out.stderr).unwrap_or_default();
|
||||
|
||||
anyhow::bail!("failed to process git plan: {}, {}", stdout, stderr)
|
||||
}
|
||||
|
||||
let temp_plan_dir = if let Some(path) = path {
|
||||
temp.0.join(path)
|
||||
} else {
|
||||
temp.0.to_path_buf()
|
||||
};
|
||||
|
||||
local::reconcile(&temp_plan_dir, plan_dir).await?;
|
||||
|
||||
drop(temp);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct TempDir(PathBuf);
|
||||
|
||||
impl TempDir {
|
||||
fn new() -> Self {
|
||||
Self(
|
||||
temp_dir()
|
||||
.join("forest")
|
||||
.join(uuid::Uuid::new_v4().to_string()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TempDir {
|
||||
fn drop(&mut self) {
|
||||
std::fs::remove_dir_all(&self.0).expect("to be able to remove temp dir");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PlanReconciler {}
|
||||
@ -43,6 +102,9 @@ impl PlanReconciler {
|
||||
let source = &destination.join(path);
|
||||
local::reconcile(source, &plan_dir).await?;
|
||||
}
|
||||
crate::model::ProjectPlan::Git { url, path } => {
|
||||
git::reconcile(url, path, &plan_dir).await?;
|
||||
}
|
||||
crate::model::ProjectPlan::NoPlan => {
|
||||
tracing::debug!("no plan, returning");
|
||||
return Ok(None);
|
||||
|
33
examples/project_git/forest.kdl
Normal file
33
examples/project_git/forest.kdl
Normal file
@ -0,0 +1,33 @@
|
||||
project {
|
||||
name local
|
||||
description """
|
||||
A simple local project that depends on ../plan for its utility scripts
|
||||
"""
|
||||
|
||||
plan {
|
||||
git "ssh://git@git.front.kjuulh.io/kjuulh/forest" path="examples/plan"
|
||||
}
|
||||
|
||||
global {
|
||||
someName "name"
|
||||
someKey {
|
||||
someNestedKey "somevalue"
|
||||
some {
|
||||
key {
|
||||
val
|
||||
val
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
templates type=jinja2 {
|
||||
path "templates/*.jinja2"
|
||||
output "output/"
|
||||
}
|
||||
|
||||
scripts {
|
||||
hello type=shell {}
|
||||
}
|
||||
}
|
||||
|
5
examples/project_git/scripts/hello.sh
Executable file
5
examples/project_git/scripts/hello.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
set -e
|
||||
|
||||
echo "hello world"
|
3
examples/project_git/templates/something.yaml.jinja2
Normal file
3
examples/project_git/templates/something.yaml.jinja2
Normal file
@ -0,0 +1,3 @@
|
||||
something
|
||||
|
||||
val is mapping: {{ global.someKey.some.key.val is mapping }}
|
Loading…
x
Reference in New Issue
Block a user