Add ignored_static to config (#2209)
* Add ignored_static to config * Make handle ignored static files correctly * cargo fmt * Match on relative path rather than incorrect target path * path -> partial path for serve static ignore * remove debug println * copy static directory if there is no ignored globset * Update docs * Deduplicate code with additional Option argument * cargo fmt
This commit is contained in:
parent
35aab566f9
commit
4430515a02
@ -28,6 +28,18 @@ pub enum Mode {
|
||||
Check,
|
||||
}
|
||||
|
||||
fn build_ignore_glob_set(ignore: &Vec<String>, name: &str) -> Result<GlobSet> {
|
||||
let mut glob_set_builder = GlobSetBuilder::new();
|
||||
for pat in ignore {
|
||||
let glob = match Glob::new(pat) {
|
||||
Ok(g) => g,
|
||||
Err(e) => bail!("Invalid ignored_{} glob pattern: {}, error = {}", name, pat, e),
|
||||
};
|
||||
glob_set_builder.add(glob);
|
||||
}
|
||||
Ok(glob_set_builder.build().expect(&format!("Bad ignored_{} in config file.", name)))
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct Config {
|
||||
@ -74,6 +86,11 @@ pub struct Config {
|
||||
#[serde(skip_serializing, skip_deserializing)] // not a typo, 2 are needed
|
||||
pub ignored_content_globset: Option<GlobSet>,
|
||||
|
||||
/// A list of file glob patterns to ignore when processing the static folder. Defaults to none.
|
||||
pub ignored_static: Vec<String>,
|
||||
#[serde(skip_serializing, skip_deserializing)] // not a typo, 2 are needed
|
||||
pub ignored_static_globset: Option<GlobSet>,
|
||||
|
||||
/// The mode Zola is currently being ran on. Some logging/feature can differ depending on the
|
||||
/// command being used.
|
||||
#[serde(skip_serializing)]
|
||||
@ -140,16 +157,13 @@ impl Config {
|
||||
// globset matcher to always exist (even though it has to be an inside an Option at the
|
||||
// moment because of the TOML serializer); if the glob set is empty the `is_match` function
|
||||
// of the globber always returns false.
|
||||
let mut glob_set_builder = GlobSetBuilder::new();
|
||||
for pat in &config.ignored_content {
|
||||
let glob = match Glob::new(pat) {
|
||||
Ok(g) => g,
|
||||
Err(e) => bail!("Invalid ignored_content glob pattern: {}, error = {}", pat, e),
|
||||
};
|
||||
glob_set_builder.add(glob);
|
||||
}
|
||||
config.ignored_content_globset =
|
||||
Some(glob_set_builder.build().expect("Bad ignored_content in config file."));
|
||||
let glob_set = build_ignore_glob_set(&config.ignored_content, "content")?;
|
||||
config.ignored_content_globset = Some(glob_set);
|
||||
}
|
||||
|
||||
if !config.ignored_static.is_empty() {
|
||||
let glob_set = build_ignore_glob_set(&config.ignored_static, "static")?;
|
||||
config.ignored_static_globset = Some(glob_set);
|
||||
}
|
||||
|
||||
Ok(config)
|
||||
@ -386,6 +400,8 @@ impl Default for Config {
|
||||
build_search_index: false,
|
||||
ignored_content: Vec::new(),
|
||||
ignored_content_globset: None,
|
||||
ignored_static: Vec::new(),
|
||||
ignored_static_globset: None,
|
||||
translations: HashMap::new(),
|
||||
output_dir: "public".to_string(),
|
||||
preserve_dotfiles_in_output: false,
|
||||
@ -648,6 +664,18 @@ base_url = "example.com"
|
||||
assert!(config.ignored_content_globset.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_ignored_static_results_in_empty_vector_and_empty_globset() {
|
||||
let config_str = r#"
|
||||
title = "My site"
|
||||
base_url = "example.com"
|
||||
"#;
|
||||
let config = Config::parse(config_str).unwrap();
|
||||
let v = config.ignored_static;
|
||||
assert_eq!(v.len(), 0);
|
||||
assert!(config.ignored_static_globset.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_ignored_content_results_in_empty_vector_and_empty_globset() {
|
||||
let config_str = r#"
|
||||
@ -661,6 +689,19 @@ ignored_content = []
|
||||
assert!(config.ignored_content_globset.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_ignored_static_results_in_empty_vector_and_empty_globset() {
|
||||
let config_str = r#"
|
||||
title = "My site"
|
||||
base_url = "example.com"
|
||||
ignored_static = []
|
||||
"#;
|
||||
|
||||
let config = Config::parse(config_str).unwrap();
|
||||
assert_eq!(config.ignored_static.len(), 0);
|
||||
assert!(config.ignored_static_globset.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_empty_ignored_content_results_in_vector_of_patterns_and_configured_globset() {
|
||||
let config_str = r#"
|
||||
@ -690,6 +731,35 @@ ignored_content = ["*.{graphml,iso}", "*.py?", "**/{target,temp_folder}"]
|
||||
assert!(g.is_match("content/poetry/zen.py2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_empty_ignored_static_results_in_vector_of_patterns_and_configured_globset() {
|
||||
let config_str = r#"
|
||||
title = "My site"
|
||||
base_url = "example.com"
|
||||
ignored_static = ["*.{graphml,iso}", "*.py?", "**/{target,temp_folder}"]
|
||||
"#;
|
||||
|
||||
let config = Config::parse(config_str).unwrap();
|
||||
let v = config.ignored_static;
|
||||
assert_eq!(v, vec!["*.{graphml,iso}", "*.py?", "**/{target,temp_folder}"]);
|
||||
|
||||
let g = config.ignored_static_globset.unwrap();
|
||||
assert_eq!(g.len(), 3);
|
||||
assert!(g.is_match("foo.graphml"));
|
||||
assert!(g.is_match("foo/bar/foo.graphml"));
|
||||
assert!(g.is_match("foo.iso"));
|
||||
assert!(!g.is_match("foo.png"));
|
||||
assert!(g.is_match("foo.py2"));
|
||||
assert!(g.is_match("foo.py3"));
|
||||
assert!(!g.is_match("foo.py"));
|
||||
assert!(g.is_match("foo/bar/target"));
|
||||
assert!(g.is_match("foo/bar/baz/temp_folder"));
|
||||
assert!(g.is_match("foo/bar/baz/temp_folder/target"));
|
||||
assert!(g.is_match("temp_folder"));
|
||||
assert!(g.is_match("my/isos/foo.iso"));
|
||||
assert!(g.is_match("content/poetry/zen.py2"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn link_checker_skip_anchor_prefixes() {
|
||||
let config_str = r#"
|
||||
|
||||
@ -587,11 +587,26 @@ impl Site {
|
||||
&self.base_path.join("themes").join(theme).join("static"),
|
||||
&self.output_path,
|
||||
false,
|
||||
None,
|
||||
)?;
|
||||
}
|
||||
// We're fine with missing static folders
|
||||
if self.static_path.exists() {
|
||||
copy_directory(&self.static_path, &self.output_path, self.config.hard_link_static)?;
|
||||
if let Some(gs) = &self.config.ignored_static_globset {
|
||||
copy_directory(
|
||||
&self.static_path,
|
||||
&self.output_path,
|
||||
self.config.hard_link_static,
|
||||
Some(gs),
|
||||
)?;
|
||||
} else {
|
||||
copy_directory(
|
||||
&self.static_path,
|
||||
&self.output_path,
|
||||
self.config.hard_link_static,
|
||||
None,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use libs::filetime::{set_file_mtime, FileTime};
|
||||
use libs::globset::GlobSet;
|
||||
use libs::walkdir::WalkDir;
|
||||
use std::fs::{copy, create_dir_all, metadata, remove_dir_all, remove_file, File};
|
||||
use std::io::prelude::*;
|
||||
@ -115,11 +116,23 @@ pub fn copy_file_if_needed(src: &Path, dest: &Path, hard_link: bool) -> Result<(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn copy_directory(src: &Path, dest: &Path, hard_link: bool) -> Result<()> {
|
||||
pub fn copy_directory(
|
||||
src: &Path,
|
||||
dest: &Path,
|
||||
hard_link: bool,
|
||||
ignore_globset: Option<&GlobSet>,
|
||||
) -> Result<()> {
|
||||
for entry in
|
||||
WalkDir::new(src).follow_links(true).into_iter().filter_map(std::result::Result::ok)
|
||||
{
|
||||
let relative_path = entry.path().strip_prefix(src).unwrap();
|
||||
|
||||
if let Some(gs) = ignore_globset {
|
||||
if gs.is_match(&relative_path) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let target_path = dest.join(relative_path);
|
||||
|
||||
if entry.path().is_dir() {
|
||||
|
||||
@ -59,6 +59,11 @@ minify_html = false
|
||||
# ignored_content = ["*.{graphml,xlsx}", "temp.*", "**/build_folder"]
|
||||
ignored_content = []
|
||||
|
||||
# Similar to ignored_content, a list of glob patterns specifying asset files to
|
||||
# ignore when the static directory is processed. Defaults to none, which means
|
||||
# that all asset files are copied over to the `public` directory
|
||||
ignored_static = []
|
||||
|
||||
# When set to "true", a feed is automatically generated.
|
||||
generate_feed = false
|
||||
|
||||
|
||||
@ -561,6 +561,12 @@ pub fn serve(
|
||||
};
|
||||
|
||||
let copy_static = |site: &Site, path: &Path, partial_path: &Path| {
|
||||
// Do nothing if the file/dir is on the ignore list
|
||||
if let Some(gs) = &site.config.ignored_static_globset {
|
||||
if gs.is_match(partial_path) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Do nothing if the file/dir was deleted
|
||||
if !path.exists() {
|
||||
return;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user