Move copy utils to utils crate
This commit is contained in:
parent
bcf42a0c10
commit
f1abbd0860
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -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
2
Cargo.lock
generated
|
@ -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]]
|
||||||
|
|
|
@ -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(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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(())
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
Loading…
Reference in a new issue