]> git.proxmox.com Git - rustc.git/blame - src/vendor/mdbook/src/utils/fs.rs
New upstream version 1.22.1+dfsg1
[rustc.git] / src / vendor / mdbook / src / utils / fs.rs
CommitLineData
ea8adc8c
XL
1use std::path::{Path, PathBuf, Component};
2use errors::*;
3use std::io::Read;
7cac9316
XL
4use std::fs::{self, File};
5
6/// Takes a path to a file and try to read the file into a String
ea8adc8c
XL
7pub fn file_to_string<P: AsRef<Path>>(path: P) -> Result<String> {
8 let path = path.as_ref();
7cac9316
XL
9 let mut file = match File::open(path) {
10 Ok(f) => f,
11 Err(e) => {
12 debug!("[*]: Failed to open {:?}", path);
ea8adc8c 13 bail!(e);
7cac9316
XL
14 },
15 };
16
17 let mut content = String::new();
18
19 if let Err(e) = file.read_to_string(&mut content) {
20 debug!("[*]: Failed to read {:?}", path);
ea8adc8c 21 bail!(e);
7cac9316
XL
22 }
23
24 Ok(content)
25}
26
041b39d2
XL
27/// Takes a path and returns a path containing just enough `../` to point to
28/// the root of the given path.
7cac9316 29///
041b39d2
XL
30/// This is mostly interesting for a relative path to point back to the
31/// directory from where the path starts.
7cac9316 32///
ea8adc8c
XL
33/// ```rust
34/// # extern crate mdbook;
35/// #
36/// # use std::path::Path;
37/// # use mdbook::utils::fs::path_to_root;
38/// #
39/// # fn main() {
40/// let path = Path::new("some/relative/path");
41/// assert_eq!(path_to_root(path), "../../");
42/// # }
7cac9316
XL
43/// ```
44///
041b39d2
XL
45/// **note:** it's not very fool-proof, if you find a situation where
46/// it doesn't return the correct path.
47/// Consider [submitting a new issue](https://github.com/azerupi/mdBook/issues)
48/// or a [pull-request](https://github.com/azerupi/mdBook/pulls) to improve it.
7cac9316 49
ea8adc8c 50pub fn path_to_root<P: Into<PathBuf>>(path: P) -> String {
7cac9316
XL
51 debug!("[fn]: path_to_root");
52 // Remove filename and add "../" for every directory
53
ea8adc8c 54 path.into()
7cac9316
XL
55 .parent()
56 .expect("")
57 .components()
58 .fold(String::new(), |mut s, c| {
59 match c {
60 Component::Normal(_) => s.push_str("../"),
61 _ => {
62 debug!("[*]: Other path component... {:?}", c);
63 },
64 }
65 s
66 })
67}
68
69
70
041b39d2
XL
71/// This function creates a file and returns it. But before creating the file
72/// it checks every directory in the path to see if it exists,
73/// and if it does not it will be created.
7cac9316 74
ea8adc8c 75pub fn create_file(path: &Path) -> Result<File> {
7cac9316
XL
76 debug!("[fn]: create_file");
77
78 // Construct path
79 if let Some(p) = path.parent() {
80 debug!("Parent directory is: {:?}", p);
81
041b39d2 82 fs::create_dir_all(p)?;
7cac9316
XL
83 }
84
85 debug!("[*]: Create file: {:?}", path);
ea8adc8c 86 File::create(path).map_err(|e| e.into())
7cac9316
XL
87}
88
89/// Removes all the content of a directory but not the directory itself
90
ea8adc8c 91pub fn remove_dir_content(dir: &Path) -> Result<()> {
041b39d2 92 for item in fs::read_dir(dir)? {
7cac9316
XL
93 if let Ok(item) = item {
94 let item = item.path();
95 if item.is_dir() {
041b39d2 96 fs::remove_dir_all(item)?;
7cac9316 97 } else {
041b39d2 98 fs::remove_file(item)?;
7cac9316
XL
99 }
100 }
101 }
102 Ok(())
103}
104
105///
106///
041b39d2
XL
107/// Copies all files of a directory to another one except the files
108/// with the extensions given in the `ext_blacklist` array
7cac9316 109
041b39d2 110pub fn copy_files_except_ext(from: &Path, to: &Path, recursive: bool, ext_blacklist: &[&str])
ea8adc8c 111 -> Result<()> {
7cac9316
XL
112 debug!("[fn] copy_files_except_ext");
113 // Check that from and to are different
114 if from == to {
115 return Ok(());
116 }
117 debug!("[*] Loop");
041b39d2
XL
118 for entry in fs::read_dir(from)? {
119 let entry = entry?;
7cac9316 120 debug!("[*] {:?}", entry.path());
041b39d2 121 let metadata = entry.metadata()?;
7cac9316
XL
122
123 // If the entry is a dir and the recursive option is enabled, call itself
124 if metadata.is_dir() && recursive {
125 if entry.path() == to.to_path_buf() {
126 continue;
127 }
128 debug!("[*] is dir");
129
130 // check if output dir already exists
131 if !to.join(entry.file_name()).exists() {
041b39d2 132 fs::create_dir(&to.join(entry.file_name()))?;
7cac9316
XL
133 }
134
041b39d2 135 copy_files_except_ext(&from.join(entry.file_name()), &to.join(entry.file_name()), true, ext_blacklist)?;
7cac9316
XL
136 } else if metadata.is_file() {
137
138 // Check if it is in the blacklist
139 if let Some(ext) = entry.path().extension() {
140 if ext_blacklist.contains(&ext.to_str().unwrap()) {
141 continue;
142 }
143 }
144 debug!("[*] creating path for file: {:?}",
041b39d2
XL
145 &to.join(entry
146 .path()
147 .file_name()
148 .expect("a file should have a file name...")));
7cac9316
XL
149
150 info!("[*] Copying file: {:?}\n to {:?}",
151 entry.path(),
041b39d2
XL
152 &to.join(entry
153 .path()
154 .file_name()
155 .expect("a file should have a file name...")));
156 fs::copy(entry.path(),
157 &to.join(entry
158 .path()
159 .file_name()
160 .expect("a file should have a file name...")))?;
7cac9316
XL
161 }
162 }
163 Ok(())
164}
165
166
167// ------------------------------------------------------------------------------------------------
168// ------------------------------------------------------------------------------------------------
169
170// tests
171
172#[cfg(test)]
173mod tests {
174 extern crate tempdir;
175
176 use super::copy_files_except_ext;
177 use std::fs;
178
179 #[test]
180 fn copy_files_except_ext_test() {
181 let tmp = match tempdir::TempDir::new("") {
182 Ok(t) => t,
183 Err(_) => panic!("Could not create a temp dir"),
184 };
185
186 // Create a couple of files
187 if let Err(_) = fs::File::create(&tmp.path().join("file.txt")) {
188 panic!("Could not create file.txt")
189 }
190 if let Err(_) = fs::File::create(&tmp.path().join("file.md")) {
191 panic!("Could not create file.md")
192 }
193 if let Err(_) = fs::File::create(&tmp.path().join("file.png")) {
194 panic!("Could not create file.png")
195 }
196 if let Err(_) = fs::create_dir(&tmp.path().join("sub_dir")) {
197 panic!("Could not create sub_dir")
198 }
199 if let Err(_) = fs::File::create(&tmp.path().join("sub_dir/file.png")) {
200 panic!("Could not create sub_dir/file.png")
201 }
202 if let Err(_) = fs::create_dir(&tmp.path().join("sub_dir_exists")) {
203 panic!("Could not create sub_dir_exists")
204 }
205 if let Err(_) = fs::File::create(&tmp.path().join("sub_dir_exists/file.txt")) {
206 panic!("Could not create sub_dir_exists/file.txt")
207 }
208
209 // Create output dir
210 if let Err(_) = fs::create_dir(&tmp.path().join("output")) {
211 panic!("Could not create output")
212 }
213 if let Err(_) = fs::create_dir(&tmp.path().join("output/sub_dir_exists")) {
214 panic!("Could not create output/sub_dir_exists")
215 }
216
217 match copy_files_except_ext(&tmp.path(), &tmp.path().join("output"), true, &["md"]) {
218 Err(e) => panic!("Error while executing the function:\n{:?}", e),
219 Ok(_) => {},
220 }
221
222 // Check if the correct files where created
223 if !(&tmp.path().join("output/file.txt")).exists() {
224 panic!("output/file.txt should exist")
225 }
226 if (&tmp.path().join("output/file.md")).exists() {
227 panic!("output/file.md should not exist")
228 }
229 if !(&tmp.path().join("output/file.png")).exists() {
230 panic!("output/file.png should exist")
231 }
232 if !(&tmp.path().join("output/sub_dir/file.png")).exists() {
233 panic!("output/sub_dir/file.png should exist")
234 }
235 if !(&tmp.path().join("output/sub_dir_exists/file.txt")).exists() {
236 panic!("output/sub_dir/file.png should exist")
237 }
238
239 }
240}