prdoclib/commands/
generate.rs

1//! Implementation of the generate command. This command generates a new PRDoc file.
2
3use crate::{
4	common::PRNumber,
5	doc_filename::DocFileName,
6	docfile::DocFile,
7	error::{self, PRdocLibError},
8	schema::PRDOC_DEFAULT_DIR,
9	title::Title,
10	utils::*,
11};
12use std::path::{Path, PathBuf};
13
14/// Wrapper to the generate command
15pub struct GenerateCmd;
16
17impl GenerateCmd {
18	fn get_output_dir(output_dir: Option<PathBuf>) -> PathBuf {
19		if let Some(dir) = output_dir {
20			dir
21		} else {
22			match get_project_root() {
23				Ok(dir) => dir.join(PRDOC_DEFAULT_DIR),
24				Err(e) => {
25					eprint!("Project root not found, falling back to the current folder: {e:?}");
26					PathBuf::from("../..")
27				},
28			}
29		}
30	}
31
32	/// Run of the generate command
33	pub fn run(
34		dry_run: bool,
35		number: PRNumber,
36		title: Option<Title>,
37		output_dir: Option<PathBuf>,
38		template: PathBuf,
39	) -> error::Result<()> {
40		let template = DocFile::generate(template)?;
41
42		if dry_run {
43			// print to stdout or save to file
44			log::debug!("Printing to stdout only due to --dry-run");
45			println!("{}", &template);
46			Ok(())
47		} else {
48			// generate filename based on number and title
49			let filename: PathBuf = DocFileName::new(number, title).into();
50			let output_dir = Self::get_output_dir(output_dir);
51			log::debug!("Storing prdoc in {output_dir:?}");
52			std::fs::create_dir_all(&output_dir).unwrap_or_else(|why| {
53				println!("! {:?}", why.kind());
54			});
55
56			let output_file = Path::new(&output_dir).join(filename);
57			log::debug!("output_file = {:?}", &output_file);
58
59			if !output_file.exists() {
60				std::fs::write(output_file, template).map_err(PRdocLibError::IO)
61			} else {
62				Err(PRdocLibError::FileAlreadyExists(output_file.clone()))
63			}
64		}
65	}
66}