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
use std::fs;
use std::io;
use std::path::Path;

use std::io::Write;

#[cfg(target_family = "unix")]
use std::os::unix::fs::PermissionsExt;

/// Checks for existence of the provided path, returning an error in case it doesn't exist.
///
/// Mostly a convenient wrapper for spawning consistent [Error](../../error/struct.Error.html) instances
/// when checking for path existence.
///
/// # Examples
/// ```
/// use rood::sys::file;
/// let result = file::ensure_exists("/non_existent_file.txt");
/// assert!(result.is_err());
/// ```
pub fn ensure_exists<T>(raw: T) -> io::Result<()>
where
    T: AsRef<Path>,
{
    let path = raw.as_ref();

    if path.exists() {
        Ok(())
    } else {
        Err(io::Error::new(
            io::ErrorKind::NotFound,
            format!("Path [{}] does not exist", path.display()),
        ))
    }
}

/// Mark the specified file as executable.
///
/// On unix systems, the implementation will be equivalent to `chmod +x {p}`.
///
/// *Note: Does nothing for now on Windows.*
///
/// # Examples
/// ```
/// use rood::sys::file;
/// use std::fs;
///
/// let file_name = "myfile.sh";
/// let file_handle = fs::File::create(file_name).unwrap();
/// file::make_executable(file_name).unwrap();
/// # fs::remove_file(file_name);
/// ```
pub fn make_executable<T>(p: T) -> io::Result<()>
where
    T: AsRef<Path>,
{
    if cfg!(unix) {
        // TODO: Actually only add +x flag, nothing else.
        let mut perms = fs::metadata(p.as_ref())?.permissions();
        perms.set_mode(0o755);
        fs::set_permissions(p, perms)?;
    }
    Ok(())
}

pub fn is_executable<T: AsRef<Path>>(path: T) -> io::Result<bool> {
    if cfg!(unix) {
        let perms = fs::metadata(path.as_ref())?.permissions();
        Ok(perms.mode() & 0o111 != 0)
    } else {
        Ok(true)
    }
}

/// Replace all instances of a pattern in file.
///
/// Will read the file into memory, and will replace every instance of the provided pattern before
/// writing back the buffer to the file.
///
/// # Examples
/// ```
/// use std::fs;
/// use rood::sys::file;
/// use std::io::Write;
///
/// let file_name = "myfile.txt";
///
/// // Create a file named "myfile.txt" and write some text to it.
/// fs::File::create(file_name).unwrap().write_all(b"Hello there world. Hello again.").unwrap();
///
/// // Use replace_all to replace all instances of "Hello" by "Goodbye".
/// file::replace_all(file_name, "Hello", "Goodbye").unwrap();
///
/// assert!(!fs::read_to_string(file_name).unwrap().contains("Hello"));
///
/// # fs::remove_file(file_name);
/// ```
pub fn replace_all<T>(p: T, pattern: &str, to: &str) -> io::Result<()>
where
    T: AsRef<Path>,
{
    let data = fs::read_to_string(p.as_ref())?;
    fs::File::create(p.as_ref())?.write_all(data.replace(pattern, to).as_bytes())?;
    Ok(())
}