clean output folder without removing dotfiles

This commit is contained in:
Gambhiro 2017-01-18 13:13:38 +00:00
parent a8021eb4e8
commit cb861a7354
3 changed files with 70 additions and 20 deletions

View File

@ -6,6 +6,7 @@ use book::toc::{TocItem, TocContent};
use utils;
use FILES;
use std::process::exit;
use std::path::{Path, PathBuf};
use std::ffi::OsStr;
use std::fs::{self, File};
@ -35,15 +36,16 @@ impl Renderer for HtmlHandlebars {
let mut book_project = MDBook::new(&project_root);
book_project.read_config();
if !book_project.get_src_base().exists() {
println!("Source folder doesn't exist: {:?}", book_project.get_src_base());
exit(2);
}
book_project.parse_books();
book_project.link_translations();
// Clean output directory
// FIXME don't remove dotfiles such as .git/ folder. It's a common
// practice to track gh-pages in a versioned output folder.
//try!(utils::fs::remove_dir_content(&book_project.get_dest_base()));
try!(utils::fs::clean_output_dir(&book_project.get_dest_base()));
// TODO talk to the user
try!(self.render(&book_project));

View File

@ -1,5 +1,6 @@
#[cfg(test)]
use std;
use std::fs::{self, File};
use std::io::Read;
use std::path::Path;
@ -8,7 +9,9 @@ use utils;
#[test]
fn it_copies_data_file() {
let dest_path = Path::new("the place was dark").join("and dusty and half-lost").join("book.css");
let dest_base = std::env::temp_dir().join("in tangles of old alleys");
let dest_path = dest_base.join("book.css");
utils::fs::copy_data_file("data/_html-template/css/books.css", &dest_path);
let mut file = match File::open(&dest_path) {
@ -26,11 +29,15 @@ fn it_copies_data_file() {
}
assert!(content.as_str().contains("Open Sans"));
if dest_base.exists() {
fs::remove_dir_all(dest_base);
}
}
#[test]
fn it_copies_data_by_pattern() {
let dest_base = Path::new("in tangles of old alleys").join("near the quays");
let dest_base = std::env::temp_dir().join("near the quays");
if let Err(e) = utils::fs::copy_data("data/_html-template/**/*",
"data/_html-template/",
@ -43,8 +50,32 @@ fn it_copies_data_by_pattern() {
assert!(dest_base.join("css").join("book.css").exists());
assert!(!dest_base.join("_layouts").exists());
let p = Path::new("in tangles of old alleys");
if p.exists() {
fs::remove_dir_all(p);
if dest_base.exists() {
fs::remove_dir_all(dest_base);
}
}
#[test]
fn it_doesnt_delete_toplevel_dotfiles() {
let dest_base = std::env::temp_dir().join("with queer curls of fog");
match utils::fs::create_with_str(&dest_base.join(".dotfile"), "that west winds tossed") {
Err(e) => { println!("Error: {:#?}", e); return; },
Ok(_) => {},
}
match utils::fs::create_with_str(&dest_base.join("door.html"), "<p>I entered, charmed</p>") {
Err(e) => { println!("Error: {:#?}", e); return; },
Ok(_) => {},
}
utils::fs::clean_output_dir(&dest_base);
assert!(dest_base.exists());
assert!(dest_base.join(".dotfile").exists());
assert!(!dest_base.join("door.html").exists());
if dest_base.exists() {
fs::remove_dir_all(dest_base);
}
}

View File

@ -89,6 +89,7 @@ pub fn copy_data(include_glob: &str,
.map(|x| {
let mut s: &str = &x.replace(include_base, "");
s = s.trim_left_matches("/");
s = s.trim_left_matches(r"\");
let p = Path::new(s);
let dest_path = dest_base.join(p);
@ -242,21 +243,37 @@ pub fn create_file(path: &Path) -> Result<File, Box<Error>> {
Ok(f)
}
// TODO why not just delete the folder and re-create it?
/// Removes all the content of a directory but not the directory itself
pub fn remove_dir_content(dir: &Path) -> Result<(), Box<Error>> {
/// A cleaning operation intended to be used on the output directory of a book
/// before producing new output files. It removes the content of the directory,
/// except for dotfiles at the toplevel.
///
/// This keeps VCS files intact such as `.git/, .gitignore`, and the output
/// folder can be used to track the gh-pages branch of the repository, which is
/// a common practice.
pub fn clean_output_dir(dir: &Path) -> Result<(), Box<Error>> {
if !dir.exists() {
return Ok(());
}
let exclude_pat = Pattern::new(".*").unwrap();
for item in try!(fs::read_dir(dir)) {
if let Ok(item) = item {
let item = item.path();
if item.is_dir() {
try!(fs::remove_dir_all(item));
if let Some(a) = item.path().to_str() {
if let Some(d) = dir.as_os_str().to_str() {
let mut s: &str = &a.replace(d, "");
s = s.trim_left_matches("/");
s = s.trim_left_matches(r"\");
if !exclude_pat.matches(s) {
let p = item.path();
if p.is_dir() {
try!(fs::remove_dir_all(p));
} else {
try!(fs::remove_file(item));
try!(fs::remove_file(p));
}
}
}
}
}
}