Copy static directory and live reload changes to it

This commit is contained in:
Vincent Prouillet 2017-03-09 16:34:12 +09:00
parent 478e7054de
commit 57fd159025
4 changed files with 61 additions and 19 deletions

6
Cargo.lock generated
View file

@ -18,7 +18,7 @@ dependencies = [
"slug 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "slug 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"staticfile 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "staticfile 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syntect 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntect 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tera 0.8.0 (git+https://github.com/Keats/tera)", "tera 0.8.0 (git+https://github.com/Keats/tera?branch=reload)",
"toml 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"ws 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "ws 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -774,7 +774,7 @@ dependencies = [
[[package]] [[package]]
name = "tera" name = "tera"
version = "0.8.0" version = "0.8.0"
source = "git+https://github.com/Keats/tera#2eb55de231e08da50ca32a443499fbce8d9003e0" source = "git+https://github.com/Keats/tera?branch=reload#31f8bd8238e3e6bdef9ecf4468079c535609b5eb"
dependencies = [ dependencies = [
"chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1095,7 +1095,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum syn 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)" = "480c834701caba3548aa991e54677281be3a5414a9d09ddbdf4ed74a569a9d19" "checksum syn 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)" = "480c834701caba3548aa991e54677281be3a5414a9d09ddbdf4ed74a569a9d19"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum syntect 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f79be04af68d5fa09e71b3274159a955a25f25a5cbfba9a6ff64139b71d848a" "checksum syntect 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f79be04af68d5fa09e71b3274159a955a25f25a5cbfba9a6ff64139b71d848a"
"checksum tera 0.8.0 (git+https://github.com/Keats/tera)" = "<none>" "checksum tera 0.8.0 (git+https://github.com/Keats/tera?branch=reload)" = "<none>"
"checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a" "checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a"
"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a" "checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" "checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"

View file

@ -20,7 +20,7 @@ glob = "0.2"
serde = "0.9" serde = "0.9"
serde_json = "0.9" serde_json = "0.9"
serde_derive = "0.9" serde_derive = "0.9"
tera = { git = "https://github.com/Keats/tera", branch = "master" } tera = { git = "https://github.com/Keats/tera", branch = "reload" }
# tera = "0.8" # tera = "0.8"
slug = "0.1" slug = "0.1"
syntect = "1" syntect = "1"

View file

@ -87,24 +87,29 @@ pub fn serve(interface: &str, port: &str) -> Result<()> {
println!("Change detected, rebuilding site"); println!("Change detected, rebuilding site");
let what_changed = detect_change_kind(&pwd, &path); let what_changed = detect_change_kind(&pwd, &path);
let mut reload_path = String::new();
match what_changed { match what_changed {
ChangeKind::Content => println!("Content changed {}", path.display()), (ChangeKind::Content, _) => println!("Content changed {}", path.display()),
ChangeKind::Templates => println!("Template changed {}", path.display()), (ChangeKind::Templates, _) => println!("Template changed {}", path.display()),
ChangeKind::StaticFiles => println!("Static file changes detected {}", path.display()), (ChangeKind::StaticFiles, p) => {
reload_path = p;
println!("Static file changes detected {}", path.display());
},
}; };
println!("Reloading {}", reload_path);
let start = Instant::now(); let start = Instant::now();
match site.rebuild() { match site.rebuild() {
Ok(_) => { Ok(_) => {
println!("Done in {:.1}s.", time_elapsed(start)); println!("Done in {:.1}s.\n", time_elapsed(start));
broadcaster.send(r#" broadcaster.send(format!(r#"
{ {{
"command": "reload", "command": "reload",
"path": "", "path": "{}",
"originalPath": "", "originalPath": "",
"liveCSS": true, "liveCSS": true,
"liveImg": true, "liveImg": true,
"protocol": ["http://livereload.com/protocols/official-7"] "protocol": ["http://livereload.com/protocols/official-7"]
}"#).unwrap(); }}"#, reload_path)).unwrap();
}, },
Err(e) => { Err(e) => {
println!("Failed to build the site"); println!("Failed to build the site");
@ -160,7 +165,7 @@ fn is_temp_file(path: &Path) -> bool {
/// Detect what changed from the given path so we have an idea what needs /// Detect what changed from the given path so we have an idea what needs
/// to be reloaded /// to be reloaded
fn detect_change_kind(pwd: &str, path: &Path) -> ChangeKind { fn detect_change_kind(pwd: &str, path: &Path) -> (ChangeKind, String) {
let path_str = format!("{}", path.display()) let path_str = format!("{}", path.display())
.replace(pwd, "") .replace(pwd, "")
.replace("\\", "/"); .replace("\\", "/");
@ -174,7 +179,7 @@ fn detect_change_kind(pwd: &str, path: &Path) -> ChangeKind {
panic!("Got a change in an unexpected path: {}", path_str); panic!("Got a change in an unexpected path: {}", path_str);
}; };
change_kind (change_kind, path_str)
} }
#[cfg(test)] #[cfg(test)]
@ -206,9 +211,18 @@ mod tests {
#[test] #[test]
fn test_can_detect_kind_of_changes() { fn test_can_detect_kind_of_changes() {
let testcases = vec![ let testcases = vec![
(ChangeKind::Templates, "/home/vincent/site", Path::new("/home/vincent/site/templates/hello.html")), (
(ChangeKind::StaticFiles, "/home/vincent/site", Path::new("/home/vincent/site/static/site.css")), (ChangeKind::Templates, "/templates/hello.html".to_string()),
(ChangeKind::Content, "/home/vincent/site", Path::new("/home/vincent/site/content/posts/hello.md")), "/home/vincent/site", Path::new("/home/vincent/site/templates/hello.html")
),
(
(ChangeKind::StaticFiles, "/static/site.css".to_string()),
"/home/vincent/site", Path::new("/home/vincent/site/static/site.css")
),
(
(ChangeKind::Content, "/content/posts/hello.md".to_string()),
"/home/vincent/site", Path::new("/home/vincent/site/content/posts/hello.md")
),
]; ];
for (expected, pwd, path) in testcases { for (expected, pwd, path) in testcases {

View file

@ -1,11 +1,12 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::iter::FromIterator; use std::iter::FromIterator;
use std::fs::{create_dir, remove_dir_all}; use std::fs::{create_dir, remove_dir_all, copy, remove_file};
use std::path::Path; use std::path::Path;
use glob::glob; use glob::glob;
use tera::{Tera, Context}; use tera::{Tera, Context};
use slug::slugify; use slug::slugify;
use walkdir::WalkDir;
use errors::{Result, ResultExt}; use errors::{Result, ResultExt};
use config::{Config, get_config}; use config::{Config, get_config};
@ -98,7 +99,32 @@ impl Site {
} }
/// Copy the content of the `static` folder into the `public` folder /// Copy the content of the `static` folder into the `public` folder
pub fn copy_static_files(&self) -> Result<()> { ///
/// TODO: only copy one file if possible because that would be a waster
/// to do re-copy the whole thing
pub fn copy_static_directory(&self) -> Result<()> {
let from = Path::new("static");
let target = Path::new("public");
for entry in WalkDir::new(from).into_iter().filter_map(|e| e.ok()) {
let relative_path = entry.path().strip_prefix(&from).unwrap();
let target_path = {
let mut target_path = target.to_path_buf();
target_path.push(relative_path);
target_path
};
if entry.path().is_dir() {
if !target_path.exists() {
create_dir(&target_path)?;
}
} else {
if target_path.exists() {
remove_file(&target_path)?;
}
copy(entry.path(), &target_path)?;
}
}
Ok(()) Ok(())
} }
@ -106,6 +132,7 @@ impl Site {
/// Very dumb for now, ideally it would only rebuild what changed /// Very dumb for now, ideally it would only rebuild what changed
pub fn rebuild(&mut self) -> Result<()> { pub fn rebuild(&mut self) -> Result<()> {
self.parse_site()?; self.parse_site()?;
self.templates.full_reload()?;
self.build() self.build()
} }
@ -174,6 +201,7 @@ impl Site {
let index = self.templates.render("index.html", &context)?; let index = self.templates.render("index.html", &context)?;
create_file(public.join("index.html"), &self.inject_livereload(index))?; create_file(public.join("index.html"), &self.inject_livereload(index))?;
self.copy_static_directory()?;
Ok(()) Ok(())
} }