omni_dev/cli/
git.rs

1//! Git-related CLI commands
2
3use anyhow::{Context, Result};
4use clap::{Parser, Subcommand};
5
6/// Git operations
7#[derive(Parser)]
8pub struct GitCommand {
9    /// Git subcommand to execute
10    #[command(subcommand)]
11    pub command: GitSubcommands,
12}
13
14/// Git subcommands
15#[derive(Subcommand)]
16pub enum GitSubcommands {
17    /// Commit-related operations
18    Commit(CommitCommand),
19}
20
21/// Commit operations
22#[derive(Parser)]
23pub struct CommitCommand {
24    /// Commit subcommand to execute
25    #[command(subcommand)]
26    pub command: CommitSubcommands,
27}
28
29/// Commit subcommands
30#[derive(Subcommand)]
31pub enum CommitSubcommands {
32    /// Commit message operations
33    Message(MessageCommand),
34}
35
36/// Message operations
37#[derive(Parser)]
38pub struct MessageCommand {
39    /// Message subcommand to execute
40    #[command(subcommand)]
41    pub command: MessageSubcommands,
42}
43
44/// Message subcommands
45#[derive(Subcommand)]
46pub enum MessageSubcommands {
47    /// Analyze commits and output repository information in YAML format
48    View(ViewCommand),
49    /// Amend commit messages based on a YAML configuration file
50    Amend(AmendCommand),
51}
52
53/// View command options
54#[derive(Parser)]
55pub struct ViewCommand {
56    /// Commit range to analyze (e.g., HEAD~3..HEAD, abc123..def456)
57    #[arg(value_name = "COMMIT_RANGE")]
58    pub commit_range: Option<String>,
59}
60
61/// Amend command options  
62#[derive(Parser)]
63pub struct AmendCommand {
64    /// YAML file containing commit amendments
65    #[arg(value_name = "YAML_FILE")]
66    pub yaml_file: String,
67}
68
69impl GitCommand {
70    /// Execute git command
71    pub fn execute(self) -> Result<()> {
72        match self.command {
73            GitSubcommands::Commit(commit_cmd) => commit_cmd.execute(),
74        }
75    }
76}
77
78impl CommitCommand {
79    /// Execute commit command
80    pub fn execute(self) -> Result<()> {
81        match self.command {
82            CommitSubcommands::Message(message_cmd) => message_cmd.execute(),
83        }
84    }
85}
86
87impl MessageCommand {
88    /// Execute message command
89    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    /// Execute view command
99    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        // Open git repository
106        let repo = GitRepository::open()
107            .context("Failed to open git repository. Make sure you're in a git repository.")?;
108
109        // Get working directory status
110        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        // Get remote information
124        let remotes = RemoteInfo::get_all_remotes(repo.repository())?;
125
126        // Parse commit range and get commits
127        let commits = repo.get_commits_in_range(commit_range)?;
128
129        // Build repository view
130        let repo_view = RepositoryView {
131            explanation: FieldExplanation::default(),
132            working_directory,
133            remotes,
134            commits,
135        };
136
137        // Output as YAML
138        let yaml_output = crate::data::to_yaml(&repo_view)?;
139        println!("{}", yaml_output);
140
141        Ok(())
142    }
143}
144
145impl AmendCommand {
146    /// Execute amend command
147    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        // Create amendment handler and apply amendments
154        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}