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:
commit
40180cdbea
62 changed files with 6329 additions and 2750 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue