Skip to content

Commit 0d4deae

Browse files
committed
---
yaml --- r: 80884 b: refs/heads/try c: 71c7798 h: refs/heads/master v: v3
1 parent 8bb5292 commit 0d4deae

File tree

3 files changed

+130
-60
lines changed

3 files changed

+130
-60
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
refs/heads/master: 4c6bf4872012c010f84dc7fa2cdfe87522533f89
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: cbd1eefbd350797b783df119fed7956d7e1c74ad
5-
refs/heads/try: daf497462844a55678e12545114bcc75d5ce8ebc
5+
refs/heads/try: 71c7798d66953e9f53192d54985a6a46736f5ca5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: 147ecfdd8221e4a4d4e090486829a06da1e0ca3c

branches/try/src/libstd/rt/io/file.rs

Lines changed: 121 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ use super::{SeekStyle,SeekSet, SeekCur, SeekEnd,
1515
Open, Read, Write, Create, ReadWrite};
1616
use rt::rtio::{RtioFileStream, IoFactory, IoFactoryObject};
1717
use rt::io::{io_error, read_error, EndOfFile,
18-
FileMode, FileAccess, FileStat};
18+
FileMode, FileAccess, FileStat, IoError,
19+
PathAlreadyExists, PathDoesntExist,
20+
MismatchedFileTypeForOperation};
1921
use rt::local::Local;
2022
use option::{Some, None};
2123
use path::Path;
@@ -100,7 +102,7 @@ pub fn stat<P: PathLike>(path: &P) -> Option<FileStat> {
100102
Some(p)
101103
},
102104
Err(ioerr) => {
103-
read_error::cond.raise(ioerr);
105+
io_error::cond.raise(ioerr);
104106
None
105107
}
106108
}
@@ -230,41 +232,53 @@ impl Seek for FileStream {
230232
}
231233
}
232234

