Skip to main content

git_spawn/command/
merge.rs

1//! `git merge` — join two or more development histories together.
2
3use crate::command::{CommandExecutor, CommandOutput, GitCommand};
4use crate::error::Result;
5use async_trait::async_trait;
6
7/// Builder for `git merge`.
8#[derive(Debug, Clone, Default)]
9pub struct MergeCommand {
10    /// Shared executor.
11    pub executor: CommandExecutor,
12    /// Commits/branches to merge.
13    pub commits: Vec<String>,
14    /// `--no-ff`.
15    pub no_ff: bool,
16    /// `--ff-only`.
17    pub ff_only: bool,
18    /// `--squash`.
19    pub squash: bool,
20    /// `--commit`.
21    pub commit: bool,
22    /// `--no-commit`.
23    pub no_commit: bool,
24    /// `-m`.
25    pub message: Option<String>,
26    /// `--strategy`.
27    pub strategy: Option<String>,
28    /// `--abort`.
29    pub abort: bool,
30    /// `--continue`.
31    pub cont: bool,
32    /// `--quiet`.
33    pub quiet: bool,
34}
35
36impl MergeCommand {
37    /// New `merge`.
38    #[must_use]
39    pub fn new() -> Self {
40        Self::default()
41    }
42
43    /// Add a commit to merge.
44    pub fn commit_ref(&mut self, c: impl Into<String>) -> &mut Self {
45        self.commits.push(c.into());
46        self
47    }
48
49    /// `--no-ff`.
50    pub fn no_ff(&mut self) -> &mut Self {
51        self.no_ff = true;
52        self
53    }
54
55    /// `--ff-only`.
56    pub fn ff_only(&mut self) -> &mut Self {
57        self.ff_only = true;
58        self
59    }
60
61    /// `--squash`.
62    pub fn squash(&mut self) -> &mut Self {
63        self.squash = true;
64        self
65    }
66
67    /// Always create a commit.
68    pub fn commit(&mut self) -> &mut Self {
69        self.commit = true;
70        self
71    }
72
73    /// Don't commit.
74    pub fn no_commit(&mut self) -> &mut Self {
75        self.no_commit = true;
76        self
77    }
78
79    /// Merge message.
80    pub fn message(&mut self, m: impl Into<String>) -> &mut Self {
81        self.message = Some(m.into());
82        self
83    }
84
85    /// Merge strategy.
86    pub fn strategy(&mut self, s: impl Into<String>) -> &mut Self {
87        self.strategy = Some(s.into());
88        self
89    }
90
91    /// Abort an in-progress merge.
92    pub fn abort(&mut self) -> &mut Self {
93        self.abort = true;
94        self
95    }
96
97    /// Continue an in-progress merge.
98    pub fn cont(&mut self) -> &mut Self {
99        self.cont = true;
100        self
101    }
102
103    /// `--quiet`.
104    pub fn quiet(&mut self) -> &mut Self {
105        self.quiet = true;
106        self
107    }
108}
109
110#[async_trait]
111impl GitCommand for MergeCommand {
112    type Output = CommandOutput;
113    fn get_executor(&self) -> &CommandExecutor {
114        &self.executor
115    }
116    fn get_executor_mut(&mut self) -> &mut CommandExecutor {
117        &mut self.executor
118    }
119    fn build_command_args(&self) -> Vec<String> {
120        let mut args = vec!["merge".to_string()];
121        if self.abort {
122            args.push("--abort".into());
123            return args;
124        }
125        if self.cont {
126            args.push("--continue".into());
127            return args;
128        }
129        if self.no_ff {
130            args.push("--no-ff".into());
131        }
132        if self.ff_only {
133            args.push("--ff-only".into());
134        }
135        if self.squash {
136            args.push("--squash".into());
137        }
138        if self.commit {
139            args.push("--commit".into());
140        }
141        if self.no_commit {
142            args.push("--no-commit".into());
143        }
144        if self.quiet {
145            args.push("--quiet".into());
146        }
147        if let Some(m) = &self.message {
148            args.push("-m".into());
149            args.push(m.clone());
150        }
151        if let Some(s) = &self.strategy {
152            args.push(format!("--strategy={s}"));
153        }
154        args.extend(self.commits.iter().cloned());
155        args
156    }
157    async fn execute(&self) -> Result<CommandOutput> {
158        self.execute_raw().await
159    }
160}