1
Fork 0

Merge remote-tracking branch 'remotes/origin/master' into remove-str-trailing-nulls

This commit is contained in:
Erick Tryzelaar 2013-08-09 18:48:01 -07:00
commit ee59aacac4
73 changed files with 1740 additions and 1109 deletions

View file

@ -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("."));
}
}