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 108 109 110 111 112 113 114 115 116 117
use super::errors::*; use directories::UserDirs; use regex::Regex; use std::path::{Path, PathBuf}; use walkdir::WalkDir; pub struct Paths; impl Paths { pub fn shebang(path: &Path) -> Result<String> { let text = std::fs::read_to_string(path) .chain_err(|| ErrorKind::ShebangNotFound(path.to_path_buf()))?; let re = Regex::new(r"#!\s*([/:\.\w\-]+)") .chain_err(|| ErrorKind::ShebangNotFound(path.to_path_buf()))?; match re.captures(&text) { Some(caps) => { if caps.len() > 1 { Ok(caps[1].to_string()) } else { Err(Error::from_kind(ErrorKind::ShebangNotFound( path.to_path_buf(), ))) } } None => Err(Error::from_kind(ErrorKind::ShebangNotFound( path.to_path_buf(), ))), } } pub fn which(name: &str) -> Result<PathBuf> { let extensions = vec![".exe", ".bat", ".cmd", ""]; for ext in extensions.iter() { let exe_name = format!("{}{}", name, ext); match Paths::which_exact(&exe_name) { Some(path) => { return Ok(path); } None => {} }; } Err(Error::from_kind(ErrorKind::UnrecognizedCommand( name.to_string(), ))) } fn which_exact(name: &str) -> Option<PathBuf> { std::env::var_os("PATH").and_then(|paths| { std::env::split_paths(&paths) .filter_map(|dir| { let full_path = dir.join(&name); if full_path.is_file() { Some(full_path) } else { None } }) .next() }) } pub fn extension(path: &Path) -> String { match path.extension() { Some(os_str) => match os_str.to_str() { Some(ext) => ext.to_string(), None => "".to_string(), }, None => "".to_string(), } } pub fn clobber<P: AsRef<Path>>(path: P) -> Result<()> { if path.as_ref().exists() { Paths::clear_read_only(&path)?; std::fs::remove_dir_all(&path)?; } Ok(()) } pub fn clear_read_only<P: AsRef<Path>>(path: P) -> super::errors::Result<()> { for entry in WalkDir::new(path).into_iter().filter_map(|e| e.ok()) { match std::fs::metadata(entry.path()) { Ok(metadata) => { let mut perms = metadata.permissions(); perms.set_readonly(false); std::fs::set_permissions(entry.path(), perms)?; } Err(_) => {} }; } Ok(()) } pub fn docs() -> PathBuf { if let Some(user_dirs) = UserDirs::new() { match user_dirs.document_dir() { Some(dir) => dir.to_path_buf(), None => std::env::temp_dir().join("docs"), } } else { std::env::temp_dir().join("docs") } } } #[cfg(test)] #[test] fn which_test() { match crate::paths::Paths::which("git") { Ok(git_path) => assert!( git_path.exists(), "path {} does not exist.", git_path.display() ), Err(e) => assert!(false, "which('git') returned an error: {}", e), } }