* serve command works from another working directory * Root dir path is expanded (canonicalized) for relative links (#1028) * Simplify watchers code * Only watch sass/themes folders when they are enabled in config Co-authored-by: southerntofu <southerntofu@thunix.net>
This commit is contained in:
parent
7e7bf2bcd3
commit
b003a47d54
|
@ -22,9 +22,8 @@
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
|
||||||
use std::fs::{read_dir, remove_dir_all};
|
use std::fs::{read_dir, remove_dir_all};
|
||||||
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
@ -58,6 +57,13 @@ enum ChangeKind {
|
||||||
Config,
|
Config,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
enum WatchMode {
|
||||||
|
Required,
|
||||||
|
Optional,
|
||||||
|
Condition(bool)
|
||||||
|
}
|
||||||
|
|
||||||
static INTERNAL_SERVER_ERROR_TEXT: &[u8] = b"Internal Server Error";
|
static INTERNAL_SERVER_ERROR_TEXT: &[u8] = b"Internal Server Error";
|
||||||
static METHOD_NOT_ALLOWED_TEXT: &[u8] = b"Method Not Allowed";
|
static METHOD_NOT_ALLOWED_TEXT: &[u8] = b"Method Not Allowed";
|
||||||
static NOT_FOUND_TEXT: &[u8] = b"Not Found";
|
static NOT_FOUND_TEXT: &[u8] = b"Not Found";
|
||||||
|
@ -234,43 +240,42 @@ pub fn serve(
|
||||||
)?;
|
)?;
|
||||||
console::report_elapsed_time(start);
|
console::report_elapsed_time(start);
|
||||||
|
|
||||||
|
// An array of (path, bool, bool) where the path should be watched for changes, and the boolean value
|
||||||
|
// indicates whether this file/folder must exist for zola serve to operate
|
||||||
|
let watch_this = vec!(
|
||||||
|
("config.toml", WatchMode::Required),
|
||||||
|
("content", WatchMode::Required),
|
||||||
|
("sass", WatchMode::Condition(site.config.compile_sass)),
|
||||||
|
("static", WatchMode::Optional),
|
||||||
|
("templates", WatchMode::Optional),
|
||||||
|
("themes", WatchMode::Condition(site.config.theme.is_some()))
|
||||||
|
);
|
||||||
|
|
||||||
// Setup watchers
|
// Setup watchers
|
||||||
let mut watching_static = false;
|
|
||||||
let mut watching_templates = false;
|
|
||||||
let mut watching_themes = false;
|
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
|
let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
|
||||||
watcher
|
|
||||||
.watch("content/", RecursiveMode::Recursive)
|
|
||||||
.map_err(|e| ZolaError::chain("Can't watch the `content` folder. Does it exist?", e))?;
|
|
||||||
watcher
|
|
||||||
.watch(config_file, RecursiveMode::Recursive)
|
|
||||||
.map_err(|e| ZolaError::chain("Can't watch the `config` file. Does it exist?", e))?;
|
|
||||||
|
|
||||||
if Path::new("static").exists() {
|
// We watch for changes on the filesystem for every entry in watch_this
|
||||||
watching_static = true;
|
// Will fail if either:
|
||||||
watcher
|
// - the path is mandatory but does not exist (eg. config.toml)
|
||||||
.watch("static/", RecursiveMode::Recursive)
|
// - the path exists but has incorrect permissions
|
||||||
.map_err(|e| ZolaError::chain("Can't watch the `static` folder.", e))?;
|
// watchers will contain the paths we're actually watching
|
||||||
|
let mut watchers = Vec::new();
|
||||||
|
for (entry, mode) in watch_this {
|
||||||
|
let watch_path = root_dir.join(entry);
|
||||||
|
let should_watch = match mode {
|
||||||
|
WatchMode::Required => true,
|
||||||
|
WatchMode::Optional => watch_path.exists(),
|
||||||
|
WatchMode::Condition(b) => b
|
||||||
|
};
|
||||||
|
if should_watch {
|
||||||
|
watcher
|
||||||
|
.watch(root_dir.join(entry), RecursiveMode::Recursive)
|
||||||
|
.map_err(|e| ZolaError::chain(format!("Can't watch `{}` for changes in folder `{}`. Do you have correct permissions?", entry, root_dir.display()), e))?;
|
||||||
|
watchers.push(entry.to_string());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if Path::new("templates").exists() {
|
|
||||||
watching_templates = true;
|
|
||||||
watcher
|
|
||||||
.watch("templates/", RecursiveMode::Recursive)
|
|
||||||
.map_err(|e| ZolaError::chain("Can't watch the `templates` folder.", e))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if Path::new("themes").exists() {
|
|
||||||
watching_themes = true;
|
|
||||||
watcher
|
|
||||||
.watch("themes/", RecursiveMode::Recursive)
|
|
||||||
.map_err(|e| ZolaError::chain("Can't watch the `themes` folder.", e))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sass support is optional so don't make it an error to no have a sass folder
|
|
||||||
let _ = watcher.watch("sass/", RecursiveMode::Recursive);
|
|
||||||
|
|
||||||
let ws_address = format!("{}:{}", interface, site.live_reload.unwrap());
|
let ws_address = format!("{}:{}", interface, site.live_reload.unwrap());
|
||||||
let output_path = Path::new(output_dir).to_path_buf();
|
let output_path = Path::new(output_dir).to_path_buf();
|
||||||
|
|
||||||
|
@ -339,26 +344,9 @@ pub fn serve(
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let pwd = env::current_dir().unwrap();
|
|
||||||
|
|
||||||
let mut watchers = vec!["content", "config.toml"];
|
|
||||||
if watching_static {
|
|
||||||
watchers.push("static");
|
|
||||||
}
|
|
||||||
if watching_templates {
|
|
||||||
watchers.push("templates");
|
|
||||||
}
|
|
||||||
if watching_themes {
|
|
||||||
watchers.push("themes");
|
|
||||||
}
|
|
||||||
if site.config.compile_sass {
|
|
||||||
watchers.push("sass");
|
|
||||||
}
|
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"Listening for changes in {}{}{{{}}}",
|
"Listening for changes in {}{{{}}}",
|
||||||
pwd.display(),
|
root_dir.display(),
|
||||||
MAIN_SEPARATOR,
|
|
||||||
watchers.join(", ")
|
watchers.join(", ")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -460,7 +448,7 @@ pub fn serve(
|
||||||
if path.is_file() && is_temp_file(&path) {
|
if path.is_file() && is_temp_file(&path) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let (change_kind, partial_path) = detect_change_kind(&pwd, &path);
|
let (change_kind, partial_path) = detect_change_kind(&root_dir, &path);
|
||||||
|
|
||||||
// We only care about changes in non-empty folders
|
// We only care about changes in non-empty folders
|
||||||
if path.is_dir() && is_folder_empty(&path) {
|
if path.is_dir() && is_folder_empty(&path) {
|
||||||
|
@ -522,7 +510,7 @@ pub fn serve(
|
||||||
);
|
);
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
match detect_change_kind(&pwd, &path) {
|
match detect_change_kind(&root_dir, &path) {
|
||||||
(ChangeKind::Content, _) => {
|
(ChangeKind::Content, _) => {
|
||||||
console::info(&format!("-> Content changed {}", path.display()));
|
console::info(&format!("-> Content changed {}", path.display()));
|
||||||
// Force refresh
|
// Force refresh
|
||||||
|
|
|
@ -14,7 +14,7 @@ fn main() {
|
||||||
|
|
||||||
let root_dir = match matches.value_of("root").unwrap() {
|
let root_dir = match matches.value_of("root").unwrap() {
|
||||||
"." => env::current_dir().unwrap(),
|
"." => env::current_dir().unwrap(),
|
||||||
path => PathBuf::from(path),
|
path => PathBuf::from(path).canonicalize().expect(&format!("Cannot find root directory: {}", path)),
|
||||||
};
|
};
|
||||||
let config_file = match matches.value_of("config") {
|
let config_file = match matches.value_of("config") {
|
||||||
Some(path) => PathBuf::from(path),
|
Some(path) => PathBuf::from(path),
|
||||||
|
|
Loading…
Reference in a new issue