1use log::*;
4use serde_yaml::Value;
5use std::{fs, path::PathBuf};
6
7use crate::{
8 common::PRNumber, doc_filename::DocFileName, error, schema::Schema, utils::get_project_root,
9};
10
11#[derive(Debug)]
13pub struct DocFile {
14 pub file: PathBuf,
16
17 pub content: Value,
19
20 pub schema: Schema,
22}
23
24impl DocFile {
32 pub fn new(schema: Schema, file: PathBuf) -> Self {
34 let content = Self::load(schema.clone(), &file).unwrap();
35 Self { file, content, schema }
36 }
37
38 pub fn load_from_number(schema: Schema, n: PRNumber) -> Self {
40 let filename = DocFileName::from(n);
41 let file = PathBuf::from(filename);
42 let content = Self::load(schema.clone(), &file).unwrap();
43 Self { file, content, schema }
44 }
45
46 pub fn load(schema: Schema, file: &PathBuf) -> crate::error::Result<Value> {
48 schema.load(file)
49 }
50
51 pub fn generate(file: PathBuf) -> error::Result<String> {
53 let template_file = if file.is_absolute() {
54 file
55 } else {
56 let repo_root = get_project_root().expect("We need to work in a repo");
57 repo_root.join(file)
58 };
59
60 match fs::read_to_string(&template_file) {
61 Ok(res) => Ok(res),
62 Err(ref e) if e.kind() == std::io::ErrorKind::NotFound =>
63 Err(error::PRdocLibError::MissingTemplateFile(template_file)),
64 Err(e) => Err(error::PRdocLibError::IO(e)),
65 }
66 }
67
68 pub fn find(
70 schema: Schema,
71 dir: &PathBuf,
72 valid_only: bool,
73 ) -> crate::error::Result<impl Iterator<Item = PathBuf>> {
74 trace!("valid_only: {valid_only}");
75
76 let res = std::fs::read_dir(dir)?
77 .filter_map(|res| res.ok())
78 .map(|dir_entry| dir_entry.path())
80 .filter_map(|path| {
82 if path.extension().map_or(false, |ext| ext == "prdoc") {
83 Some(path)
84 } else {
85 None
86 }
87 })
88 .filter_map(move |path| {
89 if valid_only {
90 let is_valid = DocFileName::is_valid(&path);
91 trace!(
92 "{}: filename {}",
93 path.display(),
94 if is_valid { " VALID " } else { "INVALID" }
95 );
96 if is_valid {
97 Some(path)
98 } else {
99 None
100 }
101 } else {
102 Some(path)
103 }
104 })
105 .filter_map(move |path| {
106 let schema_valid = schema.check_file(&path);
107 trace!(
108 "{}: schema {}",
109 path.display(),
110 if schema_valid { " VALID " } else { "INVALID" }
111 );
112
113 if valid_only {
114 if schema_valid {
115 Some(path)
116 } else {
117 None
118 }
119 } else {
120 Some(path)
121 }
122 });
123 Ok(res)
124 }
125}