From 8a737d71fb4152939b0654ae5f257bb0c8f2e192 Mon Sep 17 00:00:00 2001 From: Jakub Turski Date: Wed, 10 Jul 2019 22:37:19 +0100 Subject: [PATCH] Add an option to hard link files from static/ instead of copying. (#723) * Add hard_link_static config option. * Copy or hardlink file depending on an argument. Modify the call sites for `copy_file` to account for the extra argument. * Plug the config setting through to copy_file. Don't apply the config option to theme's static directory. * Update documentation. * Backticks make no sense in this comment. * Addressing PR comments. * Be consistent with argument naming. --- components/config/src/config.rs | 3 +++ components/site/src/lib.rs | 3 ++- components/utils/src/fs.rs | 12 ++++++++---- .../documentation/getting-started/configuration.md | 6 ++++++ .../getting-started/directory-structure.md | 2 ++ src/cmd/serve.rs | 2 +- 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/components/config/src/config.rs b/components/config/src/config.rs index 1f37192..34c8c48 100644 --- a/components/config/src/config.rs +++ b/components/config/src/config.rs @@ -106,6 +106,8 @@ pub struct Config { pub generate_rss: bool, /// The number of articles to include in the RSS feed. Defaults to including all items. pub rss_limit: Option, + /// If set, files from static/ will be hardlinked instead of copied to the output dir. + pub hard_link_static: bool, pub taxonomies: Vec, @@ -280,6 +282,7 @@ impl Default for Config { languages: Vec::new(), generate_rss: false, rss_limit: None, + hard_link_static: false, taxonomies: Vec::new(), compile_sass: false, check_external_links: false, diff --git a/components/site/src/lib.rs b/components/site/src/lib.rs index d87226e..57eb215 100644 --- a/components/site/src/lib.rs +++ b/components/site/src/lib.rs @@ -597,11 +597,12 @@ impl Site { copy_directory( &self.base_path.join("themes").join(theme).join("static"), &self.output_path, + false )?; } // We're fine with missing static folders if self.static_path.exists() { - copy_directory(&self.static_path, &self.output_path)?; + copy_directory(&self.static_path, &self.output_path, self.config.hard_link_static)?; } Ok(()) diff --git a/components/utils/src/fs.rs b/components/utils/src/fs.rs index 20298cb..646f092 100644 --- a/components/utils/src/fs.rs +++ b/components/utils/src/fs.rs @@ -95,7 +95,7 @@ pub fn find_related_assets(path: &Path) -> Vec { /// 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<()> { +pub fn copy_file(src: &Path, dest: &PathBuf, base_path: &PathBuf, hard_link: bool) -> Result<()> { let relative_path = src.strip_prefix(base_path).unwrap(); let target_path = dest.join(relative_path); @@ -103,11 +103,15 @@ pub fn copy_file(src: &Path, dest: &PathBuf, base_path: &PathBuf) -> Result<()> create_dir_all(parent_directory)?; } - copy(src, target_path)?; + if hard_link { + std::fs::hard_link(src, target_path)? + } else { + copy(src, target_path)?; + } Ok(()) } -pub fn copy_directory(src: &PathBuf, dest: &PathBuf) -> Result<()> { +pub fn copy_directory(src: &PathBuf, dest: &PathBuf, hard_link: bool) -> Result<()> { for entry in WalkDir::new(src).into_iter().filter_map(std::result::Result::ok) { let relative_path = entry.path().strip_prefix(src).unwrap(); let target_path = dest.join(relative_path); @@ -117,7 +121,7 @@ pub fn copy_directory(src: &PathBuf, dest: &PathBuf) -> Result<()> { create_directory(&target_path)?; } } else { - copy_file(entry.path(), dest, src)?; + copy_file(entry.path(), dest, src, hard_link)?; } } Ok(()) diff --git a/docs/content/documentation/getting-started/configuration.md b/docs/content/documentation/getting-started/configuration.md index 462f8cd..4a1b022 100644 --- a/docs/content/documentation/getting-started/configuration.md +++ b/docs/content/documentation/getting-started/configuration.md @@ -41,6 +41,12 @@ generate_rss = false # not set (the default). # rss_limit = 20 +# Whether to copy or hardlink files in static/ directory. Useful for sites +# whose static files are large. Note that for this to work, both static/ and +# output directory need to be on the same filesystem. Also, theme's static/ +# files are always copies, regardles of this setting. False by default. +# hard_link_static = false + # The taxonomies to be rendered for that site and their configuration # Example: # taxonomies = [ diff --git a/docs/content/documentation/getting-started/directory-structure.md b/docs/content/documentation/getting-started/directory-structure.md index 015fa6e..0bf979e 100644 --- a/docs/content/documentation/getting-started/directory-structure.md +++ b/docs/content/documentation/getting-started/directory-structure.md @@ -38,6 +38,8 @@ The directory structure of the `sass` folder will be preserved when copying over ## `static` Contains any kind of files. All the files/folders in the `static` folder will be copied as-is in the output directory. +If your static files are large you can configure Zola to [hard link](https://en.wikipedia.org/wiki/Hard_link) them +instead of copying by setting `hard_link_static = true` in the config file. ## `templates` Contains all the [Tera](https://tera.netlify.com) templates that will be used to render this site. diff --git a/src/cmd/serve.rs b/src/cmd/serve.rs index 7582e3b..ab6cbef 100644 --- a/src/cmd/serve.rs +++ b/src/cmd/serve.rs @@ -325,7 +325,7 @@ pub fn serve( } else { rebuild_done_handling( &broadcaster, - copy_file(&path, &site.output_path, &site.static_path), + copy_file(&path, &site.output_path, &site.static_path, site.config.hard_link_static), &partial_path.to_string_lossy(), ); }