Skip to content

Commit b003a47

Browse files
southerntofusoutherntofu
andauthored
Support relative links for root directory (fix #1028) (#1106)
* 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 <[email protected]>
1 parent 7e7bf2b commit b003a47

File tree

2 files changed

+43
-55
lines changed

2 files changed

+43
-55
lines changed

src/cmd/serve.rs

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,8 @@
2222
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2323

2424
use std::collections::HashMap;
25-
use std::env;
2625
use std::fs::{read_dir, remove_dir_all};
27-
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
26+
use std::path::{Path, PathBuf};
2827
use std::sync::mpsc::channel;
2928
use std::thread;
3029
use std::time::{Duration, Instant};
@@ -58,6 +57,13 @@ enum ChangeKind {
5857
Config,
5958
}
6059

60+
#[derive(Debug, PartialEq)]
61+
enum WatchMode {
62+
Required,
63+
Optional,
64+
Condition(bool)
65+
}
66+
6167
static INTERNAL_SERVER_ERROR_TEXT: &[u8] = b"Internal Server Error";
6268
static METHOD_NOT_ALLOWED_TEXT: &[u8] = b"Method Not Allowed";
6369
static NOT_FOUND_TEXT: &[u8] = b"Not Found";
@@ -234,43 +240,42 @@ pub fn serve(
234240
)?;
235241
console::report_elapsed_time(start);
236242

243+
// An array of (path, bool, bool) where the path should be watched for changes, and the boolean value
244+
// indicates whether this file/folder must exist for zola serve to operate
245+
let watch_this = vec!(
246+
("config.toml", WatchMode::Required),
247+
("content", WatchMode::Required),
248+
("sass", WatchMode::Condition(site.config.compile_sass)),
249+
("static", WatchMode::Optional),
250+
("templates", WatchMode::Optional),
251+
("themes", WatchMode::Condition(site.config.theme.is_some()))
252+
);
253+
237254
// Setup watchers
238-
let mut watching_static = false;
239-
let mut watching_templates = false;
240-
let mut watching_themes = false;
241255
let (tx, rx) = channel();
242256
let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
243-
watcher
244-
.watch("content/", RecursiveMode::Recursive)
245-
.map_err(|e| ZolaError::chain("Can't watch the `content` folder. Does it exist?", e))?;
246-
watcher
247-
.watch(config_file, RecursiveMode::Recursive)
248-
.map_err(|e| ZolaError::chain("Can't watch the `config` file. Does it exist?", e))?;
249-
250-
if Path::new("static").exists() {
251-
watching_static = true;
252-
watcher
253-
.watch("static/", RecursiveMode::Recursive)
254-
.map_err(|e| ZolaError::chain("Can't watch the `static` folder.", e))?;
255-
}
256-
257-
if Path::new("templates").exists() {
258-
watching_templates = true;
259-
watcher
260-
.watch("templates/", RecursiveMode::Recursive)
261-
.map_err(|e| ZolaError::chain("Can't watch the `templates` folder.", e))?;
262-
}
263257

264-
if Path::new("themes").exists() {
265-
watching_themes = true;
266-
watcher
267-
.watch("themes/", RecursiveMode::Recursive)
268-
.map_err(|e| ZolaError::chain("Can't watch the `themes` folder.", e))?;
258+
// We watch for changes on the filesystem for every entry in watch_this
259+
// Will fail if either:
260+
// - the path is mandatory but does not exist (eg. config.toml)
261+
// - the path exists but has incorrect permissions
262+
// watchers will contain the paths we're actually watching
263+
let mut watchers = Vec::new();
264+
for (entry, mode) in watch_this {
265+
let watch_path = root_dir.join(entry);
266+
let should_watch = match mode {
267+
WatchMode::Required => true,
268+
WatchMode::Optional => watch_path.exists(),
269+
WatchMode::Condition(b) => b
270+
};
271+
if should_watch {
272+
watcher
273+
.watch(root_dir.join(entry), RecursiveMode::Recursive)
274+
.map_err(|e| ZolaError::chain(format!("Can't watch `{}` for changes in folder `{}`. Do you have correct permissions?", entry, root_dir.display()), e))?;
275+
watchers.push(entry.to_string());
276+
}
269277
}
270278

271-
// Sass support is optional so don't make it an error to no have a sass folder
272-
let _ = watcher.watch("sass/", RecursiveMode::Recursive);
273-
274279
let ws_address = format!("{}:{}", interface, site.live_reload.unwrap());
275280
let output_path = Path::new(output_dir).to_path_buf();
276281

@@ -339,26 +344,9 @@ pub fn serve(
339344
None
340345
};
341346

342-
let pwd = env::current_dir().unwrap();
343-
344-
let mut watchers = vec!["content", "config.toml"];
345-
if watching_static {
346-
watchers.push("static");
347-
}
348-
if watching_templates {
349-
watchers.push("templates");
350-
}
351-
if watching_themes {
352-
watchers.push("themes");
353-
}
354-
if site.config.compile_sass {
355-
watchers.push("sass");
356-
}
357-
358347
println!(
359-
"Listening for changes in {}{}{{{}}}",
360-
pwd.display(),
361-
MAIN_SEPARATOR,
348+
"Listening for changes in {}{{{}}}",
349+
root_dir.display(),
362350
watchers.join(", ")
363351
);
364352

@@ -460,7 +448,7 @@ pub fn serve(
460448
if path.is_file() && is_temp_file(&path) {
461449
continue;
462450
}
463-
let (change_kind, partial_path) = detect_change_kind(&pwd, &path);
451+
let (change_kind, partial_path) = detect_change_kind(&root_dir, &path);
464452

465453
// We only care about changes in non-empty folders
466454
if path.is_dir() && is_folder_empty(&path) {
@@ -522,7 +510,7 @@ pub fn serve(
522510
);
523511

524512
let start = Instant::now();
525-
match detect_change_kind(&pwd, &path) {
513+
match detect_change_kind(&root_dir, &path) {
526514
(ChangeKind::Content, _) => {
527515
console::info(&format!("-> Content changed {}", path.display()));
528516
// Force refresh

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ fn main() {
1414

1515
let root_dir = match matches.value_of("root").unwrap() {
1616
"." => env::current_dir().unwrap(),
17-
path => PathBuf::from(path),
17+
path => PathBuf::from(path).canonicalize().expect(&format!("Cannot find root directory: {}", path)),
1818
};
1919
let config_file = match matches.value_of("config") {
2020
Some(path) => PathBuf::from(path),

0 commit comments

Comments
 (0)