Skip to main content

git_proc/
worktree.rs

1use std::path::Path;
2
3use crate::CommandError;
4
5/// Create a new `git worktree list` command builder.
6#[must_use]
7pub fn list() -> List<'static> {
8    List::new()
9}
10
11/// Create a new `git worktree add` command builder.
12#[must_use]
13pub fn add(path: &Path) -> Add<'_> {
14    Add::new(path)
15}
16
17/// Create a new `git worktree remove` command builder.
18#[must_use]
19pub fn remove(worktree: &Path) -> Remove<'_> {
20    Remove::new(worktree)
21}
22
23/// Builder for `git worktree list` command.
24///
25/// See `git worktree --help` for full documentation.
26#[derive(Debug)]
27pub struct List<'a> {
28    repo_path: Option<&'a Path>,
29    porcelain: bool,
30}
31
32crate::impl_repo_path!(List);
33crate::impl_porcelain!(List);
34
35impl<'a> List<'a> {
36    #[must_use]
37    fn new() -> Self {
38        Self {
39            repo_path: None,
40            porcelain: false,
41        }
42    }
43}
44
45impl Default for List<'_> {
46    fn default() -> Self {
47        Self::new()
48    }
49}
50
51impl crate::Build for List<'_> {
52    fn build(self) -> cmd_proc::Command {
53        crate::base_command(self.repo_path)
54            .argument("worktree")
55            .argument("list")
56            .optional_flag(self.porcelain, "--porcelain")
57    }
58}
59
60#[cfg(feature = "test-utils")]
61impl List<'_> {
62    /// Compare the built command with another command using debug representation.
63    pub fn test_eq(&self, other: &cmd_proc::Command) {
64        let command = crate::Build::build(Self {
65            repo_path: self.repo_path,
66            porcelain: self.porcelain,
67        });
68        command.test_eq(other);
69    }
70}
71
72/// Builder for `git worktree add` command.
73///
74/// See `git worktree --help` for full documentation.
75#[derive(Debug)]
76pub struct Add<'a> {
77    repo_path: Option<&'a Path>,
78    path: &'a Path,
79    branch: Option<&'a str>,
80    new_branch: Option<&'a str>,
81    commit_ish: Option<&'a str>,
82}
83
84crate::impl_repo_path!(Add);
85
86impl<'a> Add<'a> {
87    #[must_use]
88    fn new(path: &'a Path) -> Self {
89        Self {
90            repo_path: None,
91            path,
92            branch: None,
93            new_branch: None,
94            commit_ish: None,
95        }
96    }
97
98    /// Checkout existing branch in the new worktree.
99    #[must_use]
100    pub fn branch(mut self, branch: &'a str) -> Self {
101        self.branch = Some(branch);
102        self
103    }
104
105    /// Create a new branch and checkout in the new worktree.
106    ///
107    /// Corresponds to `-b <branch>`.
108    #[must_use]
109    pub fn new_branch(mut self, branch: &'a str) -> Self {
110        self.new_branch = Some(branch);
111        self
112    }
113
114    /// Set the commit-ish to create the worktree from.
115    #[must_use]
116    pub fn commit_ish(mut self, commit_ish: &'a str) -> Self {
117        self.commit_ish = Some(commit_ish);
118        self
119    }
120
121    /// Execute the command and return the exit status.
122    pub async fn status(self) -> Result<(), CommandError> {
123        crate::Build::build(self).status().await
124    }
125}
126
127impl crate::Build for Add<'_> {
128    fn build(self) -> cmd_proc::Command {
129        crate::base_command(self.repo_path)
130            .argument("worktree")
131            .argument("add")
132            .optional_option("-b", self.new_branch)
133            .argument(self.path)
134            .optional_argument(self.branch)
135            .optional_argument(self.commit_ish)
136    }
137}
138
139#[cfg(feature = "test-utils")]
140impl Add<'_> {
141    /// Compare the built command with another command using debug representation.
142    pub fn test_eq(&self, other: &cmd_proc::Command) {
143        let command = crate::Build::build(Self {
144            repo_path: self.repo_path,
145            path: self.path,
146            branch: self.branch,
147            new_branch: self.new_branch,
148            commit_ish: self.commit_ish,
149        });
150        command.test_eq(other);
151    }
152}
153
154/// Builder for `git worktree remove` command.
155///
156/// See `git worktree --help` for full documentation.
157#[derive(Debug)]
158pub struct Remove<'a> {
159    repo_path: Option<&'a Path>,
160    worktree: &'a Path,
161    force: bool,
162}
163
164crate::impl_repo_path!(Remove);
165
166impl<'a> Remove<'a> {
167    #[must_use]
168    fn new(worktree: &'a Path) -> Self {
169        Self {
170            repo_path: None,
171            worktree,
172            force: false,
173        }
174    }
175
176    crate::flag_methods! {
177        /// Force removal even if worktree is dirty.
178        ///
179        /// Corresponds to `--force`.
180        pub fn force / force_if, force, "Conditionally force removal."
181    }
182
183    /// Execute the command and return the exit status.
184    pub async fn status(self) -> Result<(), CommandError> {
185        crate::Build::build(self).status().await
186    }
187}
188
189impl crate::Build for Remove<'_> {
190    fn build(self) -> cmd_proc::Command {
191        crate::base_command(self.repo_path)
192            .argument("worktree")
193            .argument("remove")
194            .optional_flag(self.force, "--force")
195            .argument(self.worktree)
196    }
197}
198
199#[cfg(feature = "test-utils")]
200impl Remove<'_> {
201    /// Compare the built command with another command using debug representation.
202    pub fn test_eq(&self, other: &cmd_proc::Command) {
203        let command = crate::Build::build(Self {
204            repo_path: self.repo_path,
205            worktree: self.worktree,
206            force: self.force,
207        });
208        command.test_eq(other);
209    }
210}