Skip to main content

lds_git/
reset.rs

1//! Reset operations — destructive, so they're guarded by the same ownership
2//! check as `commit` / `merge`.
3//!
4//! `git reset --hard` is the most reflog-heavy thing this crate does. We
5//! capture HEAD before and after so callers can produce an audit line ("HEAD
6//! moved from X to Y, mode=hard"), and so an undo path is at least
7//! discoverable via the reflog rather than silently lost.
8
9use std::path::Path;
10
11use anyhow::Result;
12
13use crate::output::{ResetMode, ResetOutput};
14use crate::{GitModule, TIMEOUT_LOCAL, git_cmd};
15
16impl GitModule {
17    /// Move HEAD to `target`, with `mode` controlling the working tree
18    /// behaviour. The working directory MUST be owned by the current
19    /// session — see [`GitModule::ensure_session_scope`].
20    ///
21    /// * [`ResetMode::Soft`]   — move HEAD only (`git reset --soft`)
22    /// * [`ResetMode::Mixed`]  — also reset index but keep worktree (`--mixed`)
23    /// * [`ResetMode::Hard`]   — also overwrite worktree (`--hard`)
24    pub async fn reset(
25        &self,
26        working_dir: &Path,
27        mode: ResetMode,
28        target: &str,
29    ) -> Result<ResetOutput> {
30        self.ensure_session_scope(working_dir)?;
31
32        let previous_head = git_cmd(working_dir, &["rev-parse", "HEAD"], TIMEOUT_LOCAL).await?;
33        let flag = match mode {
34            ResetMode::Soft => "--soft",
35            ResetMode::Mixed => "--mixed",
36            ResetMode::Hard => "--hard",
37        };
38        git_cmd(working_dir, &["reset", flag, target], TIMEOUT_LOCAL).await?;
39        let current_head = git_cmd(working_dir, &["rev-parse", "HEAD"], TIMEOUT_LOCAL).await?;
40
41        Ok(ResetOutput {
42            mode,
43            target: target.to_string(),
44            previous_head,
45            current_head,
46        })
47    }
48}