Skip to main content

void_core/workspace/
reset.rs

1//! Reset operations for workspace staging.
2
3use std::collections::{HashMap, HashSet};
4use std::sync::Arc;
5
6use crate::VoidContext;
7use crate::index::IndexEntry;
8use crate::support::events::{emit_workspace, VoidObserver, WorkspaceEvent};
9use crate::{index::write_workspace_index, Result};
10
11use super::stage::{build_pathspec, load_head_entries, load_index_or_empty};
12
13/// Options for resetting staged paths.
14#[derive(Clone)]
15pub struct ResetOptions {
16    pub ctx: VoidContext,
17    pub patterns: Vec<String>,
18    /// Optional observer for progress events.
19    pub observer: Option<Arc<dyn VoidObserver>>,
20}
21
22/// Result of resetting paths.
23#[derive(Debug, Clone)]
24pub struct ResetResult {
25    pub reset: Vec<String>,
26}
27
28/// Reset staged paths back to HEAD.
29pub fn reset_paths(opts: ResetOptions) -> Result<ResetResult> {
30    let mut index = load_index_or_empty(&opts.ctx)?;
31    let head_entries = load_head_entries(&opts.ctx)?;
32    let pathspec = build_pathspec(&opts.patterns)?;
33
34    let mut head_map: HashMap<String, IndexEntry> = HashMap::new();
35    for entry in head_entries {
36        head_map.insert(entry.path.clone(), entry);
37    }
38
39    let mut candidates = HashSet::new();
40    for entry in index.entries.iter() {
41        if pathspec.matches(&entry.path) {
42            candidates.insert(entry.path.clone());
43        }
44    }
45    for path in head_map.keys() {
46        if pathspec.matches(path) {
47            candidates.insert(path.clone());
48        }
49    }
50
51    let mut reset = Vec::new();
52    let total = candidates.len() as u64;
53    for (i, path) in candidates.into_iter().enumerate() {
54        index.unstage_file(path.as_str(), head_map.get(&path))?;
55        emit_workspace(
56            &opts.observer,
57            WorkspaceEvent::FileUnstaged { path: path.clone() },
58        );
59        emit_workspace(
60            &opts.observer,
61            WorkspaceEvent::Progress {
62                stage: "reset".to_string(),
63                current: (i + 1) as u64,
64                total,
65            },
66        );
67        reset.push(path);
68    }
69
70    reset.sort();
71    write_workspace_index(opts.ctx.paths.workspace_dir.as_std_path(), opts.ctx.crypto.vault.index_key()?, &index)?;
72
73    Ok(ResetResult { reset })
74}