mirror of https://github.com/rwf2/Rocket.git
Avoid using 'glob' to walk templates directory.
Previously, `dyn_templates` walked the user-provided `template_dir` path by constructing a glob pattern prefixed with `template_dir`. If `template_dir` contained characters recognized by the glob pattern parser, then at best the pattern failed to parse, and at worst, incorrect directories were searched. This commit removes the use of `glob` to walk the templates directory and instead uses `walkdir`, obviating the issues described above. Fixes #2627.
This commit is contained in:
parent
f950d3e0ec
commit
ed5c755bb6
|
@ -17,7 +17,7 @@ tera = ["tera_"]
|
||||||
handlebars = ["handlebars_"]
|
handlebars = ["handlebars_"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
glob = "0.3"
|
walkdir = "2.4"
|
||||||
notify = "6"
|
notify = "6"
|
||||||
normpath = "1"
|
normpath = "1"
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,12 @@ impl Context {
|
||||||
/// template engine, and store all of the initialized state in a `Context`
|
/// template engine, and store all of the initialized state in a `Context`
|
||||||
/// structure, which is returned if all goes well.
|
/// structure, which is returned if all goes well.
|
||||||
pub fn initialize(root: &Path, callback: &Callback) -> Option<Context> {
|
pub fn initialize(root: &Path, callback: &Callback) -> Option<Context> {
|
||||||
|
fn is_file_with_ext(entry: &walkdir::DirEntry, ext: &str) -> bool {
|
||||||
|
let is_file = entry.file_type().is_file();
|
||||||
|
let has_ext = entry.path().extension().map_or(false, |e| e == ext);
|
||||||
|
is_file && has_ext
|
||||||
|
}
|
||||||
|
|
||||||
let root = match root.normalize() {
|
let root = match root.normalize() {
|
||||||
Ok(root) => root.into_path_buf(),
|
Ok(root) => root.into_path_buf(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -35,18 +41,23 @@ impl Context {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut templates: HashMap<String, TemplateInfo> = HashMap::new();
|
let mut templates: HashMap<String, TemplateInfo> = HashMap::new();
|
||||||
for ext in Engines::ENABLED_EXTENSIONS {
|
for &ext in Engines::ENABLED_EXTENSIONS {
|
||||||
let mut glob_path = root.join("**").join("*");
|
for entry in walkdir::WalkDir::new(&root).follow_links(true) {
|
||||||
glob_path.set_extension(ext);
|
let entry = match entry {
|
||||||
let glob_path = glob_path.to_str().expect("valid glob path string");
|
Ok(entry) if is_file_with_ext(&entry, ext) => entry,
|
||||||
|
Ok(_) | Err(_) => continue,
|
||||||
|
};
|
||||||
|
|
||||||
for path in glob::glob(glob_path).unwrap().filter_map(Result::ok) {
|
let (name, data_type_str) = split_path(&root, entry.path());
|
||||||
let (name, data_type_str) = split_path(&root, &path);
|
|
||||||
if let Some(info) = templates.get(&*name) {
|
if let Some(info) = templates.get(&*name) {
|
||||||
warn_!("Template name '{}' does not have a unique path.", name);
|
warn_!("Template name '{}' does not have a unique source.", name);
|
||||||
info_!("Existing path: {:?}", info.path);
|
match info.path {
|
||||||
info_!("Additional path: {:?}", path);
|
Some(ref path) => info_!("Existing path: {:?}", path),
|
||||||
warn_!("Using existing path for template '{}'.", name);
|
None => info_!("Existing Content-Type: {}", info.data_type),
|
||||||
|
}
|
||||||
|
|
||||||
|
info_!("Additional path: {:?}", entry.path());
|
||||||
|
warn_!("Keeping existing template '{}'.", name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +66,7 @@ impl Context {
|
||||||
.unwrap_or(ContentType::Text);
|
.unwrap_or(ContentType::Text);
|
||||||
|
|
||||||
templates.insert(name, TemplateInfo {
|
templates.insert(name, TemplateInfo {
|
||||||
path: Some(path.clone()),
|
path: Some(entry.into_path()),
|
||||||
engine_ext: ext,
|
engine_ext: ext,
|
||||||
data_type,
|
data_type,
|
||||||
});
|
});
|
||||||
|
|
|
@ -237,6 +237,16 @@ mod tera_tests {
|
||||||
assert_eq!(md_rendered, Some((ContentType::HTML, ESCAPED_EXPECTED.into())));
|
assert_eq!(md_rendered, Some((ContentType::HTML, ESCAPED_EXPECTED.into())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_test]
|
||||||
|
async fn test_globby_paths() {
|
||||||
|
use rocket::local::asynchronous::Client;
|
||||||
|
|
||||||
|
let client = Client::debug(rocket()).await.unwrap();
|
||||||
|
let req = client.get("/");
|
||||||
|
let metadata = Metadata::from_request(&req).await.unwrap();
|
||||||
|
assert!(metadata.contains_template("tera/[test]/html_test"));
|
||||||
|
}
|
||||||
|
|
||||||
// u128 is not supported. enable when it is.
|
// u128 is not supported. enable when it is.
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn test_tera_u128() {
|
// fn test_tera_u128() {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
{% extends "tera/base" %}
|
||||||
|
{% block title %}{{ title }}{% endblock title %}
|
||||||
|
{% block content %}
|
||||||
|
{{ content }}
|
||||||
|
{% endblock content %}
|
Loading…
Reference in New Issue