Skip to main content

git_spawn/command/
checkout.rs

1//! `git checkout` — switch branches or restore working tree files.
2
3use crate::command::{CommandExecutor, CommandOutput, GitCommand};
4use crate::error::Result;
5use async_trait::async_trait;
6
7/// Builder for `git checkout`.
8#[derive(Debug, Clone, Default)]
9pub struct CheckoutCommand {
10    /// Shared executor.
11    pub executor: CommandExecutor,
12    /// Target branch, commit, or tree-ish.
13    pub target: Option<String>,
14    /// `-b` create branch.
15    pub create: Option<String>,
16    /// `-B` create/reset branch.
17    pub create_or_reset: Option<String>,
18    /// `--force` / `-f`.
19    pub force: bool,
20    /// `--track`.
21    pub track: bool,
22    /// `--no-track`.
23    pub no_track: bool,
24    /// `--orphan`.
25    pub orphan: Option<String>,
26    /// `--detach`.
27    pub detach: bool,
28    /// Pathspecs.
29    pub paths: Vec<String>,
30    /// `--quiet`.
31    pub quiet: bool,
32}
33
34impl CheckoutCommand {
35    /// New `checkout` command.
36    #[must_use]
37    pub fn new() -> Self {
38        Self::default()
39    }
40
41    /// Switch to the named branch/commit.
42    pub fn target(&mut self, t: impl Into<String>) -> &mut Self {
43        self.target = Some(t.into());
44        self
45    }
46
47    /// Create a new branch (`-b`).
48    pub fn create(&mut self, name: impl Into<String>) -> &mut Self {
49        self.create = Some(name.into());
50        self
51    }
52
53    /// Create or reset a branch (`-B`).
54    pub fn create_or_reset(&mut self, name: impl Into<String>) -> &mut Self {
55        self.create_or_reset = Some(name.into());
56        self
57    }
58
59    /// `--force`.
60    pub fn force(&mut self) -> &mut Self {
61        self.force = true;
62        self
63    }
64
65    /// `--track`.
66    pub fn track(&mut self) -> &mut Self {
67        self.track = true;
68        self
69    }
70
71    /// `--no-track`.
72    pub fn no_track(&mut self) -> &mut Self {
73        self.no_track = true;
74        self
75    }
76
77    /// Create an orphan branch.
78    pub fn orphan(&mut self, name: impl Into<String>) -> &mut Self {
79        self.orphan = Some(name.into());
80        self
81    }
82
83    /// Detach HEAD.
84    pub fn detach(&mut self) -> &mut Self {
85        self.detach = true;
86        self
87    }
88
89    /// Restore a path from the index or tree.
90    pub fn path(&mut self, p: impl Into<String>) -> &mut Self {
91        self.paths.push(p.into());
92        self
93    }
94
95    /// Suppress output.
96    pub fn quiet(&mut self) -> &mut Self {
97        self.quiet = true;
98        self
99    }
100}
101
102#[async_trait]
103impl GitCommand for CheckoutCommand {
104    type Output = CommandOutput;
105    fn get_executor(&self) -> &CommandExecutor {
106        &self.executor
107    }
108    fn get_executor_mut(&mut self) -> &mut CommandExecutor {
109        &mut self.executor
110    }
111    fn build_command_args(&self) -> Vec<String> {
112        let mut args = vec!["checkout".to_string()];
113        if self.force {
114            args.push("--force".into());
115        }
116        if self.track {
117            args.push("--track".into());
118        }
119        if self.no_track {
120            args.push("--no-track".into());
121        }
122        if self.detach {
123            args.push("--detach".into());
124        }
125        if self.quiet {
126            args.push("--quiet".into());
127        }
128        if let Some(o) = &self.orphan {
129            args.push("--orphan".into());
130            args.push(o.clone());
131        }
132        if let Some(b) = &self.create {
133            args.push("-b".into());
134            args.push(b.clone());
135        }
136        if let Some(b) = &self.create_or_reset {
137            args.push("-B".into());
138            args.push(b.clone());
139        }
140        if let Some(t) = &self.target {
141            args.push(t.clone());
142        }
143        if !self.paths.is_empty() {
144            args.push("--".into());
145            args.extend(self.paths.iter().cloned());
146        }
147        args
148    }
149    async fn execute(&self) -> Result<CommandOutput> {
150        self.execute_raw().await
151    }
152}