233-
/// Represents passive information about a file (primarily exposed
234-
/// via the `stat()` method. Also provides methods for opening
235-
/// a file in various modes/permissions.
236-
pub trait FileInfo<'self> {
237-
/// Get the filesystem path that this `FileInfo` points at,
238-
/// whether it is valid or not. This way, it can be used to
239-
/// to specify a file path of a non-existent file which it
240-
/// later create
241-
fn get_file_path(&'self self) -> &'self Path;
242-
243-
/// Ask the operating system for information about the file
235+
// helper for grabbing a stat and ignoring any
236+
// error.. used in Info wrappers
237+
fn suppressed_stat(cb: &fn() -> Option<FileStat>) -> Option<FileStat> {
238+
do io_error::cond.trap(|_| {
239+
// just swallow the error.. downstream users
240+
// who can make a decision based on a None result
241+
// won't care
242+
}).inside {
243+
cb()
244+
}
245+
}
246+
247+
/// Shared functionality between `FileInfo` and `DirectoryInfo`
248+
pub trait FileSystemInfo {
249+
/// Get the filesystem path that this instance points at,
250+
/// whether it is valid or not. In this way, it can be used to
251+
/// to specify a path of a non-existent file which it
252+
/// later creates
253+
fn get_path<'a>(&'a self) -> &'a Path;
254+
255+
/// Ask the operating system for information about the path,
256+
/// will raise a condition if an error occurs during the process
244257
fn stat(&self) -> Option<FileStat> {
245-
use mod_stat = super::file::stat;
246-
do read_error::cond.trap(|_| {
247-
// FIXME: can we do something more useful here?
248-
}).inside {
249-
mod_stat(self.get_file_path())
250-
}
258+
stat(self.get_path())
251259
}
252260

253261
/// returns `true` if the location pointed at by the enclosing
254262
/// exists on the filesystem
255-
fn file_exists(&self) -> bool {
256-
match self.stat() {
263+
fn exists(&self) -> bool {
264+
match suppressed_stat(|| self.stat()) {
257265
Some(_) => true,
258266
None => false
259267
}
260268
}
261269

262-
/// Whether the underlying implemention (be it a file path
263-
/// or active file descriptor) is a "regular file". Will return
270+
}
271+
272+
/// Represents passive information about a file (primarily exposed
273+
/// via the `stat()` method. Also provides methods for opening
274+
/// a file in various modes/permissions.
275+
pub trait FileInfo : FileSystemInfo {
276+
/// Whether the underlying implemention (be it a file path,
277+
/// or something else) points at a "regular file" on the FS. Will return
264278
/// false for paths to non-existent locations or directories or
265279
/// other non-regular files (named pipes, etc).
266280
fn is_file(&self) -> bool {
267-
match self.stat() {
281+
match suppressed_stat(|| self.stat()) {
268282
Some(s) => s.is_file,
269283
None => false
270284
}
@@ -273,12 +287,12 @@ pub trait FileInfo<'self> {
273287
/// Attempts to open a regular file for reading/writing based
274288
/// on provided inputs
275289
fn open_stream(&self, mode: FileMode, access: FileAccess) -> Option<FileStream> {
276-
match self.stat() {
290+
match suppressed_stat(|| self.stat()) {
277291
Some(s) => match s.is_file {
278-
true => open(self.get_file_path(), mode, access),
292+
true => open(self.get_path(), mode, access),
279293
false => None // FIXME: raise condition, not a regular file..
280294
},
281-
None => open(self.get_file_path(), mode, access)
295+
None => open(self.get_path(), mode, access)
282296
}
283297
}
284298
/// Attempts to open a regular file for reading-only based
@@ -302,45 +316,82 @@ pub trait FileInfo<'self> {
302316
/// Attempt to remove a file from the filesystem, pending the closing
303317
/// of any open file descriptors pointing to the file
304318
fn unlink(&self) {
305-
unlink(self.get_file_path());
319+
unlink(self.get_path());
306320
}
307321
}
308322

309-
/// `FileInfo` implementation for `Path`s
310-
impl<'self> FileInfo<'self> for Path {
311-
fn get_file_path(&'self self) -> &'self Path { self }
323+
/// `FileSystemInfo` implementation for `Path`s
324+
impl FileSystemInfo for Path {
325+
fn get_path<'a>(&'a self) -> &'a Path { self }
312326
}
327+
/// `FileInfo` implementation for `Path`s
328+
impl FileInfo for Path { }
313329

314-
/*
315-
/// FIXME: DOCS
316-
impl DirectoryInfo<'self> {
317-
fn new<P: PathLike>(path: &P) -> FileInfo {
318-
FileInfo(Path(path.path_as_str()))
319-
}
320-
// FIXME #8873 can't put this in FileSystemInfo
321-
fn get_path(&'self self) -> &'self Path {
322-
&*self
330+
trait DirectoryInfo : FileSystemInfo {
331+
/// Whether the underlying implemention (be it a file path,
332+
/// or something else) points at a directory file" on the FS. Will return
333+
/// false for paths to non-existent locations or if the item is
334+
/// not a directory (eg files, named pipes, links, etc)
335+
fn is_dir(&self) -> bool {
336+
match suppressed_stat(|| self.stat()) {
337+
Some(s) => s.is_dir,
338+
None => false
339+
}
323340
}
324-
fn stat(&self) -> Option<FileStat> {
325-
file::stat(self.get_path())
341+
/// Create a directory at the location pointed to by the
342+
/// type underlying the given `DirectoryInfo`. Raises a
343+
/// condition if a file, directory, etc already exists
344+
/// at that location or if some other error occurs during
345+
/// the mkdir operation
346+
fn mkdir(&self) {
347+
match suppressed_stat(|| self.stat()) {
348+
Some(_) => {
349+
io_error::cond.raise(IoError {
350+
kind: PathAlreadyExists,
351+
desc: "path already exists",
352+
detail:
353+
Some(fmt!("%s already exists; can't mkdir it", self.get_path().to_str()))
354+
})
355+
},
356+
None => mkdir(self.get_path())
357+
}
326358
}
327-
fn exists(&self) -> bool {
328-
do io_error::cond.trap(|_| {
329-
}).inside {
330-
match self.stat() {
331-
Some(_) => true,
332-
None => false
333-
}
359+
/// Remove a directory at the given location pointed to by
360+
/// the type underlying the given `DirectoryInfo`. Will fail
361+
/// if there is no directory at the given location or if
362+
fn rmdir(&self) {
363+
match suppressed_stat(|| self.stat()) {
364+
Some(s) => {
365+
match s.is_dir {
366+
true => rmdir(self.get_path()),
367+
false => {
368+
let ioerr = IoError {
369+
kind: MismatchedFileTypeForOperation,
370+
desc: "Cannot do rmdir() on a non-directory",
371+
detail:
372+
Some(fmt!("%s is a non-directory; can't rmdir it", self.get_path().to_str()))
373+
};
374+
io_error::cond.raise(ioerr);
375+
}
376+
}
377+
},
378+
None =>
379+
io_error::cond.raise(IoError {
380+
kind: PathDoesntExist,
381+
desc: "path doesn't exist",
382+
detail: Some(fmt!("%s doesn't exist; can't rmdir it", self.get_path().to_str()))
383+
})
334384
}
335385
}
336-
fn is_dir(&self) -> bool {
337-
386+
fn readdir(&self) -> ~[~str] {
387+
~[]
338388
}
339-
fn create(&self);
340-
fn get_subdirs(&self, filter: &str) -> ~[Path];
341-
fn get_files(&self, filter: &str) -> ~[Path];
389+
//fn get_subdirs(&self, filter: &str) -> ~[Path];
390+
//fn get_files(&self, filter: &str) -> ~[Path];
342391
}
343-
*/
392+
393+
/// FIXME: DOCS
394+
impl DirectoryInfo for Path { }
344395

345396
fn file_test_smoke_test_impl() {
346397
do run_in_mt_newsched_task {
@@ -594,8 +645,21 @@ fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
594645
let mut w = file.open_writer(Create);
595646
w.write(msg);
596647
}
597-
assert!(file.file_exists());
648+
assert!(file.exists());
598649
file.unlink();
599-
assert!(!file.file_exists());
650+
assert!(!file.exists());
651+
}
652+
}
653+
654+
#[test]
655+
fn file_test_directoryinfo_check_exists_before_and_after_mkdir() {
656+
do run_in_mt_newsched_task {
657+
let dir = &Path("./tmp/before_and_after_dir");
658+
assert!(!dir.exists());
659+
dir.mkdir();
660+
assert!(dir.exists());
661+
assert!(dir.is_dir());
662+
dir.rmdir();
663+
assert!(!dir.exists());
600664
}
601665
}

branches/try/src/libstd/rt/io/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,10 @@ pub enum IoErrorKind {
358358
Closed,
359359
ConnectionRefused,
360360
ConnectionReset,
361-
BrokenPipe
361+
BrokenPipe,
362+
PathAlreadyExists,
363+
PathDoesntExist,
364+
MismatchedFileTypeForOperation
362365
}
363366

364367
// FIXME: #8242 implementing manually because deriving doesn't work for some reason
@@ -374,7 +377,10 @@ impl ToStr for IoErrorKind {
374377
Closed => ~"Closed",
375378
ConnectionRefused => ~"ConnectionRefused",
376379
ConnectionReset => ~"ConnectionReset",
377-
BrokenPipe => ~"BrokenPipe"
380+
BrokenPipe => ~"BrokenPipe",
381+
PathAlreadyExists => ~"PathAlreadyExists",
382+
PathDoesntExist => ~"PathDoesntExist",
383+
MismatchedFileTypeForOperation => ~"MismatchedFileTypeForOperation"
378384
}
379385
}
380386
}

0 commit comments

Comments
 (0)