mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[flutter_tools] add EACCES to list of immediate exit tool conditions (#65125)
Similar to the permission denied error on Windows, this is not resolvable by the tool.
This commit is contained in:
parent
48f1a0a8d5
commit
9248fda410
@ -357,15 +357,15 @@ Future<T> _run<T>(Future<T> Function() op, {
|
||||
} on FileSystemException catch (e) {
|
||||
if (platform.isWindows) {
|
||||
_handleWindowsException(e, failureMessage, e.osError?.errorCode ?? 0);
|
||||
} else if (platform.isLinux) {
|
||||
_handleLinuxException(e, failureMessage, e.osError?.errorCode ?? 0);
|
||||
} else if (platform.isLinux || platform.isMacOS) {
|
||||
_handlePosixException(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);
|
||||
} else if (platform.isLinux || platform.isMacOS) {
|
||||
_handlePosixException(e, failureMessage, e.errorCode ?? 0);
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
@ -381,15 +381,15 @@ T _runSync<T>(T Function() op, {
|
||||
} on FileSystemException catch (e) {
|
||||
if (platform.isWindows) {
|
||||
_handleWindowsException(e, failureMessage, e.osError?.errorCode ?? 0);
|
||||
} else if (platform.isLinux) {
|
||||
_handleLinuxException(e, failureMessage, e.osError?.errorCode ?? 0);
|
||||
} else if (platform.isLinux || platform.isMacOS) {
|
||||
_handlePosixException(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);
|
||||
} else if (platform.isLinux || platform.isMacOS) {
|
||||
_handlePosixException(e, failureMessage, e.errorCode ?? 0);
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
@ -490,11 +490,13 @@ class ErrorHandlingProcessManager extends ProcessManager {
|
||||
}
|
||||
}
|
||||
|
||||
void _handleLinuxException(Exception e, String message, int errorCode) {
|
||||
void _handlePosixException(Exception e, String message, int errorCode) {
|
||||
// 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-base.h
|
||||
// https://github.com/apple/darwin-xnu/blob/master/bsd/dev/dtrace/scripts/errno.d
|
||||
const int enospc = 28;
|
||||
const int eacces = 13;
|
||||
// Catch errors and bail when:
|
||||
switch (errorCode) {
|
||||
case enospc:
|
||||
@ -504,6 +506,13 @@ void _handleLinuxException(Exception e, String message, int errorCode) {
|
||||
'Free up space and try again.',
|
||||
);
|
||||
break;
|
||||
case eacces:
|
||||
throwToolExit(
|
||||
'$message. The flutter tool cannot access the file.\n'
|
||||
'Please ensure that the SDK and/or project is installed in a location '
|
||||
'that has read/write permissions for the current user.'
|
||||
);
|
||||
break;
|
||||
default:
|
||||
// Caller must rethrow the exception.
|
||||
break;
|
||||
|
||||
@ -28,6 +28,11 @@ final Platform linuxPlatform = FakePlatform(
|
||||
environment: <String, String>{}
|
||||
);
|
||||
|
||||
final Platform macOSPlatform = FakePlatform(
|
||||
operatingSystem: 'macos',
|
||||
environment: <String, String>{}
|
||||
);
|
||||
|
||||
void setupWriteMocks({
|
||||
FileSystem mockFileSystem,
|
||||
ErrorHandlingFileSystem fs,
|
||||
@ -194,6 +199,7 @@ void main() {
|
||||
|
||||
group('throws ToolExit on Linux', () {
|
||||
const int enospc = 28;
|
||||
const int eacces = 13;
|
||||
MockFileSystem mockFileSystem;
|
||||
ErrorHandlingFileSystem fs;
|
||||
|
||||
@ -206,6 +212,103 @@ void main() {
|
||||
when(mockFileSystem.path).thenReturn(MockPathContext());
|
||||
});
|
||||
|
||||
testWithoutContext('when access is denied', () async {
|
||||
setupWriteMocks(
|
||||
mockFileSystem: mockFileSystem,
|
||||
fs: fs,
|
||||
errorCode: eacces,
|
||||
);
|
||||
|
||||
final File file = fs.file('file');
|
||||
|
||||
const String expectedMessage = 'The flutter tool cannot access the file';
|
||||
expect(() async => await file.writeAsBytes(<int>[0]),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
expect(() async => await file.writeAsString(''),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
expect(() => file.writeAsBytesSync(<int>[0]),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
expect(() => file.writeAsStringSync(''),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
expect(() => file.openSync(),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
});
|
||||
|
||||
testWithoutContext('when writing to a full device', () async {
|
||||
setupWriteMocks(
|
||||
mockFileSystem: mockFileSystem,
|
||||
fs: fs,
|
||||
errorCode: enospc,
|
||||
);
|
||||
|
||||
final File file = fs.file('file');
|
||||
|
||||
const String expectedMessage = 'The target device is full';
|
||||
expect(() async => await file.writeAsBytes(<int>[0]),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
expect(() async => await file.writeAsString(''),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
expect(() => file.writeAsBytesSync(<int>[0]),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
expect(() => file.writeAsStringSync(''),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
});
|
||||
|
||||
testWithoutContext('when creating a temporary dir on a full device', () async {
|
||||
setupDirectoryMocks(
|
||||
mockFileSystem: mockFileSystem,
|
||||
fs: fs,
|
||||
errorCode: enospc,
|
||||
);
|
||||
|
||||
final Directory directory = fs.directory('directory');
|
||||
|
||||
const String expectedMessage = 'The target device is full';
|
||||
expect(() async => await directory.createTemp('prefix'),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
expect(() => directory.createTempSync('prefix'),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
group('throws ToolExit on macOS', () {
|
||||
const int enospc = 28;
|
||||
const int eacces = 13;
|
||||
MockFileSystem mockFileSystem;
|
||||
ErrorHandlingFileSystem fs;
|
||||
|
||||
setUp(() {
|
||||
mockFileSystem = MockFileSystem();
|
||||
fs = ErrorHandlingFileSystem(
|
||||
delegate: mockFileSystem,
|
||||
platform: macOSPlatform,
|
||||
);
|
||||
when(mockFileSystem.path).thenReturn(MockPathContext());
|
||||
});
|
||||
|
||||
testWithoutContext('when access is denied', () async {
|
||||
setupWriteMocks(
|
||||
mockFileSystem: mockFileSystem,
|
||||
fs: fs,
|
||||
errorCode: eacces,
|
||||
);
|
||||
|
||||
final File file = fs.file('file');
|
||||
|
||||
const String expectedMessage = 'The flutter tool cannot access the file';
|
||||
expect(() async => await file.writeAsBytes(<int>[0]),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
expect(() async => await file.writeAsString(''),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
expect(() => file.writeAsBytesSync(<int>[0]),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
expect(() => file.writeAsStringSync(''),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
expect(() => file.openSync(),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
});
|
||||
|
||||
testWithoutContext('when writing to a full device', () async {
|
||||
setupWriteMocks(
|
||||
mockFileSystem: mockFileSystem,
|
||||
@ -365,6 +468,7 @@ void main() {
|
||||
|
||||
group('ProcessManager on linux throws tool exit', () {
|
||||
const int enospc = 28;
|
||||
const int eacces = 13;
|
||||
|
||||
test('when writing to a full device', () {
|
||||
final MockProcessManager mockProcessManager = MockProcessManager();
|
||||
@ -386,6 +490,74 @@ void main() {
|
||||
expect(() => processManager.runSync(<String>['foo']),
|
||||
throwsToolExit(message: expectedMessage));
|
||||
});
|
||||
|
||||
test('when permissions are denied', () {
|
||||
final MockProcessManager mockProcessManager = MockProcessManager();
|
||||
final ProcessManager processManager = ErrorHandlingProcessManager(
|
||||
delegate: mockProcessManager,
|
||||
platform: linuxPlatform,
|
||||
);
|
||||
setupProcessManagerMocks(mockProcessManager, eacces);
|
||||
|
||||
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 macOS throws tool exit', () {
|
||||
const int enospc = 28;
|
||||
const int eacces = 13;
|
||||
|
||||
test('when writing to a full device', () {
|
||||
final MockProcessManager mockProcessManager = MockProcessManager();
|
||||
final ProcessManager processManager = ErrorHandlingProcessManager(
|
||||
delegate: mockProcessManager,
|
||||
platform: macOSPlatform,
|
||||
);
|
||||
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));
|
||||
});
|
||||
|
||||
test('when permissions are denied', () {
|
||||
final MockProcessManager mockProcessManager = MockProcessManager();
|
||||
final ProcessManager processManager = ErrorHandlingProcessManager(
|
||||
delegate: mockProcessManager,
|
||||
platform: linuxPlatform,
|
||||
);
|
||||
setupProcessManagerMocks(mockProcessManager, eacces);
|
||||
|
||||
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));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user