Added prompt for when zola build output-dir mentions an existing directory. (#1558)

* Next version

* Added ask prompt for output-dir flag

Added `ask_bool` prompt for `--output-dir` for when the output directory
targeted already exists in the file system.

[Issue: #1378]

* Updated the documentation for #1378

* Added missing "sure" in prompt text

* Added timeout to prompt + dirname

* Fixed complication errors

Co-authored-by: Vincent Prouillet <balthek@gmail.com>
This commit is contained in:
Gijs Burghoorn 2021-09-04 08:10:02 +02:00 committed by GitHub
parent 5c428cc141
commit eceb1bd79d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 48 additions and 3 deletions

View file

@ -1,5 +1,6 @@
# Changelog # Changelog
## 0.15.0 ## 0.15.0

View file

@ -28,7 +28,7 @@ termcolor = "1.0.4"
url = "2" url = "2"
# Below is for the serve cmd # Below is for the serve cmd
hyper = { version = "0.14.1", default-features = false, features = ["runtime", "server", "http2", "http1"] } hyper = { version = "0.14.1", default-features = false, features = ["runtime", "server", "http2", "http1"] }
tokio = { version = "1.0.1", default-features = false, features = ["rt", "fs"] } tokio = { version = "1.0.1", default-features = false, features = ["rt", "fs", "time"] }
percent-encoding = "2" percent-encoding = "2"
notify = "4" notify = "4"
ws = "0.9" ws = "0.9"

View file

@ -46,7 +46,7 @@ $ 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 output directory `public` by passing another value to the `output-dir` flag (if this directory already exists, it is deleted). You can override the default output directory `public` by passing another value to the `output-dir` flag (if this directory already exists, the user will be prompted whether to replace the folder).
```bash ```bash
$ zola build --output-dir $DOCUMENT_ROOT $ zola build --output-dir $DOCUMENT_ROOT

View file

@ -1,9 +1,12 @@
use std::path::Path; use std::path::Path;
use errors::Result; use errors::{Error, Result};
use site::Site; use site::Site;
use crate::console; use crate::console;
use crate::prompt::ask_bool_timeout;
const BUILD_PROMPT_TIMEOUT_MILLIS: u64 = 10_000;
pub fn build( pub fn build(
root_dir: &Path, root_dir: &Path,
@ -14,6 +17,27 @@ pub fn build(
) -> Result<()> { ) -> Result<()> {
let mut site = Site::new(root_dir, config_file)?; let mut site = Site::new(root_dir, config_file)?;
if let Some(output_dir) = output_dir { if let Some(output_dir) = output_dir {
// Check whether output directory exists or not
// This way we don't replace already existing files.
if output_dir.exists() {
console::warn(&format!("The directory '{}' already exists. Building to this directory will delete files contained within this directory.", output_dir.display()));
// Prompt the user to ask whether they want to continue.
let clear_dir = tokio::runtime::Runtime::new()
.expect("Tokio runtime failed to instantiate")
.block_on(ask_bool_timeout(
"Are you sure you want to continue?",
false,
std::time::Duration::from_millis(BUILD_PROMPT_TIMEOUT_MILLIS),
))?;
if !clear_dir {
return Err(Error::msg(
"Cancelled build process because output directory already exists.",
));
}
}
site.set_output_path(output_dir); site.set_output_path(output_dir);
} }
if let Some(b) = base_url { if let Some(b) = base_url {

View file

@ -1,8 +1,10 @@
use std::io::{self, BufRead, Write}; use std::io::{self, BufRead, Write};
use std::time::Duration;
use url::Url; use url::Url;
use errors::Result; use errors::Result;
use crate::console;
/// Wait for user input and return what they typed /// Wait for user input and return what they typed
fn read_line() -> Result<String> { fn read_line() -> Result<String> {
@ -32,6 +34,24 @@ pub fn ask_bool(question: &str, default: bool) -> Result<bool> {
} }
} }
/// Ask a yes/no question to the user with a timeout
pub async fn ask_bool_timeout(question: &str, default: bool, timeout: Duration) -> Result<bool> {
let (tx, rx) = tokio::sync::oneshot::channel();
let q = question.to_string();
std::thread::spawn(move || {
tx.send(ask_bool(&q, default)).unwrap();
});
match tokio::time::timeout(timeout, rx).await {
Err(_) => {
console::warn("\nWaited too long for response.");
Ok(default)
}
Ok(val) => val.expect("Tokio failed to properly execute"),
}
}
/// Ask a question to the user where they can write a URL /// Ask a question to the user where they can write a URL
pub fn ask_url(question: &str, default: &str) -> Result<String> { pub fn ask_url(question: &str, default: &str) -> Result<String> {
print!("{} ({}): ", question, default); print!("{} ({}): ", question, default);