Change Directory.create to not fail on existing directory with that name.

The new semantics is to ensure that a directory with that name
exists. There is no way to reliably guard a create call against
existing directories in an async program.

R=sgjesse@google.com
BUG=

Review URL: https://codereview.chromium.org//11175054

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@13933 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
ager@google.com 2012-10-23 09:15:01 +00:00
parent d3fa9bf981
commit ccced31671
5 changed files with 99 additions and 5 deletions

View file

@ -38,15 +38,18 @@ abstract class Directory {
bool existsSync();
/**
* Creates the directory with this name if it does not
* exist. Returns a [:Future<Directory>:] that completes with this
* directory once it has been created.
* Creates the directory with this name. If the directory already
* exists nothing is done. Returns a [:Future<Directory>:] that
* completes with this directory once it has been created. If the
* directory does not exist and cannot be created the future
* completes with an exception.
*/
Future<Directory> create();
/**
* Synchronously creates the directory with this name if it does not exist.
* Throws an exception if the directory already exists.
* Synchronously creates the directory with this name. If the
* directory already exists nothing is done. If the directory does
* not exist and cannot be created an exception is thrown.
*/
void createSync();

View file

@ -381,6 +381,9 @@ char* Directory::Current() {
bool Directory::Create(const char* dir_name) {
// If the directory already exists and is a directory do not
// attempt to create it again and treat it as a success.
if (Exists(dir_name) == EXISTS) return true;
// Create the directory with the permissions specified by the
// process umask.
return (TEMP_FAILURE_RETRY(mkdir(dir_name, 0777)) == 0);

View file

@ -381,6 +381,9 @@ char* Directory::Current() {
bool Directory::Create(const char* dir_name) {
// If the directory already exists and is a directory do not
// attempt to create it again and treat it as a success.
if (Exists(dir_name) == EXISTS) return true;
// Create the directory with the permissions specified by the
// process umask.
return (TEMP_FAILURE_RETRY(mkdir(dir_name, 0777)) == 0);

View file

@ -348,6 +348,9 @@ char* Directory::Current() {
bool Directory::Create(const char* dir_name) {
// If the directory already exists and is a directory do not
// attempt to create it again and treat it as a success.
if (Exists(dir_name) == EXISTS) return true;
return (CreateDirectory(dir_name, NULL) != 0);
}

View file

@ -16,6 +16,7 @@ class DirectoryTest {
Directory subDirectory = new Directory("${directory.path}/subdir");
Expect.isFalse(subDirectory.existsSync());
subDirectory.createSync();
Expect.isTrue(subDirectory.existsSync());
File f = new File('${subDirectory.path}/file.txt');
Expect.isFalse(f.existsSync());
f.createSync();
@ -459,6 +460,83 @@ testCreateTempError() {
}
testCreateExistingSync() {
// Test that creating an existing directory succeeds.
var d = new Directory('');
var temp = d.createTempSync();
var subDir = new Directory('${temp.path}/flaf');
Expect.isFalse(subDir.existsSync());
subDir.createSync();
Expect.isTrue(subDir.existsSync());
subDir.createSync();
Expect.isTrue(subDir.existsSync());
temp.deleteRecursivelySync();
}
testCreateExisting() {
// Test that creating an existing directory succeeds.
var port = new ReceivePort();
var d = new Directory('');
d.createTemp().then((temp) {
var subDir = new Directory('${temp.path}/flaf');
subDir.exists().then((dirExists) {
Expect.isFalse(dirExists);
subDir.create().then((_) {
subDir.exists().then((dirExists) {
Expect.isTrue(dirExists);
subDir.create().then((_) {
subDir.exists().then((dirExists) {
Expect.isTrue(dirExists);
temp.deleteRecursively().then((_) {
port.close();
});
});
});
});
});
});
});
}
testCreateDirExistingFileSync() {
// Test that creating an existing directory succeeds.
var d = new Directory('');
var temp = d.createTempSync();
var path = '${temp.path}/flaf';
var file = new File(path);
file.createSync();
Expect.isTrue(file.existsSync());
Expect.throws(new Directory(path).createSync,
(e) => e is DirectoryIOException);
temp.deleteRecursivelySync();
}
testCreateDirExistingFile() {
// Test that creating an existing directory succeeds.
var port = new ReceivePort();
var d = new Directory('');
d.createTemp().then((temp) {
var path = '${temp.path}/flaf';
var file = new File(path);
var subDir = new Directory(path);
file.create().then((_) {
subDir.create()
..then((_) { Expect.fail("dir create should fail on existing file"); })
..handleException((e) {
Expect.isTrue(e is DirectoryIOException);
temp.deleteRecursively().then((_) {
port.close();
});
return true;
});
});
});
}
testRename() {
var d = new Directory('');
var temp1 = d.createTempSync();
@ -483,5 +561,9 @@ main() {
NestedTempDirectoryTest.testMain();
testCreateTempErrorSync();
testCreateTempError();
testCreateExistingSync();
testCreateExisting();
testCreateDirExistingFileSync();
testCreateDirExistingFile();
testRename();
}