Skip to content

Commit 1520d7c

Browse files
authored
Add first round of tests, and associated bug fixes (flutter#15)
1 parent ec6b430 commit 1520d7c

File tree

7 files changed

+262
-44
lines changed

7 files changed

+262
-44
lines changed

lib/src/backends/local/local_file_system.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ class LocalFileSystem extends FileSystem {
1414
@override
1515
File file(String path) => new _LocalFile(this, new io.File(path));
1616

17+
@override
18+
Link link(String path) => new _LocalLink(this, new io.Link(path));
19+
1720
@override
1821
Directory get currentDirectory => directory(io.Directory.current.path);
1922

lib/src/backends/memory/memory_file.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ class _MemoryFile extends _MemoryFileSystemEntity implements File {
5858
if (currentSegment == finalSegment) {
5959
if (child != null) {
6060
if (_isLink(child)) {
61-
StringBuffer ledger = new StringBuffer();
61+
List<String> ledger = <String>[];
6262
child = _resolveLinks(child, () => newPath, ledger: ledger);
6363
_checkExists(child, () => newPath);
6464
parent = child.parent;
65-
childName = fileSystem._context.basename(ledger.toString());
65+
childName = ledger.last;
6666
assert(parent.children.containsKey(childName));
6767
}
6868
if (child.type != expectedType) {
@@ -289,9 +289,8 @@ class _FileSink implements io.IOSink {
289289
}
290290

291291
@override
292-
Future flush() {
292+
Future flush() async {
293293
_checkNotStreaming();
294-
return new Future.value();
295294
}
296295

297296
@override

lib/src/backends/memory/memory_file_system.dart

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,24 @@ class MemoryFileSystem extends FileSystem {
5656
@override
5757
File file(String path) => new _MemoryFile(this, path);
5858

59+
@override
60+
Link link(String path) => new _MemoryLink(this, path);
61+
5962
@override
6063
Directory get currentDirectory => directory(_cwd);
6164

6265
@override
6366
set currentDirectory(dynamic path) {
6467
String value;
65-
if (path is Directory) {
68+
if (path is io.Directory) {
6669
value = path.path;
6770
} else if (path is String) {
6871
value = path;
6972
} else {
70-
throw new TypeError();
73+
throw new ArgumentError('Invalid type for "path": ${path?.runtimeType}');
7174
}
72-
value = _context.canonicalize(value);
75+
76+
value = directory(value).resolveSymbolicLinksSync();
7377
_Node node = _findNode(value);
7478
_checkExists(node, () => value);
7579
_checkIsDir(node, () => value);
@@ -83,7 +87,7 @@ class MemoryFileSystem extends FileSystem {
8387
@override
8488
io.FileStat statSync(String path) {
8589
try {
86-
return _findNode(path)?.stat;
90+
return _findNode(path)?.stat ?? _MemoryFileStat._notFound;
8791
} on io.FileSystemException {
8892
return _MemoryFileStat._notFound;
8993
}
@@ -95,8 +99,8 @@ class MemoryFileSystem extends FileSystem {
9599

96100
@override
97101
bool identicalSync(String path1, String path2) {
98-
_Node node1 = _findNode(path1);
99-
_Node node2 = _findNode(path2);
102+
_Node node1 = _findNode(path1, resolveTailLink: true);
103+
_Node node2 = _findNode(path2, resolveTailLink: true);
100104
return node1 != null && node1 == node2;
101105
}
102106

@@ -114,16 +118,13 @@ class MemoryFileSystem extends FileSystem {
114118
io.FileSystemEntityType typeSync(String path, {bool followLinks: true}) {
115119
_Node node;
116120
try {
117-
node = _findNode(path);
121+
node = _findNode(path, resolveTailLink: followLinks);
118122
} on io.FileSystemException {
119123
node = null;
120124
}
121-
if (node = null) {
125+
if (node == null) {
122126
return io.FileSystemEntityType.NOT_FOUND;
123127
}
124-
if (followLinks && _isLink(node)) {
125-
node = _resolveLinks(node, () => path);
126-
}
127128
return node.type;
128129
}
129130

@@ -146,8 +147,9 @@ class MemoryFileSystem extends FileSystem {
146147
///
147148
/// If the last element in [path] represents a symbolic link, this will
148149
/// return the [_LinkNode] node for the link (it will not return the
149-
/// node to which the link points). However, directory links in the middle
150-
/// of the path will be followed in order to find the node.
150+
/// node to which the link points), unless [resolveTailLink] is true.
151+
/// Directory links in the middle of the path will be followed in order to
152+
/// find the node regardless of the value of [resolveTailLink].
151153
///
152154
/// If [segmentVisitor] is specified, it will be invoked for every path
153155
/// segment visited along the way starting where the reference (root folder
@@ -164,7 +166,8 @@ class MemoryFileSystem extends FileSystem {
164166
String path, {
165167
_Node reference,
166168
_SegmentVisitor segmentVisitor,
167-
StringBuffer pathWithSymlinks,
169+
List<String> pathWithSymlinks,
170+
bool resolveTailLink: false,
168171
}) {
169172
if (path == null) {
170173
throw new ArgumentError.notNull('path');
@@ -207,12 +210,17 @@ class MemoryFileSystem extends FileSystem {
207210
if (_isLink(child)) {
208211
child = _resolveLinks(child, subpath, ledger: pathWithSymlinks);
209212
} else if (pathWithSymlinks != null) {
210-
pathWithSymlinks..write(_separator)..write(basename);
213+
pathWithSymlinks..add(_separator)..add(basename);
211214
}
212215
_checkIsDir(child, subpath);
213216
directory = child;
217+
} else if (pathWithSymlinks != null) {
218+
pathWithSymlinks..add(_separator)..add(basename);
214219
}
215220
}
221+
if (_isLink(child) && resolveTailLink) {
222+
child = _resolveLinks(child, () => path);
223+
}
216224
return child;
217225
}
218226
}

lib/src/backends/memory/memory_file_system_entity.dart

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,11 @@ abstract class _MemoryFileSystemEntity implements FileSystemEntity {
5858

5959
@override
6060
String resolveSymbolicLinksSync() {
61-
StringBuffer ledger = new StringBuffer();
62-
_Node node = fileSystem._findNode(path, pathWithSymlinks: ledger);
63-
if (_isLink(node)) {
64-
_resolveLinks(node, () => path, ledger: ledger);
65-
}
66-
String resolved = ledger.toString();
61+
List<String> ledger = <String>[];
62+
_Node node = fileSystem._findNode(path,
63+
pathWithSymlinks: ledger, resolveTailLink: true);
64+
_checkExists(node, () => path);
65+
String resolved = ledger.join(_separator);
6766
if (!isAbsolute) {
6867
resolved = fileSystem._cwd + resolved;
6968
}

lib/src/backends/memory/utils.dart

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
part of file.src.backends.memory;
22

33
/// Checks if `node.type` returns [io.FileSystemEntityType.FILE].
4-
bool _isFile(_Node node) => node.type == io.FileSystemEntityType.FILE;
4+
bool _isFile(_Node node) => node?.type == io.FileSystemEntityType.FILE;
55

66
/// Checks if `node.type` returns [io.FileSystemEntityType.DIRECTORY].
7-
bool _isDirectory(_Node node) => node.type == io.FileSystemEntityType.DIRECTORY;
7+
bool _isDirectory(_Node node) =>
8+
node?.type == io.FileSystemEntityType.DIRECTORY;
89

910
/// Checks if `node.type` returns [io.FileSystemEntityType.LINK].
10-
bool _isLink(_Node node) => node.type == io.FileSystemEntityType.LINK;
11+
bool _isLink(_Node node) => node?.type == io.FileSystemEntityType.LINK;
1112

1213
/// Tells whether the specified path represents an absolute path.
1314
bool _isAbsolute(String path) => path.startsWith(_separator);
@@ -46,40 +47,33 @@ bool _isEmpty(String str) => str.isEmpty;
4647
/// [io.FileSystemException], calling [path] to generate the path.
4748
///
4849
/// If [ledger] is specified, the resolved path to the terminal node will be
49-
/// appended to the ledger. The path will not be normalized, meaning
50-
/// `..` and `.` path segments will not be resolved.
50+
/// appended to the ledger (or overwritten in the ledger if a link target
51+
/// specified an absolute path). The path will not be normalized, meaning
52+
/// `..` and `.` path segments may be present.
5153
_Node _resolveLinks(
5254
_LinkNode link,
5355
_PathGenerator path, {
54-
StringBuffer ledger,
56+
List<String> ledger,
5557
}) {
5658
// Record a breadcrumb trail to guard against symlink loops.
5759
Set<_LinkNode> breadcrumbs = new Set<_LinkNode>();
5860

59-
List<String> ledgerEntryBuilder = ledger != null ? <String>[''] : null;
6061
_Node node = link;
6162
while (_isLink(node)) {
6263
link = node;
6364
if (!breadcrumbs.add(node)) {
6465
throw new io.FileSystemException('Loop found in link chain', path());
6566
}
66-
if (ledgerEntryBuilder != null) {
67+
if (ledger != null) {
6768
if (_isAbsolute(link.target)) {
68-
ledgerEntryBuilder.clear;
69-
ledgerEntryBuilder.addAll(link.target.split(_separator));
70-
} else {
71-
if (ledgerEntryBuilder.isNotEmpty) {
72-
ledgerEntryBuilder.removeLast();
73-
}
74-
ledgerEntryBuilder.addAll(link.target.split(_separator));
69+
ledger.clear();
70+
} else if (ledger.isNotEmpty) {
71+
ledger.removeLast();
7572
}
73+
ledger.addAll(link.target.split(_separator));
7674
}
7775
node = link.referent;
7876
}
7977

80-
if (ledger != null) {
81-
ledger.write(ledgerEntryBuilder.join(_separator));
82-
}
83-
8478
return node;
8579
}

lib/src/interface/file_system.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'dart:io' as io;
33

44
import 'directory.dart';
55
import 'file.dart';
6+
import 'link.dart';
67

78
/// A generic representation of a file system.
89
///
@@ -19,6 +20,9 @@ abstract class FileSystem {
1920
/// Returns a reference to a [File] at [path].
2021
File file(String path);
2122

23+
/// Returns a reference to a [Link] at [path].
24+
Link link(String path);
25+
2226
/// Creates a directory object pointing to the current working directory.
2327
Directory get currentDirectory;
2428

0 commit comments

Comments
 (0)