credence_lib/configuration/
coordinate.rs1use super::{super::coordinator::*, error::*};
2
3use {
4 compris::resolve::*,
5 httpdate::*,
6 kutil::{cli::depict::*, http::*},
7 notify,
8 std::{fs::*, io, path::*},
9};
10
11#[derive(Clone, Debug, Depict, Resolve)]
17pub struct CoordinateConfiguration {
18 #[resolve]
20 #[depict(iter(item), as(debug), style(string))]
21 pub paths: Vec<PathBuf>,
22
23 #[resolve]
25 #[depict(option, as(debug), style(string))]
26 pub coordinator: Option<PathBuf>,
27
28 #[resolve(key = "follow-symlinks")]
30 #[depict(style(symbol))]
31 pub follow_symlinks: bool,
32
33 #[resolve(key = "compare-contents")]
35 #[depict(style(symbol))]
36 pub compare_contents: bool,
37
38 #[resolve(key = "queue-size")]
40 #[depict(style(number))]
41 pub queue_size: usize,
42}
43
44impl CoordinateConfiguration {
45 pub fn validate<PathT>(&mut self, base_path: PathT, default_paths: Vec<PathBuf>) -> Result<(), ConfigurationError>
47 where
48 PathT: AsRef<Path>,
49 {
50 let base_path = base_path.as_ref();
51
52 if let Some(coordinator) = &self.coordinator
53 && !coordinator.is_absolute()
54 {
55 self.coordinator = Some(base_path.join(&coordinator));
56 }
57
58 if self.paths.is_empty() {
59 self.paths = default_paths;
60 } else {
61 let mut paths = Vec::with_capacity(self.paths.len());
62 for path in &self.paths {
63 paths.push(if path.is_absolute() { path.clone() } else { base_path.join(path) });
64 }
65 self.paths = paths;
66 }
67
68 Ok(())
69 }
70
71 pub fn new_coordinator(&self) -> notify::Result<Option<Coordinator>> {
73 Ok(
74 if let Some(coordinator) = &self.coordinator
75 && !self.paths.is_empty()
76 {
77 if let Some(parent) = coordinator.parent() {
78 tracing::info!("creating directory: {}", parent.display());
79 create_dir_all(parent)?;
80 }
81
82 let mut coordinator = Coordinator::new(
83 coordinator.clone(),
84 self.follow_symlinks,
85 self.compare_contents,
86 self.queue_size,
87 )?;
88
89 for path in &self.paths {
90 if path.exists() {
91 coordinator.add(path)?;
92 } else {
93 tracing::info!("path does not exist: {}", path.display());
94 }
95 }
96
97 Some(coordinator)
98 } else {
99 None
100 },
101 )
102 }
103
104 pub fn coordinator_modified(&self) -> io::Result<Option<HttpDate>> {
106 Ok(match &self.coordinator {
107 Some(coordinator) => {
108 if coordinator.exists() {
109 Some(file_modified(coordinator)?)
110 } else {
111 None
112 }
113 }
114
115 None => None,
116 })
117 }
118}
119
120impl Default for CoordinateConfiguration {
121 fn default() -> Self {
122 Self {
123 paths: Default::default(),
124 coordinator: Some(PathBuf::from(".coordinator")),
125 follow_symlinks: true,
126 compare_contents: false,
127 queue_size: 128,
128 }
129 }
130}