Skip to main content

git_spawn/command/
reset.rs

1//! `git reset` — reset current HEAD to the specified state.
2
3use crate::command::{CommandExecutor, CommandOutput, GitCommand};
4use crate::error::Result;
5use async_trait::async_trait;
6
7/// Reset mode.
8#[derive(Debug, Clone, Copy)]
9pub enum ResetMode {
10    /// `--soft`: move HEAD, leave index and working tree.
11    Soft,
12    /// `--mixed` (default): move HEAD and index, leave working tree.
13    Mixed,
14    /// `--hard`: move HEAD, index, and working tree.
15    Hard,
16    /// `--merge`.
17    Merge,
18    /// `--keep`.
19    Keep,
20}
21
22/// Builder for `git reset`.
23#[derive(Debug, Clone, Default)]
24pub struct ResetCommand {
25    /// Shared executor.
26    pub executor: CommandExecutor,
27    /// Mode.
28    pub mode: Option<ResetMode>,
29    /// Target commit.
30    pub commit: Option<String>,
31    /// Pathspecs (for path-limited reset).
32    pub paths: Vec<String>,
33    /// `--quiet`.
34    pub quiet: bool,
35}
36
37impl ResetCommand {
38    /// New `reset`.
39    #[must_use]
40    pub fn new() -> Self {
41        Self::default()
42    }
43
44    /// Set mode.
45    pub fn mode(&mut self, m: ResetMode) -> &mut Self {
46        self.mode = Some(m);
47        self
48    }
49
50    /// Target commit.
51    pub fn commit(&mut self, c: impl Into<String>) -> &mut Self {
52        self.commit = Some(c.into());
53        self
54    }
55
56    /// Restrict to paths.
57    pub fn path(&mut self, p: impl Into<String>) -> &mut Self {
58        self.paths.push(p.into());
59        self
60    }
61
62    /// `--quiet`.
63    pub fn quiet(&mut self) -> &mut Self {
64        self.quiet = true;
65        self
66    }
67}
68
69#[async_trait]
70impl GitCommand for ResetCommand {
71    type Output = CommandOutput;
72    fn get_executor(&self) -> &CommandExecutor {
73        &self.executor
74    }
75    fn get_executor_mut(&mut self) -> &mut CommandExecutor {
76        &mut self.executor
77    }
78    fn build_command_args(&self) -> Vec<String> {
79        let mut args = vec!["reset".to_string()];
80        match self.mode {
81            Some(ResetMode::Soft) => args.push("--soft".into()),
82            Some(ResetMode::Mixed) => args.push("--mixed".into()),
83            Some(ResetMode::Hard) => args.push("--hard".into()),
84            Some(ResetMode::Merge) => args.push("--merge".into()),
85            Some(ResetMode::Keep) => args.push("--keep".into()),
86            None => {}
87        }
88        if self.quiet {
89            args.push("--quiet".into());
90        }
91        if let Some(c) = &self.commit {
92            args.push(c.clone());
93        }
94        if !self.paths.is_empty() {
95            args.push("--".into());
96            args.extend(self.paths.iter().cloned());
97        }
98        args
99    }
100    async fn execute(&self) -> Result<CommandOutput> {
101        self.execute_raw().await
102    }
103}