From 9acb70442f579af95f12455ff51c732d30037ad6 Mon Sep 17 00:00:00 2001 From: Erle Carrara Date: Tue, 18 Apr 2017 02:07:02 -0300 Subject: [PATCH] Copy only modified files in static directory (#27) Copy only static files that triggered the change notification --- src/cmd/serve.rs | 6 ++++-- src/site.rs | 43 ++++++++++++++++++++++--------------------- src/utils.rs | 1 - 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/cmd/serve.rs b/src/cmd/serve.rs index 606858f..936b185 100644 --- a/src/cmd/serve.rs +++ b/src/cmd/serve.rs @@ -134,8 +134,10 @@ pub fn serve(interface: &str, port: &str, config_file: &str) -> Result<()> { rebuild_done_handling(&broadcaster, site.rebuild_after_template_change(), "/x.js"); }, (ChangeKind::StaticFiles, p) => { - console::info(&format!("-> Static file changes detected {}", path.display())); - rebuild_done_handling(&broadcaster, site.copy_static_directory(), &p); + if path.is_file() { + console::info(&format!("-> Static file changes detected {}", path.display())); + rebuild_done_handling(&broadcaster, site.copy_static_file(&path), &p); + } }, }; report_elapsed_time(start); diff --git a/src/site.rs b/src/site.rs index 5060212..09371a4 100644 --- a/src/site.rs +++ b/src/site.rs @@ -1,6 +1,6 @@ use std::collections::{BTreeMap, HashMap}; use std::iter::FromIterator; -use std::fs::{remove_dir_all, copy, remove_file}; +use std::fs::{remove_dir_all, copy, create_dir_all}; use std::path::{Path, PathBuf}; use glob::glob; @@ -67,6 +67,7 @@ pub struct Site { pub tera: Tera, live_reload: bool, output_path: PathBuf, + static_path: PathBuf, pub tags: HashMap>, pub categories: HashMap>, } @@ -91,7 +92,8 @@ impl Site { sections: BTreeMap::new(), tera: tera, live_reload: false, - output_path: PathBuf::from("public"), + output_path: path.join("public"), + static_path: path.join("static"), tags: HashMap::new(), categories: HashMap::new(), }; @@ -223,31 +225,30 @@ impl Site { html } + /// Copy static file to public directory. + pub fn copy_static_file>(&self, path: P) -> Result<()> { + let relative_path = path.as_ref().strip_prefix(&self.static_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 `static` folder into the `public` folder - /// - /// TODO: only copy one file if possible because that would be a waste - /// to do re-copy the whole thing. Benchmark first to see if it's a big difference 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 - }; + for entry in WalkDir::new(&self.static_path).into_iter().filter_map(|e| e.ok()) { + let relative_path = entry.path().strip_prefix(&self.static_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 { - if target_path.exists() { - remove_file(&target_path)?; - } - copy(entry.path(), &target_path)?; + let entry_fullpath = self.base_path.join(entry.path()); + self.copy_static_file(entry_fullpath)?; } } Ok(()) @@ -255,9 +256,9 @@ impl Site { /// Deletes the `public` directory if it exists pub fn clean(&self) -> Result<()> { - if Path::new("public").exists() { + if self.output_path.exists() { // Delete current `public` directory so we can start fresh - remove_dir_all("public").chain_err(|| "Couldn't delete `public` directory")?; + remove_dir_all(&self.output_path).chain_err(|| "Couldn't delete `public` directory")?; } Ok(()) diff --git a/src/utils.rs b/src/utils.rs index 6574c6f..ed37417 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -58,7 +58,6 @@ pub fn find_content_components>(path: P) -> Vec { components } - #[cfg(test)] mod tests { use super::{find_content_components};