From 57fd159025527d67bc445b50c0adbc07e87ce880 Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Thu, 9 Mar 2017 16:34:12 +0900 Subject: [PATCH] Copy static directory and live reload changes to it --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- src/cmd/serve.rs | 40 +++++++++++++++++++++++++++------------- src/site.rs | 32 ++++++++++++++++++++++++++++++-- 4 files changed, 61 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 15104770..bc077371 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,7 +18,7 @@ dependencies = [ "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)", "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)", "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)", @@ -774,7 +774,7 @@ dependencies = [ [[package]] name = "tera" version = "0.8.0" -source = "git+https://github.com/Keats/tera#2eb55de231e08da50ca32a443499fbce8d9003e0" +source = "git+https://github.com/Keats/tera?branch=reload#31f8bd8238e3e6bdef9ecf4468079c535609b5eb" dependencies = [ "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)", @@ -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 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 tera 0.8.0 (git+https://github.com/Keats/tera)" = "" +"checksum tera 0.8.0 (git+https://github.com/Keats/tera?branch=reload)" = "" "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_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" diff --git a/Cargo.toml b/Cargo.toml index f381c61e..0ef92e45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ glob = "0.2" serde = "0.9" serde_json = "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" slug = "0.1" syntect = "1" diff --git a/src/cmd/serve.rs b/src/cmd/serve.rs index 7e4ce311..e36f1dd7 100644 --- a/src/cmd/serve.rs +++ b/src/cmd/serve.rs @@ -87,24 +87,29 @@ pub fn serve(interface: &str, port: &str) -> Result<()> { println!("Change detected, rebuilding site"); let what_changed = detect_change_kind(&pwd, &path); + let mut reload_path = String::new(); match what_changed { - ChangeKind::Content => println!("Content changed {}", path.display()), - ChangeKind::Templates => println!("Template changed {}", path.display()), - ChangeKind::StaticFiles => println!("Static file changes detected {}", path.display()), + (ChangeKind::Content, _) => println!("Content changed {}", path.display()), + (ChangeKind::Templates, _) => println!("Template changed {}", path.display()), + (ChangeKind::StaticFiles, p) => { + reload_path = p; + println!("Static file changes detected {}", path.display()); + }, }; + println!("Reloading {}", reload_path); let start = Instant::now(); match site.rebuild() { Ok(_) => { - println!("Done in {:.1}s.", time_elapsed(start)); - broadcaster.send(r#" - { + println!("Done in {:.1}s.\n", time_elapsed(start)); + broadcaster.send(format!(r#" + {{ "command": "reload", - "path": "", + "path": "{}", "originalPath": "", "liveCSS": true, "liveImg": true, "protocol": ["http://livereload.com/protocols/official-7"] - }"#).unwrap(); + }}"#, reload_path)).unwrap(); }, Err(e) => { 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 /// 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()) .replace(pwd, "") .replace("\\", "/"); @@ -174,7 +179,7 @@ fn detect_change_kind(pwd: &str, path: &Path) -> ChangeKind { panic!("Got a change in an unexpected path: {}", path_str); }; - change_kind + (change_kind, path_str) } #[cfg(test)] @@ -206,9 +211,18 @@ mod tests { #[test] fn test_can_detect_kind_of_changes() { 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::Content, "/home/vincent/site", Path::new("/home/vincent/site/content/posts/hello.md")), + ( + (ChangeKind::Templates, "/templates/hello.html".to_string()), + "/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 { diff --git a/src/site.rs b/src/site.rs index 085160d6..59fa93d4 100644 --- a/src/site.rs +++ b/src/site.rs @@ -1,11 +1,12 @@ use std::collections::HashMap; 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 glob::glob; use tera::{Tera, Context}; use slug::slugify; +use walkdir::WalkDir; use errors::{Result, ResultExt}; use config::{Config, get_config}; @@ -98,7 +99,32 @@ impl Site { } /// 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(()) } @@ -106,6 +132,7 @@ impl Site { /// Very dumb for now, ideally it would only rebuild what changed pub fn rebuild(&mut self) -> Result<()> { self.parse_site()?; + self.templates.full_reload()?; self.build() } @@ -174,6 +201,7 @@ impl Site { let index = self.templates.render("index.html", &context)?; create_file(public.join("index.html"), &self.inject_livereload(index))?; + self.copy_static_directory()?; Ok(()) }