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