1 use {
2     crate::{
3         app::AppContext,
4         file_sum::FileSum,
5         task_sync::Dam,
6     },
7     std::{
8         path::{Path, PathBuf},
9     },
10 };
11 
12 /// a staging area: selection of several paths
13 /// for later user
14 ///
15 /// The structure is versionned to allow caching
16 /// of derived structs (filtered list mainly). This
17 /// scheme implies the stage isn't cloned, and that
18 /// it exists in only one instance
19 #[derive(Default, Debug)]
20 pub struct Stage {
21     version: usize,
22     paths: Vec<PathBuf>,
23 }
24 
25 impl Stage {
contains(&self, path: &Path) -> bool26     pub fn contains(&self, path: &Path) -> bool {
27         self.paths
28             .iter()
29             .any(|p| p==path)
30     }
is_empty(&self) -> bool31     pub fn is_empty(&self) -> bool {
32         self.paths.is_empty()
33     }
34     /// return true when there's a change
add(&mut self, path: PathBuf) -> bool35     pub fn add(&mut self, path: PathBuf) -> bool {
36         if self.contains(&path) {
37             false
38         } else {
39             self.version += 1;
40             self.paths.push(path);
41             true
42         }
43     }
44     /// return true when there's a change
remove(&mut self, path: &Path) -> bool45     pub fn remove(&mut self, path: &Path) -> bool {
46         if let Some(pos) = self.paths.iter().position(|p| p == path) {
47             self.version += 1;
48             self.paths.remove(pos);
49             true
50         } else {
51             false
52         }
53     }
remove_idx(&mut self, idx: usize)54     pub fn remove_idx(&mut self, idx: usize) {
55         if idx < self.paths.len() {
56             self.version += 1;
57             self.paths.remove(idx);
58         }
59     }
clear(&mut self)60     pub fn clear(&mut self) {
61         self.version += 1;
62         self.paths.clear();
63     }
paths(&self) -> &[PathBuf]64     pub fn paths(&self) -> &[PathBuf] {
65         &self.paths
66     }
67     /// removes paths to non existing files
refresh(&mut self)68     pub fn refresh(&mut self) {
69         let len_before = self.paths.len();
70         self.paths.retain(|p| p.exists());
71         if self.paths.len() != len_before {
72             self.version += 1;
73         }
74     }
len(&self) -> usize75     pub fn len(&self) -> usize {
76         self.paths.len()
77     }
version(&self) -> usize78     pub fn version(&self) -> usize {
79         self.version
80     }
compute_sum(&self, dam: &Dam, con: &AppContext) -> Option<FileSum>81     pub fn compute_sum(&self, dam: &Dam, con: &AppContext) -> Option<FileSum> {
82         let mut sum = FileSum::zero();
83         for path in &self.paths {
84             if path.is_dir() {
85                 let dir_sum = FileSum::from_dir(path, dam, con);
86                 if let Some(dir_sum) = dir_sum {
87                     sum += dir_sum;
88                 } else {
89                     return None; // computation was interrupted
90                 }
91             } else {
92                 sum += FileSum::from_file(path);
93             }
94         }
95         Some(sum)
96     }
97 }
98