Skip to content

Commit ba7b1d9

Browse files
committed
instead of logging, ToolExit when a transformation fails
1 parent b872910 commit ba7b1d9

File tree

4 files changed

+95
-47
lines changed

4 files changed

+95
-47
lines changed

packages/flutter_tools/lib/src/build_system/targets/assets.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:pool/pool.dart';
66

77
import '../../artifacts.dart';
88
import '../../asset.dart';
9+
import '../../base/common.dart';
910
import '../../base/file_system.dart';
1011
import '../../base/logger.dart';
1112
import '../../build_info.dart';
@@ -98,7 +99,6 @@ Future<Depfile> copyAssets(
9899
);
99100
final AssetTransformer assetTransformer = AssetTransformer(
100101
processManager: environment.processManager,
101-
logger: environment.logger,
102102
fileSystem: environment.fileSystem,
103103
dartBinaryPath: environment.artifacts.getArtifactPath(Artifact.engineDartBinary),
104104
);
@@ -143,12 +143,15 @@ Future<Depfile> copyAssets(
143143
switch (entry.value.kind) {
144144
case AssetKind.regular:
145145
if (entry.value.transformers.isNotEmpty) {
146-
doCopy = !await assetTransformer.transformAsset(
146+
final AssetTransformationFailure? failure = await assetTransformer.transformAsset(
147147
asset: content.file as File,
148148
outputPath: file.path,
149149
workingDirectory: environment.projectDir.path,
150150
transformerEntries: entry.value.transformers,
151151
);
152+
if (failure != null) {
153+
throwToolExit(failure.message);
154+
}
152155
}
153156
case AssetKind.font:
154157
doCopy = !await iconTreeShaker.subsetFont(

packages/flutter_tools/lib/src/build_system/tools/asset_transformer.dart

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,20 @@ import 'package:process/process.dart';
88
import '../../base/error_handling_io.dart';
99
import '../../base/file_system.dart';
1010
import '../../base/io.dart';
11-
import '../../base/logger.dart';
1211
import '../../flutter_manifest.dart';
1312
import '../build_system.dart';
1413

1514
/// Applies a series of user-specified asset-transforming packages to an asset file.
1615
final class AssetTransformer {
1716
AssetTransformer({
1817
required ProcessManager processManager,
19-
required Logger logger,
2018
required FileSystem fileSystem,
2119
required String dartBinaryPath,
2220
}) : _processManager = processManager,
23-
_logger = logger,
2421
_fileSystem = fileSystem,
2522
_dartBinaryPath = dartBinaryPath;
2623

2724
final ProcessManager _processManager;
28-
final Logger _logger;
2925
final FileSystem _fileSystem;
3026
final String _dartBinaryPath;
3127

@@ -40,9 +36,7 @@ final class AssetTransformer {
4036

4137
/// Applies, in sequence, a list of transformers to an [asset] and then copies
4238
/// the output to [outputPath].
43-
///
44-
/// Returns `true` if successful and `false` otherwise.
45-
Future<bool> transformAsset({
39+
Future<AssetTransformationFailure?> transformAsset({
4640
required File asset,
4741
required String outputPath,
4842
required String workingDirectory,
@@ -61,19 +55,18 @@ final class AssetTransformer {
6155

6256
try {
6357
for (final (int i, AssetTransformerEntry transformer) in transformerEntries.indexed) {
64-
final _AssetTransformerFailure? transformerFailure = await _applyTransformer(
58+
final AssetTransformationFailure? transformerFailure = await _applyTransformer(
6559
asset: tempInputFile,
6660
output: tempOutputFile,
6761
transformer: transformer,
6862
workingDirectory: workingDirectory,
6963
);
7064

7165
if (transformerFailure != null) {
72-
_logger.printError(
66+
return AssetTransformationFailure(
7367
'User-defined transformation of asset "${asset.path}" failed.\n'
7468
'${transformerFailure.message}',
7569
);
76-
return false;
7770
}
7871

7972
ErrorHandlingFileSystem.deleteIfExists(tempInputFile);
@@ -89,10 +82,10 @@ final class AssetTransformer {
8982
ErrorHandlingFileSystem.deleteIfExists(tempOutputFile);
9083
}
9184

92-
return true;
85+
return null;
9386
}
9487

95-
Future<_AssetTransformerFailure?> _applyTransformer({
88+
Future<AssetTransformationFailure?> _applyTransformer({
9689
required File asset,
9790
required File output,
9891
required AssetTransformerEntry transformer,
@@ -119,7 +112,7 @@ final class AssetTransformer {
119112
final String stderr = result.stderr as String;
120113

121114
if (result.exitCode != 0) {
122-
return _AssetTransformerFailure(
115+
return AssetTransformationFailure(
123116
'Transformer process terminated with non-zero exit code: ${result.exitCode}\n'
124117
'Transformer package: ${transformer.package}\n'
125118
'Full command: ${command.join(' ')}\n'
@@ -129,7 +122,7 @@ final class AssetTransformer {
129122
}
130123

131124
if (!_fileSystem.file(output).existsSync()) {
132-
return _AssetTransformerFailure(
125+
return AssetTransformationFailure(
133126
'Asset transformer ${transformer.package} did not produce an output file.\n'
134127
'Input file provided to transformer: "${asset.path}"\n'
135128
'Expected output file at: "${output.absolute.path}"\n'
@@ -143,8 +136,8 @@ final class AssetTransformer {
143136
}
144137
}
145138

146-
final class _AssetTransformerFailure {
147-
const _AssetTransformerFailure(this.message);
139+
final class AssetTransformationFailure {
140+
const AssetTransformationFailure(this.message);
148141

149142
final String message;
150143
}

packages/flutter_tools/test/general.shard/build_system/targets/asset_transformer_test.dart

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,11 @@ void main() {
5151

5252
final AssetTransformer transformer = AssetTransformer(
5353
processManager: processManager,
54-
logger: logger,
5554
fileSystem: fileSystem,
5655
dartBinaryPath: artifacts.getArtifactPath(Artifact.engineDartBinary),
5756
);
5857

59-
final bool transformationSuccessful = await transformer.transformAsset(
58+
final AssetTransformationFailure? transformationFailure = await transformer.transformAsset(
6059
asset: asset,
6160
outputPath: outputPath,
6261
workingDirectory: fileSystem.currentDirectory.path,
@@ -72,13 +71,12 @@ void main() {
7271
],
7372
);
7473

75-
expect(transformationSuccessful, isTrue, reason: logger.errorText);
74+
expect(transformationFailure, isNull, reason: logger.errorText);
7675
expect(processManager, hasNoRemainingExpectations);
7776
});
7877

7978
testWithoutContext('logs useful error information when transformation process returns a nonzero exit code', () async {
8079
final FileSystem fileSystem = MemoryFileSystem.test();
81-
final BufferLogger logger = BufferLogger.test();
8280
final Artifacts artifacts = Artifacts.test();
8381

8482
final File asset = fileSystem.file('asset.txt')..createSync();
@@ -110,12 +108,11 @@ void main() {
110108

111109
final AssetTransformer transformer = AssetTransformer(
112110
processManager: processManager,
113-
logger: logger,
114111
fileSystem: fileSystem,
115112
dartBinaryPath: dartBinaryPath,
116113
);
117114

118-
final bool transformationSuccessful = await transformer.transformAsset(
115+
final AssetTransformationFailure? failure = await transformer.transformAsset(
119116
asset: asset,
120117
outputPath: outputPath,
121118
workingDirectory: fileSystem.currentDirectory.path,
@@ -127,10 +124,10 @@ void main() {
127124
],
128125
);
129126

130-
expect(transformationSuccessful, false, reason: logger.errorText);
131127
expect(asset, exists);
132128
expect(processManager, hasNoRemainingExpectations);
133-
expect(logger.errorText, contains(
129+
expect(failure, isNotNull);
130+
expect(failure!.message,
134131
'''
135132
User-defined transformation of asset "asset.txt" failed.
136133
Transformer process terminated with non-zero exit code: 1
@@ -139,13 +136,11 @@ Full command: $dartBinaryPath run my_transformer --input=/.tmp_rand0/asset.txt-t
139136
stdout:
140137
Beginning transformation
141138
stderr:
142-
Something went wrong
143-
'''));
139+
Something went wrong''');
144140
});
145141

146142
testWithoutContext('prints error message when the transformer does not produce an output file', () async {
147143
final FileSystem fileSystem = MemoryFileSystem.test();
148-
final BufferLogger logger = BufferLogger.test();
149144
final Artifacts artifacts = Artifacts.test();
150145

151146
final File asset = fileSystem.file('asset.txt')..createSync();
@@ -171,12 +166,11 @@ Something went wrong
171166

172167
final AssetTransformer transformer = AssetTransformer(
173168
processManager: processManager,
174-
logger: logger,
175169
fileSystem: fileSystem,
176170
dartBinaryPath: dartBinaryPath,
177171
);
178172

179-
final bool transformationSuccessful = await transformer.transformAsset(
173+
final AssetTransformationFailure? failure = await transformer.transformAsset(
180174
asset: asset,
181175
outputPath: outputPath,
182176
workingDirectory: fileSystem.currentDirectory.path,
@@ -189,7 +183,8 @@ Something went wrong
189183
);
190184

191185
expect(processManager, hasNoRemainingExpectations);
192-
expect(logger.errorText,
186+
expect(failure, isNotNull);
187+
expect(failure!.message,
193188
'''
194189
User-defined transformation of asset "asset.txt" failed.
195190
Asset transformer my_transformer did not produce an output file.
@@ -199,15 +194,12 @@ Full command: $dartBinaryPath run my_transformer --input=/.tmp_rand0/asset.txt-t
199194
stdout:
200195
201196
stderr:
202-
Transformation failed, but I forgot to exit with a non-zero code.
203-
'''
197+
Transformation failed, but I forgot to exit with a non-zero code.'''
204198
);
205-
expect(transformationSuccessful, false);
206199
});
207200

208201
testWithoutContext('correctly chains transformations when there are multiple of them', () async {
209202
final FileSystem fileSystem = MemoryFileSystem.test();
210-
final BufferLogger logger = BufferLogger.test();
211203
final Artifacts artifacts = Artifacts.test();
212204

213205
final File asset = fileSystem.file('asset.txt')
@@ -267,12 +259,11 @@ Transformation failed, but I forgot to exit with a non-zero code.
267259

268260
final AssetTransformer transformer = AssetTransformer(
269261
processManager: processManager,
270-
logger: logger,
271262
fileSystem: fileSystem,
272263
dartBinaryPath: dartBinaryPath,
273264
);
274265

275-
await transformer.transformAsset(
266+
final AssetTransformationFailure? failure = await transformer.transformAsset(
276267
asset: asset,
277268
outputPath: outputPath,
278269
workingDirectory: fileSystem.currentDirectory.path,
@@ -289,12 +280,12 @@ Transformation failed, but I forgot to exit with a non-zero code.
289280
);
290281

291282
expect(processManager, hasNoRemainingExpectations);
283+
expect(failure, isNull);
292284
expect(fileSystem.file(outputPath).readAsStringSync(), '012');
293285
});
294286

295287
testWithoutContext('prints an error when a transformer in a chain (thats not the first) does not produce an output', () async {
296288
final FileSystem fileSystem = MemoryFileSystem();
297-
final BufferLogger logger = BufferLogger.test();
298289
final Artifacts artifacts = Artifacts.test();
299290

300291
final File asset = fileSystem.file('asset.txt')
@@ -341,12 +332,11 @@ Transformation failed, but I forgot to exit with a non-zero code.
341332

342333
final AssetTransformer transformer = AssetTransformer(
343334
processManager: processManager,
344-
logger: logger,
345335
fileSystem: fileSystem,
346336
dartBinaryPath: dartBinaryPath,
347337
);
348338

349-
final bool transformationSuccessful = await transformer.transformAsset(
339+
final AssetTransformationFailure? failure = await transformer.transformAsset(
350340
asset: asset,
351341
outputPath: outputPath,
352342
workingDirectory: fileSystem.currentDirectory.path,
@@ -362,10 +352,8 @@ Transformation failed, but I forgot to exit with a non-zero code.
362352
],
363353
);
364354

365-
expect(transformationSuccessful, isFalse);
366-
expect(processManager, hasNoRemainingExpectations);
367-
expect(fileSystem.file(outputPath), isNot(exists));
368-
expect(logger.errorText,
355+
expect(failure, isNotNull);
356+
expect(failure!.message,
369357
'''
370358
User-defined transformation of asset "asset.txt" failed.
371359
Asset transformer my_distance_from_ascii_a_transformer did not produce an output file.
@@ -375,9 +363,10 @@ Full command: Artifact.engineDartBinary run my_distance_from_ascii_a_transformer
375363
stdout:
376364
377365
stderr:
378-
Transformation failed, but I forgot to exit with a non-zero code.
379-
'''
366+
Transformation failed, but I forgot to exit with a non-zero code.'''
380367
);
368+
expect(processManager, hasNoRemainingExpectations);
369+
expect(fileSystem.file(outputPath), isNot(exists));
381370
expect(fileSystem.systemTempDirectory.listSync(), isEmpty);
382371
});
383372
}

packages/flutter_tools/test/general.shard/build_system/targets/assets_test.dart

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,69 @@ flutter:
240240
),
241241
});
242242

243+
testUsingContext('exits tool if an asset transformation fails', () async {
244+
Cache.flutterRoot = Cache.defaultFlutterRoot(
245+
platform: globals.platform,
246+
fileSystem: fileSystem,
247+
userMessages: UserMessages(),
248+
);
249+
250+
final Environment environment = Environment.test(
251+
fileSystem.currentDirectory,
252+
processManager: globals.processManager,
253+
artifacts: Artifacts.test(),
254+
fileSystem: fileSystem,
255+
logger: logger,
256+
platform: globals.platform,
257+
defines: <String, String>{},
258+
);
259+
260+
await fileSystem.file('.packages').create();
261+
262+
fileSystem.file('pubspec.yaml')
263+
..createSync()
264+
..writeAsStringSync('''
265+
name: example
266+
flutter:
267+
assets:
268+
- path: input.txt
269+
transformers:
270+
- package: my_transformer
271+
args: ["-a", "-b", "--color", "green"]
272+
''');
273+
274+
await fileSystem.file('input.txt').create(recursive: true);
275+
276+
await expectToolExitLater(
277+
const CopyAssets().build(environment),
278+
startsWith('User-defined transformation of asset "/input.txt" failed.\n'),
279+
);
280+
expect(globals.processManager, hasNoRemainingExpectations);
281+
}, overrides: <Type, Generator> {
282+
Logger: () => logger,
283+
FileSystem: () => fileSystem,
284+
Platform: () => FakePlatform(),
285+
ProcessManager: () => FakeProcessManager.list(
286+
<FakeCommand>[
287+
FakeCommand(
288+
command: <Pattern>[
289+
Artifacts.test().getArtifactPath(Artifact.engineDartBinary),
290+
'run',
291+
'my_transformer',
292+
RegExp('--input=.*'),
293+
RegExp('--output=.*'),
294+
'-a',
295+
'-b',
296+
'--color',
297+
'green',
298+
],
299+
exitCode: 1,
300+
),
301+
],
302+
),
303+
});
304+
305+
243306
testUsingContext('Throws exception if pubspec contains missing files', () async {
244307
fileSystem.file('pubspec.yaml')
245308
..createSync()

0 commit comments

Comments
 (0)