Browse Source

zola init works inside existing directories (closes #406) (#777)

* zola init works without argument (defaults to current directory)

* zola init works with existing folders (no non-hidden files permitted)

* Update zola init documentation

* [docs] Optional argument is on a separate line for clarity

* Add tests for init subcommand's respect of existing folders
index-subcmd
southerntofu Vincent Prouillet 5 years ago
parent
commit
13b395b536
3 changed files with 95 additions and 7 deletions
  1. +9
    -2
      docs/content/documentation/getting-started/cli-usage.md
  2. +1
    -1
      src/cli.rs
  3. +85
    -4
      src/cmd/init.rs

+ 9
- 2
docs/content/documentation/getting-started/cli-usage.md View File

@@ -14,10 +14,17 @@ Creates the directory structure used by Zola at the given directory.


```bash ```bash
$ zola init my_site $ 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 ## build




+ 1
- 1
src/cli.rs View File

@@ -19,7 +19,7 @@ pub fn build_cli() -> App<'static, 'static> {
.about("Create a new Zola project") .about("Create a new Zola project")
.arg( .arg(
Arg::with_name("name") 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") .help("Name of the project. Will create a new directory with that name in the current directory")
), ),
SubCommand::with_name("build") SubCommand::with_name("build")


+ 85
- 4
src/cmd/init.rs View File

@@ -25,14 +25,41 @@ build_search_index = %SEARCH%
# Put all your custom variables here # 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<bool> {
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<()> { pub fn create_new_project(name: &str) -> Result<()> {
let path = Path::new(name); let path = Path::new(name);
// Better error message than the rust default // 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!"); console::info("Welcome to Zola!");


let base_url = ask_url("> What is the URL of your site?", "https://example.com")?; 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."); println!("Visit https://www.getzola.org for the full documentation.");
Ok(()) 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);
}
}

Loading…
Cancel
Save