1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
//! Some helpful functions to deal with file system operations.
//!
//! These are rather simple, but provide a quick and easy way to to common
//! tasks. Also, they have great error messages.

extern crate glob;

use std::path::{Path, PathBuf};
use std::io::{Read, Write, BufReader, BufWriter};
use std::fs::File;
use std::result::Result as StdResult;

use failure::{Error, ResultExt};

use prelude::Result;

pub use std::fs::create_dir_all as create_dir;

/// Read file content into string
///
/// # Examples
///
/// ```rust
/// # extern crate quicli;
/// # use quicli::prelude::*;
/// # fn main() { run().unwrap() }
/// # fn run() -> Result<()> {
/// let x = read_file(".gitignore")?;
/// assert!(x.len() > 0);
/// # Ok(()) }
/// ```
pub fn read_file<P: AsRef<Path>>(path: P) -> Result<String> {
    let path = path.as_ref();
    ensure!(path.exists() && path.is_file(), "Path {:?} is not a file!", path);

    let file = File::open(path)
        .with_context(|_| format!("Could not open file {:?}", path))?;
    let mut file = BufReader::new(file);

    let mut result = String::new();
    file.read_to_string(&mut result)
        .with_context(|_| format!("Could not read file {:?}", path))?;

    Ok(result)
}

/// Write string to file
///
/// _Note:_ Replaces the current file content if the file already exists.
///
/// # Examples
///
/// ```rust
/// # extern crate quicli;
/// # use quicli::prelude::*;
/// # fn main() { run().unwrap() }
/// # fn run() -> Result<()> {
/// write_to_file("/tmp/asdasidz81zasda", "foobar")?;
/// # Ok(()) }
/// ```
pub fn write_to_file<P: AsRef<Path>>(path: P, content: &str) -> Result<()> {
    let path = path.as_ref();

    let file = File::create(path)
        .with_context(|_| format!("Could not create/open file {:?}", path))?;
    let mut file = BufWriter::new(file);

    file.write_all(content.as_bytes())
        .with_context(|_| format!("Could not write to file {:?}", path))?;

    Ok(())
}

/// Find files with glob pattern
///
/// Search for a pattern like `*.md` and get an iterator of Markdown files.
///
/// # Examples
///
/// ```rust
/// # extern crate quicli;
/// # use quicli::prelude::*;
/// # fn main() { run().unwrap() }
/// # fn run() -> Result<()> {
/// let markdown_files = glob("*.md")?;
/// assert_eq!(markdown_files.len(), 2);
///
/// let weird_files = glob("**/*.weird");
/// assert!(weird_files.is_err());
/// if let Err(e) = weird_files {
///     assert_eq!(e.to_string(), "No files match pattern `**/*.weird`".to_string());
/// }
/// # Ok(()) }
/// ```
pub fn glob(pattern: &str) -> Result<Vec<PathBuf>> {
    use self::glob::{glob_with, MatchOptions};

    let options: MatchOptions = Default::default();
    let files: Vec<_> = glob_with(pattern, &options)?
        .filter_map(StdResult::ok)
        .collect();

    ensure!(files.get(0).is_some(), "No files match pattern `{}`", pattern);

    Ok(files)
}