From 962fb39dd2d53b918c6f405b1bba80577d3f4ec9 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Sun, 19 Mar 2023 16:15:06 -0400 Subject: [PATCH] wip: Render command and site::render stub --- src/bin/cli/mod.rs | 6 +++- src/bin/cli/render.rs | 75 +++++++++++++++++++++++++++++++++++++++++++ src/site.rs | 19 +++++++++++ 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/bin/cli/render.rs diff --git a/src/bin/cli/mod.rs b/src/bin/cli/mod.rs index 2a1d98c..5e8404f 100644 --- a/src/bin/cli/mod.rs +++ b/src/bin/cli/mod.rs @@ -4,11 +4,12 @@ use snafu::{ensure, ResultExt, Snafu}; use std::{env::current_dir, path::PathBuf}; mod init; +mod render; mod validate; pub use init::InitArgs; -use self::validate::ValidateArgs; +use self::{render::RenderArgs, validate::ValidateArgs}; /// Error encountered while parsing CLI #[derive(Debug, Snafu)] @@ -86,6 +87,8 @@ pub enum Command { Init(InitArgs), /// Valiate the structure and configuration of a site Validate(ValidateArgs), + /// Generate the site + Render(RenderArgs), } impl Command { @@ -94,6 +97,7 @@ impl Command { match self { Command::Init(args) => args.run(globals), Command::Validate(args) => args.run(globals), + Command::Render(args) => args.run(globals), } } } diff --git a/src/bin/cli/render.rs b/src/bin/cli/render.rs new file mode 100644 index 0000000..cef7205 --- /dev/null +++ b/src/bin/cli/render.rs @@ -0,0 +1,75 @@ +use std::{ + fs::{create_dir_all, read_dir}, + path::PathBuf, +}; + +use clap::Args; +use color_eyre::eyre::{bail, ensure, Context, Result}; +use stranger_site_gen::site::Site; +use tracing::{info, warn}; + +use super::GlobalArgs; + +/// Arguments for the render subcommand +#[derive(Args, Debug)] +pub struct RenderArgs { + /// Output directory to use + #[arg(long, short)] + pub output_directory: Option, + /// Overrite the output if needed + #[arg(long, short)] + pub force: bool, +} + +impl RenderArgs { + /// Run the render command + #[tracing::instrument] + pub fn run(self, globals: GlobalArgs) -> Result<()> { + // Get the site directory + let site_dir = globals.site_path().context("Failed getting site dir")?; + + // Read in the site state + let site = Site::read(&site_dir).context("Failed to load site state")?; + + // Figure out where we are putting the output + let output_dir = self + .output_directory + .unwrap_or_else(|| site_dir.join("output")); + info!(?output_dir); + + // Make sure the output path is valid, meaning one of the following: + // - Non existant path, in which case we create a directory + // - Empty directory + if output_dir + .try_exists() + .context("Failed to check for existance of ouput directory")? + { + ensure!(output_dir.is_dir(), "Output path was not a directory"); + let mut children = Vec::new(); + for child in + read_dir(&output_dir).context("Failed to check output directory for emptyness")? + { + let child = child.context("Failed to check output directory for emptynesss")?; + children.push(child.path()); + } + if !children.is_empty() { + if self.force { + warn!( + ?children, + "Output directory was non-empty, but force was requested, continuing anyway" + ); + } else { + bail!("Output directory was non-empty: {:?}", children); + } + } + } else { + info!(?output_dir, "Creating output directory"); + create_dir_all(&output_dir).context("Failed to create output directory")?; + } + + // Pass off to `Site` to render the site + site.render(&site_dir, &output_dir) + .context("Failed to render site")?; + Ok(()) + } +} diff --git a/src/site.rs b/src/site.rs index 33a5cc2..e9ebc81 100644 --- a/src/site.rs +++ b/src/site.rs @@ -285,6 +285,25 @@ impl Site { styles, }) } + + /// Render the site to the provided output directory + /// + /// # Errors + /// + /// Will return an error if one of the djot files is invalid, or if any IO errors occur during + /// rendering + pub fn render( + &self, + site_dir: impl AsRef, + output_dir: impl AsRef, + ) -> Result<(), SiteError> { + // Get dirs and setup logging + let site_dir = site_dir.as_ref(); + let output_dir = output_dir.as_ref(); + let span = info_span!("Site::render", ?site_dir, ?output_dir); + let _enter = span.enter(); + todo!() + } } /// Error encountered interacting with a [`Site`] #[derive(Snafu, Debug)]