Unverified Commit f766871e authored by Emmanuel Garcia's avatar Emmanuel Garcia Committed by GitHub

Forward ProcessException to error handlers (#44783)

parent 01f4f1ac
...@@ -334,39 +334,48 @@ Future<void> buildGradleApp({ ...@@ -334,39 +334,48 @@ Future<void> buildGradleApp({
} }
command.add(assembleTask); command.add(assembleTask);
final Stopwatch sw = Stopwatch()..start();
int exitCode = 1;
GradleHandledError detectedGradleError; GradleHandledError detectedGradleError;
String detectedGradleErrorLine; String detectedGradleErrorLine;
String consumeLog(String line) {
// This message was removed from first-party plugins,
// but older plugin versions still display this message.
if (androidXPluginWarningRegex.hasMatch(line)) {
// Don't pipe.
return null;
}
if (detectedGradleError != null) {
// Pipe stdout/stderr from Gradle.
return line;
}
for (final GradleHandledError gradleError in localGradleErrors) {
if (gradleError.test(line)) {
detectedGradleErrorLine = line;
detectedGradleError = gradleError;
// The first error match wins.
break;
}
}
// Pipe stdout/stderr from Gradle.
return line;
}
final Stopwatch sw = Stopwatch()..start();
int exitCode = 1;
try { try {
exitCode = await processUtils.stream( exitCode = await processUtils.stream(
command, command,
workingDirectory: project.android.hostAppGradleRoot.path, workingDirectory: project.android.hostAppGradleRoot.path,
allowReentrantFlutter: true, allowReentrantFlutter: true,
environment: gradleEnvironment, environment: gradleEnvironment,
mapFunction: (String line) { mapFunction: consumeLog,
// This message was removed from first-party plugins,
// but older plugin versions still display this message.
if (androidXPluginWarningRegex.hasMatch(line)) {
// Don't pipe.
return null;
}
if (detectedGradleError != null) {
// Pipe stdout/stderr from Gradle.
return line;
}
for (final GradleHandledError gradleError in localGradleErrors) {
if (gradleError.test(line)) {
detectedGradleErrorLine = line;
detectedGradleError = gradleError;
// The first error match wins.
break;
}
}
// Pipe stdout/stderr from Gradle.
return line;
},
); );
} on ProcessException catch(exception) {
consumeLog(exception.toString());
// Rethrow the exception if the error isn't handled by any of the
// `localGradleErrors`.
if (detectedGradleError == null) {
rethrow;
}
} finally { } finally {
status.stop(); status.stop();
} }
......
...@@ -85,7 +85,7 @@ final GradleHandledError permissionDeniedErrorHandler = GradleHandledError( ...@@ -85,7 +85,7 @@ final GradleHandledError permissionDeniedErrorHandler = GradleHandledError(
bool usesAndroidX, bool usesAndroidX,
bool shouldBuildPluginAsAar, bool shouldBuildPluginAsAar,
}) async { }) async {
printStatus('$warningMark Gradle does not have permission to execute by your user.', emphasis: true); printStatus('$warningMark Gradle does not have execution permission.', emphasis: true);
printStatus( printStatus(
'You should change the ownership of the project directory to your user, ' 'You should change the ownership of the project directory to your user, '
'or move the project to a directory with execute permissions.', 'or move the project to a directory with execute permissions.',
......
...@@ -231,7 +231,7 @@ Command: /home/android/gradlew assembleRelease ...@@ -231,7 +231,7 @@ Command: /home/android/gradlew assembleRelease
final BufferLogger logger = context.get<Logger>(); final BufferLogger logger = context.get<Logger>();
expect( expect(
logger.statusText, logger.statusText,
contains('Gradle does not have permission to execute by your user.'), contains('Gradle does not have execution permission.'),
); );
expect( expect(
logger.statusText, logger.statusText,
...@@ -399,7 +399,7 @@ Command: /home/android/gradlew assembleRelease ...@@ -399,7 +399,7 @@ Command: /home/android/gradlew assembleRelease
final BufferLogger logger = context.get<Logger>(); final BufferLogger logger = context.get<Logger>();
expect( expect(
logger.statusText, logger.statusText,
contains('Gradle does not have permission to execute by your user.'), contains('Gradle does not have execution permission.'),
); );
expect( expect(
logger.statusText, logger.statusText,
......
...@@ -1266,6 +1266,123 @@ plugin2=${plugin2.path} ...@@ -1266,6 +1266,123 @@ plugin2=${plugin2.path}
Usage: () => mockUsage, Usage: () => mockUsage,
}); });
testUsingContext('recognizes process exceptions - tool exit', () async {
when(mockProcessManager.start(any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment')))
.thenThrow(const ProcessException('', <String>[], 'Some gradle message'));
fs.directory('android')
.childFile('build.gradle')
.createSync(recursive: true);
fs.directory('android')
.childFile('gradle.properties')
.createSync(recursive: true);
fs.directory('android')
.childDirectory('app')
.childFile('build.gradle')
..createSync(recursive: true)
..writeAsStringSync('apply from: irrelevant/flutter.gradle');
bool handlerCalled = false;
await expectLater(() async {
await buildGradleApp(
project: FlutterProject.current(),
androidBuildInfo: const AndroidBuildInfo(
BuildInfo(
BuildMode.release,
null,
),
),
target: 'lib/main.dart',
isBuildingBundle: false,
localGradleErrors: <GradleHandledError>[
GradleHandledError(
test: (String line) {
return line.contains('Some gradle message');
},
handler: ({
String line,
FlutterProject project,
bool usesAndroidX,
bool shouldBuildPluginAsAar,
}) async {
handlerCalled = true;
return GradleBuildStatus.exit;
},
eventLabel: 'random-event-label',
),
],
);
},
throwsToolExit(
message: 'Gradle task assembleRelease failed with exit code 1'
));
expect(handlerCalled, isTrue);
verify(mockUsage.sendEvent(
any,
any,
label: 'gradle-random-event-label-failure',
parameters: anyNamed('parameters'),
)).called(1);
}, overrides: <Type, Generator>{
AndroidSdk: () => mockAndroidSdk,
Cache: () => cache,
Platform: () => android,
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
Usage: () => mockUsage,
});
testUsingContext('rethrows unrecognized ProcessException', () async {
when(mockProcessManager.start(any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment')))
.thenThrow(const ProcessException('', <String>[], 'Unrecognized'));
fs.directory('android')
.childFile('build.gradle')
.createSync(recursive: true);
fs.directory('android')
.childFile('gradle.properties')
.createSync(recursive: true);
fs.directory('android')
.childDirectory('app')
.childFile('build.gradle')
..createSync(recursive: true)
..writeAsStringSync('apply from: irrelevant/flutter.gradle');
await expectLater(() async {
await buildGradleApp(
project: FlutterProject.current(),
androidBuildInfo: const AndroidBuildInfo(
BuildInfo(
BuildMode.release,
null,
),
),
target: 'lib/main.dart',
isBuildingBundle: false,
localGradleErrors: const <GradleHandledError>[],
);
},
throwsA(isInstanceOf<ProcessException>()));
}, overrides: <Type, Generator>{
AndroidSdk: () => mockAndroidSdk,
Cache: () => cache,
Platform: () => android,
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
});
testUsingContext('logs success event after a sucessful retry', () async { testUsingContext('logs success event after a sucessful retry', () async {
int testFnCalled = 0; int testFnCalled = 0;
when(mockProcessManager.start(any, when(mockProcessManager.start(any,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment