1use calm_io::stdout;
2use camino::Utf8PathBuf;
3use clap::CommandFactory;
4use miette::miette;
5use miette::IntoDiagnostic;
6
7use crate::add::WorktreePlan;
8use crate::app_git::AppGit;
9use crate::cli;
10use crate::cli::ConfigCommand;
11use crate::cli::ConfigInitArgs;
12use crate::config::Config;
13use crate::convert::ConvertPlan;
14use crate::convert::ConvertPlanOpts;
15use crate::fs;
16use crate::git::Git;
17
18pub struct App {
19 config: Config,
20}
21
22impl App {
23 pub fn new(config: Config) -> Self {
24 Self { config }
25 }
26
27 pub fn git(&self) -> miette::Result<AppGit<'_, Utf8PathBuf>> {
28 Ok(Git::from_current_dir()?.with_config(&self.config))
29 }
30
31 pub fn run(self) -> miette::Result<()> {
32 match &self.config.cli.command {
33 cli::Command::Completions { shell } => {
34 let mut clap_command = cli::Cli::command();
35 clap_complete::generate(
36 *shell,
37 &mut clap_command,
38 "git-prole",
39 &mut std::io::stdout(),
40 );
41 }
42 #[cfg(feature = "clap_mangen")]
43 cli::Command::Manpages { out_dir } => {
44 use miette::Context;
45 let clap_command = cli::Cli::command();
46 clap_mangen::generate_to(clap_command, out_dir)
47 .into_diagnostic()
48 .wrap_err("Failed to generate man pages")?;
49 }
50 cli::Command::Convert(args) => ConvertPlan::new(
51 self.git()?,
52 ConvertPlanOpts {
53 default_branch: args.default_branch.clone(),
54 destination: args.destination.clone(),
55 },
56 )?
57 .execute()?,
58 cli::Command::Clone(args) => crate::clone::clone(self.git()?, args.to_owned())?,
59 cli::Command::Add(args) => WorktreePlan::new(self.git()?, args)?.execute()?,
60 cli::Command::Config(ConfigCommand::Init(args)) => self.config_init(args.to_owned())?,
61 }
62
63 Ok(())
64 }
65
66 fn config_init(&self, args: ConfigInitArgs) -> miette::Result<()> {
67 let path = match &args.output {
68 Some(path) => {
69 if path == "-" {
70 stdout!("{}", Config::DEFAULT).into_diagnostic()?;
71 return Ok(());
72 } else {
73 path
74 }
75 }
76 None => &self.config.path,
77 };
78
79 if path.exists() {
80 return Err(miette!("Default configuration file already exists: {path}"));
81 }
82
83 tracing::info!(
84 %path,
85 "Writing default configuration file"
86 );
87
88 if let Some(parent) = path.parent() {
89 fs::create_dir_all(parent)?;
90 }
91
92 fs::write(path, Config::DEFAULT)?;
93
94 Ok(())
95 }
96}