diff options
| author | Erick Tryzelaar <erick.tryzelaar@gmail.com> | 2013-08-09 18:48:01 -0700 |
|---|---|---|
| committer | Erick Tryzelaar <erick.tryzelaar@gmail.com> | 2013-08-09 18:48:01 -0700 |
| commit | ee59aacac490edd619db1c4e2fcd848f793bc3b9 (patch) | |
| tree | d4f01cefe67f55b80cfaca641a03b581823eb200 /src/libstd/path.rs | |
| parent | cab6d46e58ea6f7535d8e454f0345eccfae183c4 (diff) | |
| parent | 6f6dce7bbcfb104a8a1e23b0b93d83cbb770f338 (diff) | |
| download | rust-ee59aacac490edd619db1c4e2fcd848f793bc3b9.tar.gz rust-ee59aacac490edd619db1c4e2fcd848f793bc3b9.zip | |
Merge remote-tracking branch 'remotes/origin/master' into remove-str-trailing-nulls
Diffstat (limited to 'src/libstd/path.rs')
| -rw-r--r-- | src/libstd/path.rs | 165 |
1 files changed, 163 insertions, 2 deletions
diff --git a/src/libstd/path.rs b/src/libstd/path.rs index de34ec4bed5..14844e24006 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -21,13 +21,14 @@ use c_str; use clone::Clone; use cmp::Eq; use container::Container; -use iterator::{Iterator, IteratorUtil}; +use iterator::{Iterator, IteratorUtil, range}; use libc; +use num; use option::{None, Option, Some}; use str::{OwnedStr, Str, StrSlice, StrVector}; use to_str::ToStr; use ascii::{AsciiCast, AsciiStr}; -use vec::{OwnedVector, ImmutableVector}; +use vec::{OwnedVector, ImmutableVector, OwnedCopyableVector}; #[cfg(windows)] pub use Path = self::WindowsPath; @@ -126,6 +127,43 @@ pub trait GenericPath { /// True if `self` is an ancestor of `other`. See `test_is_ancestor_of` for examples fn is_ancestor_of(&self, (&Self)) -> bool; + + /// Find the relative path from one file to another + fn get_relative_to(&self, abs2: (&Self)) -> Self { + assert!(self.is_absolute()); + assert!(abs2.is_absolute()); + let abs1 = self.normalize(); + let abs2 = abs2.normalize(); + + let split1: &[~str] = abs1.components(); + let split2: &[~str] = abs2.components(); + let len1 = split1.len(); + let len2 = split2.len(); + assert!(len1 > 0); + assert!(len2 > 0); + + let max_common_path = num::min(len1, len2) - 1; + let mut start_idx = 0; + while start_idx < max_common_path + && split1[start_idx] == split2[start_idx] { + start_idx += 1; + } + + let mut path: ~[~str] = ~[]; + for _ in range(start_idx, len1 - 1) { path.push(~".."); }; + + path.push_all(split2.slice(start_idx, len2 - 1)); + + let mut result: Self = GenericPath::from_str("."); + if !path.is_empty() { + // Without this type hint, the typechecker doesn't seem to like it + let p: Self = GenericPath::from_str(""); + result = p.push_many(path); + }; + result + } + + fn components(self) -> ~[~str]; } #[cfg(target_os = "linux")] @@ -711,6 +749,7 @@ impl GenericPath for PosixPath { self.is_ancestor_of(&other.pop())) } + fn components(self) -> ~[~str] { self.components } } @@ -998,6 +1037,8 @@ impl GenericPath for WindowsPath { (!other.components.is_empty() && !(self.components.is_empty() && !self.is_absolute) && self.is_ancestor_of(&other.pop())) } + + fn components(self) -> ~[~str] { self.components } } pub fn normalize(components: &[~str]) -> ~[~str] { @@ -1354,4 +1395,124 @@ mod tests { } + #[test] + fn test_relative_to1() { + let p1 = PosixPath("/usr/bin/rustc"); + let p2 = PosixPath("/usr/lib/mylib"); + let res = p1.get_relative_to(&p2); + assert_eq!(res, PosixPath("../lib")); + + let p1 = WindowsPath("C:\\usr\\bin\\rustc"); + let p2 = WindowsPath("C:\\usr\\lib\\mylib"); + let res = p1.get_relative_to(&p2); + assert_eq!(res, WindowsPath("..\\lib")); + + } + + #[test] + fn test_relative_to2() { + let p1 = PosixPath("/usr/bin/rustc"); + let p2 = PosixPath("/usr/bin/../lib/mylib"); + let res = p1.get_relative_to(&p2); + assert_eq!(res, PosixPath("../lib")); + + let p1 = WindowsPath("C:\\usr\\bin\\rustc"); + let p2 = WindowsPath("C:\\usr\\bin\\..\\lib\\mylib"); + let res = p1.get_relative_to(&p2); + assert_eq!(res, WindowsPath("..\\lib")); + } + + #[test] + fn test_relative_to3() { + let p1 = PosixPath("/usr/bin/whatever/rustc"); + let p2 = PosixPath("/usr/lib/whatever/mylib"); + let res = p1.get_relative_to(&p2); + assert_eq!(res, PosixPath("../../lib/whatever")); + + let p1 = WindowsPath("C:\\usr\\bin\\whatever\\rustc"); + let p2 = WindowsPath("C:\\usr\\lib\\whatever\\mylib"); + let res = p1.get_relative_to(&p2); + assert_eq!(res, WindowsPath("..\\..\\lib\\whatever")); + + } + + #[test] + fn test_relative_to4() { + let p1 = PosixPath("/usr/bin/whatever/../rustc"); + let p2 = PosixPath("/usr/lib/whatever/mylib"); + let res = p1.get_relative_to(&p2); + assert_eq!(res, PosixPath("../lib/whatever")); + + let p1 = WindowsPath("C:\\usr\\bin\\whatever\\..\\rustc"); + let p2 = WindowsPath("C:\\usr\\lib\\whatever\\mylib"); + let res = p1.get_relative_to(&p2); + assert_eq!(res, WindowsPath("..\\lib\\whatever")); + + } + + #[test] + fn test_relative_to5() { + let p1 = PosixPath("/usr/bin/whatever/../rustc"); + let p2 = PosixPath("/usr/lib/whatever/../mylib"); + let res = p1.get_relative_to(&p2); + assert_eq!(res, PosixPath("../lib")); + + let p1 = WindowsPath("C:\\usr\\bin/whatever\\..\\rustc"); + let p2 = WindowsPath("C:\\usr\\lib\\whatever\\..\\mylib"); + let res = p1.get_relative_to(&p2); + assert_eq!(res, WindowsPath("..\\lib")); + } + + #[test] + fn test_relative_to6() { + let p1 = PosixPath("/1"); + let p2 = PosixPath("/2/3"); + let res = p1.get_relative_to(&p2); + assert_eq!(res, PosixPath("2")); + + let p1 = WindowsPath("C:\\1"); + let p2 = WindowsPath("C:\\2\\3"); + let res = p1.get_relative_to(&p2); + assert_eq!(res, WindowsPath("2")); + + } + + #[test] + fn test_relative_to7() { + let p1 = PosixPath("/1/2"); + let p2 = PosixPath("/3"); + let res = p1.get_relative_to(&p2); + assert_eq!(res, PosixPath("..")); + + let p1 = WindowsPath("C:\\1\\2"); + let p2 = WindowsPath("C:\\3"); + let res = p1.get_relative_to(&p2); + assert_eq!(res, WindowsPath("..")); + + } + + #[test] + fn test_relative_to8() { + let p1 = PosixPath("/home/brian/Dev/rust/build/").push_rel( + &PosixPath("stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so")); + let p2 = PosixPath("/home/brian/Dev/rust/build/stage2/bin/..").push_rel( + &PosixPath("lib/rustc/i686-unknown-linux-gnu/lib/libstd.so")); + let res = p1.get_relative_to(&p2); + debug!("test_relative_to8: %s vs. %s", + res.to_str(), + PosixPath(".").to_str()); + assert_eq!(res, PosixPath(".")); + + let p1 = WindowsPath("C:\\home\\brian\\Dev\\rust\\build\\").push_rel( + &WindowsPath("stage2\\lib\\rustc\\i686-unknown-linux-gnu\\lib\\librustc.so")); + let p2 = WindowsPath("\\home\\brian\\Dev\\rust\\build\\stage2\\bin\\..").push_rel( + &WindowsPath("lib\\rustc\\i686-unknown-linux-gnu\\lib\\libstd.so")); + let res = p1.get_relative_to(&p2); + debug!("test_relative_to8: %s vs. %s", + res.to_str(), + WindowsPath(".").to_str()); + assert_eq!(res, WindowsPath(".")); + + } + } |
