use std::{
fs,
path::{Path, PathBuf},
};
use anyhow::{Context, bail};
pub fn run(
source: PathBuf,
folder: String,
title: Option<String>,
id: Option<String>,
tags: Vec<String>,
force: bool,
) -> anyhow::Result<()> {
let root = crate::commands::root_dir()?;
let target = root.join(&source);
let title = title.unwrap_or_else(|| crate::commands::register::title_from_path(&source));
create_mdbook_skeleton(&target, &title, force)
.with_context(|| format!("failed to create mdBook at {}", source.display()))?;
let registered =
crate::commands::register::register_book(source, folder, Some(title), id, tags)?;
println!("created {}", target.display());
println!("added {}: {}", registered.id, registered.title);
Ok(())
}
fn create_mdbook_skeleton(path: &Path, title: &str, force: bool) -> anyhow::Result<()> {
if path.exists() {
if !path.is_dir() {
bail!("{} already exists and is not a directory", path.display());
}
if !force && !is_empty_dir(path)? {
bail!(
"{} already exists and is not empty; pass --force to write generated files",
path.display()
);
}
}
let src_dir = path.join("src");
fs::create_dir_all(&src_dir)
.with_context(|| format!("failed to create {}", src_dir.display()))?;
write_generated(
&path.join("book.toml"),
&format!("[book]\ntitle = {title:?}\n"),
force,
)?;
write_generated(
&src_dir.join("SUMMARY.md"),
"# Summary\n\n- [Introduction](./index.md)\n",
force,
)?;
write_generated(&src_dir.join("index.md"), &format!("# {title}\n"), force)?;
Ok(())
}
fn is_empty_dir(path: &Path) -> anyhow::Result<bool> {
Ok(fs::read_dir(path)
.with_context(|| format!("failed to read {}", path.display()))?
.next()
.is_none())
}
fn write_generated(path: &Path, contents: &str, force: bool) -> anyhow::Result<()> {
if path.exists() && !force {
bail!("{} already exists; pass --force to replace it", path.display());
}
fs::write(path, contents).with_context(|| format!("failed to write {}", path.display()))
}