Skip to main content

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}