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 std::env; use std::ffi::{OsStr, OsString}; use std::fs::File; use std::io::prelude::*; use std::path::{Path, PathBuf, Component}; use util::{human, internal, CargoResult, ChainError}; pub fn join_paths<T: AsRef<OsStr>>(paths: &[T], env: &str) -> CargoResult<OsString> { env::join_paths(paths.iter()).or_else(|e| { let paths = paths.iter().map(Path::new).collect::<Vec<_>>(); internal(format!("failed to join path array: {:?}", paths)).chain_error(|| { human(format!("failed to join search paths together: {}\n\ Does ${} have an unterminated quote character?", e, env)) }) }) } pub fn dylib_path_envvar() -> &'static str { if cfg!(windows) {"PATH"} else if cfg!(target_os = "macos") {"DYLD_LIBRARY_PATH"} else {"LD_LIBRARY_PATH"} } pub fn dylib_path() -> Vec<PathBuf> { match env::var_os(dylib_path_envvar()) { Some(var) => env::split_paths(&var).collect(), None => Vec::new(), } } pub fn normalize_path(path: &Path) -> PathBuf { let mut components = path.components().peekable(); let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek() .cloned() { components.next(); PathBuf::from(c.as_os_str()) } else { PathBuf::new() }; for component in components { match component { Component::Prefix(..) => unreachable!(), Component::RootDir => { ret.push(component.as_os_str()); } Component::CurDir => {} Component::ParentDir => { ret.pop(); } Component::Normal(c) => { ret.push(c); } } } ret } pub fn without_prefix<'a>(a: &'a Path, b: &'a Path) -> Option<&'a Path> { let mut a = a.components(); let mut b = b.components(); loop { match b.next() { Some(y) => match a.next() { Some(x) if x == y => continue, _ => return None, }, None => return Some(a.as_path()), } } } pub fn read(path: &Path) -> CargoResult<String> { (|| -> CargoResult<String> { let mut ret = String::new(); let mut f = try!(File::open(path)); try!(f.read_to_string(&mut ret)); Ok(ret) }).chain_error(|| { internal(format!("failed to read `{}`", path.display())) }) } pub fn write(path: &Path, contents: &[u8]) -> CargoResult<()> { (|| -> CargoResult<()> { let mut f = try!(File::create(path)); try!(f.write_all(contents)); Ok(()) }).chain_error(|| { internal(format!("failed to write `{}`", path.display())) }) } #[cfg(unix)] pub fn path2bytes(path: &Path) -> CargoResult<&[u8]> { use std::os::unix::prelude::*; Ok(path.as_os_str().as_bytes()) } #[cfg(windows)] pub fn path2bytes(path: &Path) -> CargoResult<&[u8]> { match path.as_os_str().to_str() { Some(s) => Ok(s.as_bytes()), None => Err(human(format!("invalid non-unicode path: {}", path.display()))) } } #[cfg(unix)] pub fn bytes2path(bytes: &[u8]) -> CargoResult<PathBuf> { use std::os::unix::prelude::*; use std::ffi::OsStr; Ok(PathBuf::from(OsStr::from_bytes(bytes))) } #[cfg(windows)] pub fn bytes2path(bytes: &[u8]) -> CargoResult<PathBuf> { use std::str; match str::from_utf8(bytes) { Ok(s) => Ok(PathBuf::from(s)), Err(..) => Err(human("invalid non-unicode path")), } }