auto merge of #9655 : kballard/rust/path-rewrite, r=alexcrichton

Rewrite the entire `std::path` module from scratch.

`PosixPath` is now based on `~[u8]`, which fixes #7225.
Unnecessary allocation has been eliminated.

There are a lot of clients of `Path` that still assume utf-8 paths.
This is covered in #9639.
This commit is contained in:
bors 2013-10-16 11:26:35 -07:00
commit 40180cdbea
62 changed files with 6329 additions and 2750 deletions

View file

@ -627,12 +627,13 @@ pub trait DirectoryInfo : FileSystemInfo {
fn mkdir(&self) {
match ignore_io_error(|| self.stat()) {
Some(_) => {
let path = self.get_path();
io_error::cond.raise(IoError {
kind: PathAlreadyExists,
desc: "Path already exists",
detail:
Some(format!("{} already exists; can't mkdir it",
self.get_path().to_str()))
path.display()))
})
},
None => mkdir(self.get_path())
@ -655,24 +656,27 @@ pub trait DirectoryInfo : FileSystemInfo {
match s.is_dir {
true => rmdir(self.get_path()),
false => {
let path = self.get_path();
let ioerr = IoError {
kind: MismatchedFileTypeForOperation,
desc: "Cannot do rmdir() on a non-directory",
detail: Some(format!(
"{} is a non-directory; can't rmdir it",
self.get_path().to_str()))
path.display()))
};
io_error::cond.raise(ioerr);
}
}
},
None =>
None => {
let path = self.get_path();
io_error::cond.raise(IoError {
kind: PathDoesntExist,
desc: "Path doesn't exist",
detail: Some(format!("{} doesn't exist; can't rmdir it",
self.get_path().to_str()))
path.display()))
})
}
}
}
@ -699,7 +703,7 @@ mod test {
fn file_test_io_smoke_test() {
do run_in_mt_newsched_task {
let message = "it's alright. have a good time";
let filename = &Path("./tmp/file_rt_io_file_test.txt");
let filename = &Path::new("./tmp/file_rt_io_file_test.txt");
{
let mut write_stream = open(filename, Create, ReadWrite).unwrap();
write_stream.write(message.as_bytes());
@ -721,7 +725,7 @@ mod test {
#[test]
fn file_test_io_invalid_path_opened_without_create_should_raise_condition() {
do run_in_mt_newsched_task {
let filename = &Path("./tmp/file_that_does_not_exist.txt");
let filename = &Path::new("./tmp/file_that_does_not_exist.txt");
let mut called = false;
do io_error::cond.trap(|_| {
called = true;
@ -736,7 +740,7 @@ mod test {
#[test]
fn file_test_iounlinking_invalid_path_should_raise_condition() {
do run_in_mt_newsched_task {
let filename = &Path("./tmp/file_another_file_that_does_not_exist.txt");
let filename = &Path::new("./tmp/file_another_file_that_does_not_exist.txt");
let mut called = false;
do io_error::cond.trap(|_| {
called = true;
@ -753,7 +757,7 @@ mod test {
use str;
let message = "ten-four";
let mut read_mem = [0, .. 8];
let filename = &Path("./tmp/file_rt_io_file_test_positional.txt");
let filename = &Path::new("./tmp/file_rt_io_file_test_positional.txt");
{
let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
rw_stream.write(message.as_bytes());
@ -784,7 +788,7 @@ mod test {
let set_cursor = 4 as u64;
let mut tell_pos_pre_read;
let mut tell_pos_post_read;
let filename = &Path("./tmp/file_rt_io_file_test_seeking.txt");
let filename = &Path::new("./tmp/file_rt_io_file_test_seeking.txt");
{
let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
rw_stream.write(message.as_bytes());
@ -813,7 +817,7 @@ mod test {
let final_msg = "foo-the-bar!!";
let seek_idx = 3;
let mut read_mem = [0, .. 13];
let filename = &Path("./tmp/file_rt_io_file_test_seek_and_write.txt");
let filename = &Path::new("./tmp/file_rt_io_file_test_seek_and_write.txt");
{
let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
rw_stream.write(initial_msg.as_bytes());
@ -839,7 +843,7 @@ mod test {
let chunk_two = "asdf";
let chunk_three = "zxcv";
let mut read_mem = [0, .. 4];
let filename = &Path("./tmp/file_rt_io_file_test_seek_shakedown.txt");
let filename = &Path::new("./tmp/file_rt_io_file_test_seek_shakedown.txt");
{
let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
rw_stream.write(initial_msg.as_bytes());
@ -869,7 +873,7 @@ mod test {
#[test]
fn file_test_stat_is_correct_on_is_file() {
do run_in_mt_newsched_task {
let filename = &Path("./tmp/file_stat_correct_on_is_file.txt");
let filename = &Path::new("./tmp/file_stat_correct_on_is_file.txt");
{
let mut fs = open(filename, Create, ReadWrite).unwrap();
let msg = "hw";
@ -887,7 +891,7 @@ mod test {
#[test]
fn file_test_stat_is_correct_on_is_dir() {
do run_in_mt_newsched_task {
let filename = &Path("./tmp/file_stat_correct_on_is_dir");
let filename = &Path::new("./tmp/file_stat_correct_on_is_dir");
mkdir(filename);
let stat_res = match stat(filename) {
Some(s) => s,
@ -901,7 +905,7 @@ mod test {
#[test]
fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() {
do run_in_mt_newsched_task {
let dir = &Path("./tmp/fileinfo_false_on_dir");
let dir = &Path::new("./tmp/fileinfo_false_on_dir");
mkdir(dir);
assert!(dir.is_file() == false);
rmdir(dir);
@ -911,7 +915,7 @@ mod test {
#[test]
fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
do run_in_mt_newsched_task {
let file = &Path("./tmp/fileinfo_check_exists_b_and_a.txt");
let file = &Path::new("./tmp/fileinfo_check_exists_b_and_a.txt");
{
let msg = "foo".as_bytes();
let mut w = file.open_writer(Create);
@ -926,7 +930,7 @@ mod test {
#[test]
fn file_test_directoryinfo_check_exists_before_and_after_mkdir() {
do run_in_mt_newsched_task {
let dir = &Path("./tmp/before_and_after_dir");
let dir = &Path::new("./tmp/before_and_after_dir");
assert!(!dir.exists());
dir.mkdir();
assert!(dir.exists());
@ -940,11 +944,11 @@ mod test {
fn file_test_directoryinfo_readdir() {
use str;
do run_in_mt_newsched_task {
let dir = &Path("./tmp/di_readdir");
let dir = &Path::new("./tmp/di_readdir");
dir.mkdir();
let prefix = "foo";
for n in range(0,3) {
let f = dir.push(format!("{}.txt", n));
let f = dir.join(format!("{}.txt", n));
let mut w = f.open_writer(Create);
let msg_str = (prefix + n.to_str().to_owned()).to_owned();
let msg = msg_str.as_bytes();
@ -955,13 +959,13 @@ mod test {
let mut mem = [0u8, .. 4];
for f in files.iter() {
{
let n = f.filestem();
let n = f.filestem_str();
let mut r = f.open_reader(Open);
r.read(mem);
let read_str = str::from_utf8(mem);
let expected = match n {
Some(n) => prefix+n,
None => fail2!("really shouldn't happen..")
None|Some("") => fail2!("really shouldn't happen.."),
Some(n) => prefix+n
};
assert!(expected == read_str);
}

View file

@ -22,7 +22,7 @@ impl<'self> PathLike for &'self str {
impl PathLike for Path {
fn path_as_str<T>(&self, f: &fn(&str) -> T) -> T {
let s = self.to_str();
let s = self.as_str().unwrap();
f(s)
}
}
@ -35,7 +35,7 @@ mod test {
#[test]
fn path_like_smoke_test() {
let expected = if cfg!(unix) { "/home" } else { "C:\\" };
let path = Path(expected);
let path = Path::new(expected);
path.path_as_str(|p| assert!(p == expected));
path.path_as_str(|p| assert!(p == expected));
}

View file

@ -16,6 +16,7 @@ use container::Container;
use iter::{Iterator, range};
use super::io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr};
use vec::{OwnedVector, MutableVector, ImmutableVector};
use path::GenericPath;
use rt::sched::Scheduler;
use unstable::{run_in_bare_thread};
use rt::thread::Thread;
@ -346,7 +347,6 @@ it is running in and assigns a port range based on it.
fn base_port() -> uint {
use os;
use str::StrSlice;
use to_str::ToStr;
use vec::ImmutableVector;
let base = 9600u;
@ -363,12 +363,14 @@ fn base_port() -> uint {
("dist", base + range * 8)
];
let path = os::getcwd().to_str();
// FIXME (#9639): This needs to handle non-utf8 paths
let path = os::getcwd();
let path_s = path.as_str().unwrap();
let mut final_base = base;
for &(dir, base) in bases.iter() {
if path.contains(dir) {
if path_s.contains(dir) {
final_base = base;
break;
}

View file

@ -391,7 +391,7 @@ mod test {
let read_mem = vec::from_elem(read_buf_len, 0u8);
let read_buf = slice_to_uv_buf(read_mem);
let read_buf_ptr: *Buf = &read_buf;
let p = Path(path_str);
let p = Path::new(path_str);
let open_req = FsRequest::new();
do open_req.open(&loop_, &p, create_flags as int, mode as int)
|req, uverr| {
@ -405,7 +405,7 @@ mod test {
assert!(uverr.is_none());
let loop_ = req.get_loop();
let open_req = FsRequest::new();
do open_req.open(&loop_, &Path(path_str), read_flags as int,0)
do open_req.open(&loop_, &Path::new(path_str), read_flags as int,0)
|req, uverr| {
assert!(uverr.is_none());
let loop_ = req.get_loop();
@ -431,7 +431,7 @@ mod test {
assert!(uverr.is_none());
let loop_ = &req.get_loop();
let unlink_req = FsRequest::new();
do unlink_req.unlink(loop_, &Path(path_str))
do unlink_req.unlink(loop_, &Path::new(path_str))
|_,uverr| {
assert!(uverr.is_none());
};
@ -465,7 +465,7 @@ mod test {
let write_buf = slice_to_uv_buf(write_val);
// open/create
let open_req = FsRequest::new();
let result = open_req.open_sync(&loop_, &Path(path_str),
let result = open_req.open_sync(&loop_, &Path::new(path_str),
create_flags as int, mode as int);
assert!(result.is_ok());
let fd = result.unwrap();
@ -479,7 +479,7 @@ mod test {
assert!(result.is_ok());
// re-open
let open_req = FsRequest::new();
let result = open_req.open_sync(&loop_, &Path(path_str),
let result = open_req.open_sync(&loop_, &Path::new(path_str),
read_flags as int,0);
assert!(result.is_ok());
let len = 1028;
@ -503,7 +503,7 @@ mod test {
assert!(result.is_ok());
// unlink
let unlink_req = FsRequest::new();
let result = unlink_req.unlink_sync(&loop_, &Path(path_str));
let result = unlink_req.unlink_sync(&loop_, &Path::new(path_str));
assert!(result.is_ok());
} else { fail2!("nread was 0.. wudn't expectin' that."); }
loop_.close();

View file

@ -18,6 +18,7 @@ use ops::Drop;
use option::*;
use ptr;
use str;
use str::Str;
use result::*;
use rt::io::IoError;
use rt::io::net::ip::{SocketAddr, IpAddr};
@ -34,7 +35,7 @@ use rt::uv::idle::IdleWatcher;
use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr, accum_sockaddrs};
use rt::uv::addrinfo::GetAddrInfoRequest;
use unstable::sync::Exclusive;
use path::Path;
use path::{GenericPath, Path};
use super::super::io::support::PathLike;
use libc::{lseek, off_t, O_CREAT, O_APPEND, O_TRUNC, O_RDWR, O_RDONLY, O_WRONLY,
S_IRUSR, S_IWUSR, S_IRWXU};
@ -631,7 +632,7 @@ impl IoFactory for UvIoFactory {
None => {
let stat = req.get_stat();
Ok(FileStat {
path: Path(path_str),
path: Path::new(path_str.as_slice()),
is_file: stat.is_file(),
is_dir: stat.is_dir(),
size: stat.st_size,
@ -720,7 +721,9 @@ impl IoFactory for UvIoFactory {
let rel_paths = req.get_paths();
let mut paths = ~[];
for r in rel_paths.iter() {
paths.push(Path(path_str+"/"+*r));
let mut p = Path::new(path_str.as_slice());
p.push(r.as_slice());
paths.push(p);
}
Ok(paths)
},
@ -2177,20 +2180,20 @@ fn file_test_uvio_full_simple_impl() {
{
let create_fm = Create;
let create_fa = ReadWrite;
let mut fd = (*io).fs_open(&Path(path), create_fm, create_fa).unwrap();
let mut fd = (*io).fs_open(&Path::new(path), create_fm, create_fa).unwrap();
let write_buf = write_val.as_bytes();
fd.write(write_buf);
}
{
let ro_fm = Open;
let ro_fa = Read;
let mut fd = (*io).fs_open(&Path(path), ro_fm, ro_fa).unwrap();
let mut fd = (*io).fs_open(&Path::new(path), ro_fm, ro_fa).unwrap();
let mut read_vec = [0, .. 1028];
let nread = fd.read(read_vec).unwrap();
let read_val = str::from_utf8(read_vec.slice(0, nread as uint));
assert!(read_val == write_val.to_owned());
}
(*io).fs_unlink(&Path(path));
(*io).fs_unlink(&Path::new(path));
}
}