[flutter_tools] rethrow process exceptions as tool exit from gradle build (#64745)
The flutter tool is currently unable to detect missing permissions in gradle/gradle.bat that would cause a gradle build to fail via process exception. Rather than crashing and exiting, we can display the exception as an error message and tool exit. While linux/macOS are able to add the +x bit, this is not possible on windows with our current file system/OS API. These crashes represent a substantial amount of crash reporting, but are otherwise not actionable on our end.
This commit is contained in:
parent
20936eeac4
commit
bd3eee75f3
@ -28,7 +28,7 @@ import 'src/runner/flutter_command_runner.dart';
|
|||||||
// TODO(jonahwilliams): update command type once g3 has rolled.
|
// TODO(jonahwilliams): update command type once g3 has rolled.
|
||||||
Future<int> run(
|
Future<int> run(
|
||||||
List<String> args,
|
List<String> args,
|
||||||
dynamic commands, {
|
List<FlutterCommand> Function() commands, {
|
||||||
bool muteCommandLogging = false,
|
bool muteCommandLogging = false,
|
||||||
bool verbose = false,
|
bool verbose = false,
|
||||||
bool verboseHelp = false,
|
bool verboseHelp = false,
|
||||||
@ -42,17 +42,11 @@ Future<int> run(
|
|||||||
args = List<String>.of(args);
|
args = List<String>.of(args);
|
||||||
args.removeWhere((String option) => option == '-v' || option == '--verbose');
|
args.removeWhere((String option) => option == '-v' || option == '--verbose');
|
||||||
}
|
}
|
||||||
List<FlutterCommand> Function() commandGenerator;
|
|
||||||
if (commands is List<FlutterCommand>) {
|
|
||||||
commandGenerator = () => commands;
|
|
||||||
} else {
|
|
||||||
commandGenerator = commands as List<FlutterCommand> Function();
|
|
||||||
}
|
|
||||||
|
|
||||||
return runInContext<int>(() async {
|
return runInContext<int>(() async {
|
||||||
reportCrashes ??= !await globals.isRunningOnBot;
|
reportCrashes ??= !await globals.isRunningOnBot;
|
||||||
final FlutterCommandRunner runner = FlutterCommandRunner(verboseHelp: verboseHelp);
|
final FlutterCommandRunner runner = FlutterCommandRunner(verboseHelp: verboseHelp);
|
||||||
commandGenerator().forEach(runner.addCommand);
|
commands().forEach(runner.addCommand);
|
||||||
|
|
||||||
// Initialize the system locale.
|
// Initialize the system locale.
|
||||||
final String systemLocale = await intl_standalone.findSystemLocale();
|
final String systemLocale = await intl_standalone.findSystemLocale();
|
||||||
|
@ -397,7 +397,7 @@ Future<void> buildGradleApp({
|
|||||||
environment: gradleEnvironment,
|
environment: gradleEnvironment,
|
||||||
mapFunction: consumeLog,
|
mapFunction: consumeLog,
|
||||||
);
|
);
|
||||||
} on ProcessException catch(exception) {
|
} on ProcessException catch (exception) {
|
||||||
consumeLog(exception.toString());
|
consumeLog(exception.toString());
|
||||||
// Rethrow the exception if the error isn't handled by any of the
|
// Rethrow the exception if the error isn't handled by any of the
|
||||||
// `localGradleErrors`.
|
// `localGradleErrors`.
|
||||||
|
@ -3,16 +3,17 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io' as io show Directory, File, Link;
|
import 'dart:io' as io show Directory, File, Link, ProcessException, ProcessResult, ProcessSignal, systemEncoding, Process, ProcessStartMode;
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:path/path.dart' as p; // ignore: package_path_import
|
import 'package:path/path.dart' as p; // ignore: package_path_import
|
||||||
|
import 'package:process/process.dart';
|
||||||
|
|
||||||
import 'common.dart' show throwToolExit;
|
import 'common.dart' show throwToolExit;
|
||||||
import 'platform.dart';
|
import 'platform.dart';
|
||||||
|
|
||||||
// The Flutter tool hits file system errors that only the end-user can address.
|
// The Flutter tool hits file system and process errors that only the end-user can address.
|
||||||
// We would like these errors to not hit crash logging. In these cases, we
|
// We would like these errors to not hit crash logging. In these cases, we
|
||||||
// should exit gracefully and provide potentially useful advice. For example, if
|
// should exit gracefully and provide potentially useful advice. For example, if
|
||||||
// a write fails because the target device is full, we can explain that with a
|
// a write fails because the target device is full, we can explain that with a
|
||||||
@ -355,9 +356,16 @@ Future<T> _run<T>(Future<T> Function() op, {
|
|||||||
return await op();
|
return await op();
|
||||||
} on FileSystemException catch (e) {
|
} on FileSystemException catch (e) {
|
||||||
if (platform.isWindows) {
|
if (platform.isWindows) {
|
||||||
_handleWindowsException(e, failureMessage);
|
_handleWindowsException(e, failureMessage, e.osError?.errorCode ?? 0);
|
||||||
} else if (platform.isLinux) {
|
} else if (platform.isLinux) {
|
||||||
_handleLinuxException(e, failureMessage);
|
_handleLinuxException(e, failureMessage, e.osError?.errorCode ?? 0);
|
||||||
|
}
|
||||||
|
rethrow;
|
||||||
|
} on io.ProcessException catch (e) {
|
||||||
|
if (platform.isWindows) {
|
||||||
|
_handleWindowsException(e, failureMessage, e.errorCode ?? 0);
|
||||||
|
} else if (platform.isLinux) {
|
||||||
|
_handleLinuxException(e, failureMessage, e.errorCode ?? 0);
|
||||||
}
|
}
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
@ -372,20 +380,121 @@ T _runSync<T>(T Function() op, {
|
|||||||
return op();
|
return op();
|
||||||
} on FileSystemException catch (e) {
|
} on FileSystemException catch (e) {
|
||||||
if (platform.isWindows) {
|
if (platform.isWindows) {
|
||||||
_handleWindowsException(e, failureMessage);
|
_handleWindowsException(e, failureMessage, e.osError?.errorCode ?? 0);
|
||||||
} else if (platform.isLinux) {
|
} else if (platform.isLinux) {
|
||||||
_handleLinuxException(e, failureMessage);
|
_handleLinuxException(e, failureMessage, e.osError?.errorCode ?? 0);
|
||||||
|
}
|
||||||
|
rethrow;
|
||||||
|
} on io.ProcessException catch (e) {
|
||||||
|
if (platform.isWindows) {
|
||||||
|
_handleWindowsException(e, failureMessage, e.errorCode ?? 0);
|
||||||
|
} else if (platform.isLinux) {
|
||||||
|
_handleLinuxException(e, failureMessage, e.errorCode ?? 0);
|
||||||
}
|
}
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleLinuxException(FileSystemException e, String message) {
|
/// A [ProcessManager] that throws a [ToolExit] on certain errors.
|
||||||
|
///
|
||||||
|
/// If a [ProcessException] is not caused by the Flutter tool, and can only be
|
||||||
|
/// addressed by the user, it should be caught by this [ProcessManager] and thrown
|
||||||
|
/// as a [ToolExit] using [throwToolExit].
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
/// * [ErrorHandlngFileSystem], for a similar file system strategy.
|
||||||
|
class ErrorHandlingProcessManager extends ProcessManager {
|
||||||
|
ErrorHandlingProcessManager({
|
||||||
|
@required ProcessManager delegate,
|
||||||
|
@required Platform platform,
|
||||||
|
}) : _delegate = delegate,
|
||||||
|
_platform = platform;
|
||||||
|
|
||||||
|
final ProcessManager _delegate;
|
||||||
|
final Platform _platform;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool canRun(dynamic executable, {String workingDirectory}) {
|
||||||
|
return _runSync(
|
||||||
|
() => _delegate.canRun(executable, workingDirectory: workingDirectory),
|
||||||
|
platform: _platform,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool killPid(int pid, [io.ProcessSignal signal = io.ProcessSignal.sigterm]) {
|
||||||
|
return _runSync(
|
||||||
|
() => _delegate.killPid(pid, signal),
|
||||||
|
platform: _platform,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<io.ProcessResult> run(
|
||||||
|
List<dynamic> command, {
|
||||||
|
String workingDirectory,
|
||||||
|
Map<String, String> environment,
|
||||||
|
bool includeParentEnvironment = true,
|
||||||
|
bool runInShell = false,
|
||||||
|
Encoding stdoutEncoding = io.systemEncoding,
|
||||||
|
Encoding stderrEncoding = io.systemEncoding,
|
||||||
|
}) {
|
||||||
|
return _run(() => _delegate.run(
|
||||||
|
command,
|
||||||
|
workingDirectory: workingDirectory,
|
||||||
|
environment: environment,
|
||||||
|
includeParentEnvironment: includeParentEnvironment,
|
||||||
|
runInShell: runInShell,
|
||||||
|
stdoutEncoding: stdoutEncoding,
|
||||||
|
stderrEncoding: stderrEncoding,
|
||||||
|
), platform: _platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<io.Process> start(
|
||||||
|
List<dynamic> command, {
|
||||||
|
String workingDirectory,
|
||||||
|
Map<String, String> environment,
|
||||||
|
bool includeParentEnvironment = true,
|
||||||
|
bool runInShell = false,
|
||||||
|
io.ProcessStartMode mode = io.ProcessStartMode.normal,
|
||||||
|
}) {
|
||||||
|
return _run(() => _delegate.start(
|
||||||
|
command,
|
||||||
|
workingDirectory: workingDirectory,
|
||||||
|
environment: environment,
|
||||||
|
includeParentEnvironment: includeParentEnvironment,
|
||||||
|
runInShell: runInShell,
|
||||||
|
), platform: _platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
io.ProcessResult runSync(
|
||||||
|
List<dynamic> command, {
|
||||||
|
String workingDirectory,
|
||||||
|
Map<String, String> environment,
|
||||||
|
bool includeParentEnvironment = true,
|
||||||
|
bool runInShell = false,
|
||||||
|
Encoding stdoutEncoding = io.systemEncoding,
|
||||||
|
Encoding stderrEncoding = io.systemEncoding,
|
||||||
|
}) {
|
||||||
|
return _runSync(() => _delegate.runSync(
|
||||||
|
command,
|
||||||
|
workingDirectory: workingDirectory,
|
||||||
|
environment: environment,
|
||||||
|
includeParentEnvironment: includeParentEnvironment,
|
||||||
|
runInShell: runInShell,
|
||||||
|
stdoutEncoding: stdoutEncoding,
|
||||||
|
stderrEncoding: stderrEncoding,
|
||||||
|
), platform: _platform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleLinuxException(Exception e, String message, int errorCode) {
|
||||||
// From:
|
// From:
|
||||||
// https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/errno.h
|
// https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/errno.h
|
||||||
// https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/errno-base.h
|
// https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/errno-base.h
|
||||||
const int enospc = 28;
|
const int enospc = 28;
|
||||||
final int errorCode = e.osError?.errorCode ?? 0;
|
|
||||||
// Catch errors and bail when:
|
// Catch errors and bail when:
|
||||||
switch (errorCode) {
|
switch (errorCode) {
|
||||||
case enospc:
|
case enospc:
|
||||||
@ -401,13 +510,12 @@ void _handleLinuxException(FileSystemException e, String message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleWindowsException(FileSystemException e, String message) {
|
void _handleWindowsException(Exception e, String message, int errorCode) {
|
||||||
// From:
|
// From:
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes
|
// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes
|
||||||
const int kDeviceFull = 112;
|
const int kDeviceFull = 112;
|
||||||
const int kUserMappedSectionOpened = 1224;
|
const int kUserMappedSectionOpened = 1224;
|
||||||
const int kAccessDenied = 5;
|
const int kAccessDenied = 5;
|
||||||
final int errorCode = e.osError?.errorCode ?? 0;
|
|
||||||
// Catch errors and bail when:
|
// Catch errors and bail when:
|
||||||
switch (errorCode) {
|
switch (errorCode) {
|
||||||
case kAccessDenied:
|
case kAccessDenied:
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:process/process.dart';
|
||||||
|
|
||||||
import 'android/android_sdk.dart';
|
import 'android/android_sdk.dart';
|
||||||
import 'android/android_studio.dart';
|
import 'android/android_studio.dart';
|
||||||
import 'android/android_workflow.dart';
|
import 'android/android_workflow.dart';
|
||||||
@ -13,6 +15,7 @@ import 'artifacts.dart';
|
|||||||
import 'asset.dart';
|
import 'asset.dart';
|
||||||
import 'base/config.dart';
|
import 'base/config.dart';
|
||||||
import 'base/context.dart';
|
import 'base/context.dart';
|
||||||
|
import 'base/error_handling_io.dart';
|
||||||
import 'base/io.dart';
|
import 'base/io.dart';
|
||||||
import 'base/logger.dart';
|
import 'base/logger.dart';
|
||||||
import 'base/os.dart';
|
import 'base/os.dart';
|
||||||
@ -214,6 +217,10 @@ Future<T> runInContext<T>(
|
|||||||
platform: globals.platform,
|
platform: globals.platform,
|
||||||
),
|
),
|
||||||
ProcessInfo: () => ProcessInfo(),
|
ProcessInfo: () => ProcessInfo(),
|
||||||
|
ProcessManager: () => ErrorHandlingProcessManager(
|
||||||
|
delegate: const LocalProcessManager(),
|
||||||
|
platform: globals.platform,
|
||||||
|
),
|
||||||
ProcessUtils: () => ProcessUtils(
|
ProcessUtils: () => ProcessUtils(
|
||||||
processManager: globals.processManager,
|
processManager: globals.processManager,
|
||||||
logger: globals.logger,
|
logger: globals.logger,
|
||||||
|
@ -28,7 +28,7 @@ class Utf8Codec extends Encoding {
|
|||||||
String get name => cnv.utf8.name;
|
String get name => cnv.utf8.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
Encoding get utf8 => const Utf8Codec();
|
const Encoding utf8 = Utf8Codec();
|
||||||
|
|
||||||
class Utf8Decoder extends cnv.Utf8Decoder {
|
class Utf8Decoder extends cnv.Utf8Decoder {
|
||||||
const Utf8Decoder({this.reportErrors = true}) : super(allowMalformed: true);
|
const Utf8Decoder({this.reportErrors = true}) : super(allowMalformed: true);
|
||||||
|
@ -10,7 +10,7 @@ import 'artifacts.dart';
|
|||||||
import 'base/bot_detector.dart';
|
import 'base/bot_detector.dart';
|
||||||
import 'base/config.dart';
|
import 'base/config.dart';
|
||||||
import 'base/context.dart';
|
import 'base/context.dart';
|
||||||
import 'base/error_handling_file_system.dart';
|
import 'base/error_handling_io.dart';
|
||||||
import 'base/file_system.dart';
|
import 'base/file_system.dart';
|
||||||
import 'base/io.dart';
|
import 'base/io.dart';
|
||||||
import 'base/logger.dart';
|
import 'base/logger.dart';
|
||||||
|
@ -3,13 +3,15 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
import 'package:flutter_tools/src/base/error_handling_file_system.dart';
|
import 'package:flutter_tools/src/base/error_handling_io.dart';
|
||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
|
import 'package:flutter_tools/src/base/io.dart';
|
||||||
import 'package:flutter_tools/src/base/platform.dart';
|
import 'package:flutter_tools/src/base/platform.dart';
|
||||||
import 'package:mockito/mockito.dart';
|
import 'package:mockito/mockito.dart';
|
||||||
import 'package:path/path.dart' as path; // ignore: package_path_import
|
import 'package:path/path.dart' as path; // ignore: package_path_import
|
||||||
|
|
||||||
import '../../src/common.dart';
|
import '../../src/common.dart';
|
||||||
|
import '../../src/context.dart';
|
||||||
|
|
||||||
class MockFile extends Mock implements File {}
|
class MockFile extends Mock implements File {}
|
||||||
class MockFileSystem extends Mock implements FileSystem {}
|
class MockFileSystem extends Mock implements FileSystem {}
|
||||||
@ -191,7 +193,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
group('throws ToolExit on Linux', () {
|
group('throws ToolExit on Linux', () {
|
||||||
const int enospc= 28;
|
const int enospc = 28;
|
||||||
MockFileSystem mockFileSystem;
|
MockFileSystem mockFileSystem;
|
||||||
ErrorHandlingFileSystem fs;
|
ErrorHandlingFileSystem fs;
|
||||||
|
|
||||||
@ -291,4 +293,135 @@ void main() {
|
|||||||
expect(fs.file('file').toString(), equals(mockFile.toString()));
|
expect(fs.file('file').toString(), equals(mockFile.toString()));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('ProcessManager on windows throws tool exit', () {
|
||||||
|
const int kDeviceFull = 112;
|
||||||
|
const int kUserMappedSectionOpened = 1224;
|
||||||
|
const int kUserPermissionDenied = 5;
|
||||||
|
|
||||||
|
test('when the device is full', () {
|
||||||
|
final MockProcessManager mockProcessManager = MockProcessManager();
|
||||||
|
final ProcessManager processManager = ErrorHandlingProcessManager(
|
||||||
|
delegate: mockProcessManager,
|
||||||
|
platform: windowsPlatform,
|
||||||
|
);
|
||||||
|
setupProcessManagerMocks(mockProcessManager, kDeviceFull);
|
||||||
|
|
||||||
|
const String expectedMessage = 'The target device is full';
|
||||||
|
expect(() => processManager.canRun('foo'),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() => processManager.killPid(1),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() async => await processManager.start(<String>['foo']),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() async => await processManager.run(<String>['foo']),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() => processManager.runSync(<String>['foo']),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('when the file is being used by another program', () {
|
||||||
|
final MockProcessManager mockProcessManager = MockProcessManager();
|
||||||
|
final ProcessManager processManager = ErrorHandlingProcessManager(
|
||||||
|
delegate: mockProcessManager,
|
||||||
|
platform: windowsPlatform,
|
||||||
|
);
|
||||||
|
setupProcessManagerMocks(mockProcessManager, kUserMappedSectionOpened);
|
||||||
|
|
||||||
|
const String expectedMessage = 'The file is being used by another program';
|
||||||
|
expect(() => processManager.canRun('foo'),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() => processManager.killPid(1),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() async => await processManager.start(<String>['foo']),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() async => await processManager.run(<String>['foo']),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() => processManager.runSync(<String>['foo']),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('when permissions are denied', () {
|
||||||
|
final MockProcessManager mockProcessManager = MockProcessManager();
|
||||||
|
final ProcessManager processManager = ErrorHandlingProcessManager(
|
||||||
|
delegate: mockProcessManager,
|
||||||
|
platform: windowsPlatform,
|
||||||
|
);
|
||||||
|
setupProcessManagerMocks(mockProcessManager, kUserPermissionDenied);
|
||||||
|
|
||||||
|
const String expectedMessage = 'The flutter tool cannot access the file';
|
||||||
|
expect(() => processManager.canRun('foo'),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() => processManager.killPid(1),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() async => await processManager.start(<String>['foo']),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() async => await processManager.run(<String>['foo']),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() => processManager.runSync(<String>['foo']),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('ProcessManager on linux throws tool exit', () {
|
||||||
|
const int enospc = 28;
|
||||||
|
|
||||||
|
test('when writing to a full device', () {
|
||||||
|
final MockProcessManager mockProcessManager = MockProcessManager();
|
||||||
|
final ProcessManager processManager = ErrorHandlingProcessManager(
|
||||||
|
delegate: mockProcessManager,
|
||||||
|
platform: linuxPlatform,
|
||||||
|
);
|
||||||
|
setupProcessManagerMocks(mockProcessManager, enospc);
|
||||||
|
|
||||||
|
const String expectedMessage = 'The target device is full';
|
||||||
|
expect(() => processManager.canRun('foo'),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() => processManager.killPid(1),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() async => await processManager.start(<String>['foo']),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() async => await processManager.run(<String>['foo']),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
expect(() => processManager.runSync(<String>['foo']),
|
||||||
|
throwsToolExit(message: expectedMessage));
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setupProcessManagerMocks(
|
||||||
|
MockProcessManager processManager,
|
||||||
|
int errorCode,
|
||||||
|
) {
|
||||||
|
when(processManager.canRun(any, workingDirectory: anyNamed('workingDirectory')))
|
||||||
|
.thenThrow(ProcessException('', <String>[], '', errorCode));
|
||||||
|
when(processManager.killPid(any, any))
|
||||||
|
.thenThrow(ProcessException('', <String>[], '', errorCode));
|
||||||
|
when(processManager.runSync(
|
||||||
|
any,
|
||||||
|
environment: anyNamed('environment'),
|
||||||
|
includeParentEnvironment: anyNamed('includeParentEnvironment'),
|
||||||
|
runInShell: anyNamed('runInShell'),
|
||||||
|
workingDirectory: anyNamed('workingDirectory'),
|
||||||
|
stdoutEncoding: anyNamed('stdoutEncoding'),
|
||||||
|
stderrEncoding: anyNamed('stderrEncoding'),
|
||||||
|
)).thenThrow(ProcessException('', <String>[], '', errorCode));
|
||||||
|
when(processManager.run(
|
||||||
|
any,
|
||||||
|
environment: anyNamed('environment'),
|
||||||
|
includeParentEnvironment: anyNamed('includeParentEnvironment'),
|
||||||
|
runInShell: anyNamed('runInShell'),
|
||||||
|
workingDirectory: anyNamed('workingDirectory'),
|
||||||
|
stdoutEncoding: anyNamed('stdoutEncoding'),
|
||||||
|
stderrEncoding: anyNamed('stderrEncoding'),
|
||||||
|
)).thenThrow(ProcessException('', <String>[], '', errorCode));
|
||||||
|
when(processManager.start(
|
||||||
|
any,
|
||||||
|
environment: anyNamed('environment'),
|
||||||
|
includeParentEnvironment: anyNamed('includeParentEnvironment'),
|
||||||
|
runInShell: anyNamed('runInShell'),
|
||||||
|
workingDirectory: anyNamed('workingDirectory'),
|
||||||
|
)).thenThrow(ProcessException('', <String>[], '', errorCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
class MockProcessManager extends Mock implements ProcessManager {}
|
@ -62,7 +62,7 @@ void main() {
|
|||||||
final List<String> allowedPaths = <String>[
|
final List<String> allowedPaths = <String>[
|
||||||
globals.fs.path.join(flutterTools, 'lib', 'src', 'base', 'io.dart'),
|
globals.fs.path.join(flutterTools, 'lib', 'src', 'base', 'io.dart'),
|
||||||
globals.fs.path.join(flutterTools, 'lib', 'src', 'base', 'platform.dart'),
|
globals.fs.path.join(flutterTools, 'lib', 'src', 'base', 'platform.dart'),
|
||||||
globals.fs.path.join(flutterTools, 'lib', 'src', 'base', 'error_handling_file_system.dart'),
|
globals.fs.path.join(flutterTools, 'lib', 'src', 'base', 'error_handling_io.dart'),
|
||||||
];
|
];
|
||||||
bool _isNotAllowed(FileSystemEntity entity) => allowedPaths.every((String path) => path != entity.path);
|
bool _isNotAllowed(FileSystemEntity entity) => allowedPaths.every((String path) => path != entity.path);
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ void main() {
|
|||||||
test('no unauthorized imports of dart:convert', () {
|
test('no unauthorized imports of dart:convert', () {
|
||||||
final List<String> allowedPaths = <String>[
|
final List<String> allowedPaths = <String>[
|
||||||
globals.fs.path.join(flutterTools, 'lib', 'src', 'convert.dart'),
|
globals.fs.path.join(flutterTools, 'lib', 'src', 'convert.dart'),
|
||||||
globals.fs.path.join(flutterTools, 'lib', 'src', 'base', 'error_handling_file_system.dart'),
|
globals.fs.path.join(flutterTools, 'lib', 'src', 'base', 'error_handling_io.dart'),
|
||||||
];
|
];
|
||||||
bool _isNotAllowed(FileSystemEntity entity) => allowedPaths.every((String path) => path != entity.path);
|
bool _isNotAllowed(FileSystemEntity entity) => allowedPaths.every((String path) => path != entity.path);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import 'dart:io' as io;
|
|||||||
|
|
||||||
import 'package:args/command_runner.dart';
|
import 'package:args/command_runner.dart';
|
||||||
import 'package:flutter_tools/src/base/common.dart';
|
import 'package:flutter_tools/src/base/common.dart';
|
||||||
import 'package:flutter_tools/src/base/error_handling_file_system.dart';
|
import 'package:flutter_tools/src/base/error_handling_io.dart';
|
||||||
import 'package:flutter_tools/src/base/io.dart';
|
import 'package:flutter_tools/src/base/io.dart';
|
||||||
import 'package:flutter_tools/src/base/signals.dart';
|
import 'package:flutter_tools/src/base/signals.dart';
|
||||||
import 'package:flutter_tools/src/base/time.dart';
|
import 'package:flutter_tools/src/base/time.dart';
|
||||||
|
@ -108,7 +108,7 @@ void main() {
|
|||||||
() {
|
() {
|
||||||
unawaited(runner.run(
|
unawaited(runner.run(
|
||||||
<String>['crash'],
|
<String>['crash'],
|
||||||
<FlutterCommand>[
|
() => <FlutterCommand>[
|
||||||
CrashingFlutterCommand(asyncCrash: true, completer: commandCompleter),
|
CrashingFlutterCommand(asyncCrash: true, completer: commandCompleter),
|
||||||
],
|
],
|
||||||
// This flutterVersion disables crash reporting.
|
// This flutterVersion disables crash reporting.
|
||||||
|
@ -9,7 +9,7 @@ import 'package:file/file.dart';
|
|||||||
import 'package:file/memory.dart';
|
import 'package:file/memory.dart';
|
||||||
import 'package:flutter_tools/src/base/context.dart';
|
import 'package:flutter_tools/src/base/context.dart';
|
||||||
import 'package:flutter_tools/src/base/file_system.dart';
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
import 'package:flutter_tools/src/base/error_handling_file_system.dart';
|
import 'package:flutter_tools/src/base/error_handling_io.dart';
|
||||||
import 'package:flutter_tools/src/base/process.dart';
|
import 'package:flutter_tools/src/base/process.dart';
|
||||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user