[[package]]
name = "linux-raw-sys"
-version = "0.3.7"
+version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
name = "log"
"pandoc",
"pest",
"pest_derive",
+ "rayon",
"thiserror",
]
--- /dev/null
+use crate::{MetaError, Options};
+use eyre::Result;
+use rayon::prelude::*;
+use std::{fs, path::PathBuf};
+
+use super::*;
+
+#[derive(Debug, Clone)]
+pub struct DirNode<'a> {
+ path: PathBuf,
+ opts: &'a Options,
+ global: MetaFile<'a>,
+ files: Vec<MetaFile<'a>>,
+ dirs: Vec<DirNode<'a>>,
+}
+
+impl<'a> DirNode<'a> {
+ pub fn build(path: PathBuf, opts: &'a Options) -> Result<Self> {
+ assert!(path.is_dir() && path.exists());
+
+ // copy over directory structure from source dir
+ let build_dir = opts.build.join(path.strip_prefix(&opts.source)?);
+ if !build_dir.exists() {
+ fs::create_dir_all(build_dir)?;
+ }
+
+ let files: Vec<MetaFile> = Vec::new();
+ let dirs: Vec<DirNode> = Vec::new();
+ let global = MetaFile::new(opts);
+
+ Ok(Self {
+ path,
+ opts,
+ global,
+ files,
+ dirs,
+ })
+ }
+
+ // parses all contained files and directories and pushes
+ // parsed structures into the files and directories vectors
+ pub fn map(&mut self, global: &'a MetaFile) -> Result<()> {
+ if self.opts.parallel {}
+
+ for f in fs::read_dir(&self.path)? {
+ let file = f?.path();
+
+ if file.is_dir() {
+ let dir = DirNode::build(file, self.opts)?;
+ self.dirs.push(dir);
+ } else if file.file_name().and_then(|f| f.to_str()) == Some("default.meta") {
+ let mut new_global = MetaFile::build(file, self.opts)?;
+ new_global.merge(global);
+ self.global = new_global;
+ } else if file.extension().and_then(|f| f.to_str()) == Some("meta") {
+ let file = MetaFile::build(file, self.opts)?;
+ self.files.push(file)
+ }
+ }
+
+ Ok(())
+ }
+
+ pub fn build_files(&mut self) -> Result<()> {
+ for file in self.files.iter_mut() {
+ file.merge(&self.global);
+ match file.construct() {
+ Ok(str) => {
+ fs::write(file.dest()?, str)?;
+ }
+ Err(e) => {
+ // print a line to stderr about failure but continue with other files
+ if self.opts.force {
+ eprintln!("ignoring {}: {}", file.path.display(), e);
+ continue;
+ } else {
+ // we raise an ignored error to quickly abort any file parsing
+ if let MetaError::Ignored = *e {
+ continue;
+ // anything else gets wrapped up and passed up the calling chain
+ } else {
+ return Err(e.into());
+ }
+ }
+ }
+ }
+ }
+ Ok(())
+ }
+
+ pub fn build_dir(&'a mut self) -> Result<()> {
+ self.build_files()?;
+
+ for dir in self.dirs.iter_mut() {
+ dir.map(&self.global)?;
+ dir.build_dir()?;
+ }
+
+ Ok(())
+ }
+}
use crate::{MetaError, Options};
use eyre::Result;
+use rayon::prelude::*;
use std::{fs, path::PathBuf};
use super::*;
/// only build a single file
#[arg(short, long, value_name = "FILENAME")]
pub file: Option<String>,
+ /// parallel processing
+ #[arg(short, long, default_value_t = false)]
+ pub parallel: bool,
/// create a new skeleton directory
#[arg(long, default_value_t = false)]
pub new: bool,
pub input: String,
pub output: String,
pub verbose: u8,
+ pub parallel: bool,
pub quiet: bool,
pub force: bool,
pub undefined: bool,
input: String::default(),
output: String::default(),
verbose: 0,
+ parallel: false,
quiet: false,
force: false,
undefined: false,
opts.clean = value.clean;
opts.no_pandoc = value.no_pandoc;
opts.new = value.new;
+ opts.parallel = value.parallel;
- if let Some(root) = value.root.as_deref() {
- opts.root = PathBuf::from(root).canonicalize()?;
+ opts.root = if let Some(root) = value.root.as_deref() {
+ PathBuf::from(root).canonicalize()
} else {
- opts.root = std::env::current_dir()?;
- }
+ std::env::current_dir()
+ }?;
- if let Some(source) = value.source.as_deref() {
- opts.source = PathBuf::from(source).canonicalize()?;
+ opts.source = if let Some(source) = value.source.as_deref() {
+ PathBuf::from(source).canonicalize()
} else {
- opts.source = opts.root.join("source");
- }
+ Ok(opts.root.join("source"))
+ }?;
- if let Some(build) = value.build.as_deref() {
- opts.build = PathBuf::from(build).canonicalize()?;
+ opts.build = if let Some(build) = value.build.as_deref() {
+ PathBuf::from(build).canonicalize()
} else {
- opts.build = opts.root.join("build");
- }
+ Ok(opts.root.join("build"))
+ }?;
- if let Some(pattern) = value.pattern.as_deref() {
- opts.pattern = PathBuf::from(pattern).canonicalize()?;
+ opts.pattern = if let Some(pattern) = value.pattern.as_deref() {
+ PathBuf::from(pattern).canonicalize()
} else {
- opts.pattern = opts.root.join("pattern");
- }
+ Ok(opts.root.join("pattern"))
+ }?;
if let Some(file) = value.file.as_deref() {
opts.file = Some(PathBuf::from(file).canonicalize()?);
}
- if let Some(input) = value.input {
- opts.input = input;
+ opts.input = if let Some(input) = value.input {
+ input
} else {
- opts.input = String::from("html");
- }
+ String::from("html")
+ };
- if let Some(output) = value.output {
- opts.output = output;
+ opts.output = if let Some(output) = value.output {
+ output
} else {
- opts.output = String::from("markdown");
- }
+ String::from("markdown")
+ };
Ok(opts)
}