1use anyhow::{Context, Result};
4use clap::{Parser, Subcommand};
5
6#[derive(Parser)]
8pub struct GitCommand {
9 #[command(subcommand)]
11 pub command: GitSubcommands,
12}
13
14#[derive(Subcommand)]
16pub enum GitSubcommands {
17 Commit(CommitCommand),
19}
20
21#[derive(Parser)]
23pub struct CommitCommand {
24 #[command(subcommand)]
26 pub command: CommitSubcommands,
27}
28
29#[derive(Subcommand)]
31pub enum CommitSubcommands {
32 Message(MessageCommand),
34}
35
36#[derive(Parser)]
38pub struct MessageCommand {
39 #[command(subcommand)]
41 pub command: MessageSubcommands,
42}
43
44#[derive(Subcommand)]
46pub enum MessageSubcommands {
47 View(ViewCommand),
49 Amend(AmendCommand),
51}
52
53#[derive(Parser)]
55pub struct ViewCommand {
56 #[arg(value_name = "COMMIT_RANGE")]
58 pub commit_range: Option<String>,
59}
60
61#[derive(Parser)]
63pub struct AmendCommand {
64 #[arg(value_name = "YAML_FILE")]
66 pub yaml_file: String,
67}
68
69impl GitCommand {
70 pub fn execute(self) -> Result<()> {
72 match self.command {
73 GitSubcommands::Commit(commit_cmd) => commit_cmd.execute(),
74 }
75 }
76}
77
78impl CommitCommand {
79 pub fn execute(self) -> Result<()> {
81 match self.command {
82 CommitSubcommands::Message(message_cmd) => message_cmd.execute(),
83 }
84 }
85}
86
87impl MessageCommand {
88 pub fn execute(self) -> Result<()> {
90 match self.command {
91 MessageSubcommands::View(view_cmd) => view_cmd.execute(),
92 MessageSubcommands::Amend(amend_cmd) => amend_cmd.execute(),
93 }
94 }
95}
96
97impl ViewCommand {
98 pub fn execute(self) -> Result<()> {
100 use crate::data::{FieldExplanation, FileStatusInfo, RepositoryView, WorkingDirectoryInfo};
101 use crate::git::{GitRepository, RemoteInfo};
102
103 let commit_range = self.commit_range.as_deref().unwrap_or("HEAD");
104
105 let repo = GitRepository::open()
107 .context("Failed to open git repository. Make sure you're in a git repository.")?;
108
109 let wd_status = repo.get_working_directory_status()?;
111 let working_directory = WorkingDirectoryInfo {
112 clean: wd_status.clean,
113 untracked_changes: wd_status
114 .untracked_changes
115 .into_iter()
116 .map(|fs| FileStatusInfo {
117 status: fs.status,
118 file: fs.file,
119 })
120 .collect(),
121 };
122
123 let remotes = RemoteInfo::get_all_remotes(repo.repository())?;
125
126 let commits = repo.get_commits_in_range(commit_range)?;
128
129 let repo_view = RepositoryView {
131 explanation: FieldExplanation::default(),
132 working_directory,
133 remotes,
134 commits,
135 };
136
137 let yaml_output = crate::data::to_yaml(&repo_view)?;
139 println!("{}", yaml_output);
140
141 Ok(())
142 }
143}
144
145impl AmendCommand {
146 pub fn execute(self) -> Result<()> {
148 use crate::git::AmendmentHandler;
149
150 println!("🔄 Starting commit amendment process...");
151 println!("📄 Loading amendments from: {}", self.yaml_file);
152
153 let handler = AmendmentHandler::new().context("Failed to initialize amendment handler")?;
155
156 handler
157 .apply_amendments(&self.yaml_file)
158 .context("Failed to apply amendments")?;
159
160 Ok(())
161 }
162}