prdoclib/commands/
load.rs1use crate::{
6 common::PRNumber,
7 config::PRDocConfig,
8 doc_filename::DocFileName,
9 docfile::DocFile,
10 docfile_wrapper::DocFileWrapper,
11 error::{self, Result},
12 schema::Schema,
13 utils::{get_numbers_from_file, get_project_root},
14};
15use std::{
16 collections::HashSet,
17 path::{Path, PathBuf},
18};
19
20pub struct LoadCmd {
22 pub(crate) schema: Schema,
23}
24
25pub type LoadResult = (bool, HashSet<DocFileWrapper>);
27
28impl LoadCmd {
29 pub fn new(schema: Schema) -> Self {
31 Self { schema }
32 }
33
34 pub(crate) fn load_numbers(
36 &self,
37 numbers: Vec<PRNumber>,
38 dir: &PathBuf,
39 ) -> error::Result<LoadResult> {
40 let mut global_result = true;
41
42 let res = numbers
43 .iter()
44 .filter_map(|&number| {
45 log::debug!("Loading PR #{}", number);
46 let file_maybe = DocFileName::find(number, None, dir);
47
48 match file_maybe {
49 Ok(file) => {
50 let filename = DocFileName::try_from(&file)
51 .expect("If we found a file, it should be valid");
52
53 let yaml = self.schema.load(&file);
54
55 if let Ok(value) = yaml {
56 Some(DocFileWrapper::new(file, filename, Some(value)))
57 } else {
58 global_result &= false;
59 None
60 }
61 },
62 Err(e) => {
63 global_result &= false;
64 log::warn!("{e:?}");
65 None
66 },
67 }
68 })
69 .collect();
70
71 Ok((global_result, res))
72 }
73
74 pub fn load_file(&self, file: &PathBuf) -> Result<DocFileWrapper> {
76 let filename = DocFileName::try_from(file)?;
77 let value = self.schema.load(&file).ok();
78 let wrapper = DocFileWrapper::new(file.clone(), filename, value);
79 Ok(wrapper)
80 }
81
82 pub(crate) fn load_list(&self, file: &PathBuf, dir: &PathBuf) -> Result<LoadResult> {
83 let extract_numbers = get_numbers_from_file(file)?;
84 let numbers: Vec<PRNumber> =
85 extract_numbers.iter().filter_map(|(_, _, n)| n.to_owned()).collect();
86
87 let mut global_result = extract_numbers.iter().map(|(_, status, _)| status).all(|&x| x);
88
89 let (r, wrapper) = self.load_numbers(numbers, dir).unwrap();
90 global_result &= r;
91 Ok((global_result, wrapper))
92 }
93
94 pub(crate) fn load_from_folder(&self, dir: &PathBuf) -> Result<LoadResult> {
95 let res = DocFile::find(self.schema.clone(), dir, false);
96 let mut global_result = res.is_ok();
97
98 let wrapper = res
99 .unwrap()
100 .filter_map(|file| {
101 let filename_maybe = DocFileName::try_from(&file);
102
103 if let Ok(filename) = filename_maybe {
104 let yaml = self.schema.load(&file);
105 if let Ok(value) = yaml {
106 let wrapper = DocFileWrapper::new(file.clone(), filename, Some(value));
107
108 global_result &= true;
109 log::debug!("OK {}", file.display());
110 Some(wrapper)
111 } else {
112 global_result &= false;
113 log::warn!("ERR {}", file.display());
114 None
115 }
116 } else {
117 log::warn!("Invalid file {:?}", file.display());
118 None
119 }
120 })
121 .collect();
122
123 Ok((global_result, wrapper))
124 }
125
126 pub fn run(
128 config: &PRDocConfig,
129 schema: Option<PathBuf>,
130 dir: &PathBuf,
131 file: Option<PathBuf>,
132 numbers: Option<Vec<PRNumber>>,
133 list: Option<PathBuf>,
134 ) -> Result<LoadResult> {
135 log::debug!("Loading from directory {}", dir.display());
136
137 let repo_root = get_project_root()?;
138 log::debug!("From repo root: {}", repo_root.canonicalize().unwrap().display());
139
140 let schema_path = if let Some(schema_path) = schema {
141 schema_path
142 } else if config.schema_path().is_absolute() {
143 config.schema_path()
144 } else {
145 repo_root.join(config.schema_path())
146 };
147 log::info!("Using schema: {}", schema_path.canonicalize().unwrap().display());
148
149 let schema = Schema::new(schema_path);
150 let load_cmd = LoadCmd::new(schema);
151
152 Ok(match (file, numbers, list) {
153 (Some(f), None, None) => {
154 let file_abs = if f.is_relative() { Path::new(&dir).join(&f) } else { f.clone() };
155 let mut wrapper = HashSet::new();
156 wrapper.insert(load_cmd.load_file(&file_abs)?);
157
158 (true, wrapper)
159 },
160
161 (None, Some(numbers), None) => {
162 log::debug!("Loading numbers {:?}", numbers);
163 let (global_result, wrapper) = load_cmd.load_numbers(numbers, dir)?;
164 (global_result, wrapper)
165 },
166
167 (None, None, Some(list)) => {
168 log::debug!("Loading list from {:?}", list);
169 let (global_result, wrapper) = load_cmd.load_list(&list, dir)?;
170 (global_result, wrapper)
171 },
172
173 (None, None, None) => {
174 log::debug!("Loading all files in folder {}", dir.display());
175 let (global_result, wrapper) = load_cmd.load_from_folder(dir)?;
176 (global_result, wrapper)
177 },
178
179 _ => unreachable!(),
180 })
181 }
182}