1use std::path::{Path, PathBuf};
2
3use color_eyre::eyre::{self, Result};
4
5pub fn ensure_executable_exists<T>(name: T) -> Result<()>
6where
7 T: AsRef<str>,
8{
9 let name = name.as_ref();
10
11 if let Err(error) = which::which(name) {
12 eyre::bail!("{}: `{}`", error, name);
13 }
14
15 Ok(())
16}
17
18pub fn ensure_epub_file<T>(path: T) -> Result<()>
19where
20 T: AsRef<Path>,
21{
22 if !is_epub_file(&path)? {
23 eyre::bail!("File `{}` is not epub file", path.as_ref().display())
24 }
25
26 Ok(())
27}
28
29pub fn ensure_epub_dir<T>(path: T) -> Result<()>
30where
31 T: AsRef<Path>,
32{
33 if !is_epub_dir(&path)? {
34 eyre::bail!(
35 "Directory `{}` is not epub directory",
36 path.as_ref().display()
37 )
38 }
39
40 Ok(())
41}
42
43pub fn is_markdown_or_txt_file<T>(path: T) -> Result<bool>
44where
45 T: AsRef<Path>,
46{
47 Ok(is_some_file(&path, "md")? || is_some_file(&path, "txt")?)
48}
49
50pub fn is_epub_file<T>(path: T) -> Result<bool>
51where
52 T: AsRef<Path>,
53{
54 is_some_file(path, "epub")
55}
56
57pub fn try_get_markdown_or_txt_file_name_in_dir<T>(path: T) -> Result<Option<PathBuf>>
58where
59 T: AsRef<Path>,
60{
61 let path = path.as_ref();
62
63 ensure_exists(path)?;
64
65 let markdown_file_name = PathBuf::from(path.file_stem().unwrap()).with_extension("md");
66 let markdown_file_path = path.join(markdown_file_name);
67
68 let txt_file_name = PathBuf::from(path.file_stem().unwrap()).with_extension("txt");
69 let txt_file_path = path.join(txt_file_name);
70
71 if markdown_file_path.is_file() && txt_file_path.is_file() {
72 eyre::bail!("Both markdown and txt files exist in the directory");
73 }
74
75 if markdown_file_path.is_file() {
76 Ok(Some(dunce::canonicalize(markdown_file_path)?))
77 } else if txt_file_path.is_file() {
78 Ok(Some(dunce::canonicalize(txt_file_path)?))
79 } else {
80 Ok(None)
81 }
82}
83
84pub fn is_mdbook_dir<T>(path: T) -> Result<bool>
85where
86 T: AsRef<Path>,
87{
88 let path = path.as_ref();
89
90 ensure_exists(path)?;
91
92 if !path.is_dir() {
93 return Ok(false);
94 }
95
96 let src_path = path.join("src");
97 let toml_path = path.join("book.toml");
98
99 Ok(src_path.is_dir() && toml_path.is_file())
100}
101
102pub fn is_epub_dir<T>(path: T) -> Result<bool>
103where
104 T: AsRef<Path>,
105{
106 let path = path.as_ref();
107
108 ensure_exists(path)?;
109
110 if !path.is_dir() {
111 return Ok(false);
112 }
113
114 let epub_path = path.join("EPUB");
115 let meta_path = path.join("META-INF");
116 let mimetype_path = path.join("mimetype");
117
118 Ok(epub_path.is_dir() && meta_path.is_dir() && mimetype_path.is_file())
119}
120
121fn is_some_file<T, E>(path: T, extension: E) -> Result<bool>
122where
123 T: AsRef<Path>,
124 E: AsRef<str>,
125{
126 let path = path.as_ref();
127
128 ensure_exists(path)?;
129
130 if !path.is_file() {
131 return Ok(false);
132 }
133
134 Ok(path
135 .extension()
136 .is_some_and(|ext| ext == extension.as_ref()))
137}
138
139fn ensure_exists<T>(path: T) -> Result<()>
140where
141 T: AsRef<Path>,
142{
143 let path = path.as_ref();
144
145 eyre::ensure!(
146 path.try_exists()?,
147 "File or directory `{}` does not exist",
148 path.display()
149 );
150
151 Ok(())
152}
153
154pub fn ensure_pandoc_dir<T>(path: T) -> Result<()>
155where
156 T: AsRef<Path>,
157{
158 if !is_pandoc_dir(&path)? {
159 eyre::bail!(
160 "Directory `{}` is not pandoc directory",
161 path.as_ref().display()
162 )
163 }
164
165 Ok(())
166}
167
168pub fn ensure_mdbook_dir<T>(path: T) -> Result<()>
169where
170 T: AsRef<Path>,
171{
172 if !is_mdbook_dir(&path)? {
173 eyre::bail!(
174 "Directory `{}` is not mdbook directory",
175 path.as_ref().display()
176 )
177 }
178
179 Ok(())
180}
181
182pub fn is_pandoc_dir<T>(path: T) -> Result<bool>
183where
184 T: AsRef<Path>,
185{
186 let path = path.as_ref();
187
188 ensure_exists(path)?;
189
190 if !path.is_dir() {
191 return Ok(false);
192 }
193
194 let markdown = path.join(path.file_stem().unwrap()).with_extension("md");
195
196 Ok(markdown.is_file())
197}