Change how File/Directory/Link .delete works.

Now:
- File.delete works iff path is File or Link.
- Directory.delete works iff path is Directory or Link.
- Link.delete works iff path Link.

This now matches .exists.

BUG=

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

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@21045 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
ajohnsen@google.com
2013-04-08 07:44:18 +00:00
parent 8809ce7e07
commit e75df511a6
18 changed files with 817 additions and 74 deletions
+1
View File
@@ -44,6 +44,7 @@
V(File_CreateLink, 2) \
V(File_LinkTarget, 1) \
V(File_Delete, 1) \
V(File_DeleteLink, 1) \
V(File_Directory, 1) \
V(File_FullPath, 1) \
V(File_OpenStdio, 1) \
+10 -2
View File
@@ -239,7 +239,11 @@ static bool DeleteRecursively(PathBuffer* path) {
if (TEMP_FAILURE_RETRY(lstat(path->data, &st)) == -1) {
return false;
} else if (S_ISLNK(st.st_mode)) {
return (remove(path->data) == 0);
if (TEMP_FAILURE_RETRY(stat(path->data, &st)) == -1) {
return false;
} else if (S_ISDIR(st.st_mode)) {
return (unlink(path->data) == 0);
}
}
if (!path->Add(File::PathSeparator())) return false;
@@ -441,7 +445,11 @@ char* Directory::CreateTemp(const char* const_template) {
bool Directory::Delete(const char* dir_name, bool recursive) {
if (!recursive) {
return (TEMP_FAILURE_RETRY(remove(dir_name)) == 0);
if (File::GetType(dir_name, false) == File::kIsLink &&
File::GetType(dir_name, true) == File::kIsDirectory) {
return (TEMP_FAILURE_RETRY(unlink(dir_name)) == 0);
}
return (TEMP_FAILURE_RETRY(rmdir(dir_name)) == 0);
} else {
PathBuffer path;
if (!path.Add(dir_name)) {
+10 -2
View File
@@ -239,7 +239,11 @@ static bool DeleteRecursively(PathBuffer* path) {
if (TEMP_FAILURE_RETRY(lstat(path->data, &st)) == -1) {
return false;
} else if (S_ISLNK(st.st_mode)) {
return (remove(path->data) == 0);
if (TEMP_FAILURE_RETRY(stat(path->data, &st)) == -1) {
return false;
} else if (S_ISDIR(st.st_mode)) {
return (unlink(path->data) == 0);
}
}
if (!path->Add(File::PathSeparator())) return false;
@@ -409,7 +413,11 @@ char* Directory::CreateTemp(const char* const_template) {
bool Directory::Delete(const char* dir_name, bool recursive) {
if (!recursive) {
return (TEMP_FAILURE_RETRY(remove(dir_name)) == 0);
if (File::GetType(dir_name, false) == File::kIsLink &&
File::GetType(dir_name, true) == File::kIsDirectory) {
return (TEMP_FAILURE_RETRY(unlink(dir_name)) == 0);
}
return (TEMP_FAILURE_RETRY(rmdir(dir_name)) == 0);
} else {
PathBuffer path;
if (!path.Add(dir_name)) {
+10 -2
View File
@@ -239,7 +239,11 @@ static bool DeleteRecursively(PathBuffer* path) {
if (TEMP_FAILURE_RETRY(lstat(path->data, &st)) == -1) {
return false;
} else if (S_ISLNK(st.st_mode)) {
return (remove(path->data) == 0);
if (TEMP_FAILURE_RETRY(stat(path->data, &st)) == -1) {
return false;
} else if (S_ISDIR(st.st_mode)) {
return (unlink(path->data) == 0);
}
}
if (!path->Add(File::PathSeparator())) return false;
@@ -409,7 +413,11 @@ char* Directory::CreateTemp(const char* const_template) {
bool Directory::Delete(const char* dir_name, bool recursive) {
if (!recursive) {
return (TEMP_FAILURE_RETRY(remove(dir_name)) == 0);
if (File::GetType(dir_name, false) == File::kIsLink &&
File::GetType(dir_name, true) == File::kIsDirectory) {
return (TEMP_FAILURE_RETRY(unlink(dir_name)) == 0);
}
return (TEMP_FAILURE_RETRY(rmdir(dir_name)) == 0);
} else {
PathBuffer path;
if (!path.Add(dir_name)) {
+37 -14
View File
@@ -6,6 +6,7 @@
#if defined(TARGET_OS_WINDOWS)
#include "bin/directory.h"
#include "bin/file.h"
#include <errno.h> // NOLINT
#include <sys/stat.h> // NOLINT
@@ -48,6 +49,25 @@ class PathBuffer {
}
};
// If link_name points to a link, IsBrokenLink will return true if link_name
// points to an invalid target.
static bool IsBrokenLink(const wchar_t* link_name) {
HANDLE handle = CreateFileW(
link_name,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (handle == INVALID_HANDLE_VALUE) {
return true;
} else {
CloseHandle(handle);
return false;
}
}
// Forward declarations.
static bool ListRecursively(PathBuffer* path,
@@ -122,18 +142,13 @@ static bool HandleEntry(LPWIN32_FIND_DATAW find_file_data,
if (!follow_links) {
return HandleLink(find_file_data->cFileName, path, listing);
}
// Attempt to list the directory, to see if it's a valid link or not.
int path_length = path->length;
if (!path->Add(find_file_data->cFileName)) return false;
if (!path->Add(L"\\*")) return false;
WIN32_FIND_DATAW tmp_file_data;
HANDLE find_handle = FindFirstFileW(path->data, &tmp_file_data);
bool broken = IsBrokenLink(path->data);
path->Reset(path_length);
if (find_handle == INVALID_HANDLE_VALUE) {
// Invalid handle, report as (broken) link.
if (broken) {
// Report as (broken) link.
return HandleLink(find_file_data->cFileName, path, listing);
} else {
FindClose(find_handle);
}
}
if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
@@ -253,8 +268,12 @@ static bool DeleteRecursively(PathBuffer* path) {
DWORD attributes = GetFileAttributesW(path->data);
if ((attributes != INVALID_FILE_ATTRIBUTES) &&
(attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
// Just delete the junction itself.
return RemoveDirectoryW(path->data) != 0;
if (IsBrokenLink(path->data)) {
return false;
} else {
// Just delete the junction itself.
return RemoveDirectoryW(path->data) != 0;
}
}
if (!path->Add(L"\\*")) return false;
@@ -318,6 +337,7 @@ static Directory::ExistsResult ExistsHelper(const wchar_t* dir_name) {
}
}
bool exists = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
exists = exists && !IsBrokenLink(dir_name);
return exists ? Directory::EXISTS : Directory::DOES_NOT_EXIST;
}
@@ -407,13 +427,16 @@ bool Directory::Delete(const char* dir_name, bool recursive) {
bool result = false;
const wchar_t* system_dir_name = StringUtils::Utf8ToWide(dir_name);
if (!recursive) {
result = (RemoveDirectoryW(system_dir_name) != 0);
if (File::GetType(dir_name, true) == File::kIsDirectory) {
result = (RemoveDirectoryW(system_dir_name) != 0);
} else {
SetLastError(ERROR_DIRECTORY);
}
} else {
PathBuffer path;
if (!path.Add(system_dir_name)) {
return false;
if (path.Add(system_dir_name)) {
result = DeleteRecursively(&path);
}
result = DeleteRecursively(&path);
}
free(const_cast<wchar_t*>(system_dir_name));
return result;
+33
View File
@@ -488,6 +488,22 @@ void FUNCTION_NAME(File_Delete)(Dart_NativeArguments args) {
}
void FUNCTION_NAME(File_DeleteLink)(Dart_NativeArguments args) {
Dart_EnterScope();
const char* str =
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
bool result = File::DeleteLink(str);
if (result) {
Dart_SetReturnValue(args, Dart_NewBoolean(result));
} else {
Dart_Handle err = DartUtils::NewDartOSError();
if (Dart_IsError(err)) Dart_PropagateError(err);
Dart_SetReturnValue(args, err);
}
Dart_ExitScope();
}
void FUNCTION_NAME(File_Directory)(Dart_NativeArguments args) {
Dart_EnterScope();
const char* str =
@@ -997,6 +1013,20 @@ static CObject* FileWriteListRequest(const CObjectArray& request) {
}
static CObject* FileDeleteLinkRequest(const CObjectArray& request) {
if (request.Length() == 2 && request[1]->IsString()) {
CObjectString filename(request[1]);
bool result = File::DeleteLink(filename.CString());
if (result) {
return CObject::True();
} else {
return CObject::NewOSError();
}
}
return CObject::False();
}
static void FileService(Dart_Port dest_port_id,
Dart_Port reply_port_id,
Dart_CObject* message) {
@@ -1063,6 +1093,9 @@ static void FileService(Dart_Port dest_port_id,
case File::kWriteListRequest:
response = FileWriteListRequest(request);
break;
case File::kDeleteLinkRequest:
response = FileDeleteLinkRequest(request);
break;
default:
UNREACHABLE();
}
+3 -1
View File
@@ -76,7 +76,8 @@ class File {
kWriteByteRequest = 15,
kReadRequest = 16,
kReadListRequest = 17,
kWriteListRequest = 18
kWriteListRequest = 18,
kDeleteLinkRequest = 19
};
~File();
@@ -131,6 +132,7 @@ class File {
static bool Create(const char* path);
static bool CreateLink(const char* path, const char* target);
static bool Delete(const char* path);
static bool DeleteLink(const char* path);
static off_t LengthFromPath(const char* path);
static time_t LastModified(const char* path);
static char* LinkTarget(const char* pathname);
+18 -4
View File
@@ -166,11 +166,25 @@ bool File::CreateLink(const char* name, const char* target) {
bool File::Delete(const char* name) {
int status = TEMP_FAILURE_RETRY(remove(name));
if (status == -1) {
return false;
File::Type type = File::GetType(name, true);
if (type == kIsFile) {
return TEMP_FAILURE_RETRY(unlink(name)) == 0;
} else if (type == kIsDirectory) {
errno = EISDIR;
} else {
errno = ENOENT;
}
return true;
return false;
}
bool File::DeleteLink(const char* name) {
File::Type type = File::GetType(name, false);
if (type == kIsLink) {
return TEMP_FAILURE_RETRY(unlink(name)) == 0;
}
errno = EINVAL;
return false;
}
+18 -4
View File
@@ -167,11 +167,25 @@ bool File::CreateLink(const char* name, const char* target) {
bool File::Delete(const char* name) {
int status = TEMP_FAILURE_RETRY(remove(name));
if (status == -1) {
return false;
File::Type type = File::GetType(name, true);
if (type == kIsFile) {
return TEMP_FAILURE_RETRY(unlink(name)) == 0;
} else if (type == kIsDirectory) {
errno = EISDIR;
} else {
errno = ENOENT;
}
return true;
return false;
}
bool File::DeleteLink(const char* name) {
File::Type type = File::GetType(name, false);
if (type == kIsLink) {
return TEMP_FAILURE_RETRY(unlink(name)) == 0;
}
errno = EINVAL;
return false;
}
+18 -4
View File
@@ -169,11 +169,25 @@ bool File::CreateLink(const char* name, const char* target) {
bool File::Delete(const char* name) {
int status = TEMP_FAILURE_RETRY(remove(name));
if (status == -1) {
return false;
File::Type type = File::GetType(name, true);
if (type == kIsFile) {
return TEMP_FAILURE_RETRY(unlink(name)) == 0;
} else if (type == kIsDirectory) {
errno = EISDIR;
} else {
errno = ENOENT;
}
return true;
return false;
}
bool File::DeleteLink(const char* name) {
File::Type type = File::GetType(name, false);
if (type == kIsLink) {
return TEMP_FAILURE_RETRY(unlink(name)) == 0;
}
errno = EINVAL;
return false;
}
+1
View File
@@ -13,6 +13,7 @@ patch class _File {
native "File_CreateLink";
/* patch */ static _linkTarget(String path) native "File_LinkTarget";
/* patch */ static _delete(String path) native "File_Delete";
/* patch */ static _deleteLink(String path) native "File_DeleteLink";
/* patch */ static _directory(String path) native "File_Directory";
/* patch */ static _lengthFromPath(String path) native "File_LengthFromPath";
/* patch */ static _lastModified(String path) native "File_LastModified";
+24 -29
View File
@@ -259,19 +259,25 @@ bool File::CreateLink(const char* utf8_name, const char* utf8_target) {
bool File::Delete(const char* name) {
const wchar_t* system_name = StringUtils::Utf8ToWide(name);
int status = _wremove(system_name);
free(const_cast<wchar_t*>(system_name));
return status != -1;
}
bool File::DeleteLink(const char* name) {
const wchar_t* system_name = StringUtils::Utf8ToWide(name);
bool result = false;
DWORD attributes = GetFileAttributesW(system_name);
if ((attributes != INVALID_FILE_ATTRIBUTES) &&
(attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
// It's a junction(link), delete it.
return RemoveDirectoryW(system_name) != 0;
result = (RemoveDirectoryW(system_name) != 0);
} else {
int status = _wremove(system_name);
free(const_cast<wchar_t*>(system_name));
if (status == -1) {
return false;
}
return true;
SetLastError(ERROR_NOT_A_REPARSE_POINT);
}
free(const_cast<wchar_t*>(system_name));
return result;
}
@@ -480,15 +486,11 @@ File::StdioHandleType File::GetStdioHandleType(int fd) {
File::Type File::GetType(const char* pathname, bool follow_links) {
const wchar_t* name = StringUtils::Utf8ToWide(pathname);
WIN32_FIND_DATAW file_data;
HANDLE find_handle = FindFirstFileW(name, &file_data);
if (find_handle == INVALID_HANDLE_VALUE) {
// TODO(whesse): Distinguish other errors from does not exist.
return File::kDoesNotExist;
}
FindClose(find_handle);
DWORD attributes = file_data.dwFileAttributes;
if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
DWORD attributes = GetFileAttributesW(name);
File::Type result = kIsFile;
if (attributes == INVALID_FILE_ATTRIBUTES) {
result = kDoesNotExist;
} else if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
if (follow_links) {
HANDLE dir_handle = CreateFileW(
name,
@@ -499,26 +501,19 @@ File::Type File::GetType(const char* pathname, bool follow_links) {
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (dir_handle == INVALID_HANDLE_VALUE) {
// TODO(whesse): Distinguish other errors from does not exist.
return File::kDoesNotExist;
result = File::kIsLink;
} else {
CloseHandle(dir_handle);
return File::kIsDirectory;
result = File::kIsDirectory;
}
} else {
DWORD reparse_tag = file_data.dwReserved0;
if (reparse_tag == IO_REPARSE_TAG_SYMLINK ||
reparse_tag == IO_REPARSE_TAG_MOUNT_POINT) {
return File::kIsLink;
} else {
return File::kDoesNotExist;
}
result = kIsLink;
}
} else if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
return File::kIsDirectory;
} else {
return File::kIsFile;
result = kIsDirectory;
}
free(const_cast<wchar_t*>(name));
return result;
}
+1
View File
@@ -220,6 +220,7 @@ const int _WRITE_BYTE_REQUEST = 15;
const int _READ_REQUEST = 16;
const int _READ_LIST_REQUEST = 17;
const int _WRITE_LIST_REQUEST = 18;
const int _DELETE_LINK_REQUEST = 19;
// Base class for _File and _RandomAccessFile with shared functions.
class _FileBase {
+32 -8
View File
@@ -108,6 +108,8 @@ abstract class Link extends FileSystemEntity {
class _Link extends FileSystemEntity implements Link {
final String path;
SendPort _fileService;
_Link(String this.path);
_Link.fromPath(Path inputPath) : path = inputPath.toNativePath();
@@ -134,9 +136,7 @@ class _Link extends FileSystemEntity implements Link {
target = _makeWindowsLinkTarget(target);
}
var result = _File._createLink(path, target);
if (result is OSError) {
throw new LinkIOException("Error in Link.createSync", result);
}
throwIfError(result, "Cannot create link '$path'");
}
// Put target into the form "\??\C:\my\target\dir".
@@ -164,11 +164,21 @@ class _Link extends FileSystemEntity implements Link {
}
Future<Link> delete() {
return new File(path).delete().then((_) => this);
_ensureFileService();
List request = new List(2);
request[0] = _DELETE_LINK_REQUEST;
request[1] = path;
return _fileService.call(request).then((response) {
if (_isErrorResponse(response)) {
throw _exceptionFromResponse(response, "Cannot delete link '$path'");
}
return this;
});
}
void deleteSync() {
new File(path).deleteSync();
var result = _File._deleteLink(path);
throwIfError(result, "Cannot delete link '$path'");
}
Future<String> target() {
@@ -178,11 +188,25 @@ class _Link extends FileSystemEntity implements Link {
String targetSync() {
var result = _File._linkTarget(path);
if (result is OSError) {
throw new LinkIOException("Error in Link.targetSync", result);
}
throwIfError(result, "Cannot read link '$path'");
return result;
}
static throwIfError(Object result, String msg) {
if (result is OSError) {
throw new FileIOException(msg, result);
}
}
bool _isErrorResponse(response) {
return response is List && response[0] != _SUCCESS_RESPONSE;
}
void _ensureFileService() {
if (_fileService == null) {
_fileService = _FileUtils._newServicePort();
}
}
}
@@ -0,0 +1,393 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "dart:async";
import "dart:io";
Future throws(callback()) {
return new Future.immediate(null)
.then((_) => callback())
.then((_) { throw "Expected error"; },
onError: (_) {});
}
void testDeleteFileSync() {
var tmp = new Directory("").createTempSync();
var path = "${tmp.path}${Platform.pathSeparator}";
var file = new File("${path}myFile");
file.createSync();
Expect.isTrue(file.existsSync());
new File(file.path).deleteSync();
Expect.isFalse(file.existsSync());
file.createSync();
Expect.isTrue(file.existsSync());
Expect.throws(() => new Directory(file.path).deleteSync());
Expect.isTrue(file.existsSync());
Expect.isTrue(file.existsSync());
Expect.throws(() => new Directory(file.path).deleteSync(recursive: true));
Expect.isTrue(file.existsSync());
Expect.isTrue(file.existsSync());
Expect.throws(() => new Link(file.path).deleteSync());
Expect.isTrue(file.existsSync());
file.deleteSync();
Expect.isFalse(file.existsSync());
tmp.deleteSync();
}
void testDeleteFile() {
new Directory("").createTemp().then((tmp) {
var path = "${tmp.path}${Platform.pathSeparator}";
var file = new File("${path}myFile");
return file.create()
.then((_) => file.exists().then(Expect.isTrue))
.then((_) => new File(file.path).delete())
.then((_) => file.exists().then(Expect.isFalse))
.then((_) => file.create())
.then((_) => file.exists().then(Expect.isTrue))
.then((_) => throws(() => new Directory(file.path).delete()))
.then((_) => file.exists().then(Expect.isTrue))
.then((_) => file.exists().then(Expect.isTrue))
.then((_) => throws(
() => new Directory(file.path).delete(recursive: true)))
.then((_) => file.exists().then(Expect.isTrue))
.then((_) => file.exists().then(Expect.isTrue))
.then((_) => throws(() => new Link(file.path).delete()))
.then((_) => file.exists().then(Expect.isTrue))
.then((_) => file.delete())
.then((_) => tmp.delete());
});
}
void testDeleteDirectorySync() {
var tmp = new Directory("").createTempSync();
var path = "${tmp.path}${Platform.pathSeparator}";
var dir = new Directory("${path}myDirectory");
dir.createSync();
Expect.isTrue(dir.existsSync());
new Directory(dir.path).deleteSync();
Expect.isFalse(dir.existsSync());
dir.createSync();
Expect.isTrue(dir.existsSync());
new Directory(dir.path).deleteSync(recursive: true);
Expect.isFalse(dir.existsSync());
dir.createSync();
Expect.isTrue(dir.existsSync());
Expect.throws(() => new File(dir.path).deleteSync());
Expect.isTrue(dir.existsSync());
Expect.isTrue(dir.existsSync());
Expect.throws(() => new Link(dir.path).deleteSync());
Expect.isTrue(dir.existsSync());
dir.deleteSync();
Expect.isFalse(dir.existsSync());
tmp.deleteSync();
}
void testDeleteDirectory() {
new Directory("").createTemp().then((tmp) {
var path = "${tmp.path}${Platform.pathSeparator}";
var dir = new Directory("${path}myDirectory");
return dir.create()
.then((_) => dir.exists().then(Expect.isTrue))
.then((_) => new Directory(dir.path).delete())
.then((_) => dir.exists().then(Expect.isFalse))
.then((_) => dir.create())
.then((_) => dir.exists().then(Expect.isTrue))
.then((_) => new Directory(dir.path).delete(recursive: true))
.then((_) => dir.exists().then(Expect.isFalse))
.then((_) => dir.create())
.then((_) => dir.exists().then(Expect.isTrue))
.then((_) => throws(() => new File(dir.path).delete()))
.then((_) => dir.exists().then(Expect.isTrue))
.then((_) => dir.exists().then(Expect.isTrue))
.then((_) => throws(() => new Link(dir.path).delete()))
.then((_) => dir.exists().then(Expect.isTrue))
.then((_) => dir.delete())
.then((_) => tmp.delete());
});
}
void testDeleteFileLinkSync() {
var tmp = new Directory("").createTempSync();
var path = "${tmp.path}${Platform.pathSeparator}";
var file = new File("${path}myFile");
file.createSync();
var link = new Link("${path}myLink");
link.createSync(file.path);
Expect.isTrue(link.existsSync());
new File(link.path).deleteSync();
Expect.isFalse(link.existsSync());
link.createSync(file.path);
Expect.isTrue(link.existsSync());
new Link(link.path).deleteSync();
Expect.isFalse(link.existsSync());
link.createSync(file.path);
Expect.isTrue(link.existsSync());
Expect.throws(() => new Directory(link.path).deleteSync());
Expect.isTrue(link.existsSync());
Expect.isTrue(link.existsSync());
Expect.throws(() => new Directory(link.path).deleteSync(recursive: true));
Expect.isTrue(link.existsSync());
link.deleteSync();
Expect.isFalse(link.existsSync());
Expect.isTrue(file.existsSync());
file.deleteSync();
Expect.isFalse(file.existsSync());
tmp.deleteSync();
}
void testDeleteFileLink() {
new Directory("").createTemp().then((tmp) {
var path = "${tmp.path}${Platform.pathSeparator}";
var file = new File("${path}myFile");
var link = new Link("${path}myLink");
return file.create()
.then((_) => link.create(file.path))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => new File(link.path).delete())
.then((_) => link.exists().then(Expect.isFalse))
.then((_) => link.create(file.path))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => new Link(link.path).delete())
.then((_) => link.exists().then(Expect.isFalse))
.then((_) => link.create(file.path))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => throws(() => new Directory(link.path).delete()))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => throws(
() => new Directory(link.path).delete(recursive: true)))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => link.deleteSync())
.then((_) => link.exists().then(Expect.isFalse))
.then((_) => file.exists().then(Expect.isTrue))
.then((_) => file.delete())
.then((_) => file.exists().then(Expect.isFalse))
.then((_) => tmp.delete());
});
}
void testDeleteDirectoryLinkSync() {
var tmp = new Directory("").createTempSync();
var path = "${tmp.path}${Platform.pathSeparator}";
var directory = new Directory("${path}myDirectory");
directory.createSync();
var link = new Link("${path}myLink");
link.createSync(directory.path);
Expect.isTrue(link.existsSync());
new Link(link.path).deleteSync();
Expect.isFalse(link.existsSync());
link.createSync(directory.path);
Expect.isTrue(link.existsSync());
new Directory(link.path).deleteSync();
Expect.isFalse(link.existsSync());
link.createSync(directory.path);
Expect.isTrue(link.existsSync());
new Directory(link.path).deleteSync(recursive: true);
Expect.isFalse(link.existsSync());
link.createSync(directory.path);
Expect.isTrue(link.existsSync());
Expect.throws(() => new File(link.path).deleteSync());
Expect.isTrue(link.existsSync());
link.deleteSync();
Expect.isFalse(link.existsSync());
Expect.isTrue(directory.existsSync());
directory.deleteSync();
Expect.isFalse(directory.existsSync());
tmp.deleteSync();
}
void testDeleteDirectoryLink() {
new Directory("").createTemp().then((tmp) {
var path = "${tmp.path}${Platform.pathSeparator}";
var dir = new Directory("${path}myDir");
var link = new Link("${path}myLink");
return dir.create()
.then((_) => link.create(dir.path))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => new Directory(link.path).delete())
.then((_) => link.exists().then(Expect.isFalse))
.then((_) => link.create(dir.path))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => new Directory(link.path).delete(recursive: true))
.then((_) => link.exists().then(Expect.isFalse))
.then((_) => link.create(dir.path))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => new Link(link.path).delete())
.then((_) => link.exists().then(Expect.isFalse))
.then((_) => link.create(dir.path))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => throws(() => new File(link.path).delete()))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => link.deleteSync())
.then((_) => link.exists().then(Expect.isFalse))
.then((_) => dir.exists().then(Expect.isTrue))
.then((_) => dir.delete())
.then((_) => dir.exists().then(Expect.isFalse))
.then((_) => tmp.delete());
});
}
void testDeleteBrokenLinkSync() {
var tmp = new Directory("").createTempSync();
var path = "${tmp.path}${Platform.pathSeparator}";
var directory = new Directory("${path}myDirectory");
directory.createSync();
var link = new Link("${path}myLink");
link.createSync(directory.path);
directory.deleteSync();
Expect.isTrue(link.existsSync());
new Link(link.path).deleteSync();
Expect.isFalse(link.existsSync());
directory.createSync();
link.createSync(directory.path);
directory.deleteSync();
Expect.isTrue(link.existsSync());
Expect.throws(() => new Directory(link.path).deleteSync());
Expect.isTrue(link.existsSync());
Expect.isTrue(link.existsSync());
Expect.throws(() => new Directory(link.path).deleteSync(recursive: true));
Expect.isTrue(link.existsSync());
Expect.isTrue(link.existsSync());
Expect.throws(() => new File(link.path).deleteSync());
Expect.isTrue(link.existsSync());
link.deleteSync();
Expect.isFalse(link.existsSync());
tmp.deleteSync();
}
void testDeleteBrokenLink() {
new Directory("").createTemp().then((tmp) {
var path = "${tmp.path}${Platform.pathSeparator}";
var dir = new Directory("${path}myDir");
var link = new Link("${path}myLink");
return dir.create()
.then((_) => link.create(dir.path))
.then((_) => dir.delete())
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => new Link(link.path).delete())
.then((_) => link.exists().then(Expect.isFalse))
.then((_) => dir.create())
.then((_) => link.create(dir.path))
.then((_) => dir.delete())
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => throws(() => new Directory(link.path).delete()))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => throws(
() => new Directory(link.path).delete(recursive: true)))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => throws(() => new File(link.path).delete()))
.then((_) => link.exists().then(Expect.isTrue))
.then((_) => link.deleteSync())
.then((_) => link.exists().then(Expect.isFalse))
.then((_) => tmp.delete());
});
}
void main() {
testDeleteFileSync();
testDeleteFile();
testDeleteDirectorySync();
testDeleteDirectory();
if (Platform.operatingSystem != 'windows') {
testDeleteFileLinkSync();
testDeleteFileLink();
}
testDeleteDirectoryLinkSync();
testDeleteDirectoryLink();
testDeleteBrokenLinkSync();
testDeleteBrokenLink();
}
@@ -0,0 +1,204 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "dart:io";
void testFileExistsSync() {
var tmp = new Directory("").createTempSync();
var path = "${tmp.path}${Platform.pathSeparator}";
var file = new File("${path}myFile");
file.createSync();
Expect.isTrue(new File(file.path).existsSync());
Expect.isFalse(new Directory(file.path).existsSync());
Expect.isFalse(new Link(file.path).existsSync());
file.deleteSync();
Expect.isFalse(file.existsSync());
tmp.deleteSync();
}
void testFileExists() {
new Directory("").createTemp().then((tmp) {
var path = "${tmp.path}${Platform.pathSeparator}";
var file = new File("${path}myFile");
return file.create()
.then((_) => new File(file.path).exists().then(Expect.isTrue))
.then((_) => new Directory(file.path).exists().then(Expect.isFalse))
.then((_) => new Link(file.path).exists().then(Expect.isFalse))
.then((_) => file.delete())
.then((_) => tmp.delete());
});
}
void testDirectoryExistsSync() {
var tmp = new Directory("").createTempSync();
var path = "${tmp.path}${Platform.pathSeparator}";
var dir = new Directory("${path}myDirectory");
dir.createSync();
Expect.isFalse(new File(dir.path).existsSync());
Expect.isTrue(new Directory(dir.path).existsSync());
Expect.isFalse(new Link(dir.path).existsSync());
dir.deleteSync();
Expect.isFalse(dir.existsSync());
tmp.deleteSync();
}
void testDirectoryExists() {
new Directory("").createTemp().then((tmp) {
var path = "${tmp.path}${Platform.pathSeparator}";
var dir = new Directory("${path}myDirectory");
return dir.create()
.then((_) => new File(dir.path).exists().then(Expect.isFalse))
.then((_) => new Directory(dir.path).exists().then(Expect.isTrue))
.then((_) => new Link(dir.path).exists().then(Expect.isFalse))
.then((_) => dir.delete())
.then((_) => tmp.delete());
});
}
void testFileLinkExistsSync() {
var tmp = new Directory("").createTempSync();
var path = "${tmp.path}${Platform.pathSeparator}";
var file = new File("${path}myFile");
file.createSync();
var link = new Link("${path}myLink");
link.createSync(file.path);
Expect.isTrue(new File(link.path).existsSync());
Expect.isFalse(new Directory(link.path).existsSync());
Expect.isTrue(new Link(link.path).existsSync());
link.deleteSync();
Expect.isFalse(link.existsSync());
file.deleteSync();
Expect.isFalse(file.existsSync());
tmp.deleteSync();
}
void testFileLinkExists() {
new Directory("").createTemp().then((tmp) {
var path = "${tmp.path}${Platform.pathSeparator}";
var file = new File("${path}myFile");
var link = new Link("${path}myLink");
return file.create()
.then((_) => link.create(file.path))
.then((_) => new File(link.path).exists().then(Expect.isTrue))
.then((_) => new Directory(link.path).exists().then(Expect.isFalse))
.then((_) => new Link(link.path).exists().then(Expect.isTrue))
.then((_) => link.delete())
.then((_) => file.delete())
.then((_) => tmp.delete());
});
}
void testDirectoryLinkExistsSync() {
var tmp = new Directory("").createTempSync();
var path = "${tmp.path}${Platform.pathSeparator}";
var directory = new Directory("${path}myDirectory");
directory.createSync();
var link = new Link("${path}myLink");
link.createSync(directory.path);
Expect.isFalse(new File(link.path).existsSync());
Expect.isTrue(new Directory(link.path).existsSync());
Expect.isTrue(new Link(link.path).existsSync());
link.deleteSync();
Expect.isFalse(link.existsSync());
directory.deleteSync();
Expect.isFalse(directory.existsSync());
tmp.deleteSync();
}
void testDirectoryLinkExists() {
new Directory("").createTemp().then((tmp) {
var path = "${tmp.path}${Platform.pathSeparator}";
var dir = new Directory("${path}myDir");
var link = new Link("${path}myLink");
return dir.create()
.then((_) => link.create(dir.path))
.then((_) => new File(link.path).exists().then(Expect.isFalse))
.then((_) => new Directory(link.path).exists().then(Expect.isTrue))
.then((_) => new Link(link.path).exists().then(Expect.isTrue))
.then((_) => link.delete())
.then((_) => dir.delete())
.then((_) => tmp.delete());
});
}
void testBrokenLinkExistsSync() {
var tmp = new Directory("").createTempSync();
var path = "${tmp.path}${Platform.pathSeparator}";
var directory = new Directory("${path}myDirectory");
directory.createSync();
var link = new Link("${path}myLink");
link.createSync(directory.path);
directory.deleteSync();
Expect.isFalse(new File(link.path).existsSync());
Expect.isFalse(new Directory(link.path).existsSync());
Expect.isTrue(new Link(link.path).existsSync());
link.deleteSync();
Expect.isFalse(link.existsSync());
tmp.deleteSync();
}
void testBrokenLinkExists() {
new Directory("").createTemp().then((tmp) {
var path = "${tmp.path}${Platform.pathSeparator}";
var dir = new Directory("${path}myDir");
var link = new Link("${path}myLink");
return dir.create()
.then((_) => link.create(dir.path))
.then((_) => dir.delete())
.then((_) => new File(link.path).exists().then(Expect.isFalse))
.then((_) => new Directory(link.path).exists().then(Expect.isFalse))
.then((_) => new Link(link.path).exists().then(Expect.isTrue))
.then((_) => link.delete())
.then((_) => tmp.delete());
});
}
void main() {
testFileExistsSync();
testFileExists();
testDirectoryExistsSync();
testDirectoryExists();
if (Platform.operatingSystem != 'windows') {
testFileLinkExistsSync();
testFileLinkExists();
}
testDirectoryLinkExistsSync();
testDirectoryLinkExists();
testBrokenLinkExistsSync();
testBrokenLinkExists();
}
@@ -58,7 +58,7 @@ testFileExistsCreate() {
FileSystemEntity.typeSync(x, followLinks: false));
Expect.equals(x, new Link(y).targetSync());
new File(y).deleteSync();
new Link(y).deleteSync();
Expect.isFalse(FileSystemEntity.isLinkSync(y));
Expect.isFalse(FileSystemEntity.isLinkSync(x));
Expect.equals(FileSystemEntityType.NOT_FOUND, FileSystemEntity.typeSync(y));
@@ -30,13 +30,13 @@ testJunctionTypeDelete() {
// Test Junction pointing to a missing directory.
new Directory(x).deleteSync();
Expect.isTrue(new Directory(y).existsSync());
Expect.isTrue(new Link(y).existsSync());
Expect.isFalse(new Directory(x).existsSync());
Expect.isTrue(FileSystemEntity.isLinkSync(y));
Expect.isFalse(FileSystemEntity.isLinkSync(x));
Expect.isFalse(FileSystemEntity.isDirectorySync(y));
Expect.isFalse(FileSystemEntity.isDirectorySync(x));
Expect.equals(FileSystemEntityType.NOT_FOUND,
Expect.equals(FileSystemEntityType.LINK,
FileSystemEntity.typeSync(y));
Expect.equals(FileSystemEntityType.NOT_FOUND,
FileSystemEntity.typeSync(x));
@@ -47,7 +47,7 @@ testJunctionTypeDelete() {
Expect.equals(x, new Link(y).targetSync());
// Delete Junction pointing to a missing directory.
new Directory(y).deleteSync();
new Link(y).deleteSync();
Expect.isFalse(FileSystemEntity.isLinkSync(y));
Expect.equals(FileSystemEntityType.NOT_FOUND,
FileSystemEntity.typeSync(y));