lattice_vcs/commit.rs
1use crate::{Repository, Result, VcsError};
2
3/// Commit operations — create and amend commits.
4///
5/// Uses the git CLI.
6pub struct Commit;
7
8impl Commit {
9 /// Create a new commit with the given message.
10 ///
11 /// Only staged changes are committed. Equivalent to
12 /// `git commit -m <message>`.
13 pub fn create(repo: &Repository, message: &str) -> Result<()> {
14 repo.run_git(["commit", "-m", message])
15 .map(|_| ())
16 .map_err(|e| VcsError::Index(format!("commit create: {}", e)))
17 }
18
19 /// Amend the most recent commit, replacing its message and
20 /// incorporating any currently staged changes.
21 ///
22 /// Equivalent to `git commit --amend -m <message>`.
23 pub fn amend(repo: &Repository, message: &str) -> Result<()> {
24 repo.run_git(["commit", "--amend", "-m", message])
25 .map(|_| ())
26 .map_err(|e| VcsError::Index(format!("commit amend: {}", e)))
27 }
28
29 /// MG.42-E1: record a `squash!` marker for `target` carrying the
30 /// user's own note — magit's `A` augment.
31 ///
32 /// `--squash` with `-m` is additive, not conflicting: git writes
33 /// `squash! <subject>` as the first line and appends the message
34 /// below it. That is precisely augment's semantics — a squash the
35 /// author annotated — so no second commit step is needed.
36 pub fn augment(repo: &Repository, target: &str, message: &str) -> Result<()> {
37 repo.run_git(["commit", &format!("--squash={target}"), "-m", message])
38 .map(|_| ())
39 .map_err(|e| VcsError::Index(format!("commit augment: {}", e)))
40 }
41
42 /// MG.42-E1: merge `branch` with a message the user wrote — magit's
43 /// merge `e` edit.
44 ///
45 /// Genuinely different from the `n` don't-commit row: this
46 /// completes the merge in one step with an authored message, rather
47 /// than leaving a staged merge for a separate commit.
48 pub fn merge_with_message(repo: &Repository, branch: &str, message: &str) -> Result<()> {
49 repo.run_git(["merge", "-m", message, branch])
50 .map(|_| ())
51 .map_err(|e| VcsError::Index(format!("merge: {}", e)))
52 }
53
54 /// MG.42-E1: replace the last commit's MESSAGE ONLY, leaving the
55 /// index alone — magit's `w` reword.
56 ///
57 /// `--only` is the whole difference from [`Self::amend`]. Without
58 /// it, anything currently staged is swept into the commit being
59 /// reworded, which is a content change the user did not ask for
60 /// and would not see coming from a row labelled "reword".
61 pub fn reword(repo: &Repository, message: &str) -> Result<()> {
62 repo.run_git(["commit", "--amend", "--only", "-m", message])
63 .map(|_| ())
64 .map_err(|e| VcsError::Index(format!("commit reword: {}", e)))
65 }
66}