xargo/
util.rs

1use std::fs::File;
2use std::io::{Read, Write};
3use std::path::Path;
4use std::fs;
5
6use toml::Value;
7use walkdir::WalkDir;
8
9use errors::*;
10
11pub fn cp_r(src: &Path, dst: &Path) -> Result<()> {
12    for e in WalkDir::new(src) {
13        // This is only an error when there's some sort of intermittent IO error
14        // during iteration.
15        // see https://doc.rust-lang.org/std/fs/struct.ReadDir.html
16        let e = e.chain_err(|| {
17            format!(
18                "intermittent IO error while iterating directory `{}`",
19                src.display()
20            )
21        })?;
22
23        let src_file = e.path();
24        let relative_path = src_file.strip_prefix(src).chain_err(|| {
25            format!(
26                "Could not retrieve relative path of child directory or \
27                 file `{}` with regards to parent directory `{}`",
28                src_file.display(),
29                src.display()
30            )
31        })?;
32
33        let dst_file = dst.join(relative_path);
34        let metadata = e.metadata().chain_err(|| {
35            format!("Could not retrieve metadata of `{}`", e.path().display())
36        })?;
37
38        if metadata.is_dir() {
39            // ensure the destination directory exists
40            fs::create_dir_all(&dst_file).chain_err(|| {
41                format!("Could not create directory `{}`", dst_file.display())
42            })?;
43        } else {
44            // else copy the file
45            fs::copy(&src_file, &dst_file).chain_err(|| {
46                format!(
47                    "copying files from `{}` to `{}` failed",
48                    src_file.display(),
49                    dst_file.display()
50                )
51            })?;
52        };
53    }
54
55    Ok(())
56}
57
58pub fn mkdir(path: &Path) -> Result<()> {
59    fs::create_dir(path).chain_err(|| format!("couldn't create directory {}", path.display()))
60}
61
62/// Parses `path` as TOML
63pub fn parse(path: &Path) -> Result<Value> {
64    Ok(toml::from_str(&read(path)?)
65        .map_err(|_| format!("{} is not valid TOML", path.display()))?)
66}
67
68pub fn read(path: &Path) -> Result<String> {
69    let mut s = String::new();
70
71    let p = path.display();
72    File::open(path)
73        .chain_err(|| format!("couldn't open {}", p))?
74        .read_to_string(&mut s)
75        .chain_err(|| format!("couldn't read {}", p))?;
76
77    Ok(s)
78}
79
80/// Search for `file` in `path` and its parent directories
81pub fn search<'p>(mut path: &'p Path, file: &str) -> Option<&'p Path> {
82    loop {
83        if path.join(file).exists() {
84            return Some(path);
85        }
86
87        if let Some(p) = path.parent() {
88            path = p;
89        } else {
90            return None;
91        }
92    }
93}
94
95pub fn write(path: &Path, contents: &str) -> Result<()> {
96    let p = path.display();
97    File::create(path)
98        .chain_err(|| format!("couldn't open {}", p))?
99        .write_all(contents.as_bytes())
100        .chain_err(|| format!("couldn't write to {}", p))
101}