#![deny(missing_docs)]
pub mod command;
pub mod config;
pub mod engine;
pub mod eval_cache;
pub mod formatter;
use anyhow::Result;
use filetime::FileTime;
use path_clean::PathClean;
use serde::{Deserialize, Serialize};
use std::env;
use std::fs::Metadata;
use std::path::{Path, PathBuf};
use which::which_in;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, Copy, Clone)]
pub struct FileMeta {
pub mtime: i64,
pub size: u64,
}
pub fn get_path_meta(path: &Path) -> Result<FileMeta> {
let metadata = std::fs::metadata(path)?;
Ok(get_meta(&metadata))
}
#[must_use]
pub fn get_meta(metadata: &Metadata) -> FileMeta {
FileMeta {
mtime: FileTime::from_last_modification_time(metadata).unix_seconds(),
size: metadata.len(),
}
}
fn expand_exe(command: &str, reference: &Path) -> Result<PathBuf> {
Ok(which_in(command, env::var_os("PATH"), reference)?.clean())
}
#[must_use]
pub fn expand_path(path: &Path, reference: &Path) -> PathBuf {
let new_path = if path.is_absolute() {
path.to_path_buf()
} else {
reference.join(path)
};
new_path.clean()
}
pub fn expand_if_path(str: String, reference: &Path) -> String {
if str.contains('/') {
expand_path(Path::new(&str), reference)
.to_string_lossy()
.to_string()
} else {
format!("*/{}", str)
}
}
#[cfg(test)]
mod tests {
use super::expand_if_path;
use globset::{GlobBuilder, GlobSetBuilder};
use std::path::Path;
#[test]
fn test_expand_if_path_single_pattern() {
let path = vec![
"/Foo.hs",
"/nested/Foo.hs",
"/nested/nested_again/Foo.hs",
"/different_folder/Foo.hs",
"/nested/different_folder/Foo.hs",
];
let pattern = "Foo.hs";
let mut sum = GlobSetBuilder::new();
let tree_root = Path::new("/");
let pat = expand_if_path(pattern.to_string(), &tree_root);
let glob = GlobBuilder::new(&pat).build().unwrap();
sum.add(glob);
let result = sum.build().unwrap();
let test = path
.clone()
.into_iter()
.filter(|p| result.is_match(p))
.collect::<Vec<&str>>();
assert_eq!(path, test);
}
#[test]
fn test_expand_if_path_wildcard() {
let path = vec![
"/Foo.hs",
"/nested/Foo.hs",
"/nested/nested_again/Foo.hs",
"/different_folder/Foo.hs",
"/nested/different_folder/Foo.hs",
"/nested/Bar.hs",
"/nested/different_folder/Bar.hs",
];
let pattern = "*.hs";
let mut sum = GlobSetBuilder::new();
let tree_root = Path::new("/");
let pat = expand_if_path(pattern.to_string(), &tree_root);
let glob = GlobBuilder::new(&pat).build().unwrap();
sum.add(glob);
let result = sum.build().unwrap();
let test = path
.clone()
.into_iter()
.filter(|p| result.is_match(p))
.collect::<Vec<&str>>();
assert_eq!(path, test);
}
#[test]
fn test_expand_if_path_single_pattern_with_slash() {
let path = vec![
"/Foo.hs",
"/nested/Foo.hs",
"/nested/nested/Foo.hs",
"/different_folder/Foo.hs",
"/nested/different_folder/Foo.hs",
"/nested/Bar.hs",
"/nested/different_folder/Bar.hs",
];
let pattern = "nested/Foo.hs";
let mut sum = GlobSetBuilder::new();
let tree_root = Path::new("/");
let pat = expand_if_path(pattern.to_string(), &tree_root);
let glob = GlobBuilder::new(&pat).build().unwrap();
sum.add(glob);
let result = sum.build().unwrap();
let test = path
.into_iter()
.filter(|p| result.is_match(p))
.collect::<Vec<&str>>();
assert_eq!(vec!["/nested/Foo.hs"], test);
}
}