|
|
@ -1,6 +1,6 @@
|
|
|
|
use globset::{Glob, GlobSet, GlobSetBuilder};
|
|
|
|
use globset::{Glob, GlobSet, GlobSetBuilder};
|
|
|
|
use miette::{bail, Context, IntoDiagnostic, Result};
|
|
|
|
use miette::{bail, Context, IntoDiagnostic, Result};
|
|
|
|
use serde::Deserialize;
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use std::{
|
|
|
|
use std::{
|
|
|
|
env,
|
|
|
|
env,
|
|
|
|
fs::{self},
|
|
|
|
fs::{self},
|
|
|
@ -25,10 +25,14 @@ impl SiloRepo {
|
|
|
|
if !path.try_exists().into_diagnostic()? {
|
|
|
|
if !path.try_exists().into_diagnostic()? {
|
|
|
|
bail!("The repository {path:?} does not exist");
|
|
|
|
bail!("The repository {path:?} does not exist");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let config = read_config(path)?;
|
|
|
|
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
Ok(Self {
|
|
|
|
config: read_config(path)?,
|
|
|
|
root: DirEntry::parse(
|
|
|
|
root: DirEntry::parse(Rc::new(ParseContext::default()), path.to_owned())?,
|
|
|
|
Rc::new(ParseContext::new(GlobSet::empty(), config.clone())),
|
|
|
|
|
|
|
|
path.to_owned(),
|
|
|
|
|
|
|
|
)?,
|
|
|
|
|
|
|
|
config,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -45,19 +49,12 @@ impl SiloRepo {
|
|
|
|
|
|
|
|
|
|
|
|
pub struct ParseContext {
|
|
|
|
pub struct ParseContext {
|
|
|
|
ignored: GlobSet,
|
|
|
|
ignored: GlobSet,
|
|
|
|
|
|
|
|
config: SiloConfig,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl ParseContext {
|
|
|
|
impl ParseContext {
|
|
|
|
pub fn new(ignored: GlobSet) -> Self {
|
|
|
|
pub fn new(ignored: GlobSet, config: SiloConfig) -> Self {
|
|
|
|
Self { ignored }
|
|
|
|
Self { ignored, config }
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Default for ParseContext {
|
|
|
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
|
|
|
Self {
|
|
|
|
|
|
|
|
ignored: GlobSet::empty(),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -81,7 +78,7 @@ pub enum DirEntry {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl DirEntry {
|
|
|
|
impl DirEntry {
|
|
|
|
fn parse(mut context: Rc<ParseContext>, path: PathBuf) -> Result<Self> {
|
|
|
|
fn parse(mut ctx: Rc<ParseContext>, path: PathBuf) -> Result<Self> {
|
|
|
|
if path.is_dir() {
|
|
|
|
if path.is_dir() {
|
|
|
|
log::debug!("Parsing directory {path:?}");
|
|
|
|
log::debug!("Parsing directory {path:?}");
|
|
|
|
|
|
|
|
|
|
|
@ -91,13 +88,20 @@ impl DirEntry {
|
|
|
|
let metadata = if meta_file.exists() {
|
|
|
|
let metadata = if meta_file.exists() {
|
|
|
|
log::debug!("Found metadata file");
|
|
|
|
log::debug!("Found metadata file");
|
|
|
|
let metadata = RootDirData::read(&meta_file)?;
|
|
|
|
let metadata = RootDirData::read(&meta_file)?;
|
|
|
|
context = Rc::new(ParseContext::new(metadata.ignored.clone()));
|
|
|
|
ctx = Rc::new(ParseContext::new(
|
|
|
|
|
|
|
|
metadata.ignored.clone(),
|
|
|
|
|
|
|
|
ctx.config.clone(),
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
Some(metadata)
|
|
|
|
Some(metadata)
|
|
|
|
} else if meta_tmpl.exists() {
|
|
|
|
} else if meta_tmpl.exists() {
|
|
|
|
log::debug!("Found metadata template");
|
|
|
|
log::debug!("Found metadata template");
|
|
|
|
let metadata = RootDirData::read_template(&meta_tmpl)?;
|
|
|
|
let metadata =
|
|
|
|
context = Rc::new(ParseContext::new(metadata.ignored.clone()));
|
|
|
|
RootDirData::read_template(&meta_tmpl, &ctx.config.template_context)?;
|
|
|
|
|
|
|
|
ctx = Rc::new(ParseContext::new(
|
|
|
|
|
|
|
|
metadata.ignored.clone(),
|
|
|
|
|
|
|
|
ctx.config.clone(),
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
Some(metadata)
|
|
|
|
Some(metadata)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -112,8 +116,8 @@ impl DirEntry {
|
|
|
|
let entry_path = read_entry.path();
|
|
|
|
let entry_path = read_entry.path();
|
|
|
|
let test_path = entry_path.strip_prefix(&path).into_diagnostic()?;
|
|
|
|
let test_path = entry_path.strip_prefix(&path).into_diagnostic()?;
|
|
|
|
|
|
|
|
|
|
|
|
if !IGNORED_PATHS.is_match(&test_path) && !context.ignored.is_match(&test_path) {
|
|
|
|
if !IGNORED_PATHS.is_match(&test_path) && !ctx.ignored.is_match(&test_path) {
|
|
|
|
children.push(DirEntry::parse(context.clone(), entry_path)?);
|
|
|
|
children.push(DirEntry::parse(ctx.clone(), entry_path)?);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
log::debug!("Entry {entry_path:?} is ignored")
|
|
|
|
log::debug!("Entry {entry_path:?} is ignored")
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -152,14 +156,7 @@ impl DirEntry {
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DirEntry::Root(_, data, children) => {
|
|
|
|
DirEntry::Root(_, data, children) => {
|
|
|
|
let engine = templating::engine();
|
|
|
|
let rendered_path = templating::render(&data.path, &ctx.config.template_context)?;
|
|
|
|
let rendered_path = engine
|
|
|
|
|
|
|
|
.render_template(
|
|
|
|
|
|
|
|
&data.path,
|
|
|
|
|
|
|
|
&templating::context(&ctx.config.template_context),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.into_diagnostic()
|
|
|
|
|
|
|
|
.with_context(|| format!("render template {}", data.path))?;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let cwd = PathBuf::from(rendered_path);
|
|
|
|
let cwd = PathBuf::from(rendered_path);
|
|
|
|
|
|
|
|
|
|
|
@ -201,22 +198,12 @@ impl FileEntry {
|
|
|
|
log::debug!("Processing template {path:?}");
|
|
|
|
log::debug!("Processing template {path:?}");
|
|
|
|
let contents = fs::read_to_string(path).into_diagnostic()?;
|
|
|
|
let contents = fs::read_to_string(path).into_diagnostic()?;
|
|
|
|
|
|
|
|
|
|
|
|
let rendered = templating::engine()
|
|
|
|
|
|
|
|
.render_template(
|
|
|
|
|
|
|
|
&contents,
|
|
|
|
|
|
|
|
&templating::context(&ctx.config.template_context),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.into_diagnostic()
|
|
|
|
|
|
|
|
.with_context(|| format!("rendering template {path:?}"))?;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let new_path = path.with_extension("");
|
|
|
|
let new_path = path.with_extension("");
|
|
|
|
let filename = new_path.file_name().unwrap();
|
|
|
|
let filename = new_path.file_name().unwrap();
|
|
|
|
let dest = cwd.join(filename);
|
|
|
|
let dest = cwd.join(filename);
|
|
|
|
log::info!("Writing {path:?} -> {dest:?}");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fs::write(&dest, rendered)
|
|
|
|
templating::render_to_file(&dest, &contents, &ctx.config.template_context)?;
|
|
|
|
.into_diagnostic()
|
|
|
|
log::info!("Render {path:?} -> {dest:?}");
|
|
|
|
.with_context(|| format!("write to destination {dest:?}"))?;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FileEntry::Plain(path) => {
|
|
|
|
FileEntry::Plain(path) => {
|
|
|
|
let filename = path.file_name().unwrap();
|
|
|
|
let filename = path.file_name().unwrap();
|
|
|
@ -250,14 +237,11 @@ impl RootDirData {
|
|
|
|
.with_context(|| format!("parsing metadata file {path:?}"))
|
|
|
|
.with_context(|| format!("parsing metadata file {path:?}"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn read_template(path: &Path) -> Result<Self> {
|
|
|
|
fn read_template<T: Serialize>(path: &Path, ctx: T) -> Result<Self> {
|
|
|
|
let contents = fs::read_to_string(path)
|
|
|
|
let contents = fs::read_to_string(path)
|
|
|
|
.into_diagnostic()
|
|
|
|
.into_diagnostic()
|
|
|
|
.with_context(|| format!("reading metadata file {path:?}"))?;
|
|
|
|
.with_context(|| format!("reading metadata file {path:?}"))?;
|
|
|
|
let rendered = templating::engine()
|
|
|
|
let rendered = templating::render(&contents, ctx)?;
|
|
|
|
.render_template(&contents, &templating::context(()))
|
|
|
|
|
|
|
|
.into_diagnostic()
|
|
|
|
|
|
|
|
.with_context(|| format!("processing template {path:?}"))?;
|
|
|
|
|
|
|
|
toml::from_str(&rendered)
|
|
|
|
toml::from_str(&rendered)
|
|
|
|
.into_diagnostic()
|
|
|
|
.into_diagnostic()
|
|
|
|
.with_context(|| format!("parsing metadata file {path:?}"))
|
|
|
|
.with_context(|| format!("parsing metadata file {path:?}"))
|
|
|
|