Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

os::make_absolute() and WindowsPath Refactoring and Fixes #5023

Merged
merged 3 commits into from
Feb 26, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions src/libcore/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -565,17 +565,13 @@ pub fn path_exists(p: &Path) -> bool {
*
* If the given path is relative, return it prepended with the current working
* directory. If the given path is already an absolute path, return it
* as is.
* as is. This is a shortcut for calling os::getcwd().unsafe_join(p)
*/
// NB: this is here rather than in path because it is a form of environment
// querying; what it does depends on the process working directory, not just
// the input paths.
pub fn make_absolute(p: &Path) -> Path {
if p.is_absolute {
copy *p
} else {
getcwd().push_many(p.components)
}
getcwd().unsafe_join(p)
}


Expand Down
148 changes: 143 additions & 5 deletions src/libcore/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ pub trait GenericPath {
pure fn push_many((&[~str])) -> Self;
pure fn pop() -> Self;

pure fn unsafe_join((&Self)) -> Self;
pure fn is_restricted() -> bool;

pure fn normalize() -> Self;
}

Expand Down Expand Up @@ -485,6 +488,19 @@ impl GenericPath for PosixPath {
self.push_many(other.components)
}

pure fn unsafe_join(other: &PosixPath) -> PosixPath {
if other.is_absolute {
PosixPath { is_absolute: true,
components: copy other.components }
} else {
self.push_rel(other)
}
}

pure fn is_restricted() -> bool {
false
}

pure fn push_many(cs: &[~str]) -> PosixPath {
let mut v = copy self.components;
for cs.each |e| {
Expand Down Expand Up @@ -685,6 +701,61 @@ impl GenericPath for WindowsPath {
self.push_many(other.components)
}

pure fn unsafe_join(other: &WindowsPath) -> WindowsPath {
/* rhs not absolute is simple push */
if !other.is_absolute {
return self.push_many(other.components);
}

/* if rhs has a host set, then the whole thing wins */
match other.host {
Some(copy host) => {
return WindowsPath {
host: Some(host),
device: copy other.device,
is_absolute: true,
components: copy other.components
};
}
_ => {}
}

/* if rhs has a device set, then a part wins */
match other.device {
Some(copy device) => {
return WindowsPath {
host: None,
device: Some(device),
is_absolute: true,
components: copy other.components
};
}
_ => {}
}

/* fallback: host and device of lhs win, but the
whole path of the right */
WindowsPath {
host: copy self.host,
device: copy self.device,
is_absolute: self.is_absolute || other.is_absolute,
components: copy other.components
}
}

pure fn is_restricted() -> bool {
match self.filestem() {
Some(stem) => {
match stem.to_lower() {
~"con" | ~"aux" | ~"com1" | ~"com2" | ~"com3" | ~"com4" |
~"lpt1" | ~"lpt2" | ~"lpt3" | ~"prn" | ~"nul" => true,
_ => false
}
},
None => false
}
}

pure fn push_many(cs: &[~str]) -> WindowsPath {
let mut v = copy self.components;
for cs.each |e| {
Expand Down Expand Up @@ -725,7 +796,10 @@ impl GenericPath for WindowsPath {
pure fn normalize() -> WindowsPath {
return WindowsPath {
host: copy self.host,
device: copy self.device,
device: match self.device {
None => None,
Some(ref device) => Some(device.to_upper())
},
is_absolute: self.is_absolute,
components: normalize(self.components)
}
Expand Down Expand Up @@ -764,13 +838,13 @@ pub mod windows {

pub pure fn extract_unc_prefix(s: &str) -> Option<(~str,~str)> {
if (s.len() > 1 &&
s[0] == '\\' as u8 &&
s[1] == '\\' as u8) {
(s[0] == '\\' as u8 || s[0] == '/' as u8) &&
s[0] == s[1]) {
let mut i = 2;
while i < s.len() {
if s[i] == '\\' as u8 {
if is_sep(s[i]) {
let pre = s.slice(2, i);
let rest = s.slice(i, s.len());
let mut rest = s.slice(i, s.len());
return Some((pre, rest));
}
i += 1;
Expand Down Expand Up @@ -916,13 +990,21 @@ mod tests {
#[test]
fn test_extract_unc_prefixes() {
assert windows::extract_unc_prefix("\\\\").is_none();
assert windows::extract_unc_prefix("//").is_none();
assert windows::extract_unc_prefix("\\\\hi").is_none();
assert windows::extract_unc_prefix("//hi").is_none();
assert windows::extract_unc_prefix("\\\\hi\\") ==
Some((~"hi", ~"\\"));
assert windows::extract_unc_prefix("//hi\\") ==
Some((~"hi", ~"\\"));
assert windows::extract_unc_prefix("\\\\hi\\there") ==
Some((~"hi", ~"\\there"));
assert windows::extract_unc_prefix("//hi/there") ==
Some((~"hi", ~"/there"));
assert windows::extract_unc_prefix("\\\\hi\\there\\friends.txt") ==
Some((~"hi", ~"\\there\\friends.txt"));
assert windows::extract_unc_prefix("//hi\\there\\friends.txt") ==
Some((~"hi", ~"\\there\\friends.txt"));
}

#[test]
Expand Down Expand Up @@ -981,5 +1063,61 @@ mod tests {
.push_many([~"lib", ~"thingy.dll"])
.with_filename("librustc.dll")),
"c:\\program files (x86)\\rust\\lib\\librustc.dll");

t(&(WindowsPath("\\\\computer\\share")
.unsafe_join(&WindowsPath("\\a"))),
"\\\\computer\\a");

t(&(WindowsPath("//computer/share")
.unsafe_join(&WindowsPath("\\a"))),
"\\\\computer\\a");

t(&(WindowsPath("//computer/share")
.unsafe_join(&WindowsPath("\\\\computer\\share"))),
"\\\\computer\\share");

t(&(WindowsPath("C:/whatever")
.unsafe_join(&WindowsPath("//computer/share/a/b"))),
"\\\\computer\\share\\a\\b");

t(&(WindowsPath("C:")
.unsafe_join(&WindowsPath("D:/foo"))),
"D:\\foo");

t(&(WindowsPath("C:")
.unsafe_join(&WindowsPath("B"))),
"C:B");

t(&(WindowsPath("C:")
.unsafe_join(&WindowsPath("/foo"))),
"C:\\foo");

t(&(WindowsPath("C:\\")
.unsafe_join(&WindowsPath("\\bar"))),
"C:\\bar");

t(&(WindowsPath("")
.unsafe_join(&WindowsPath(""))),
"");

t(&(WindowsPath("")
.unsafe_join(&WindowsPath("a"))),
"a");

t(&(WindowsPath("")
.unsafe_join(&WindowsPath("C:\\a"))),
"C:\\a");

t(&(WindowsPath("c:\\foo")
.normalize()),
"C:\\foo");
}

#[test]
fn test_windows_path_restrictions() {
assert WindowsPath("hi").is_restricted() == false;
assert WindowsPath("C:\\NUL").is_restricted() == true;
assert WindowsPath("C:\\COM1.TXT").is_restricted() == true;
assert WindowsPath("c:\\prn.exe").is_restricted() == true;
}
}