summaryrefslogtreecommitdiff
path: root/src/site.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/site.rs')
-rw-r--r--src/site.rs181
1 files changed, 105 insertions, 76 deletions
diff --git a/src/site.rs b/src/site.rs
index fd28a2b..2d1368d 100644
--- a/src/site.rs
+++ b/src/site.rs
@@ -1,23 +1,23 @@
use crate::error::SiteError;
+use crate::name::{Name, NameBuilder, Names};
use crate::page::{MarkdownPage, UnprocessedPage, WikitextPage};
use crate::parser::WikitextParser;
use crate::token::TokenPatterns;
-use crate::util::{join_subpath, make_path_absolute, make_path_relative_to, make_relative_link};
+use crate::util::make_relative_link;
use log::{debug, info, trace};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;
pub struct Site {
+ builder: NameBuilder,
wikitext_pages: Vec<WikitextPage>,
unprocessed_pages: Vec<UnprocessedPage>,
markdown_pages: Vec<MarkdownPage>,
- files: Vec<PathBuf>,
- included_files: Vec<PathBuf>,
+ files: Names,
patterns: TokenPatterns,
- srcdir: PathBuf,
- destdir: PathBuf,
- pages: PageSet,
+ name_queue: Vec<Name>,
+ page_queue: PageSet,
}
impl Site {
@@ -29,55 +29,73 @@ impl Site {
P: AsRef<Path>,
{
Self {
+ builder: NameBuilder::new(srcdir.as_ref(), destdir.as_ref()),
wikitext_pages: vec![],
unprocessed_pages: vec![],
markdown_pages: vec![],
- files: vec![],
- included_files: vec![],
+ files: Names::default(),
patterns: TokenPatterns::default(),
- srcdir: srcdir.as_ref().into(),
- destdir: destdir.as_ref().into(),
- pages: PageSet::default(),
+ name_queue: vec![],
+ page_queue: PageSet::default(),
}
}
pub fn scan(&mut self) -> Result<(), SiteError> {
- for filename in Self::all_files(&self.srcdir)? {
- self.included_files
- .push(make_path_relative_to(&self.srcdir, &filename));
- if Self::is_markdown(&filename) {
- let page = WikitextPage::read(&self.srcdir, &filename)?;
- self.add_wikitextpage(page);
- } else if filename.is_file() || filename.is_symlink() {
- self.add_other_file(filename);
+ for name in self.all_files()? {
+ trace!("scan: name={}", name);
+ if name.is_wikitext_page() {
+ trace!("scan: it's a page");
+ self.name_queue.push(name);
+ } else {
+ trace!("scan: it's a non-page file");
+ let filename = name.source_path();
+ if filename.is_file() || filename.is_symlink() {
+ self.add_other_file(name);
+ }
}
}
Ok(())
}
- pub fn add_wikitextpage(&mut self, page: WikitextPage) {
+ fn add_wikitextpage(&mut self, page: WikitextPage) {
info!("add wikitext page {}", page.meta().path().display());
- self.pages.insert(&page);
+ self.page_queue.insert(&page);
self.wikitext_pages.push(page);
}
- pub fn add_other_file(&mut self, filename: PathBuf) {
- info!("add other file {}", filename.display());
- let filename = make_path_relative_to(&self.srcdir, &filename);
- let filename = make_path_absolute(&filename);
- self.files.push(filename);
+ fn add_other_file(&mut self, name: Name) {
+ info!("add other file {}", name);
+ self.files.insert(name);
}
pub fn process(&mut self) -> Result<(), SiteError> {
+ trace!("processing queues");
loop {
- if !self.process_wikipage()? && !self.process_unrocessed_page()? {
+ if !self.process_name()?
+ && !self.process_wikipage()?
+ && !self.process_unrocessed_page()?
+ {
+ trace!("processing queues done");
break;
}
}
Ok(())
}
- pub fn process_wikipage(&mut self) -> Result<bool, SiteError> {
+ fn process_name(&mut self) -> Result<bool, SiteError> {
+ if let Some(name) = self.name_queue.pop() {
+ debug!("loading wikitext page {}", name.source_path().display());
+ let page = WikitextPage::read(&name)?;
+ self.files.insert(name);
+ self.add_wikitextpage(page);
+ Ok(true)
+ } else {
+ trace!("name_queue was empty");
+ Ok(false)
+ }
+ }
+
+ fn process_wikipage(&mut self) -> Result<bool, SiteError> {
if let Some(page) = self.wikitext_pages.pop() {
debug!("processing wikitext page {}", page.meta().path().display());
let mut parser = WikitextParser::new(page.wikitext(), &self.patterns);
@@ -85,11 +103,12 @@ impl Site {
self.unprocessed_pages.push(page);
Ok(true)
} else {
+ trace!("wikitext_ages was empty");
Ok(false)
}
}
- pub fn process_unrocessed_page(&mut self) -> Result<bool, SiteError> {
+ fn process_unrocessed_page(&mut self) -> Result<bool, SiteError> {
if let Some(page) = self.unprocessed_pages.pop() {
debug!(
"processing unprocessed page {}",
@@ -99,6 +118,7 @@ impl Site {
self.markdown_pages.push(page);
Ok(true)
} else {
+ trace!("unprocessed_ages was empty");
Ok(false)
}
}
@@ -107,35 +127,38 @@ impl Site {
&self.markdown_pages
}
- pub fn files(&self) -> &[PathBuf] {
- &self.files
- }
-
- pub fn included_files(&self) -> &[PathBuf] {
- &self.included_files
- }
-
- pub fn input_filename(&self, filename: &Path) -> Result<PathBuf, SiteError> {
- Ok(join_subpath(&self.srcdir, filename))
+ pub fn files_only(&self) -> impl Iterator<Item = &Name> {
+ self.files.files()
}
- pub fn output_filename(&self, filename: &Path) -> Result<PathBuf, SiteError> {
- Ok(join_subpath(&self.destdir, filename))
+ pub fn pages_and_files(&self) -> impl Iterator<Item = &Name> {
+ self.files.iter().chain(self.name_queue.iter())
}
- fn all_files(root: &Path) -> Result<Vec<PathBuf>, SiteError> {
- let mut files = vec![];
+ fn all_files(&self) -> Result<Vec<Name>, SiteError> {
+ let mut names = vec![];
+ let root = self.builder.srcdir();
+ trace!("all_files: root={}", root.display());
for e in WalkDir::new(root) {
let e = e.map_err(|err| SiteError::WalkDir(root.to_path_buf(), err))?;
let path = e.path();
+ trace!("all_files: path={}", path.display());
if Self::is_excluded(path) {
debug!("exclude {}", path.display());
} else {
debug!("include {}", path.display());
- files.push(path.to_path_buf());
+ if Self::is_markdown(path) {
+ trace!("it's markdown");
+ names.push(self.builder.page(path));
+ } else if path.is_file() {
+ trace!("it's not markdown");
+ names.push(self.builder.file(path));
+ } else {
+ trace!("it's not a file");
+ }
}
}
- Ok(files)
+ Ok(names)
}
fn is_excluded(path: &Path) -> bool {
@@ -182,7 +205,7 @@ impl Site {
// Is target absolute?
if target.starts_with("/") {
- if let Some(path) = self.pages.get(target) {
+ if let Some(path) = self.page_queue.get(target) {
trace!("absolute target exists");
return Ok(path.into());
} else {
@@ -194,7 +217,7 @@ impl Site {
// Does a sub-page exist?
let path = page.join(target);
trace!("checking for subpage {}", path.display());
- if let Some(path) = self.pages.get(&path) {
+ if let Some(path) = self.page_queue.get(&path) {
trace!("subpage exists: {}", path.display());
return Ok(path.into());
}
@@ -207,7 +230,7 @@ impl Site {
parent.display(),
path.display()
);
- if let Some(path) = self.pages.get(path.as_path()) {
+ if let Some(path) = self.page_queue.get(path.as_path()) {
trace!("sibling page exists: {}", path.display());
return Ok(path.into());
}
@@ -224,8 +247,8 @@ impl Site {
}
fn file_exists(&self, filename: &Path) -> bool {
- for existing in self.files.iter() {
- if filename == existing {
+ for existing in self.files.files() {
+ if filename == existing.page_path() {
return true;
}
}
@@ -256,32 +279,37 @@ impl PageSet {
#[cfg(test)]
mod test {
- use super::{Site, SiteError, WikitextPage};
+ use super::{NameBuilder, Site, SiteError, WikitextPage};
use crate::page::MetaBuilder;
use std::{
path::{Path, PathBuf},
time::SystemTime,
};
+ fn site() -> Site {
+ Site::new("/src", "/dest")
+ }
+
+ fn builder() -> NameBuilder {
+ NameBuilder::new(Path::new("/src"), Path::new("/dest"))
+ }
+
fn page(path: &str) -> WikitextPage {
+ let name = builder().page(Path::new(path));
let mtime = SystemTime::now();
- let meta = MetaBuilder::default()
- .path(PathBuf::from(path))
- .mtime(mtime)
- .build();
+ let meta = MetaBuilder::default().name(name).mtime(mtime).build();
WikitextPage::new(meta, "".into())
}
#[test]
fn has_no_pages_initially() {
- let site = Site::new(".", ".");
- assert_eq!(site.markdown_pages().to_vec(), vec![]);
+ assert_eq!(site().markdown_pages().to_vec(), vec![]);
}
#[test]
fn absolute_link_resolves_to_link_relative_root_of_site() {
- let mut site = Site::new(".", ".");
- site.add_wikitextpage(page("/yo/yoyo"));
+ let mut site = site();
+ site.add_wikitextpage(page("/src/yo/yoyo"));
assert_eq!(
site.resolve("/foo/bar", "/yo/yoyo").unwrap(),
Path::new("../yo/yoyo")
@@ -290,11 +318,11 @@ mod test {
#[test]
fn link_to_missing_is_an_error() {
- let site = Site::new(".", ".");
- match site.resolve("/foo/bar", "yo") {
+ let site = site();
+ match site.resolve("/src/foo/bar", "yo") {
Err(SiteError::PageMissing(page, target)) => {
assert_eq!(target, PathBuf::from("yo"));
- assert_eq!(page, PathBuf::from("/foo/bar"));
+ assert_eq!(page, PathBuf::from("/src/foo/bar"));
}
_ => panic!("unexpected success"),
}
@@ -302,40 +330,40 @@ mod test {
#[test]
fn link_to_sibling_resolves_to_it() {
- let mut site = Site::new(".", ".");
- site.add_wikitextpage(page("/foo/yo"));
+ let mut site = site();
+ site.add_wikitextpage(page("/src/foo/yo"));
site.process().unwrap();
assert_eq!(site.resolve("/foo/bar", "yo").unwrap(), Path::new("yo"));
}
#[test]
fn link_using_other_casing_is_resolved() {
- let mut site = Site::new(".", ".");
- site.add_wikitextpage(page("/foo/yo"));
+ let mut site = site();
+ site.add_wikitextpage(page("/src/foo/yo"));
site.process().unwrap();
assert_eq!(site.resolve("/foo/bar", "YO").unwrap(), Path::new("yo"));
}
#[test]
fn link_to_sublpage_resolves_to_it() {
- let mut site = Site::new(".", ".");
- site.add_wikitextpage(page("/foo/bar/yo"));
+ let mut site = site();
+ site.add_wikitextpage(page("/src/foo/bar/yo"));
site.process().unwrap();
assert_eq!(site.resolve("/foo/bar", "yo").unwrap(), Path::new("bar/yo"));
}
#[test]
fn link_to_sublpage_resolves_to_it_and_not_sibling() {
- let mut site = Site::new(".", ".");
- site.add_wikitextpage(page("/foo/bar/yo"));
- site.add_wikitextpage(page("/foo/yo"));
+ let mut site = site();
+ site.add_wikitextpage(page("/src/foo/bar/yo"));
+ site.add_wikitextpage(page("/src/foo/yo"));
site.process().unwrap();
assert_eq!(site.resolve("/foo/bar", "yo").unwrap(), Path::new("bar/yo"));
}
#[test]
fn link_to_unrelated_subpage_is_an_error() {
- let mut site = Site::new(".", ".");
+ let mut site = site();
site.process().unwrap();
match site.resolve("/foo/bar", "yo/yoyo") {
Err(SiteError::PageMissing(page, target)) => {
@@ -348,8 +376,8 @@ mod test {
#[test]
fn link_to_subsubpage_resolves_to_it() {
- let mut site = Site::new(".", ".");
- site.add_wikitextpage(page("/foo/bar/yo/yoyo"));
+ let mut site = site();
+ site.add_wikitextpage(page("/src/foo/bar/yo/yoyo"));
site.process().unwrap();
assert_eq!(
site.resolve("/foo/bar", "yo/yoyo").unwrap(),
@@ -359,8 +387,9 @@ mod test {
#[test]
fn link_to_sibling_file_resolves_to_it() {
- let mut site = Site::new("/src", "/dest");
- site.add_other_file(PathBuf::from("/src/foo/bar.jpg"));
+ let mut site = site();
+ let name = builder().file(Path::new("/src/foo/bar.jpg"));
+ site.add_other_file(name);
site.process().unwrap();
assert_eq!(
site.resolve("/foo/bar", "bar.jpg").unwrap(),