Skip to content
This repository was archived by the owner on Aug 11, 2025. It is now read-only.

Commit 5e3c680

Browse files
committed
ABC123 fix(refactor): Add new function to handle interactive commit making the code easier to read and main won't be so cluttered
TODO: - [ ] All relevant automated tests (unit, integration) pass successfully. - [ ] New features or bug fixes are covered by appropriate new tests. - [ ] Relevant documentation (code comments, READMEs, etc.) is updated.
1 parent 8c54859 commit 5e3c680

1 file changed

Lines changed: 53 additions & 29 deletions

File tree

src/main.rs

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ struct DodConfig {
1313
checklist: Vec<String>,
1414
}
1515

16+
/// Reads the DoD configuration from `.dod.yml` file in the current directory (root of the git repository).
1617
fn read_dod_config() -> Result<DodConfig> {
1718
let content = fs::read_to_string(".dod.yml")
1819
.context("Failed to read .dod.yml")?;
@@ -21,6 +22,7 @@ fn read_dod_config() -> Result<DodConfig> {
2122
Ok(config)
2223
}
2324

25+
/// Runs the checklist interactively, allowing the user to confirm each item before committing.
2426
fn run_checklist_interactive(checklist: &[String]) -> anyhow::Result<Vec<usize>> {
2527
let selections = MultiSelect::with_theme(&ColorfulTheme::default())
2628
.with_prompt("Please confirm each item before committing:")
@@ -29,6 +31,7 @@ fn run_checklist_interactive(checklist: &[String]) -> anyhow::Result<Vec<usize>>
2931
Ok(selections)
3032
}
3133

34+
/// Builds the TODO footer for the commit message based on unchecked items in the checklist.
3235
fn build_todo_footer(checklist: &[String], checked_indices: &[usize]) -> String {
3336
//let checked_indices: Vec<usize> = checked_indices.iter().cloned().collect();
3437
let unchecked_items: Vec<String> = checklist
@@ -45,6 +48,40 @@ fn build_todo_footer(checklist: &[String], checked_indices: &[usize]) -> String
4548
}
4649
}
4750

51+
/// Handles the interactive commit process, including checklist confirmation and issue reference handling.
52+
fn handle_interactive_commit(
53+
config: &DodConfig,
54+
base_message: &str,
55+
issue: &Option<String>,
56+
) -> Result<Option<String>> {
57+
let mut commit_message = base_message.to_string();
58+
if let Some(issue_ref) = issue {
59+
commit_message = format!("{} {}", issue_ref, commit_message);
60+
}
61+
62+
let checked = run_checklist_interactive(&config.checklist)?;
63+
if checked.len() != config.checklist.len() {
64+
if Confirm::with_theme(&ColorfulTheme::default())
65+
.with_prompt("Warning: Not all DoD items were checked. Proceed by adding a 'TODO' list to the commit message?")
66+
.interact()?
67+
{
68+
let todo_footer = build_todo_footer(&config.checklist, &checked);
69+
commit_message.push_str(&todo_footer);
70+
} else {
71+
println!("Commit aborted.");
72+
return Ok(None);
73+
}
74+
}
75+
76+
if config.issue_reference_required.unwrap_or(false) && issue.is_none() {
77+
println!("{}", "Issue reference is required for commits.".red());
78+
return Err(anyhow::anyhow!("Aborted: Issue reference required."));
79+
}
80+
81+
Ok(Some(commit_message))
82+
}
83+
84+
/// Main function that parses command line arguments and executes the appropriate git operations.
4885
fn main() -> anyhow::Result<()> {
4986
let cli = cli::Cli::parse();
5087
let config = read_dod_config()?;
@@ -62,38 +99,25 @@ fn main() -> anyhow::Result<()> {
6299
println!("--- Committing changes ---");
63100
let scope_part = scope.map_or("".to_string(), |s| format!("({})", s));
64101
let header = format!("{}{}: {}", r#type, scope_part, message);
65-
let mut commit_message = format!("{}", header);
66-
if let Some(issue_ref) = &issue {
67-
commit_message = format!("{} {}", issue_ref, commit_message);
68-
}
69102

70-
if !no_verify {
71-
let checked = run_checklist_interactive(&config.checklist)?;
72-
if checked.len() != config.checklist.len() {
73-
if Confirm::with_theme(&ColorfulTheme::default())
74-
.with_prompt("Warning: Not all DoD items were checked. Proceed by adding a 'TODO' list to the commit message? (Y/n)")
75-
.interact()?
76-
{
77-
let todo_footer = build_todo_footer(&config.checklist, &checked);
78-
commit_message.push_str(&todo_footer);
79-
} else {
80-
println!("Commit aborted.");
81-
return Ok(());
82-
}
103+
let final_commit_message = if no_verify {
104+
let mut msg = header;
105+
if let Some(issue_ref) = &issue {
106+
msg = format!("{} {}", issue_ref, msg);
83107
}
84-
if config.issue_reference_required.unwrap_or(false) && issue.is_none() {
85-
println!("{}", "Issue reference is required for commits.".red());
86-
return Err(anyhow::anyhow!("Issue reference required"));
87-
}
88-
}
108+
Some(msg)
109+
} else {
110+
handle_interactive_commit(&config, &header, &issue)?
111+
};
89112

90-
println!("{}", format!("Commit message will be:\n---\n{}\n---", commit_message).blue());
91-
// Stage changes first, before any other operations.
92-
git::add_all()?;
93-
git::pull_latest_with_rebase()?;
94-
git::commit(&commit_message)?;
95-
git::push()?;
96-
println!("{}", "Successfully committed and pushed changes.".green());
113+
if let Some(commit_message) = final_commit_message {
114+
println!("{}", format!("Commit message will be:\n---\n{}\n---", commit_message).blue());
115+
git::add_all()?;
116+
git::pull_latest_with_rebase()?;
117+
git::commit(&commit_message)?;
118+
git::push()?;
119+
println!("{}", "Successfully committed and pushed changes.".green());
120+
}
97121
}
98122
}
99123
Ok(())

0 commit comments

Comments
 (0)