use anyhow::{anyhow, Context, Result}; use chrono::{DateTime, Utc}; use std::{ borrow::Cow, path::Path, time::{Duration, SystemTime, UNIX_EPOCH}, }; pub fn unix_now() -> Result { SystemTime::now() .duration_since(UNIX_EPOCH) .with_context(|| "Invalid system time") } pub fn encode_uri(v: &str) -> String { let parts: Vec<_> = v.split('/').map(urlencoding::encode).collect(); parts.join("/") } pub fn decode_uri(v: &str) -> Option> { percent_encoding::percent_decode(v.as_bytes()) .decode_utf8() .ok() } pub fn get_file_name(path: &Path) -> &str { path.file_name() .and_then(|v| v.to_str()) .unwrap_or_default() } #[cfg(unix)] pub async fn get_file_mtime_and_mode(path: &Path) -> Result<(DateTime, u16)> { use std::os::unix::prelude::MetadataExt; let meta = tokio::fs::metadata(path).await?; let datetime: DateTime = meta.modified()?.into(); Ok((datetime, meta.mode() as u16)) } #[cfg(not(unix))] pub async fn get_file_mtime_and_mode(path: &Path) -> Result<(DateTime, u16)> { let meta = tokio::fs::metadata(&path).await?; let datetime: DateTime = meta.modified()?.into(); Ok((datetime, 0o644)) } pub fn try_get_file_name(path: &Path) -> Result<&str> { path.file_name() .and_then(|v| v.to_str()) .ok_or_else(|| anyhow!("Failed to get file name of `{}`", path.display())) } pub fn glob(pattern: &str, target: &str) -> bool { let pat = match ::glob::Pattern::new(pattern) { Ok(pat) => pat, Err(_) => return false, }; pat.matches(target) } #[test] fn test_glob_key() { assert!(glob("", "")); assert!(glob(".*", ".git")); assert!(glob("abc", "abc")); assert!(glob("a*c", "abc")); assert!(glob("a?c", "abc")); assert!(glob("a*c", "abbc")); assert!(glob("*c", "abc")); assert!(glob("a*", "abc")); assert!(glob("?c", "bc")); assert!(glob("a?", "ab")); assert!(!glob("abc", "adc")); assert!(!glob("abc", "abcd")); assert!(!glob("a?c", "abbc")); assert!(!glob("*.log", "log")); assert!(glob("*.abc-cba", "xyz.abc-cba")); assert!(glob("*.abc-cba", "123.xyz.abc-cba")); assert!(glob("*.log", ".log")); assert!(glob("*.log", "a.log")); assert!(glob("*/", "abc/")); assert!(!glob("*/", "abc")); }