Skip to main content

git_spawn/command/
reflog.rs

1//! `git reflog` — manage and inspect reflog information.
2
3use crate::command::{CommandExecutor, CommandOutput, GitCommand};
4use crate::error::Result;
5use async_trait::async_trait;
6
7/// Actions supported by `git reflog`.
8#[derive(Debug, Clone)]
9pub enum ReflogAction {
10    /// `git reflog [show] [<ref>]`.
11    Show {
12        /// Ref to inspect (default `HEAD`).
13        ref_name: Option<String>,
14        /// `-n N` / `--max-count=N`.
15        max_count: Option<u32>,
16        /// Extra arbitrary format.
17        format: Option<String>,
18    },
19    /// `git reflog expire [options] <refs>`.
20    Expire {
21        /// `--all`.
22        all: bool,
23        /// `--expire=<time>`.
24        expire: Option<String>,
25        /// `--expire-unreachable=<time>`.
26        expire_unreachable: Option<String>,
27        /// `--stale-fix`.
28        stale_fix: bool,
29        /// Refs to expire.
30        refs: Vec<String>,
31    },
32    /// `git reflog delete <entry>…`.
33    Delete {
34        /// Entries to delete (e.g. `HEAD@{0}`).
35        entries: Vec<String>,
36        /// `--rewrite`.
37        rewrite: bool,
38    },
39    /// `git reflog exists <ref>`.
40    Exists {
41        /// Ref to check.
42        ref_name: String,
43    },
44}
45
46/// Builder for `git reflog`.
47#[derive(Debug, Clone)]
48pub struct ReflogCommand {
49    /// Shared executor.
50    pub executor: CommandExecutor,
51    /// Action.
52    pub action: ReflogAction,
53}
54
55impl ReflogCommand {
56    /// `reflog` / `reflog show`.
57    #[must_use]
58    pub fn show() -> Self {
59        Self {
60            executor: CommandExecutor::default(),
61            action: ReflogAction::Show {
62                ref_name: None,
63                max_count: None,
64                format: None,
65            },
66        }
67    }
68
69    /// Set the ref (for `show`).
70    pub fn ref_name(&mut self, r: impl Into<String>) -> &mut Self {
71        if let ReflogAction::Show { ref_name, .. } = &mut self.action {
72            *ref_name = Some(r.into());
73        }
74        self
75    }
76
77    /// `-n` / `--max-count` (for `show`).
78    pub fn max_count(&mut self, n: u32) -> &mut Self {
79        if let ReflogAction::Show { max_count, .. } = &mut self.action {
80            *max_count = Some(n);
81        }
82        self
83    }
84
85    /// Set `--format` (for `show`).
86    pub fn format(&mut self, f: impl Into<String>) -> &mut Self {
87        if let ReflogAction::Show { format, .. } = &mut self.action {
88            *format = Some(f.into());
89        }
90        self
91    }
92
93    /// `reflog expire`.
94    #[must_use]
95    pub fn expire() -> Self {
96        Self {
97            executor: CommandExecutor::default(),
98            action: ReflogAction::Expire {
99                all: false,
100                expire: None,
101                expire_unreachable: None,
102                stale_fix: false,
103                refs: vec![],
104            },
105        }
106    }
107
108    /// `reflog delete`.
109    #[must_use]
110    pub fn delete(entries: Vec<String>) -> Self {
111        Self {
112            executor: CommandExecutor::default(),
113            action: ReflogAction::Delete {
114                entries,
115                rewrite: false,
116            },
117        }
118    }
119
120    /// `reflog exists <ref>`.
121    pub fn exists(r: impl Into<String>) -> Self {
122        Self {
123            executor: CommandExecutor::default(),
124            action: ReflogAction::Exists { ref_name: r.into() },
125        }
126    }
127}
128
129#[async_trait]
130impl GitCommand for ReflogCommand {
131    type Output = CommandOutput;
132    fn get_executor(&self) -> &CommandExecutor {
133        &self.executor
134    }
135    fn get_executor_mut(&mut self) -> &mut CommandExecutor {
136        &mut self.executor
137    }
138    fn build_command_args(&self) -> Vec<String> {
139        let mut args = vec!["reflog".to_string()];
140        match &self.action {
141            ReflogAction::Show {
142                ref_name,
143                max_count,
144                format,
145            } => {
146                args.push("show".into());
147                if let Some(n) = max_count {
148                    args.push(format!("-n{n}"));
149                }
150                if let Some(f) = format {
151                    args.push(format!("--format={f}"));
152                }
153                if let Some(r) = ref_name {
154                    args.push(r.clone());
155                }
156            }
157            ReflogAction::Expire {
158                all,
159                expire,
160                expire_unreachable,
161                stale_fix,
162                refs,
163            } => {
164                args.push("expire".into());
165                if *all {
166                    args.push("--all".into());
167                }
168                if *stale_fix {
169                    args.push("--stale-fix".into());
170                }
171                if let Some(e) = expire {
172                    args.push(format!("--expire={e}"));
173                }
174                if let Some(e) = expire_unreachable {
175                    args.push(format!("--expire-unreachable={e}"));
176                }
177                args.extend(refs.iter().cloned());
178            }
179            ReflogAction::Delete { entries, rewrite } => {
180                args.push("delete".into());
181                if *rewrite {
182                    args.push("--rewrite".into());
183                }
184                args.extend(entries.iter().cloned());
185            }
186            ReflogAction::Exists { ref_name } => {
187                args.push("exists".into());
188                args.push(ref_name.clone());
189            }
190        }
191        args
192    }
193    async fn execute(&self) -> Result<CommandOutput> {
194        self.execute_raw().await
195    }
196}