void_core/workspace/
reset.rs1use 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#[derive(Clone)]
15pub struct ResetOptions {
16 pub ctx: VoidContext,
17 pub patterns: Vec<String>,
18 pub observer: Option<Arc<dyn VoidObserver>>,
20}
21
22#[derive(Debug, Clone)]
24pub struct ResetResult {
25 pub reset: Vec<String>,
26}
27
28pub 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}