Move copy utils to utils crate

This commit is contained in:
Vincent Prouillet 2018-03-14 22:03:06 +01:00
parent bcf42a0c10
commit f1abbd0860
11 changed files with 76 additions and 42 deletions

2
.gitignore vendored
View file

@ -1,6 +1,6 @@
target target
.idea/ .idea/
components/site/test_site/public test_site/public
docs/public docs/public
small-blog small-blog

2
Cargo.lock generated
View file

@ -1153,7 +1153,6 @@ dependencies = [
"templates 0.1.0", "templates 0.1.0",
"tera 0.11.5 (registry+https://github.com/rust-lang/crates.io-index)", "tera 0.11.5 (registry+https://github.com/rust-lang/crates.io-index)",
"utils 0.1.0", "utils 0.1.0",
"walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -1465,6 +1464,7 @@ dependencies = [
"errors 0.1.0", "errors 0.1.0",
"tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tera 0.11.5 (registry+https://github.com/rust-lang/crates.io-index)", "tera 0.11.5 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]

View file

@ -94,6 +94,10 @@ pub struct PageFrontMatter {
/// Specify a template different from `page.html` to use for that page /// Specify a template different from `page.html` to use for that page
#[serde(skip_serializing)] #[serde(skip_serializing)]
pub template: Option<String>, pub template: Option<String>,
/// Whether the page is included in the search index
/// Defaults to `true` but is only used if search if explicitly enabled in the config.
#[serde(default, skip_serializing)]
pub in_search_index: bool,
/// Any extra parameter present in the front matter /// Any extra parameter present in the front matter
#[serde(default)] #[serde(default)]
pub extra: Map<String, Value>, pub extra: Map<String, Value>,
@ -174,6 +178,7 @@ impl Default for PageFrontMatter {
order: None, order: None,
weight: None, weight: None,
aliases: None, aliases: None,
in_search_index: true,
template: None, template: None,
extra: Map::new(), extra: Map::new(),
} }

View file

@ -48,7 +48,7 @@ pub struct SectionFrontMatter {
#[serde(skip_serializing)] #[serde(skip_serializing)]
pub redirect_to: Option<String>, pub redirect_to: Option<String>,
/// Whether the section content and its pages/subsections are included in the index. /// Whether the section content and its pages/subsections are included in the index.
/// Defaults to `true` but is only used if search if explicitely enabled in the config. /// Defaults to `true` but is only used if search if explicitly enabled in the config.
#[serde(skip_serializing)] #[serde(skip_serializing)]
pub in_search_index: bool, pub in_search_index: bool,
/// Any extra parameter present in the front matter /// Any extra parameter present in the front matter

View file

@ -6,7 +6,6 @@ authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"]
[dependencies] [dependencies]
tera = "0.11" tera = "0.11"
glob = "0.2" glob = "0.2"
walkdir = "2"
rayon = "1" rayon = "1"
serde = "1" serde = "1"
serde_derive = "1" serde_derive = "1"

View file

@ -1,7 +1,6 @@
extern crate tera; extern crate tera;
extern crate rayon; extern crate rayon;
extern crate glob; extern crate glob;
extern crate walkdir;
extern crate serde; extern crate serde;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@ -21,7 +20,7 @@ extern crate content;
extern crate tempdir; extern crate tempdir;
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::{remove_dir_all, copy, create_dir_all}; use std::fs::{remove_dir_all, copy};
use std::mem; use std::mem;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -32,7 +31,7 @@ use sass_rs::{Options as SassOptions, OutputStyle, compile_file};
use errors::{Result, ResultExt}; use errors::{Result, ResultExt};
use config::{Config, get_config}; use config::{Config, get_config};
use utils::fs::{create_file, create_directory, ensure_directory_exists}; use utils::fs::{create_file, copy_directory, create_directory, ensure_directory_exists};
use utils::templates::{render_template, rewrite_theme_paths}; use utils::templates::{render_template, rewrite_theme_paths};
use content::{Page, Section, populate_previous_and_next_pages, sort_pages}; use content::{Page, Section, populate_previous_and_next_pages, sort_pages};
use templates::{GUTENBERG_TERA, global_fns, render_redirect_template}; use templates::{GUTENBERG_TERA, global_fns, render_redirect_template};
@ -67,7 +66,7 @@ pub struct Site {
pub sections: HashMap<PathBuf, Section>, pub sections: HashMap<PathBuf, Section>,
pub tera: Tera, pub tera: Tera,
live_reload: bool, live_reload: bool,
output_path: PathBuf, pub output_path: PathBuf,
pub static_path: PathBuf, pub static_path: PathBuf,
pub tags: Option<Taxonomy>, pub tags: Option<Taxonomy>,
pub categories: Option<Taxonomy>, pub categories: Option<Taxonomy>,
@ -125,6 +124,11 @@ impl Site {
Ok(site) Ok(site)
} }
/// The index section is ALWAYS at that path
pub fn index_section_path(&self) -> PathBuf {
self.base_path.join("content").join("_index.md")
}
/// What the function name says /// What the function name says
pub fn enable_live_reload(&mut self) { pub fn enable_live_reload(&mut self) {
self.live_reload = true; self.live_reload = true;
@ -198,7 +202,17 @@ impl Site {
// Insert a default index section if necessary so we don't need to create // Insert a default index section if necessary so we don't need to create
// a _index.md to render the index page // a _index.md to render the index page
let index_path = self.base_path.join("content").join("_index.md"); let index_path = self.index_section_path();
if let Some(ref index_section) = self.sections.get(&index_path) {
if self.config.build_search_index && index_section.meta.in_search_index {
bail!(
"You have enabled search in the config but disabled it in the index section: \
either turn off the search in the config or remote `in_search_index = true` from the \
section front-matter."
)
}
}
// Not in else because of borrow checker
if !self.sections.contains_key(&index_path) { if !self.sections.contains_key(&index_path) {
let mut index_section = Section::default(); let mut index_section = Section::default();
index_section.permalink = self.config.make_permalink(""); index_section.permalink = self.config.make_permalink("");
@ -409,45 +423,18 @@ impl Site {
html html
} }
/// Copy the file at the given path into the public folder
pub fn copy_static_file<P: AsRef<Path>>(&self, path: P, base_path: &PathBuf) -> Result<()> {
let relative_path = path.as_ref().strip_prefix(base_path).unwrap();
let target_path = self.output_path.join(relative_path);
if let Some(parent_directory) = target_path.parent() {
create_dir_all(parent_directory)?;
}
copy(path.as_ref(), &target_path)?;
Ok(())
}
/// Copy the content of the given folder into the `public` folder
fn copy_static_directory(&self, path: &PathBuf) -> Result<()> {
for entry in WalkDir::new(path).into_iter().filter_map(|e| e.ok()) {
let relative_path = entry.path().strip_prefix(path).unwrap();
let target_path = self.output_path.join(relative_path);
if entry.path().is_dir() {
if !target_path.exists() {
create_directory(&target_path)?;
}
} else {
let entry_fullpath = self.base_path.join(entry.path());
self.copy_static_file(entry_fullpath, path)?;
}
}
Ok(())
}
/// Copy the main `static` folder and the theme `static` folder if a theme is used /// Copy the main `static` folder and the theme `static` folder if a theme is used
pub fn copy_static_directories(&self) -> Result<()> { pub fn copy_static_directories(&self) -> Result<()> {
// The user files will overwrite the theme files // The user files will overwrite the theme files
if let Some(ref theme) = self.config.theme { if let Some(ref theme) = self.config.theme {
self.copy_static_directory( copy_directory(
&self.base_path.join("themes").join(theme).join("static") &self.base_path.join("themes").join(theme).join("static"),
&self.output_path
)?; )?;
} }
// We're fine with missing static folders // We're fine with missing static folders
if self.static_path.exists() { if self.static_path.exists() {
self.copy_static_directory(&self.static_path)?; copy_directory(&self.static_path, &self.output_path)?;
} }
Ok(()) Ok(())

View file

@ -445,3 +445,10 @@ fn can_build_rss_feed() {
// Next is posts/python.md // Next is posts/python.md
assert!(file_contains!(public, "rss.xml", "Python in posts")); assert!(file_contains!(public, "rss.xml", "Python in posts"));
} }
#[test]
fn can_build_search_index() {
// TODO: generate an index somehow and check for correctness with
// another one
}

View file

@ -6,6 +6,7 @@ authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"]
[dependencies] [dependencies]
errors = { path = "../errors" } errors = { path = "../errors" }
tera = "0.11" tera = "0.11"
walkdir = "2"
[dev-dependencies] [dev-dependencies]

View file

@ -1,9 +1,12 @@
use std::io::prelude::*; use std::io::prelude::*;
use std::fs::{File, create_dir_all, read_dir}; use std::fs::{File, create_dir_all, read_dir, copy};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use walkdir::WalkDir;
use errors::{Result, ResultExt}; use errors::{Result, ResultExt};
/// Create a file with the content given /// Create a file with the content given
pub fn create_file(path: &Path, content: &str) -> Result<()> { pub fn create_file(path: &Path, content: &str) -> Result<()> {
let mut file = File::create(&path)?; let mut file = File::create(&path)?;
@ -60,6 +63,36 @@ pub fn find_related_assets(path: &Path) -> Vec<PathBuf> {
assets assets
} }
/// Copy a file but takes into account where to start the copy as
/// there might be folders we need to create on the way
pub fn copy_file(src: &Path, dest: &PathBuf, base_path: &PathBuf) -> Result<()> {
let relative_path = src.strip_prefix(base_path).unwrap();
let target_path = dest.join(relative_path);
if let Some(parent_directory) = target_path.parent() {
create_dir_all(parent_directory)?;
}
copy(src, target_path)?;
Ok(())
}
pub fn copy_directory(src: &PathBuf, dest: &PathBuf) -> Result<()> {
for entry in WalkDir::new(src).into_iter().filter_map(|e| e.ok()) {
let relative_path = entry.path().strip_prefix(src).unwrap();
let target_path = dest.join(relative_path);
if entry.path().is_dir() {
if !target_path.exists() {
create_directory(&target_path)?;
}
} else {
copy_file(entry.path(), dest, src)?;
}
}
Ok(())
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::fs::File; use std::fs::File;

View file

@ -4,6 +4,7 @@ extern crate errors;
#[cfg(test)] #[cfg(test)]
extern crate tempdir; extern crate tempdir;
extern crate tera; extern crate tera;
extern crate walkdir;
pub mod fs; pub mod fs;
pub mod site; pub mod site;

View file

@ -38,6 +38,7 @@ use ctrlc;
use site::Site; use site::Site;
use errors::{Result, ResultExt}; use errors::{Result, ResultExt};
use utils::fs::copy_file;
use console; use console;
use rebuild; use rebuild;
@ -207,7 +208,7 @@ pub fn serve(interface: &str, port: &str, output_dir: &str, base_url: &str, conf
(ChangeKind::StaticFiles, p) => { (ChangeKind::StaticFiles, p) => {
if path.is_file() { if path.is_file() {
console::info(&format!("-> Static file changes detected {}", path.display())); console::info(&format!("-> Static file changes detected {}", path.display()));
rebuild_done_handling(&broadcaster, site.copy_static_file(&path, &site.static_path), &p); rebuild_done_handling(&broadcaster, copy_file(&path, &site.output_path, &site.static_path), &p);
} }
}, },
(ChangeKind::Sass, p) => { (ChangeKind::Sass, p) => {