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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
use std::env; use std::ffi::{OsStr, OsString}; use std::fs::File; use std::fs::OpenOptions; 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<_> { let mut ret = String::new(); let mut f = try!(File::open(path)); try!(f.read_to_string(&mut ret)); Ok(ret) })().map_err(human).chain_error(|| { human(format!("failed to read `{}`", path.display())) }) } pub fn read_bytes(path: &Path) -> CargoResult<Vec<u8>> { (|| -> CargoResult<_> { let mut ret = Vec::new(); let mut f = try!(File::open(path)); try!(f.read_to_end(&mut ret)); Ok(ret) })().map_err(human).chain_error(|| { human(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(()) })().map_err(human).chain_error(|| { human(format!("failed to write `{}`", path.display())) }) } pub fn append(path: &Path, contents: &[u8]) -> CargoResult<()> { (|| -> CargoResult<()> { let mut f = try!(OpenOptions::new() .write(true) .append(true) .create(true) .open(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")), } }