diff --git a/docs/content/documentation/getting-started/cli-usage.md b/docs/content/documentation/getting-started/cli-usage.md index a91daa1..16a64bc 100644 --- a/docs/content/documentation/getting-started/cli-usage.md +++ b/docs/content/documentation/getting-started/cli-usage.md @@ -14,10 +14,17 @@ Creates the directory structure used by Zola at the given directory. ```bash $ zola init my_site +$ zola init ``` -will create a new folder named `my_site` and the files/folders needed by -zola. +If the `my_site` folder already exists, Zola will only populate it if it does not contain non-hidden files (dotfiles are ignored). If no `my_site` argument is passed, Zola will try to populate the current directory. + +You can initialize a git repository and a Zola site directly from within a new folder: + +```bash +$ git init +$ zola init +``` ## build diff --git a/src/cli.rs b/src/cli.rs index c47710c..8951840 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -19,7 +19,7 @@ pub fn build_cli() -> App<'static, 'static> { .about("Create a new Zola project") .arg( Arg::with_name("name") - .required(true) + .default_value(".") .help("Name of the project. Will create a new directory with that name in the current directory") ), SubCommand::with_name("build") diff --git a/src/cmd/init.rs b/src/cmd/init.rs index b263482..a243c1a 100644 --- a/src/cmd/init.rs +++ b/src/cmd/init.rs @@ -25,14 +25,41 @@ build_search_index = %SEARCH% # Put all your custom variables here "#; +// Given a path, return true if it is a directory and it doesn't have any +// non-hidden files, otherwise return false (path is assumed to exist) +pub fn is_directory_quasi_empty(path: &Path) -> Result { + if path.is_dir() { + let mut entries = match path.read_dir() { + Ok(entries) => entries, + Err(e) => { bail!("Could not read `{}` because of error: {}", path.to_string_lossy().to_string(), e); } + }; + // If any entry raises an error or isn't hidden (i.e. starts with `.`), we raise an error + if entries.any(|x| match x { + Ok(file) => !file.file_name().to_str().expect("Could not convert filename to &str").starts_with("."), + Err(_) => true + }) { + return Ok(false) + } + return Ok(true) + } else { + return Ok(false) + } +} + pub fn create_new_project(name: &str) -> Result<()> { let path = Path::new(name); // Better error message than the rust default - if path.exists() && path.is_dir() { - bail!("Folder `{}` already exists", path.to_string_lossy().to_string()); + if path.exists() { + if !is_directory_quasi_empty(&path)? { + if name == "." { + bail!("The current directory is not an empty folder (hidden files are ignored)."); + } else { + bail!("`{}` is not an empty folder (hidden files are ignored).", path.to_string_lossy().to_string()) + } + } + } else { + create_dir(path)?; } - - create_dir(path)?; console::info("Welcome to Zola!"); let base_url = ask_url("> What is the URL of your site?", "https://example.com")?; @@ -66,3 +93,57 @@ pub fn create_new_project(name: &str) -> Result<()> { println!("Visit https://www.getzola.org for the full documentation."); Ok(()) } + +#[cfg(test)] +mod tests { + use std::env::temp_dir; + use std::fs::{create_dir,remove_dir,remove_dir_all}; + use super::*; + + #[test] + fn init_empty_directory() { + let mut dir = temp_dir(); + dir.push("test_empty_dir"); + if dir.exists() { + remove_dir_all(&dir).expect("Could not free test directory"); + } + create_dir(&dir).expect("Could not create test directory"); + let allowed = is_directory_quasi_empty(&dir).expect("An error happened reading the directory's contents"); + remove_dir(&dir).unwrap(); + assert_eq!(true, allowed); + } + + #[test] + fn init_non_empty_directory() { + let mut dir = temp_dir(); + dir.push("test_non_empty_dir"); + if dir.exists() { + remove_dir_all(&dir).expect("Could not free test directory"); + } + create_dir(&dir).expect("Could not create test directory"); + let mut content = dir.clone(); + content.push("content"); + create_dir(&content).unwrap(); + let allowed = is_directory_quasi_empty(&dir).expect("An error happened reading the directory's contents"); + remove_dir(&content).unwrap(); + remove_dir(&dir).unwrap(); + assert_eq!(false, allowed); + } + + #[test] + fn init_quasi_empty_directory() { + let mut dir = temp_dir(); + dir.push("test_quasi_empty_dir"); + if dir.exists() { + remove_dir_all(&dir).expect("Could not free test directory"); + } + create_dir(&dir).expect("Could not create test directory"); + let mut git = dir.clone(); + git.push(".git"); + create_dir(&git).unwrap(); + let allowed = is_directory_quasi_empty(&dir).expect("An error happened reading the directory's contents"); + remove_dir(&git).unwrap(); + remove_dir(&dir).unwrap(); + assert_eq!(true, allowed); + } +}