Allow default base-path command line option to be set for building and serving

This commit is contained in:
Blake Smith 2019-03-23 20:14:01 -05:00
parent 97e796a724
commit 1815155c1d
7 changed files with 66 additions and 20 deletions

1
Cargo.lock generated
View File

@ -1,5 +1,6 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]] [[package]]
name = "MacTypes-sys" name = "MacTypes-sys"
version = "2.1.0" version = "2.1.0"

View File

@ -66,7 +66,7 @@ pub struct Site {
impl Site { impl Site {
/// Parse a site at the given path. Defaults to the current dir /// Parse a site at the given path. Defaults to the current dir
/// Passing in a path is only used in tests /// Passing in a path is possible using the `base-path` command line build option
pub fn new<P: AsRef<Path>>(path: P, config_file: &str) -> Result<Site> { pub fn new<P: AsRef<Path>>(path: P, config_file: &str) -> Result<Site> {
let path = path.as_ref(); let path = path.as_ref();
let mut config = get_config(path, config_file); let mut config = get_config(path, config_file);

View File

@ -36,6 +36,14 @@ $ zola build --base-url $DEPLOY_URL
This is useful for example when you want to deploy previews of a site to a dynamic URL, such as Netlify This is useful for example when you want to deploy previews of a site to a dynamic URL, such as Netlify
deploy previews. deploy previews.
You can override the default `base_path` by passing a new directory to the `base-path` flag. If no `base-path` flag
is provided, zola defaults to your current working directory. This is useful if your zola project is located in
a different directory from where you're executing zola from.
```bash
$ zola build --base-path /path/to/zola/site
```
You can override the default output directory 'public' by passing a other value to the `output-dir` flag. You can override the default output directory 'public' by passing a other value to the `output-dir` flag.
```bash ```bash
@ -67,6 +75,7 @@ $ zola serve --interface 0.0.0.0
$ zola serve --interface 0.0.0.0 --port 2000 $ zola serve --interface 0.0.0.0 --port 2000
$ zola serve --interface 0.0.0.0 --base-url 127.0.0.1 $ zola serve --interface 0.0.0.0 --base-url 127.0.0.1
$ zola serve --interface 0.0.0.0 --port 2000 --output-dir www/public $ zola serve --interface 0.0.0.0 --port 2000 --output-dir www/public
$ zola serve --interface 0.0.0.0 --port 2000 --base-path mysite/ --output-dir mysite/www/public
$ zola serve --watch-only $ zola serve --watch-only
``` ```

View File

@ -30,6 +30,11 @@ pub fn build_cli() -> App<'static, 'static> {
.long("base-url") .long("base-url")
.takes_value(true) .takes_value(true)
.help("Force the base URL to be that value (default to the one in config.toml)"), .help("Force the base URL to be that value (default to the one in config.toml)"),
Arg::with_name("base_path")
.short("b")
.long("base-path")
.takes_value(true)
.help("Force the base site path to a certain directory [default: the current working directory]"),
Arg::with_name("output_dir") Arg::with_name("output_dir")
.short("o") .short("o")
.long("output-dir") .long("output-dir")
@ -56,6 +61,11 @@ pub fn build_cli() -> App<'static, 'static> {
.default_value("public") .default_value("public")
.takes_value(true) .takes_value(true)
.help("Outputs the generated site in the given path"), .help("Outputs the generated site in the given path"),
Arg::with_name("base_path")
.short("b")
.long("base-path")
.takes_value(true)
.help("Force the base site path to a certain directory [default: the current working directory]"),
Arg::with_name("base_url") Arg::with_name("base_url")
.short("u") .short("u")
.long("base-url") .long("base-url")

View File

@ -1,12 +1,19 @@
use std::env; use std::env;
use std::path::PathBuf;
use errors::Result; use errors::Result;
use site::Site; use site::Site;
use console; use console;
pub fn build(config_file: &str, base_url: Option<&str>, output_dir: &str) -> Result<()> { pub fn build(
let mut site = Site::new(env::current_dir().unwrap(), config_file)?; config_file: &str,
base_path: Option<&str>,
base_url: Option<&str>,
output_dir: &str,
) -> Result<()> {
let bp = base_path.map(PathBuf::from).unwrap_or(env::current_dir().unwrap());
let mut site = Site::new(bp, config_file)?;
site.set_output_path(output_dir); site.set_output_path(output_dir);
if let Some(b) = base_url { if let Some(b) = base_url {
site.set_base_url(b.to_string()); site.set_base_url(b.to_string());

View File

@ -114,14 +114,15 @@ fn rebuild_done_handling(broadcaster: &Option<Sender>, res: Result<()>, reload_p
} }
} }
fn create_new_site( fn create_new_site<P: AsRef<Path>>(
interface: &str, interface: &str,
port: u16, port: u16,
output_dir: &str, output_dir: &str,
base_path: P,
base_url: &str, base_url: &str,
config_file: &str, config_file: &str,
) -> Result<(Site, String)> { ) -> Result<(Site, String)> {
let mut site = Site::new(env::current_dir().unwrap(), config_file)?; let mut site = Site::new(base_path, config_file)?;
let base_address = format!("{}:{}", base_url, port); let base_address = format!("{}:{}", base_url, port);
let address = format!("{}:{}", interface, port); let address = format!("{}:{}", interface, port);
@ -166,12 +167,15 @@ pub fn serve(
interface: &str, interface: &str,
port: u16, port: u16,
output_dir: &str, output_dir: &str,
base_path: Option<&str>,
base_url: &str, base_url: &str,
config_file: &str, config_file: &str,
watch_only: bool, watch_only: bool,
) -> Result<()> { ) -> Result<()> {
let start = Instant::now(); let start = Instant::now();
let (mut site, address) = create_new_site(interface, port, output_dir, base_url, config_file)?; let bp = base_path.map(PathBuf::from).unwrap_or(env::current_dir().unwrap());
let (mut site, address) =
create_new_site(interface, port, output_dir, bp.clone(), base_url, config_file)?;
console::report_elapsed_time(start); console::report_elapsed_time(start);
// Setup watchers // Setup watchers
@ -180,28 +184,28 @@ pub fn serve(
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 watcher
.watch("content/", RecursiveMode::Recursive) .watch(bp.join("content/"), RecursiveMode::Recursive)
.map_err(|e| ZolaError::chain("Can't watch the `content` folder. Does it exist?", e))?; .map_err(|e| ZolaError::chain("Can't watch the `content` folder. Does it exist?", e))?;
watcher watcher
.watch(config_file, RecursiveMode::Recursive) .watch(bp.join(config_file), RecursiveMode::Recursive)
.map_err(|e| ZolaError::chain("Can't watch the `config` file. Does it exist?", e))?; .map_err(|e| ZolaError::chain("Can't watch the `config` file. Does it exist?", e))?;
if Path::new("static").exists() { if bp.join("static").exists() {
watching_static = true; watching_static = true;
watcher watcher
.watch("static/", RecursiveMode::Recursive) .watch(bp.join("static/"), RecursiveMode::Recursive)
.map_err(|e| ZolaError::chain("Can't watch the `static` folder.", e))?; .map_err(|e| ZolaError::chain("Can't watch the `static` folder.", e))?;
} }
if Path::new("templates").exists() { if bp.join("templates").exists() {
watching_templates = true; watching_templates = true;
watcher watcher
.watch("templates/", RecursiveMode::Recursive) .watch(bp.join("templates/"), RecursiveMode::Recursive)
.map_err(|e| ZolaError::chain("Can't watch the `templates` folder.", e))?; .map_err(|e| ZolaError::chain("Can't watch the `templates` folder.", e))?;
} }
// Sass support is optional so don't make it an error to no have a sass folder // Sass support is optional so don't make it an error to no have a sass folder
let _ = watcher.watch("sass/", RecursiveMode::Recursive); let _ = watcher.watch(bp.join("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();
@ -258,8 +262,6 @@ pub fn serve(
None None
}; };
let pwd = env::current_dir().unwrap();
let mut watchers = vec!["content", "config.toml"]; let mut watchers = vec!["content", "config.toml"];
if watching_static { if watching_static {
watchers.push("static"); watchers.push("static");
@ -273,7 +275,7 @@ pub fn serve(
println!( println!(
"Listening for changes in {}{}{{{}}}", "Listening for changes in {}{}{{{}}}",
pwd.display(), bp.display(),
MAIN_SEPARATOR, MAIN_SEPARATOR,
watchers.join(", ") watchers.join(", ")
); );
@ -349,7 +351,8 @@ 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(&bp.canonicalize().unwrap(), &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) {
@ -381,6 +384,7 @@ pub fn serve(
interface, interface,
port, port,
output_dir, output_dir,
bp.clone(),
base_url, base_url,
config_file, config_file,
) )
@ -401,7 +405,7 @@ pub fn serve(
); );
let start = Instant::now(); let start = Instant::now();
match detect_change_kind(&pwd, &path) { match detect_change_kind(&bp.canonicalize().unwrap(), &path) {
(ChangeKind::Content, _) => { (ChangeKind::Content, _) => {
console::info(&format!("-> Content changed {}", path.display())); console::info(&format!("-> Content changed {}", path.display()));
// Force refresh // Force refresh
@ -420,6 +424,7 @@ pub fn serve(
interface, interface,
port, port,
output_dir, output_dir,
bp.clone(),
base_url, base_url,
config_file, config_file,
) )

View File

@ -46,7 +46,12 @@ fn main() {
console::info("Building site..."); console::info("Building site...");
let start = Instant::now(); let start = Instant::now();
let output_dir = matches.value_of("output_dir").unwrap(); let output_dir = matches.value_of("output_dir").unwrap();
match cmd::build(config_file, matches.value_of("base_url"), output_dir) { match cmd::build(
config_file,
matches.value_of("base_path"),
matches.value_of("base_url"),
output_dir,
) {
Ok(()) => console::report_elapsed_time(start), Ok(()) => console::report_elapsed_time(start),
Err(e) => { Err(e) => {
console::unravel_errors("Failed to build the site", &e); console::unravel_errors("Failed to build the site", &e);
@ -79,9 +84,18 @@ fn main() {
} }
let watch_only = matches.is_present("watch_only"); let watch_only = matches.is_present("watch_only");
let output_dir = matches.value_of("output_dir").unwrap(); let output_dir = matches.value_of("output_dir").unwrap();
let base_path = matches.value_of("base_path");
let base_url = matches.value_of("base_url").unwrap(); let base_url = matches.value_of("base_url").unwrap();
console::info("Building site..."); console::info("Building site...");
match cmd::serve(interface, port, output_dir, base_url, config_file, watch_only) { match cmd::serve(
interface,
port,
output_dir,
base_path,
base_url,
config_file,
watch_only,
) {
Ok(()) => (), Ok(()) => (),
Err(e) => { Err(e) => {
console::unravel_errors("", &e); console::unravel_errors("", &e);