1use crate::{
2 core::*,
3 errors::*,
4 sys::{self, user},
5};
6use gory::*;
7use std::{
8 collections::HashMap,
9 ffi::OsStr,
10 fs, io,
11 os::unix::fs::{MetadataExt, PermissionsExt},
12 path::{Component, Path, PathBuf},
13};
14use walkdir::WalkDir;
15
16pub fn abs<T: AsRef<Path>>(path: T) -> FuResult<PathBuf> {
26 let path = path.as_ref();
27
28 if path.empty() {
30 return Err(PathError::Empty.into());
31 }
32
33 let mut path_buf = path.expand()?;
35
36 path_buf = path_buf.trim_protocol();
38
39 path_buf = path_buf.clean()?;
41
42 if !path_buf.is_absolute() {
44 let mut curr = sys::cwd()?;
45 while let Ok(path) = path_buf.first() {
46 match path {
47 Component::CurDir => {
48 path_buf = path_buf.trim_first();
49 },
50 Component::ParentDir => {
51 curr = curr.dir()?;
52 path_buf = path_buf.trim_first();
53 },
54 _ => return Ok(curr.mash(path_buf)),
55 }
56 }
57 return Ok(curr);
58 }
59
60 Ok(path_buf)
61}
62
63pub fn all_dirs<T: AsRef<Path>>(path: T) -> FuResult<Vec<PathBuf>> {
80 let abs = path.as_ref().abs()?;
81 if abs.exists() {
82 let mut paths: Vec<PathBuf> = Vec::new();
83 let mut distinct = HashMap::<PathBuf, bool>::new();
84 if abs.is_dir() {
85 for entry in WalkDir::new(&abs).min_depth(1).follow_links(false).sort_by(|x, y| x.file_name().cmp(y.file_name())) {
86 let path = entry?.into_path();
87
88 if path.is_dir() && !distinct.contains_key(&path) {
90 distinct.insert(path.clone(), true);
91 paths.push(path);
92 }
93 }
94 return Ok(paths);
95 }
96 return Err(PathError::is_not_dir(abs).into());
97 }
98 Err(PathError::does_not_exist(abs).into())
99}
100
101pub fn all_files<T: AsRef<Path>>(path: T) -> FuResult<Vec<PathBuf>> {
121 let abs = path.as_ref().abs()?;
122 if abs.exists() {
123 let mut paths: Vec<PathBuf> = Vec::new();
124 let mut distinct = HashMap::<PathBuf, bool>::new();
125 if abs.is_dir() {
126 for entry in WalkDir::new(&abs).min_depth(1).follow_links(false).sort_by(|x, y| x.file_name().cmp(y.file_name())) {
127 let path = entry?.into_path();
128
129 if path.is_file() && !distinct.contains_key(&path) {
131 distinct.insert(path.clone(), true);
132 paths.push(path);
133 }
134 }
135 return Ok(paths);
136 }
137 return Err(PathError::is_not_dir(abs).into());
138 }
139 Err(PathError::does_not_exist(abs).into())
140}
141
142pub fn all_paths<T: AsRef<Path>>(path: T) -> FuResult<Vec<PathBuf>> {
164 let abs = path.as_ref().abs()?;
165 if abs.exists() {
166 let mut paths: Vec<PathBuf> = Vec::new();
167 let mut distinct = HashMap::<PathBuf, bool>::new();
168 if abs.is_dir() {
169 for entry in WalkDir::new(&abs).min_depth(1).follow_links(false).sort_by(|x, y| x.file_name().cmp(y.file_name())) {
170 let path = entry?.into_path();
171
172 if !distinct.contains_key(&path) {
174 distinct.insert(path.clone(), true);
175 paths.push(path);
176 }
177 }
178 return Ok(paths);
179 }
180 return Err(PathError::is_not_dir(abs).into());
181 }
182 Err(PathError::does_not_exist(abs).into())
183}
184
185pub fn dirs<T: AsRef<Path>>(path: T) -> FuResult<Vec<PathBuf>> {
203 let abs = path.as_ref().abs()?;
204 if abs.exists() {
205 if abs.is_dir() {
206 let mut paths: Vec<PathBuf> = Vec::new();
207 for entry in fs::read_dir(abs)? {
208 let entry = entry?;
209 let path = entry.path();
210 if path.is_dir() {
211 paths.push(path.abs()?);
212 }
213 }
214 paths.sort();
215 return Ok(paths);
216 }
217 return Err(PathError::is_not_dir(abs).into());
218 }
219 Err(PathError::does_not_exist(abs).into())
220}
221
222pub fn exists<T: AsRef<Path>>(path: T) -> bool {
231 metadata(path).is_ok()
232}
233
234pub fn expand<T: AsRef<Path>>(path: T) -> FuResult<PathBuf> {
247 let mut path = path.as_ref().to_path_buf();
248 let pathstr = path.to_string()?;
249
250 match pathstr.matches('~').count() {
252 cnt if cnt > 1 => return Err(PathError::multiple_home_symbols(path).into()),
254
255 cnt if cnt == 1 && !path.has_prefix("~/") && pathstr != "~" => {
257 return Err(PathError::invalid_expansion(path).into());
258 },
259
260 cnt if cnt == 1 && pathstr == "~" => {
262 path = user::home_dir()?;
263 },
264
265 1 => path = user::home_dir()?.mash(&pathstr[2..]),
267 _ => {},
268 }
269
270 let pathstr = path.to_string()?;
272 if pathstr.matches('$').some() {
273 let mut path_buf = PathBuf::new();
274 for x in path.components() {
275 match x {
276 Component::Normal(y) => {
277 let seg = y.to_string()?;
278 if let Some(chunk) = seg.strip_prefix("${") {
279 if let Some(key) = chunk.strip_suffix("}") {
280 let var = sys::var(key)?;
281 path_buf.push(var);
282 } else {
283 return Err(PathError::invalid_expansion(seg).into());
284 }
285 } else if let Some(key) = seg.strip_prefix('$') {
286 let var = sys::var(key)?;
287 path_buf.push(var);
288 } else {
289 path_buf.push(seg);
290 }
291 },
292 _ => path_buf.push(x),
293 }
294 }
295 path = path_buf;
296 }
297
298 Ok(path)
299}
300
301pub fn files<T: AsRef<Path>>(path: T) -> FuResult<Vec<PathBuf>> {
320 let abs = path.as_ref().abs()?;
321 if abs.exists() {
322 if abs.is_dir() {
323 let mut paths: Vec<PathBuf> = Vec::new();
324 for entry in fs::read_dir(abs)? {
325 let entry = entry?;
326 let path = entry.path();
327 if path.is_file() {
328 paths.push(path.abs()?);
329 }
330 }
331 paths.sort();
332 return Ok(paths);
333 }
334 return Err(PathError::is_not_dir(abs).into());
335 }
336 Err(PathError::does_not_exist(abs).into())
337}
338
339pub fn is_dir<T: AsRef<Path>>(path: T) -> bool {
348 match metadata(path) {
349 Ok(x) => x.is_dir(),
350 Err(_) => false,
351 }
352}
353
354pub fn is_exec<T: AsRef<Path>>(path: T) -> bool {
372 match metadata(path) {
373 Ok(x) => x.permissions().mode() & 0o111 != 0,
374 Err(_) => false,
375 }
376}
377
378pub fn is_file<T: AsRef<Path>>(path: T) -> bool {
387 match metadata(path) {
388 Ok(x) => x.is_file(),
389 Err(_) => false,
390 }
391}
392
393pub fn is_readonly<T: AsRef<Path>>(path: T) -> bool {
411 match metadata(path) {
412 Ok(x) => x.permissions().readonly(),
413 Err(_) => false,
414 }
415}
416
417pub fn is_symlink<T: AsRef<Path>>(path: T) -> bool {
434 match path.as_ref().abs() {
435 Ok(abs) => readlink(abs).is_ok(),
436 Err(_) => false,
437 }
438}
439
440pub fn is_symlink_dir<T: AsRef<Path>>(path: T) -> bool {
457 match path.as_ref().abs() {
458 Ok(abs) => match readlink(&abs) {
459 Ok(target) => match target.abs_from(&abs) {
460 Ok(x) => x.is_dir(),
461 Err(_) => false,
462 },
463 Err(_) => false,
464 },
465 Err(_) => false,
466 }
467}
468
469pub fn is_symlink_file<T: AsRef<Path>>(path: T) -> bool {
487 match path.as_ref().abs() {
488 Ok(abs) => match readlink(&abs) {
489 Ok(target) => match target.abs_from(&abs) {
490 Ok(x) => x.is_file(),
491 Err(_) => false,
492 },
493 Err(_) => false,
494 },
495 Err(_) => false,
496 }
497}
498
499pub fn gid<T: AsRef<Path>>(path: T) -> FuResult<u32> {
508 Ok(metadata(path)?.gid())
509}
510
511pub fn glob<T: AsRef<Path>>(src: T) -> FuResult<Vec<PathBuf>> {
530 let abs = src.as_ref().abs()?.to_string()?;
531 let mut paths: Vec<PathBuf> = Vec::new();
532 for x in glob::glob(&abs)? {
533 paths.push(x.map_err(|err| io::Error::new(io::ErrorKind::Other, format!("glob failure: {}", err.to_string())))?.abs()?);
534 }
535 Ok(paths)
536}
537
538pub fn mash<T: AsRef<Path>, U: AsRef<Path>>(dir: T, base: U) -> PathBuf {
550 dir.as_ref().join(base.as_ref().trim_prefix("/")).components().collect::<PathBuf>()
551}
552
553pub fn metadata<T: AsRef<Path>>(path: T) -> FuResult<fs::Metadata> {
564 let abs = path.as_ref().abs()?;
565 let meta = fs::metadata(abs)?;
566 Ok(meta)
567}
568
569pub fn parse_paths<T: AsRef<str>>(value: T) -> FuResult<Vec<PathBuf>> {
580 let mut paths: Vec<PathBuf> = Vec::new();
581 for dir in value.as_ref().split(':') {
582 let path = match dir == "" {
584 true => sys::cwd()?,
585 false => PathBuf::from(dir),
586 };
587 paths.push(path);
588 }
589 Ok(paths)
590}
591
592pub fn paths<T: AsRef<Path>>(path: T) -> FuResult<Vec<PathBuf>> {
612 let abs = path.as_ref().abs()?;
613 if abs.exists() {
614 if abs.is_dir() {
615 let mut paths: Vec<PathBuf> = Vec::new();
616 for entry in fs::read_dir(abs)? {
617 let entry = entry?;
618 let path = entry.path();
619 paths.push(path.abs()?);
620 }
621 paths.sort();
622 return Ok(paths);
623 }
624 return Err(PathError::is_not_dir(abs).into());
625 }
626 Err(PathError::does_not_exist(abs).into())
627}
628
629pub fn readlink<T: AsRef<Path>>(path: T) -> FuResult<PathBuf> {
646 let abs = path.as_ref().abs()?;
647 let abs = fs::read_link(abs)?;
648 Ok(abs)
649}
650
651pub fn rel_to(dir: &str) -> FuResult<PathBuf> {
660 let cwd = sys::cwd()?;
661
662 let mut path = cwd.expand()?;
664
665 if dir.is_empty() {
667 return Ok(path);
668 }
669
670 let target = OsStr::new(dir);
671 while path.last()? != Component::Normal(&target) {
672 path = path.trim_last();
673 }
674
675 Ok(path)
676}
677
678pub fn uid<T: AsRef<Path>>(path: T) -> FuResult<u32> {
687 Ok(metadata(path)?.uid())
688}
689
690pub trait PathExt {
693 fn abs(&self) -> FuResult<PathBuf>;
703
704 fn abs_from<T: AsRef<Path>>(&self, path: T) -> FuResult<PathBuf>;
715
716 fn base(&self) -> FuResult<String>;
725
726 fn chmod(&self, mode: u32) -> FuResult<()>;
744
745 fn clean(&self) -> FuResult<PathBuf>;
761
762 fn concat<T: AsRef<str>>(&self, val: T) -> FuResult<PathBuf>;
771
772 fn dir(&self) -> FuResult<PathBuf>;
782
783 fn empty(&self) -> bool;
792
793 fn exists(&self) -> bool;
802
803 fn expand(&self) -> FuResult<PathBuf>;
813
814 fn ext(&self) -> FuResult<String>;
823
824 fn first(&self) -> FuResult<Component>;
835
836 fn gid(&self) -> FuResult<u32>;
845
846 fn has<T: AsRef<Path>>(&self, path: T) -> bool;
857
858 fn has_prefix<T: AsRef<Path>>(&self, prefix: T) -> bool;
869
870 fn has_suffix<T: AsRef<Path>>(&self, suffix: T) -> bool;
881
882 fn is_dir(&self) -> bool;
891
892 fn is_exec(&self) -> bool;
910
911 fn is_file(&self) -> bool;
920
921 fn is_readonly(&self) -> bool;
939
940 fn is_symlink(&self) -> bool;
957
958 fn is_symlink_dir(&self) -> bool;
974
975 fn is_symlink_file(&self) -> bool;
993
994 fn last(&self) -> FuResult<Component>;
1005
1006 fn mash<T: AsRef<Path>>(&self, path: T) -> PathBuf;
1018
1019 fn metadata(&self) -> FuResult<fs::Metadata>;
1029
1030 fn mode(&self) -> FuResult<u32>;
1046
1047 fn name(&self) -> FuResult<String>;
1056
1057 fn perms(&self) -> FuResult<fs::Permissions>;
1073
1074 fn readlink(&self) -> FuResult<PathBuf>;
1091
1092 fn relative_from<T: AsRef<Path>>(&self, path: T) -> FuResult<PathBuf>;
1101
1102 fn setperms(&self, perms: fs::Permissions) -> FuResult<PathBuf>;
1120
1121 fn trim_ext(&self) -> FuResult<PathBuf>;
1130
1131 fn trim_first(&self) -> PathBuf;
1140
1141 fn trim_last(&self) -> PathBuf;
1150
1151 fn trim_prefix<T: AsRef<Path>>(&self, prefix: T) -> PathBuf;
1160
1161 fn trim_protocol(&self) -> PathBuf;
1171
1172 fn trim_suffix<T: AsRef<Path>>(&self, suffix: T) -> PathBuf;
1181
1182 fn uid(&self) -> FuResult<u32>;
1191}
1192
1193impl PathExt for Path {
1194 fn abs(&self) -> FuResult<PathBuf> {
1195 abs(self)
1196 }
1197
1198 fn abs_from<T: AsRef<Path>>(&self, base: T) -> FuResult<PathBuf> {
1199 let base = base.as_ref().abs()?;
1200 if !self.is_absolute() && self != base {
1201 let mut path = base.trim_last();
1202 let mut components = self.components();
1203 loop {
1204 match components.next() {
1205 Some(component) => match component {
1206 Component::ParentDir => path = path.trim_last(),
1207 Component::Normal(x) => return Ok(path.mash(x).mash(components.collect::<PathBuf>()).clean()?),
1208 _ => {},
1209 },
1210 None => return Err(PathError::Empty.into()),
1211 }
1212 }
1213 }
1214 Ok(self.to_path_buf())
1215 }
1216
1217 fn base(&self) -> FuResult<String> {
1218 self.file_name().ok_or_else(|| PathError::filename_not_found(self))?.to_string()
1219 }
1220
1221 fn chmod(&self, mode: u32) -> FuResult<()> {
1222 sys::chmod(self, mode)?;
1223 Ok(())
1224 }
1225
1226 fn clean(&self) -> FuResult<PathBuf> {
1227 let mut cnt = 0;
1234 let mut prev = None;
1235 let mut path_buf = PathBuf::new();
1236 for component in self.components() {
1237 match component {
1238 x if x == Component::CurDir && cnt == 0 => continue,
1240
1241 x if x == Component::ParentDir && cnt > 0 && !prev.has(Component::ParentDir) => {
1243 match prev.unwrap() {
1244 Component::RootDir => {},
1246
1247 Component::Normal(_) => {
1249 cnt -= 1;
1250 path_buf.pop();
1251 prev = path_buf.components().last();
1252 },
1253 _ => {},
1254 }
1255 continue;
1256 },
1257
1258 _ => {
1260 cnt += 1;
1261 path_buf.push(component);
1262 prev = Some(component);
1263 },
1264 };
1265 }
1266
1267 if path_buf.empty() {
1269 path_buf.push(".");
1270 }
1271 Ok(path_buf)
1272 }
1273
1274 fn concat<T: AsRef<str>>(&self, val: T) -> FuResult<PathBuf> {
1275 Ok(PathBuf::from(format!("{}{}", self.to_string()?, val.as_ref())))
1276 }
1277
1278 fn dir(&self) -> FuResult<PathBuf> {
1279 let dir = self.parent().ok_or_else(|| PathError::parent_not_found(self))?;
1280 Ok(dir.to_path_buf())
1281 }
1282
1283 fn empty(&self) -> bool {
1284 self == PathBuf::new()
1285 }
1286
1287 fn exists(&self) -> bool {
1288 exists(&self)
1289 }
1290
1291 fn expand(&self) -> FuResult<PathBuf> {
1292 expand(&self)
1293 }
1294
1295 fn ext(&self) -> FuResult<String> {
1296 match self.extension() {
1297 Some(val) => val.to_string(),
1298 None => Err(PathError::extension_not_found(self).into()),
1299 }
1300 }
1301
1302 fn first(&self) -> FuResult<Component> {
1303 self.components().first_result()
1304 }
1305
1306 fn gid(&self) -> FuResult<u32> {
1307 gid(&self)
1308 }
1309
1310 fn has<T: AsRef<Path>>(&self, path: T) -> bool {
1311 match (self.to_string(), path.as_ref().to_string()) {
1312 (Ok(base), Ok(path)) => base.contains(&path),
1313 _ => false,
1314 }
1315 }
1316
1317 fn has_prefix<T: AsRef<Path>>(&self, prefix: T) -> bool {
1318 match (self.to_string(), prefix.as_ref().to_string()) {
1319 (Ok(base), Ok(prefix)) => base.starts_with(&prefix),
1320 _ => false,
1321 }
1322 }
1323
1324 fn has_suffix<T: AsRef<Path>>(&self, suffix: T) -> bool {
1325 match (self.to_string(), suffix.as_ref().to_string()) {
1326 (Ok(base), Ok(suffix)) => base.ends_with(&suffix),
1327 _ => false,
1328 }
1329 }
1330
1331 fn is_dir(&self) -> bool {
1332 is_dir(self)
1333 }
1334
1335 fn is_exec(&self) -> bool {
1336 is_exec(self)
1337 }
1338
1339 fn is_file(&self) -> bool {
1340 is_file(self)
1341 }
1342
1343 fn is_readonly(&self) -> bool {
1344 is_readonly(self)
1345 }
1346
1347 fn is_symlink(&self) -> bool {
1348 is_symlink(self)
1349 }
1350
1351 fn is_symlink_dir(&self) -> bool {
1352 is_symlink_dir(self)
1353 }
1354
1355 fn is_symlink_file(&self) -> bool {
1356 is_symlink_file(self)
1357 }
1358
1359 fn last(&self) -> FuResult<Component> {
1360 self.components().last_result()
1361 }
1362
1363 fn mash<T: AsRef<Path>>(&self, path: T) -> PathBuf {
1364 mash(self, path)
1365 }
1366
1367 fn metadata(&self) -> FuResult<fs::Metadata> {
1368 let meta = fs::metadata(self)?;
1369 Ok(meta)
1370 }
1371
1372 fn mode(&self) -> FuResult<u32> {
1373 let perms = self.perms()?;
1374 Ok(perms.mode())
1375 }
1376
1377 fn name(&self) -> FuResult<String> {
1378 self.trim_ext()?.base()
1379 }
1380
1381 fn perms(&self) -> FuResult<fs::Permissions> {
1382 Ok(self.metadata()?.permissions())
1383 }
1384
1385 fn readlink(&self) -> FuResult<PathBuf> {
1386 readlink(self)
1387 }
1388
1389 fn relative_from<T: AsRef<Path>>(&self, base: T) -> FuResult<PathBuf> {
1390 let path = self.abs()?;
1391 let base = base.as_ref().abs()?;
1392 if path != base {
1393 let mut x = path.components();
1394 let mut y = base.components();
1395 let mut comps: Vec<Component> = vec![];
1396 loop {
1397 match (x.next(), y.next()) {
1398 (None, None) => break,
1399 (Some(a), None) => {
1400 comps.push(a);
1401 comps.extend(x.by_ref());
1402 break;
1403 },
1404 (None, _) => comps.push(Component::ParentDir),
1405 (Some(a), Some(b)) if comps.is_empty() && a == b => {},
1406 (Some(a), Some(b)) if b == Component::CurDir => comps.push(a),
1407 (Some(_), Some(b)) if b == Component::ParentDir => return Ok(path),
1408 (Some(a), Some(_)) => {
1409 for _ in y {
1410 comps.push(Component::ParentDir);
1411 }
1412 comps.push(a);
1413 comps.extend(x.by_ref());
1414 break;
1415 },
1416 }
1417 }
1418 return Ok(comps.iter().collect::<PathBuf>());
1419 }
1420 Ok(path)
1421 }
1422
1423 fn setperms(&self, perms: fs::Permissions) -> FuResult<PathBuf> {
1424 fs::set_permissions(&self, perms)?;
1425 Ok(self.to_path_buf())
1426 }
1427
1428 fn trim_ext(&self) -> FuResult<PathBuf> {
1429 Ok(match self.extension() {
1430 Some(val) => self.trim_suffix(format!(".{}", val.to_string()?)),
1431 None => self.to_path_buf(),
1432 })
1433 }
1434
1435 fn trim_first(&self) -> PathBuf {
1436 self.components().drop(1).as_path().to_path_buf()
1437 }
1438
1439 fn trim_last(&self) -> PathBuf {
1440 self.components().drop(-1).as_path().to_path_buf()
1441 }
1442
1443 fn trim_prefix<T: AsRef<Path>>(&self, prefix: T) -> PathBuf {
1444 match (self.to_string(), prefix.as_ref().to_string()) {
1445 (Ok(base), Ok(prefix)) if base.starts_with(&prefix) => PathBuf::from(&base[prefix.size()..]),
1446 _ => self.to_path_buf(),
1447 }
1448 }
1449
1450 fn trim_protocol(&self) -> PathBuf {
1451 match self.to_string() {
1452 Ok(base) => match base.find("//") {
1453 Some(i) => {
1454 let (prefix, suffix) = base.split_at(i + 2);
1455 let lower = prefix.to_lowercase();
1456 let lower = lower.trim_start_matches("file://");
1457 let lower = lower.trim_start_matches("ftp://");
1458 let lower = lower.trim_start_matches("http://");
1459 let lower = lower.trim_start_matches("https://");
1460 if lower != "" {
1461 PathBuf::from(format!("{}{}", prefix, suffix))
1462 } else {
1463 PathBuf::from(suffix)
1464 }
1465 },
1466 _ => PathBuf::from(base),
1467 },
1468 _ => self.to_path_buf(),
1469 }
1470 }
1471
1472 fn trim_suffix<T: AsRef<Path>>(&self, suffix: T) -> PathBuf {
1473 match (self.to_string(), suffix.as_ref().to_string()) {
1474 (Ok(base), Ok(suffix)) if base.ends_with(&suffix) => PathBuf::from(&base[..base.size() - suffix.size()]),
1475 _ => self.to_path_buf(),
1476 }
1477 }
1478
1479 fn uid(&self) -> FuResult<u32> {
1480 uid(&self)
1481 }
1482}
1483
1484pub trait PathColorExt {
1485 fn black(&self) -> ColorString;
1486 fn red(&self) -> ColorString;
1487 fn green(&self) -> ColorString;
1488 fn yellow(&self) -> ColorString;
1489 fn blue(&self) -> ColorString;
1490 fn magenta(&self) -> ColorString;
1491 fn cyan(&self) -> ColorString;
1492 fn white(&self) -> ColorString;
1493}
1494impl PathColorExt for Path {
1495 fn black(&self) -> ColorString {
1496 self.display().to_string().black()
1497 }
1498
1499 fn red(&self) -> ColorString {
1500 self.display().to_string().red()
1501 }
1502
1503 fn green(&self) -> ColorString {
1504 self.display().to_string().green()
1505 }
1506
1507 fn yellow(&self) -> ColorString {
1508 self.display().to_string().yellow()
1509 }
1510
1511 fn blue(&self) -> ColorString {
1512 self.display().to_string().blue()
1513 }
1514
1515 fn magenta(&self) -> ColorString {
1516 self.display().to_string().magenta()
1517 }
1518
1519 fn cyan(&self) -> ColorString {
1520 self.display().to_string().cyan()
1521 }
1522
1523 fn white(&self) -> ColorString {
1524 self.display().to_string().white()
1525 }
1526}
1527
1528#[cfg(test)]
1531mod tests {
1532 use crate::prelude::*;
1533 use std::path::Component;
1534
1535 fn setup() -> PathBuf {
1537 let temp = PathBuf::from("tests/temp").abs().unwrap();
1538 sys::mkdir(&temp).unwrap();
1539 temp
1540 }
1541
1542 #[test]
1543 fn test_abs() {
1544 let cwd = sys::cwd().unwrap();
1545 let prev = cwd.dir().unwrap();
1546
1547 assert_eq!(sys::abs("foo").unwrap(), cwd.mash("foo"));
1549
1550 assert_eq!(sys::abs("..//").unwrap(), prev);
1552 assert_eq!(sys::abs("../").unwrap(), prev);
1553 assert_eq!(sys::abs("..").unwrap(), prev);
1554
1555 assert_eq!(sys::abs(".//").unwrap(), cwd);
1557 assert_eq!(sys::abs("./").unwrap(), cwd);
1558 assert_eq!(sys::abs(".").unwrap(), cwd);
1559
1560 let home = PathBuf::from(user::home_dir().unwrap());
1562 assert_eq!(sys::abs("~").unwrap(), home);
1563 assert_eq!(sys::abs("~/").unwrap(), home);
1564
1565 assert_eq!(sys::abs("~/foo").unwrap(), home.mash("foo"));
1567
1568 assert_eq!(sys::abs("~/foo/bar/../.").unwrap(), home.mash("foo"));
1570 assert_eq!(sys::abs("~/foo/bar/../").unwrap(), home.mash("foo"));
1571 assert_eq!(sys::abs("~/foo/bar/../blah").unwrap(), home.mash("foo/blah"));
1572
1573 }
1580
1581 #[test]
1582 fn test_all_dirs() {
1583 let tmpdir = setup().mash("path_all_dirs");
1584 let tmpdir1 = tmpdir.mash("dir1");
1585 let tmpdir2 = tmpdir1.mash("dir2");
1586 let tmpfile1 = tmpdir.mash("file1");
1587 let tmpfile2 = tmpdir.mash("file2");
1588
1589 assert!(sys::all_dirs("").is_err());
1591 assert!(sys::all_dirs("foobar").is_err());
1592
1593 assert!(sys::mkdir(&tmpdir1).is_ok());
1595 assert!(sys::mkdir(&tmpdir2).is_ok());
1596 assert_eq!(tmpdir.is_dir(), true);
1597 assert_eq!(tmpdir.is_file(), false);
1598 assert_eq!(tmpdir1.is_dir(), true);
1599 assert_eq!(tmpdir2.is_dir(), true);
1600 assert!(sys::touch(&tmpfile1).is_ok());
1601 assert_eq!(tmpfile1.is_dir(), false);
1602 assert_eq!(tmpfile1.is_file(), true);
1603 assert!(sys::touch(&tmpfile2).is_ok());
1604 assert_eq!(tmpfile2.is_dir(), false);
1605 assert_eq!(tmpfile2.is_file(), true);
1606
1607 assert!(sys::all_dirs(&tmpfile1).is_err());
1609
1610 let dirs = sys::all_dirs(&tmpdir).unwrap();
1612 assert_iter_eq(dirs, vec![tmpdir1, tmpdir2]);
1613
1614 assert!(sys::remove_all(&tmpdir).is_ok());
1616 assert_eq!(tmpdir.exists(), false);
1617 }
1618
1619 #[test]
1620 fn test_all_files() {
1621 let tmpdir = setup().mash("path_all_files");
1622 let tmpdir1 = tmpdir.mash("dir1");
1623 let tmpdir2 = tmpdir1.mash("dir2");
1624 let tmpfile1 = tmpdir1.mash("file1");
1625 let tmpfile2 = tmpdir2.mash("file2");
1626
1627 assert!(sys::all_files("").is_err());
1629 assert!(sys::all_files("foobar").is_err());
1630
1631 assert!(sys::mkdir(&tmpdir1).is_ok());
1633 assert!(sys::mkdir(&tmpdir2).is_ok());
1634 assert_eq!(tmpdir.is_dir(), true);
1635 assert_eq!(tmpdir.is_file(), false);
1636 assert_eq!(tmpdir1.is_dir(), true);
1637 assert_eq!(tmpdir2.is_dir(), true);
1638 assert!(sys::touch(&tmpfile1).is_ok());
1639 assert_eq!(tmpfile1.is_dir(), false);
1640 assert_eq!(tmpfile1.is_file(), true);
1641 assert!(sys::touch(&tmpfile2).is_ok());
1642 assert_eq!(tmpfile2.is_dir(), false);
1643 assert_eq!(tmpfile2.is_file(), true);
1644
1645 assert!(sys::all_files(&tmpfile1).is_err());
1647
1648 let files = sys::all_files(&tmpdir).unwrap();
1650 assert_iter_eq(files, vec![tmpfile2, tmpfile1]);
1651
1652 assert!(sys::remove_all(&tmpdir).is_ok());
1654 assert_eq!(tmpdir.exists(), false);
1655 }
1656
1657 #[test]
1658 fn test_all_paths() {
1659 let tmpdir = setup().mash("path_all_paths");
1660 let tmpdir1 = tmpdir.mash("dir1");
1661 let tmpdir2 = tmpdir1.mash("dir2");
1662 let tmpfile1 = tmpdir1.mash("file1");
1663 let tmpfile2 = tmpdir2.mash("file2");
1664
1665 assert!(sys::all_paths("").is_err());
1667 assert!(sys::all_paths("foobar").is_err());
1668
1669 assert!(sys::mkdir(&tmpdir1).is_ok());
1671 assert!(sys::mkdir(&tmpdir2).is_ok());
1672 assert_eq!(tmpdir.is_dir(), true);
1673 assert_eq!(tmpdir.is_file(), false);
1674 assert_eq!(tmpdir1.is_dir(), true);
1675 assert_eq!(tmpdir2.is_dir(), true);
1676 assert!(sys::touch(&tmpfile1).is_ok());
1677 assert_eq!(tmpfile1.is_dir(), false);
1678 assert_eq!(tmpfile1.is_file(), true);
1679 assert!(sys::touch(&tmpfile2).is_ok());
1680 assert_eq!(tmpfile2.is_dir(), false);
1681 assert_eq!(tmpfile2.is_file(), true);
1682
1683 assert!(sys::all_paths(&tmpfile1).is_err());
1685
1686 let paths = sys::all_paths(&tmpdir).unwrap();
1688 assert_iter_eq(paths, vec![tmpdir1, tmpdir2, tmpfile2, tmpfile1]);
1689
1690 assert!(sys::remove_all(&tmpdir).is_ok());
1692 assert_eq!(tmpdir.exists(), false);
1693 }
1694
1695 #[test]
1696 fn test_dirs() {
1697 let tmpdir = setup().mash("path_dirs");
1698 let tmpdir1 = tmpdir.mash("dir1");
1699 let tmpdir2 = tmpdir.mash("dir2");
1700 let tmpfile1 = tmpdir.mash("file1");
1701 let tmpfile2 = tmpdir.mash("file2");
1702
1703 assert!(sys::dirs("").is_err());
1705 assert!(sys::dirs("foobar").is_err());
1706
1707 assert!(sys::mkdir(&tmpdir1).is_ok());
1709 assert!(sys::mkdir(&tmpdir2).is_ok());
1710 assert_eq!(tmpdir.is_dir(), true);
1711 assert_eq!(tmpdir.is_file(), false);
1712 assert_eq!(tmpdir1.is_dir(), true);
1713 assert_eq!(tmpdir2.is_dir(), true);
1714 assert!(sys::touch(&tmpfile1).is_ok());
1715 assert_eq!(tmpfile1.is_dir(), false);
1716 assert_eq!(tmpfile1.is_file(), true);
1717 assert!(sys::touch(&tmpfile2).is_ok());
1718 assert_eq!(tmpfile2.is_dir(), false);
1719 assert_eq!(tmpfile2.is_file(), true);
1720
1721 assert!(sys::dirs(&tmpfile1).is_err());
1723
1724 let dirs = sys::dirs(&tmpdir).unwrap();
1726 assert_iter_eq(dirs, vec![tmpdir1, tmpdir2]);
1727
1728 assert!(sys::remove_all(&tmpdir).is_ok());
1730 assert_eq!(tmpdir.exists(), false);
1731 }
1732
1733 #[test]
1734 fn test_exists() {
1735 let tmpdir = setup().mash("path_exists");
1736 let tmpfile = tmpdir.mash("file");
1737 assert!(sys::remove_all(&tmpdir).is_ok());
1738 assert!(sys::mkdir(&tmpdir).is_ok());
1739 assert_eq!(sys::exists(&tmpfile), false);
1740 assert!(sys::touch(&tmpfile).is_ok());
1741 assert_eq!(sys::exists(&tmpfile), true);
1742 assert!(sys::remove_all(&tmpdir).is_ok());
1743 }
1744
1745 #[test]
1746 fn test_files() {
1747 let tmpdir = setup().mash("path_files");
1748 let tmpdir1 = tmpdir.mash("dir1");
1749 let tmpdir2 = tmpdir.mash("dir2");
1750 let tmpfile1 = tmpdir.mash("file1");
1751 let tmpfile2 = tmpdir.mash("file2");
1752
1753 assert!(sys::files("").is_err());
1755 assert!(sys::files("foobar").is_err());
1756
1757 assert!(sys::mkdir(&tmpdir1).is_ok());
1759 assert!(sys::mkdir(&tmpdir2).is_ok());
1760 assert_eq!(tmpdir.is_dir(), true);
1761 assert_eq!(tmpdir.is_file(), false);
1762 assert_eq!(tmpdir1.is_dir(), true);
1763 assert_eq!(tmpdir2.is_dir(), true);
1764 assert!(sys::touch(&tmpfile1).is_ok());
1765 assert_eq!(tmpfile1.is_dir(), false);
1766 assert_eq!(tmpfile1.is_file(), true);
1767 assert!(sys::touch(&tmpfile2).is_ok());
1768 assert_eq!(tmpfile2.is_dir(), false);
1769 assert_eq!(tmpfile2.is_file(), true);
1770
1771 assert!(sys::files(&tmpfile1).is_err());
1773
1774 let files = sys::files(&tmpdir).unwrap();
1776 assert_iter_eq(files, vec![tmpfile1, tmpfile2]);
1777
1778 assert!(sys::remove_all(&tmpdir).is_ok());
1780 assert_eq!(tmpdir.exists(), false);
1781 }
1782
1783 #[test]
1784 fn test_rel_to() {
1785 assert_eq!(sys::rel_to("home").unwrap(), PathBuf::from("/home"));
1786 }
1787
1788 #[test]
1789 fn test_uid() {
1790 assert!(sys::uid(".").is_ok());
1791 assert!(Path::new(".").uid().is_ok());
1792 }
1793
1794 #[test]
1795 fn test_gid() {
1796 assert!(sys::gid(".").is_ok());
1797 assert!(Path::new(".").gid().is_ok());
1798 }
1799
1800 #[test]
1801 fn test_is_dir() {
1802 assert_eq!(sys::is_dir("."), true);
1803 assert_eq!(sys::is_dir(setup()), true);
1804 assert_eq!(sys::is_dir("/foobar"), false);
1805 }
1806
1807 #[test]
1808 fn test_is_exec() {
1809 let tmpdir = setup().mash("path_is_exec");
1810 let file1 = tmpdir.mash("file1");
1811
1812 assert!(sys::remove_all(&tmpdir).is_ok());
1814 assert!(sys::mkdir(&tmpdir).is_ok());
1815 assert_eq!(sys::is_exec(&file1), false);
1816 assert!(sys::touch_p(&file1, 0o644).is_ok());
1817 assert_eq!(file1.mode().unwrap(), 0o100644);
1818 assert_eq!(file1.is_exec(), false);
1819
1820 assert!(sys::chmod_p(&file1).unwrap().add_x().chmod().is_ok());
1822 assert_eq!(file1.mode().unwrap(), 0o100755);
1823 assert_eq!(file1.is_exec(), true);
1824
1825 assert!(sys::remove_all(&tmpdir).is_ok());
1827 }
1828
1829 #[test]
1830 fn test_is_file() {
1831 let tmpdir = setup().mash("path_is_file");
1832 let tmpfile = tmpdir.mash("file1");
1833
1834 assert!(sys::remove_all(&tmpdir).is_ok());
1835 assert!(sys::mkdir(&tmpdir).is_ok());
1836 assert_eq!(sys::is_file(&tmpfile), false);
1837 assert!(sys::touch(&tmpfile).is_ok());
1838 assert_eq!(sys::is_file(tmpfile), true);
1839
1840 assert!(sys::remove_all(&tmpdir).is_ok());
1842 }
1843
1844 #[test]
1845 fn test_is_readonly() {
1846 let tmpdir = setup().mash("path_is_readonly");
1847 let file1 = tmpdir.mash("file1");
1848 assert!(sys::remove_all(&tmpdir).is_ok());
1849 assert!(sys::mkdir(&tmpdir).is_ok());
1850
1851 assert_eq!(sys::is_readonly(&file1), false);
1852 assert!(sys::touch_p(&file1, 0o644).is_ok());
1853 assert_eq!(file1.is_readonly(), false);
1854 assert!(sys::chmod_p(&file1).unwrap().readonly().chmod().is_ok());
1855 assert_eq!(file1.mode().unwrap(), 0o100444);
1856 assert_eq!(sys::is_readonly(&file1), true);
1857 assert!(sys::remove_all(&tmpdir).is_ok());
1858 }
1859
1860 #[test]
1861 fn test_is_symlink() {
1862 let tmpdir = setup().mash("path_is_symlink");
1863 let file1 = tmpdir.mash("file1");
1864 let link1 = tmpdir.mash("link1");
1865
1866 assert!(sys::remove_all(&tmpdir).is_ok());
1867 assert!(sys::mkdir(&tmpdir).is_ok());
1868 assert_eq!(sys::is_symlink(&link1), false);
1869 assert!(sys::touch(&file1).is_ok());
1870 assert!(sys::symlink(&link1, &file1).is_ok());
1871 assert_eq!(sys::is_symlink(link1), true);
1872
1873 assert!(sys::remove_all(&tmpdir).is_ok());
1875 }
1876
1877 #[test]
1878 fn test_is_symlink_dir() {
1879 let tmpdir = setup().mash("path_is_symlink_dir");
1880 let dir1 = tmpdir.mash("dir1");
1881 let link1 = tmpdir.mash("link1");
1882 let link2 = tmpdir.mash("link2");
1883
1884 assert!(sys::remove_all(&tmpdir).is_ok());
1886 assert!(sys::mkdir(&dir1).is_ok());
1887
1888 assert!(sys::symlink(&link1, &dir1).is_ok());
1890 assert_eq!(sys::is_symlink_dir(&link1), true);
1891 assert_eq!(sys::is_symlink_file(&link1), false);
1892
1893 assert!(sys::symlink(&link2, "dir1").is_ok());
1895 assert_eq!(sys::is_symlink_dir(&link2), true);
1896 assert_eq!(sys::is_symlink_file(&link2), false);
1897
1898 assert!(sys::remove_all(&tmpdir).is_ok());
1900 }
1901
1902 #[test]
1903 fn test_is_symlink_file() {
1904 let tmpdir = setup().mash("path_is_symlink_file");
1905 let file1 = tmpdir.mash("file1");
1906 let link1 = tmpdir.mash("link1");
1907 let link2 = tmpdir.mash("link2");
1908
1909 assert_eq!(sys::is_symlink_file(""), false);
1911
1912 assert!(sys::remove_all(&tmpdir).is_ok());
1914 assert!(sys::mkdir(&tmpdir).is_ok());
1915 assert!(sys::touch(&file1).is_ok());
1916
1917 assert!(sys::symlink(&link1, &file1).is_ok());
1919 assert_eq!(sys::is_symlink_file(&link1), true);
1920 assert_eq!(sys::is_symlink_dir(&link1), false);
1921
1922 assert!(sys::symlink(&link2, "file1").is_ok());
1924 assert_eq!(sys::is_symlink_file(&link2), true);
1925 assert_eq!(sys::is_symlink_dir(&link2), false);
1926
1927 assert!(sys::remove_all(&tmpdir).is_ok());
1929 }
1930
1931 #[test]
1932 fn test_glob() {
1933 let tmpdir = setup().mash("path_glob");
1934 let tmpdir1 = tmpdir.mash("dir1");
1935 let tmpdir2 = tmpdir.mash("dir2");
1936 let tmpfile1 = tmpdir.mash("file1");
1937 let tmpfile2 = tmpdir.mash("file2");
1938
1939 assert!(sys::mkdir(&tmpdir1).is_ok());
1941 assert!(sys::mkdir(&tmpdir2).is_ok());
1942 assert_eq!(tmpdir.is_dir(), true);
1943 assert_eq!(tmpdir.is_file(), false);
1944 assert_eq!(tmpdir1.is_dir(), true);
1945 assert_eq!(tmpdir2.is_dir(), true);
1946 assert!(sys::touch(&tmpfile1).is_ok());
1947 assert_eq!(tmpfile1.is_dir(), false);
1948 assert_eq!(tmpfile1.is_file(), true);
1949 assert!(sys::touch(&tmpfile2).is_ok());
1950 assert_eq!(tmpfile2.is_dir(), false);
1951 assert_eq!(tmpfile2.is_file(), true);
1952
1953 let paths = sys::glob(tmpdir.mash("*")).unwrap();
1955 assert_iter_eq(paths, vec![tmpdir1, tmpdir2, tmpfile1, tmpfile2]);
1956
1957 assert!(sys::remove_all(&tmpdir).is_ok());
1959 assert_eq!(tmpdir.exists(), false);
1960 }
1961
1962 #[test]
1963 fn test_metadata() {
1964 let meta = sys::metadata(setup()).unwrap();
1965 assert_eq!(meta.is_dir(), true);
1966 }
1967
1968 #[test]
1969 fn test_paths() {
1970 let tmpdir = setup().mash("path_paths");
1971 let tmpdir1 = tmpdir.mash("dir1");
1972 let tmpdir2 = tmpdir.mash("dir2");
1973 let tmpfile1 = tmpdir.mash("file1");
1974 let tmpfile2 = tmpdir.mash("file2");
1975
1976 assert!(sys::paths("").is_err());
1978 assert!(sys::paths("foobar").is_err());
1979
1980 assert!(sys::mkdir(&tmpdir1).is_ok());
1982 assert!(sys::mkdir(&tmpdir2).is_ok());
1983 assert_eq!(tmpdir.is_dir(), true);
1984 assert_eq!(tmpdir.is_file(), false);
1985 assert_eq!(tmpdir1.is_dir(), true);
1986 assert_eq!(tmpdir2.is_dir(), true);
1987 assert!(sys::touch(&tmpfile1).is_ok());
1988 assert_eq!(tmpfile1.is_dir(), false);
1989 assert_eq!(tmpfile1.is_file(), true);
1990 assert!(sys::touch(&tmpfile2).is_ok());
1991 assert_eq!(tmpfile2.is_dir(), false);
1992 assert_eq!(tmpfile2.is_file(), true);
1993
1994 assert!(sys::paths(&tmpfile1).is_err());
1996
1997 let paths = sys::paths(&tmpdir).unwrap();
1999 assert_iter_eq(paths, vec![tmpdir1, tmpdir2, tmpfile1, tmpfile2]);
2000
2001 assert!(sys::remove_all(&tmpdir).is_ok());
2003 assert_eq!(tmpdir.exists(), false);
2004 }
2005
2006 #[test]
2007 fn test_parse_paths() {
2008 let paths = vec![PathBuf::from("/foo1"), PathBuf::from("/foo2/bar")];
2009 assert_iter_eq(sys::parse_paths("/foo1:/foo2/bar").unwrap(), paths);
2010
2011 let paths = vec![
2012 sys::cwd().unwrap(),
2013 PathBuf::from("/foo1"),
2014 PathBuf::from("/foo2/bar"),
2015 ];
2016 assert_iter_eq(sys::parse_paths(":/foo1:/foo2/bar").unwrap(), paths);
2017 }
2018
2019 #[test]
2020 fn test_readlink() {
2021 let tmpdir = setup().mash("path_readlink");
2022 let file1 = tmpdir.mash("file1");
2023 let link1 = tmpdir.mash("link1");
2024
2025 assert!(sys::remove_all(&tmpdir).is_ok());
2026 assert!(sys::mkdir(&tmpdir).is_ok());
2027 assert!(sys::touch(&file1).is_ok());
2028 assert!(sys::symlink(&link1, &file1).is_ok());
2029 assert_eq!(sys::is_symlink_file(&link1), true);
2030 assert_eq!(sys::is_symlink_dir(&link1), false);
2031 assert_eq!(sys::readlink(&link1).unwrap(), file1);
2032
2033 assert!(sys::remove_all(&tmpdir).is_ok());
2035 }
2036
2037 #[test]
2041 fn test_pathext_abs_from() {
2042 let home = PathBuf::from("~").abs().unwrap();
2043
2044 assert!(PathBuf::from("foo").abs_from("").is_err());
2046
2047 assert_eq!(PathBuf::from("/foo").abs_from("foo1").unwrap(), PathBuf::from("/foo"));
2049
2050 assert_eq!(PathBuf::from("foo2").abs_from(home.mash("foo1").abs().unwrap()).unwrap(), home.mash("foo2"));
2052 assert_eq!(PathBuf::from("./foo2").abs_from(home.mash("foo1").abs().unwrap()).unwrap(), home.mash("foo2"));
2053
2054 assert_eq!(PathBuf::from("../foo2").abs_from(home.mash("bar1/foo1").abs().unwrap()).unwrap(), home.mash("foo2"));
2056 assert_eq!(PathBuf::from("bar2/foo2").abs_from(home.mash("bar1/foo1").abs().unwrap()).unwrap(), home.mash("bar1/bar2/foo2"));
2057 assert_eq!(PathBuf::from("../../foo2").abs_from(home.mash("bar1/foo1").abs().unwrap()).unwrap(), home.trim_last().mash("foo2"));
2058
2059 assert_eq!(PathBuf::from("blah1/bar2/foo2").abs_from(home.mash("bar1/foo1").abs().unwrap()).unwrap(), home.mash("bar1/blah1/bar2/foo2"));
2061 }
2062
2063 #[test]
2064 fn test_pathext_base() {
2065 assert_eq!("bar", PathBuf::from("/foo/bar").base().unwrap());
2066 }
2067
2068 #[test]
2069 fn test_pathext_chmod() {
2070 let tmpdir = setup().mash("path_pathbuf_chmod");
2071 let file1 = tmpdir.mash("file1");
2072
2073 assert!(sys::remove_all(&tmpdir).is_ok());
2074 assert!(sys::mkdir(&tmpdir).is_ok());
2075 assert!(sys::touch(&file1).is_ok());
2076 assert!(file1.chmod(0o644).is_ok());
2077 assert_eq!(file1.mode().unwrap(), 0o100644);
2078 assert!(file1.chmod(0o555).is_ok());
2079 assert_eq!(file1.mode().unwrap(), 0o100555);
2080 assert!(sys::remove_all(&tmpdir).is_ok());
2081 }
2082
2083 #[test]
2084 fn test_pathext_clean() {
2085 let tests = vec![
2086 ("/", "/"),
2088 ("/", "//"),
2090 ("/", "///"),
2091 (".", ".//"),
2092 ("/", "//.."),
2094 ("..", "..//"),
2095 ("/", "/..//"),
2096 ("foo/bar/blah", "foo//bar///blah"),
2097 ("/foo/bar/blah", "/foo//bar///blah"),
2098 ("/", "/.//./"),
2100 (".", "././/./"),
2101 (".", "./"),
2102 ("/", "/./"),
2103 ("foo", "./foo"),
2104 ("foo/bar", "./foo/./bar"),
2105 ("/foo/bar", "/foo/./bar"),
2106 ("foo/bar", "foo/bar/."),
2107 ("/", "/.."),
2109 ("/foo", "/../foo"),
2110 (".", "foo/.."),
2111 ("../foo", "../foo"),
2112 ("/bar", "/foo/../bar"),
2113 ("foo", "foo/bar/.."),
2114 ("bar", "foo/../bar"),
2115 ("/bar", "/foo/../bar"),
2116 (".", "foo/bar/../../"),
2117 ("..", "foo/bar/../../.."),
2118 ("/", "/foo/bar/../../.."),
2119 ("/", "/foo/bar/../../../.."),
2120 ("../..", "foo/bar/../../../.."),
2121 ("blah/bar", "foo/bar/../../blah/bar"),
2122 ("blah", "foo/bar/../../blah/bar/.."),
2123 ("../foo", "../foo"),
2124 ("../foo", "../foo/"),
2125 ("../foo/bar", "../foo/bar"),
2126 ("..", "../foo/.."),
2127 ("~/foo", "~/foo"),
2128 ];
2129 for test in tests {
2130 assert_eq!(PathBuf::from(test.0), PathBuf::from(test.1).clean().unwrap());
2131 }
2132 }
2133
2134 #[test]
2135 fn test_pathext_concat() {
2136 assert_eq!(Path::new("").concat(".rs").unwrap(), PathBuf::from(".rs"));
2137 assert_eq!(Path::new("foo").concat(".rs").unwrap(), PathBuf::from("foo.rs"));
2138 assert_eq!(Path::new("foo.exe").concat(".rs").unwrap(), PathBuf::from("foo.exe.rs"));
2139 assert_eq!(Path::new("/foo/bar").concat(".rs").unwrap(), PathBuf::from("/foo/bar.rs"));
2140 }
2141
2142 #[test]
2143 fn test_pathext_dirname() {
2144 assert_eq!(PathBuf::from("/").as_path(), PathBuf::from("/foo/").dir().unwrap());
2145 assert_eq!(PathBuf::from("/foo").as_path(), PathBuf::from("/foo/bar").dir().unwrap());
2146 }
2147
2148 #[test]
2149 fn test_pathext_empty() {
2150 assert_eq!(PathBuf::from("").empty(), true);
2152
2153 assert_eq!(PathBuf::from("/foo").empty(), false);
2155 }
2156
2157 #[test]
2158 fn test_pathext_exists() {
2159 assert_eq!(setup().exists(), true);
2160 }
2161
2162 #[test]
2163 fn test_pathext_expand() {
2164 let home = PathBuf::from(user::home_dir().unwrap());
2165
2166 assert_eq!(PathBuf::from("~/").expand().unwrap(), home);
2168 assert_eq!(PathBuf::from("~").expand().unwrap(), home);
2169
2170 assert!(PathBuf::from("~/foo~").expand().is_err());
2172
2173 assert!(PathBuf::from("~foo").expand().is_err());
2175
2176 assert_eq!(PathBuf::from(""), PathBuf::from("").expand().unwrap());
2178
2179 if !sys::flag("GITHUB_ACTIONS") {
2181 assert_eq!(PathBuf::from("$XDG_CONFIG_HOME").expand().unwrap(), home.mash(".config"));
2182 assert_eq!(PathBuf::from("${XDG_CONFIG_HOME}").expand().unwrap(), home.mash(".config"));
2183 }
2184
2185 sys::set_var("PATHEXT_EXPAND", "bar");
2187 assert_eq!(PathBuf::from("~/foo/$PATHEXT_EXPAND").expand().unwrap(), home.mash("foo/bar"));
2188 assert_eq!(PathBuf::from("~/foo/${PATHEXT_EXPAND}").expand().unwrap(), home.mash("foo/bar"));
2189 assert_eq!(PathBuf::from("~/foo/$PATHEXT_EXPAND/blah").expand().unwrap(), home.mash("foo/bar/blah"));
2190 }
2191
2192 #[test]
2193 fn test_pathext_ext() {
2194 assert!(PathBuf::from("").ext().is_err());
2195 assert!(PathBuf::from("foo").ext().is_err());
2196 assert_eq!(PathBuf::from("foo.exe").ext().unwrap(), "exe");
2197 assert_eq!(PathBuf::from("/foo/bar.exe").ext().unwrap(), "exe");
2198 }
2199
2200 #[test]
2201 fn test_pathext_first() {
2202 assert_eq!(Component::RootDir, PathBuf::from("/").first().unwrap());
2203 assert_eq!(Component::CurDir, PathBuf::from(".").first().unwrap());
2204 assert_eq!(Component::ParentDir, PathBuf::from("..").first().unwrap());
2205 assert_eq!(Component::Normal(OsStr::new("foo")), PathBuf::from("foo").first().unwrap());
2206 assert_eq!(Component::Normal(OsStr::new("foo")), PathBuf::from("foo/bar").first().unwrap());
2207 }
2208
2209 #[test]
2210 fn test_pathext_has() {
2211 let path = PathBuf::from("/foo/bar");
2212 assert_eq!(path.has("foo"), true);
2213 assert_eq!(path.has("/foo"), true);
2214 assert_eq!(path.has("/"), true);
2215 assert_eq!(path.has("/ba"), true);
2216 assert_eq!(path.has("bob"), false);
2217 }
2218
2219 #[test]
2220 fn test_pathext_has_prefix() {
2221 let path = PathBuf::from("/foo/bar");
2222 assert_eq!(path.has_prefix("/foo"), true);
2223 assert_eq!(path.has_prefix("foo"), false);
2224 }
2225
2226 #[test]
2227 fn test_pathext_has_suffix() {
2228 let path = PathBuf::from("/foo/bar");
2229 assert_eq!(path.has_suffix("/foo"), false);
2230 assert_eq!(path.has_suffix("/bar"), true);
2231 }
2232
2233 #[test]
2234 fn test_pathext_is_dir() {
2235 let tmpdir = setup().mash("path_pathext_is_dir");
2236
2237 assert!(sys::remove_all(&tmpdir).is_ok());
2238 assert_eq!(tmpdir.is_dir(), false);
2239 assert!(sys::mkdir(&tmpdir).is_ok());
2240 assert_eq!(tmpdir.is_dir(), true);
2241
2242 assert!(sys::remove_all(&tmpdir).is_ok());
2244 }
2245
2246 #[test]
2247 fn test_pathext_is_file() {
2248 let tmpdir = setup().mash("path_pathext_is_file");
2249 let tmpfile = tmpdir.mash("file1");
2250
2251 assert!(sys::remove_all(&tmpdir).is_ok());
2252 assert!(sys::mkdir(&tmpdir).is_ok());
2253 assert!(sys::touch(&tmpfile).is_ok());
2254 assert_eq!(tmpfile.is_file(), true);
2255
2256 assert!(sys::remove_all(&tmpdir).is_ok());
2258 }
2259
2260 #[test]
2261 fn test_pathext_is_symlink_file() {
2262 let tmpdir = setup().mash("path_pathext_is_symlink_file");
2263 let file1 = tmpdir.mash("file1");
2264 let link1 = tmpdir.mash("link1");
2265
2266 assert!(sys::remove_all(&tmpdir).is_ok());
2267 assert!(sys::mkdir(&tmpdir).is_ok());
2268 assert_eq!(link1.is_symlink_file(), false);
2269 assert!(sys::touch(&file1).is_ok());
2270 assert!(sys::symlink(&link1, &file1).is_ok());
2271 assert_eq!(link1.is_symlink_file(), true);
2272
2273 assert!(sys::remove_all(&tmpdir).is_ok());
2275 }
2276
2277 #[test]
2278 fn test_pathext_last() {
2279 assert_eq!(Component::RootDir, PathBuf::from("/").last().unwrap());
2280 assert_eq!(Component::CurDir, PathBuf::from(".").last().unwrap());
2281 assert_eq!(Component::ParentDir, PathBuf::from("..").last().unwrap());
2282 assert_eq!(Component::Normal(OsStr::new("foo")), PathBuf::from("foo").last().unwrap());
2283 assert_eq!(Component::Normal(OsStr::new("bar")), PathBuf::from("/foo/bar").last().unwrap());
2284 }
2285
2286 #[test]
2287 fn test_pathext_metadata() {
2288 let tmpdir = setup().mash("path_pathext_metadata");
2289
2290 assert!(sys::remove_all(&tmpdir).is_ok());
2291 assert!(tmpdir.metadata().is_err());
2292 assert!(sys::mkdir(&tmpdir).is_ok());
2293 assert!(tmpdir.metadata().is_ok());
2294
2295 assert!(sys::remove_all(&tmpdir).is_ok());
2297 }
2298
2299 #[test]
2300 fn test_pathext_mash() {
2301 assert_eq!(Path::new("/foo").mash("/bar"), PathBuf::from("/foo/bar"));
2303
2304 assert_eq!(Path::new("/foo").mash("bar/"), PathBuf::from("/foo/bar"));
2306 }
2307
2308 #[test]
2309 fn test_pathext_meta() {
2310 let meta = setup().metadata().unwrap();
2311 assert_eq!(meta.is_dir(), true);
2312 }
2313
2314 #[test]
2315 fn test_pathext_mode() {
2316 let tmpdir = setup().mash("path_pathbuf_mode");
2317 let file1 = tmpdir.mash("file1");
2318
2319 assert!(sys::remove_all(&tmpdir).is_ok());
2320 assert!(sys::mkdir(&tmpdir).is_ok());
2321 assert!(sys::touch(&file1).is_ok());
2322 assert!(file1.chmod(0o644).is_ok());
2323 assert_eq!(file1.mode().unwrap(), 0o100644);
2324 assert!(sys::remove_all(&tmpdir).is_ok());
2325 }
2326
2327 #[test]
2328 fn test_pathext_name() {
2329 assert!(PathBuf::from("").name().is_err());
2330 assert_eq!(PathBuf::from("foo").name().unwrap(), "foo");
2331 assert_eq!(PathBuf::from("foo.exe").name().unwrap(), "foo");
2332 assert_eq!(PathBuf::from("/foo/bar.exe").name().unwrap(), "bar");
2333 }
2334
2335 #[test]
2336 fn test_pathext_perms() {
2337 let tmpdir = setup().mash("path_pathbuf_perms");
2338 let file1 = tmpdir.mash("file1");
2339
2340 assert!(sys::remove_all(&tmpdir).is_ok());
2341 assert!(sys::mkdir(&tmpdir).is_ok());
2342 assert!(sys::touch(&file1).is_ok());
2343 assert!(file1.chmod(0o644).is_ok());
2344 assert_eq!(file1.perms().unwrap().mode(), 0o100644);
2345 assert!(sys::remove_all(&tmpdir).is_ok());
2346 }
2347
2348 #[test]
2349 fn test_pathext_setperms() {
2350 let tmpdir = setup().mash("path_pathbuf_setperms");
2351 let file1 = tmpdir.mash("file1");
2352
2353 assert!(sys::remove_all(&tmpdir).is_ok());
2354 assert!(sys::mkdir(&tmpdir).is_ok());
2355 assert!(sys::touch(&file1).is_ok());
2356 assert!(file1.chmod(0o644).is_ok());
2357 let mut perms = file1.perms().unwrap();
2358 assert_eq!(perms.mode(), 0o100644);
2359 perms.set_mode(0o555);
2360 assert!(file1.setperms(perms).is_ok());
2361 assert_eq!(file1.mode().unwrap(), 0o100555);
2362 assert!(sys::remove_all(&tmpdir).is_ok());
2363 }
2364
2365 #[test]
2366 fn test_pathext_relative_from() {
2367 let cwd = sys::cwd().unwrap();
2368
2369 assert_eq!(PathBuf::from("bar1").relative_from("bar1").unwrap(), cwd.mash("bar1"));
2371
2372 assert_eq!(PathBuf::from("bar1").relative_from("bar2").unwrap(), PathBuf::from("bar1"));
2374 assert_eq!(PathBuf::from("foo/bar1").relative_from("foo/bar2").unwrap(), PathBuf::from("bar1"));
2375 assert_eq!(PathBuf::from("~/foo/bar1").relative_from("~/foo/bar2").unwrap(), PathBuf::from("bar1"));
2376 assert_eq!(PathBuf::from("../foo/bar1").relative_from("../foo/bar2").unwrap(), PathBuf::from("bar1"));
2377
2378 assert_eq!(PathBuf::from("foo1/bar1").relative_from("foo2/bar2").unwrap(), PathBuf::from("../foo1/bar1"));
2380
2381 assert_eq!(PathBuf::from("blah1/foo1/bar1").relative_from("blah2/foo2/bar2").unwrap(), PathBuf::from("../../blah1/foo1/bar1"));
2383 }
2384
2385 #[test]
2386 fn test_pathext_trim_ext() {
2387 assert_eq!(PathBuf::from("").trim_ext().unwrap(), PathBuf::new());
2388 assert_eq!(PathBuf::from("foo").trim_ext().unwrap(), PathBuf::from("foo"));
2389 assert_eq!(PathBuf::from("foo.exe").trim_ext().unwrap(), PathBuf::from("foo"));
2390 assert_eq!(PathBuf::from("/foo/bar.exe").trim_ext().unwrap(), PathBuf::from("/foo/bar"));
2391 }
2392
2393 #[test]
2394 fn test_pathext_trim_last() {
2395 assert_eq!(PathBuf::new(), PathBuf::from("/").trim_last());
2396 assert_eq!(PathBuf::from("/"), PathBuf::from("/foo").trim_last());
2397 }
2398
2399 #[test]
2400 fn test_pathext_trim_first() {
2401 assert_eq!(PathBuf::new(), PathBuf::from("/").trim_first());
2402 assert_eq!(PathBuf::from("foo"), PathBuf::from("/foo").trim_first());
2403 }
2404
2405 #[test]
2406 fn test_pathext_trim_prefix() {
2407 assert_eq!(PathBuf::from("/").trim_prefix("/"), PathBuf::new());
2409
2410 assert_eq!(Path::new("/foo/bar").trim_prefix("/foo"), PathBuf::from("/bar"));
2412
2413 assert_eq!(PathBuf::from("/").trim_prefix(""), PathBuf::from("/"));
2415 assert_eq!(PathBuf::from("/foo").trim_prefix("blah"), PathBuf::from("/foo"));
2416 }
2417
2418 #[test]
2419 fn test_pathext_trim_protocol() {
2420 assert_eq!(PathBuf::from("/foo"), PathBuf::from("/foo").trim_protocol());
2422
2423 assert_eq!(PathBuf::from("/foo"), PathBuf::from("file:///foo").trim_protocol());
2425
2426 assert_eq!(PathBuf::from("foo"), PathBuf::from("ftp://foo").trim_protocol());
2428
2429 assert_eq!(PathBuf::from("foo"), PathBuf::from("http://foo").trim_protocol());
2431
2432 assert_eq!(PathBuf::from("foo"), PathBuf::from("https://foo").trim_protocol());
2434
2435 assert_eq!(PathBuf::from("Foo"), PathBuf::from("HTTPS://Foo").trim_protocol());
2437 assert_eq!(PathBuf::from("Foo"), PathBuf::from("Https://Foo").trim_protocol());
2438 assert_eq!(PathBuf::from("FoO"), PathBuf::from("HttpS://FoO").trim_protocol());
2439
2440 assert_eq!(PathBuf::from("foo"), PathBuf::from("foo").trim_protocol());
2442 assert_eq!(PathBuf::from("foo/bar"), PathBuf::from("foo/bar").trim_protocol());
2443 assert_eq!(PathBuf::from("foo//bar"), PathBuf::from("foo//bar").trim_protocol());
2444 assert_eq!(PathBuf::from("ntp:://foo"), PathBuf::from("ntp:://foo").trim_protocol());
2445 }
2446
2447 #[test]
2448 fn test_pathext_trim_suffix() {
2449 assert_eq!(PathBuf::new(), PathBuf::from("/").trim_suffix("/"));
2451
2452 assert_eq!(PathBuf::from("/foo"), PathBuf::from("/foo/").trim_suffix("/"));
2454
2455 assert_eq!(PathBuf::from("/foo"), PathBuf::from("/foo").trim_suffix("/"));
2457 }
2458
2459 #[test]
2460 fn test_pathcolorext() {
2461 assert_eq!("foo".black(), PathBuf::from("foo").black());
2462 assert_eq!("foo".red(), PathBuf::from("foo").red());
2463 assert_eq!("foo".green(), PathBuf::from("foo").green());
2464 assert_eq!("foo".yellow(), PathBuf::from("foo").yellow());
2465 assert_eq!("foo".blue(), PathBuf::from("foo").blue());
2466 assert_eq!("foo".magenta(), PathBuf::from("foo").magenta());
2467 assert_eq!("foo".cyan(), PathBuf::from("foo").cyan());
2468 assert_eq!("foo".white(), PathBuf::from("foo").white());
2469 }
2470}