use std::fs::{File, create_dir_all};
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use memchr::memchr;
use tera::{Context, Tera};
use crate::errors::{ErrorKind, Result, map_io_err, new_error};
use crate::filters::register_all_filters;
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Source {
Local(PathBuf),
Git(String),
}
pub fn read_file(p: &Path) -> Result<String> {
let mut f = map_io_err(File::open(p), p)?;
let mut contents = String::new();
map_io_err(f.read_to_string(&mut contents), p)?;
Ok(contents)
}
pub fn write_file(p: &Path, contents: &str) -> Result<()> {
let mut f = map_io_err(File::create(p), p)?;
map_io_err(f.write_all(contents.as_bytes()), p)?;
Ok(())
}
pub fn create_directory(path: &Path) -> Result<()> {
if !path.exists() {
map_io_err(create_dir_all(path), path)?;
}
Ok(())
}
pub fn get_source(input: &str) -> Source {
let path = Path::new(input);
if path.is_dir() { Source::Local(path.to_path_buf()) } else { Source::Git(input.to_string()) }
}
pub fn render_one_off_template(
content: &str,
context: &Context,
path: Option<PathBuf>,
) -> Result<String> {
let mut tera = Tera::default();
register_all_filters(&mut tera);
tera.render_str(content, context).map_err(|err| new_error(ErrorKind::Tera { err, path }))
}
pub fn is_binary(buf: &[u8]) -> bool {
memchr(b'\x00', buf).is_some()
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use tempfile::tempdir;
#[test]
fn can_detect_sources() {
let dir = tempdir().unwrap();
let folder1 = dir.path().join("working");
let folder2 = dir.path().join("also-working");
fs::create_dir(&folder1).unwrap();
fs::create_dir(&folder2).unwrap();
let mut inputs = vec![
(folder1.to_string_lossy().to_string(), Source::Local(folder1.to_path_buf())),
(folder2.to_string_lossy().to_string(), Source::Local(folder2.to_path_buf())),
(
"https://git-server.local/git/Test".to_string(),
Source::Git("https://git-server.local/git/Test".to_string()),
),
(
"gitUser@git-server.local:git/Test".to_string(),
Source::Git("gitUser@git-server.local:git/Test".to_string()),
),
("git:git/Test".to_string(), Source::Git("git:git/Test".to_string())),
("hello".to_string(), Source::Git("hello".to_string())),
];
if !cfg!(windows) {
let folder3 = dir.path().join("not:git");
fs::create_dir(&folder3).unwrap();
inputs.push((
folder3.to_string_lossy().to_string(),
Source::Local(folder3.to_path_buf()),
));
}
for (input, expected) in inputs {
assert_eq!(get_source(&input), expected);
}
}
}