Skip to content

Commit cb8fc64

Browse files
committed
Introduce TestReaderWriter with test-specific API.
Move `FilesystemCache` and `AssetPathProvider` out of `Filesystem` and into the `Reader` classes.
1 parent 2f2eca0 commit cb8fc64

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+588
-447
lines changed

_test_common/lib/in_memory_reader_writer.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import 'dart:convert';
77
import 'package:build/build.dart';
88
import 'package:build_runner_core/build_runner_core.dart';
99
import 'package:build_test/build_test.dart';
10+
// ignore: implementation_imports
11+
import 'package:build_test/src/in_memory_reader_writer.dart';
1012
import 'package:path/path.dart' as p;
1113
import 'package:watcher/watcher.dart';
1214

@@ -26,7 +28,7 @@ class InMemoryRunnerAssetReaderWriter extends InMemoryAssetReaderWriter
2628

2729
@override
2830
Future writeAsBytes(AssetId id, List<int> bytes) async {
29-
var type = assets.containsKey(id) ? ChangeType.MODIFY : ChangeType.ADD;
31+
var type = testing.exists(id) ? ChangeType.MODIFY : ChangeType.ADD;
3032
await super.writeAsBytes(id, bytes);
3133
FakeWatcher.notifyWatchers(
3234
WatchEvent(type, p.absolute(id.package, p.fromUri(id.path))),
@@ -39,7 +41,7 @@ class InMemoryRunnerAssetReaderWriter extends InMemoryAssetReaderWriter
3941
String contents, {
4042
Encoding encoding = utf8,
4143
}) async {
42-
var type = assets.containsKey(id) ? ChangeType.MODIFY : ChangeType.ADD;
44+
var type = testing.exists(id) ? ChangeType.MODIFY : ChangeType.ADD;
4345
await super.writeAsString(id, contents, encoding: encoding);
4446
FakeWatcher.notifyWatchers(
4547
WatchEvent(type, p.absolute(id.package, p.fromUri(id.path))),
@@ -49,7 +51,7 @@ class InMemoryRunnerAssetReaderWriter extends InMemoryAssetReaderWriter
4951
@override
5052
Future delete(AssetId id) async {
5153
onDelete?.call(id);
52-
assets.remove(id);
54+
testing.delete(id);
5355
FakeWatcher.notifyWatchers(
5456
WatchEvent(ChangeType.REMOVE, p.absolute(id.package, p.fromUri(id.path))),
5557
);

_test_common/lib/test_phases.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ Future<TestBuildersResult> testBuilders(
116116
inputs.forEach((serializedId, contents) {
117117
var id = makeAssetId(serializedId);
118118
if (contents is String) {
119-
readerWriter.filesystem.writeAsStringSync(id, contents);
119+
readerWriter.testing.writeString(id, contents);
120120
} else if (contents is List<int>) {
121-
readerWriter.filesystem.writeAsBytesSync(id, contents);
121+
readerWriter.testing.writeBytes(id, contents);
122122
}
123123
});
124124

@@ -179,7 +179,7 @@ Future<TestBuildersResult> testBuilders(
179179
void checkBuild(
180180
BuildResult result, {
181181
Map<String, Object>? outputs,
182-
required InMemoryAssetReaderWriter readerWriter,
182+
required TestReaderWriter readerWriter,
183183
BuildStatus status = BuildStatus.success,
184184
String rootPackage = 'a',
185185
String expectedGeneratedDir = 'generated',

build/lib/src/builder/build_step_impl.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ class BuildStepImpl implements BuildStep, AssetReaderState {
100100
@override
101101
Filesystem get filesystem => _reader.filesystem;
102102

103+
@override
104+
FilesystemCache get cache => _reader.cache;
105+
103106
@override
104107
AssetFinder get assetFinder => _reader.assetFinder;
105108

build/lib/src/state/filesystem.dart

Lines changed: 65 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -8,58 +8,44 @@ import 'dart:typed_data';
88

99
import 'package:pool/pool.dart';
1010

11-
import '../asset/id.dart';
12-
import 'asset_path_provider.dart';
13-
import 'filesystem_cache.dart';
14-
1511
/// The filesystem the build is running on.
1612
///
1713
/// Methods behave as the `dart:io` methods with the same names, with some
1814
/// exceptions noted in the docs.
19-
///
20-
/// Some methods cache, all uses of the cache are noted in the docs.
21-
///
22-
/// The cache might be a [PassthroughFilesystemCache] in which case it has no
23-
/// effect.
24-
///
25-
/// TODO(davidmorgan): extend caching to sync methods, deletes, writes.
2615
abstract interface class Filesystem {
27-
FilesystemCache get cache;
28-
29-
/// Returns a new instance with optionally updated [cache].
30-
Filesystem copyWith({FilesystemCache? cache});
16+
/// Whether the file exists.
17+
Future<bool> exists(String path);
3118

3219
/// Whether the file exists.
33-
///
34-
/// Uses [cache].
35-
Future<bool> exists(AssetId id);
20+
bool existsSync(String path);
3621

3722
/// Reads a file as a string.
38-
///
39-
/// Uses [cache]. For `utf8`, the `String` is cached; for any other encoding
40-
/// the bytes are cached but the conversion runs on every read.
41-
Future<String> readAsString(AssetId id, {Encoding encoding = utf8});
23+
Future<String> readAsString(String path, {Encoding encoding = utf8});
24+
25+
/// Reads a file as a string.
26+
String readAsStringSync(String path, {Encoding encoding = utf8});
4227

4328
/// Reads a file as bytes.
44-
///
45-
/// Uses [cache].
46-
Future<Uint8List> readAsBytes(AssetId id);
29+
Future<Uint8List> readAsBytes(String path);
30+
31+
/// Reads a file as bytes.
32+
Uint8List readAsBytesSync(String path);
4733

4834
/// Deletes a file.
4935
///
5036
/// If the file does not exist, does nothing.
51-
Future<void> delete(AssetId id);
37+
Future<void> delete(String path);
5238

5339
/// Deletes a file.
5440
///
5541
/// If the file does not exist, does nothing.
56-
void deleteSync(AssetId id);
42+
void deleteSync(String path);
5743

5844
/// Writes a file.
5945
///
6046
/// Creates enclosing directories as needed if they don't exist.
6147
void writeAsStringSync(
62-
AssetId id,
48+
String path,
6349
String contents, {
6450
Encoding encoding = utf8,
6551
});
@@ -68,205 +54,165 @@ abstract interface class Filesystem {
6854
///
6955
/// Creates enclosing directories as needed if they don't exist.
7056
Future<void> writeAsString(
71-
AssetId id,
57+
String path,
7258
String contents, {
7359
Encoding encoding = utf8,
7460
});
7561

7662
/// Writes a file.
7763
///
7864
/// Creates enclosing directories as needed if they don't exist.
79-
void writeAsBytesSync(AssetId id, List<int> contents);
65+
void writeAsBytesSync(String path, List<int> contents);
8066

8167
/// Writes a file.
8268
///
8369
/// Creates enclosing directories as needed if they don't exist.
84-
Future<void> writeAsBytes(AssetId id, List<int> contents);
70+
Future<void> writeAsBytes(String path, List<int> contents);
8571
}
8672

87-
/// A filesystem using [assetPathProvider] to map to the `dart:io` filesystem.
73+
/// The `dart:io` filesystem.
8874
class IoFilesystem implements Filesystem {
89-
@override
90-
final FilesystemCache cache;
91-
92-
final AssetPathProvider assetPathProvider;
93-
9475
/// Pool for async file operations.
9576
final _pool = Pool(32);
9677

97-
IoFilesystem({
98-
required this.assetPathProvider,
99-
this.cache = const PassthroughFilesystemCache(),
100-
});
78+
@override
79+
Future<bool> exists(String path) => _pool.withResource(File(path).exists);
10180

10281
@override
103-
IoFilesystem copyWith({FilesystemCache? cache}) => IoFilesystem(
104-
assetPathProvider: assetPathProvider,
105-
cache: cache ?? this.cache,
106-
);
82+
bool existsSync(String path) => File(path).existsSync();
10783

10884
@override
109-
Future<bool> exists(AssetId id) =>
110-
cache.exists(id, ifAbsent: () => _pool.withResource(_fileFor(id).exists));
85+
Future<Uint8List> readAsBytes(String path) =>
86+
_pool.withResource(File(path).readAsBytes);
11187

11288
@override
113-
Future<Uint8List> readAsBytes(AssetId id) => cache.readAsBytes(
114-
id,
115-
ifAbsent: () => _pool.withResource(_fileFor(id).readAsBytes),
116-
);
89+
Uint8List readAsBytesSync(String path) => File(path).readAsBytesSync();
11790

11891
@override
119-
Future<String> readAsString(AssetId id, {Encoding encoding = utf8}) async {
120-
// The cache only directly supports utf8, for other encodings get the
121-
// bytes via the cache then convert.
122-
if (encoding == utf8) {
123-
return cache.readAsString(
124-
id,
125-
ifAbsent: () => _pool.withResource(_fileFor(id).readAsString),
126-
);
127-
} else {
128-
return encoding.decode(await readAsBytes(id));
129-
}
130-
}
92+
Future<String> readAsString(String path, {Encoding encoding = utf8}) =>
93+
_pool.withResource(() => File(path).readAsString(encoding: encoding));
13194

13295
@override
133-
void deleteSync(AssetId id) {
134-
final file = _fileFor(id);
96+
String readAsStringSync(String path, {Encoding encoding = utf8}) =>
97+
File(path).readAsStringSync(encoding: encoding);
98+
99+
@override
100+
void deleteSync(String path) {
101+
final file = File(path);
135102
if (file.existsSync()) file.deleteSync();
136103
}
137104

138105
@override
139-
Future<void> delete(AssetId id) {
106+
Future<void> delete(String path) {
140107
return _pool.withResource(() async {
141-
final file = _fileFor(id);
108+
final file = File(path);
142109
if (await file.exists()) await file.delete();
143110
});
144111
}
145112

146113
@override
147114
void writeAsBytesSync(
148-
AssetId id,
115+
String path,
149116
List<int> contents, {
150117
Encoding encoding = utf8,
151118
}) {
152-
final file = _fileFor(id);
119+
final file = File(path);
153120
file.parent.createSync(recursive: true);
154121
file.writeAsBytesSync(contents);
155122
}
156123

157124
@override
158-
Future<void> writeAsBytes(AssetId id, List<int> contents) {
125+
Future<void> writeAsBytes(String path, List<int> contents) {
159126
return _pool.withResource(() async {
160-
final file = _fileFor(id);
127+
final file = File(path);
161128
await file.parent.create(recursive: true);
162129
await file.writeAsBytes(contents);
163130
});
164131
}
165132

166133
@override
167134
void writeAsStringSync(
168-
AssetId id,
135+
String path,
169136
String contents, {
170137
Encoding encoding = utf8,
171138
}) {
172-
final file = _fileFor(id);
139+
final file = File(path);
173140
file.parent.createSync(recursive: true);
174141
file.writeAsStringSync(contents, encoding: encoding);
175142
}
176143

177144
@override
178145
Future<void> writeAsString(
179-
AssetId id,
146+
String path,
180147
String contents, {
181148
Encoding encoding = utf8,
182149
}) {
183150
return _pool.withResource(() async {
184-
final file = _fileFor(id);
151+
final file = File(path);
185152
await file.parent.create(recursive: true);
186153
await file.writeAsString(contents, encoding: encoding);
187154
});
188155
}
189-
190-
/// Returns a [File] for [id] for the current [assetPathProvider].
191-
File _fileFor(AssetId id) {
192-
return File(assetPathProvider.pathFor(id));
193-
}
194156
}
195157

196158
/// An in-memory [Filesystem].
197159
class InMemoryFilesystem implements Filesystem {
198-
@override
199-
FilesystemCache cache;
160+
final Map<String, Uint8List> _files = {};
200161

201-
final Map<AssetId, List<int>> assets;
162+
/// The paths to all files present on the filesystem.
163+
Iterable<String> get filePaths => _files.keys;
202164

203-
InMemoryFilesystem({FilesystemCache? cache})
204-
: cache = cache ?? const PassthroughFilesystemCache(),
205-
assets = {};
165+
@override
166+
Future<bool> exists(String path) async => _files.containsKey(path);
206167

207-
InMemoryFilesystem._({required this.cache, required this.assets});
168+
@override
169+
bool existsSync(String path) => _files.containsKey(path);
208170

209171
@override
210-
InMemoryFilesystem copyWith({FilesystemCache? cache}) =>
211-
InMemoryFilesystem._(assets: assets, cache: cache ?? this.cache);
172+
Future<Uint8List> readAsBytes(String path) async => _files[path]!;
212173

213174
@override
214-
Future<bool> exists(AssetId id) async =>
215-
cache.exists(id, ifAbsent: () async => assets.containsKey(id));
175+
Uint8List readAsBytesSync(String path) => _files[path]!;
216176

217177
@override
218-
Future<Uint8List> readAsBytes(AssetId id) async =>
219-
cache.readAsBytes(id, ifAbsent: () async => assets[id] as Uint8List);
178+
Future<String> readAsString(String path, {Encoding encoding = utf8}) async =>
179+
encoding.decode(_files[path]!);
220180

221181
@override
222-
Future<String> readAsString(AssetId id, {Encoding encoding = utf8}) async {
223-
// The cache only directly supports utf8, for other encodings get the
224-
// bytes via the cache then convert.
225-
if (encoding == utf8) {
226-
return cache.readAsString(
227-
id,
228-
ifAbsent: () async => encoding.decode(assets[id]!),
229-
);
230-
} else {
231-
return encoding.decode(await readAsBytes(id));
232-
}
233-
}
182+
String readAsStringSync(String path, {Encoding encoding = utf8}) =>
183+
encoding.decode(_files[path]!);
234184

235185
@override
236-
Future<void> delete(AssetId id) async {
237-
assets.remove(id);
238-
}
186+
Future<void> delete(String path) async => _files.remove(path);
239187

240188
@override
241-
void deleteSync(AssetId id) async {
242-
assets.remove(id);
243-
}
189+
void deleteSync(String path) async => _files.remove(path);
244190

245191
@override
246-
void writeAsBytesSync(AssetId id, List<int> contents) {
247-
assets[id] = contents;
192+
void writeAsBytesSync(String path, List<int> contents) {
193+
_files[path] = Uint8List.fromList(contents);
248194
}
249195

250196
@override
251-
Future<void> writeAsBytes(AssetId id, List<int> contents) async {
252-
assets[id] = contents;
197+
Future<void> writeAsBytes(String path, List<int> contents) async {
198+
_files[path] = Uint8List.fromList(contents);
253199
}
254200

255201
@override
256202
void writeAsStringSync(
257-
AssetId id,
203+
String path,
258204
String contents, {
259205
Encoding encoding = utf8,
260206
}) {
261-
assets[id] = encoding.encode(contents);
207+
_files[path] = Uint8List.fromList(encoding.encode(contents));
262208
}
263209

264210
@override
265211
Future<void> writeAsString(
266-
AssetId id,
212+
String path,
267213
String contents, {
268214
Encoding encoding = utf8,
269215
}) async {
270-
assets[id] = encoding.encode(contents);
216+
_files[path] = Uint8List.fromList(encoding.encode(contents));
271217
}
272218
}

0 commit comments

Comments
 (0)