Catch failure to create directory in cache (#37871)
diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart index 68fd2ad..ae0a4e9 100644 --- a/packages/flutter_tools/lib/src/cache.dart +++ b/packages/flutter_tools/lib/src/cache.dart
@@ -398,7 +398,15 @@ return; } if (!location.existsSync()) { - location.createSync(recursive: true); + try { + location.createSync(recursive: true); + } on FileSystemException catch (err) { + printError(err.toString()); + throwToolExit( + 'Failed to create directory for flutter cache at ${location.path}. ' + 'Flutter may be missing permissions in its cache directory.' + ); + } } await updateInner(); cache.setStampFor(stampName, version);
diff --git a/packages/flutter_tools/test/general.shard/cache_test.dart b/packages/flutter_tools/test/general.shard/cache_test.dart index f4a8ef4..aa9d940 100644 --- a/packages/flutter_tools/test/general.shard/cache_test.dart +++ b/packages/flutter_tools/test/general.shard/cache_test.dart
@@ -243,6 +243,27 @@ Platform: () => fakePlatform, }); }); + + testUsingContext('throws tool exit on fs exception', () async { + final FakeCachedArtifact fakeCachedArtifact = FakeCachedArtifact( + cache: MockCache(), + requiredArtifacts: <DevelopmentArtifact>{ + DevelopmentArtifact.android, + } + ); + final Directory mockDirectory = MockDirectory(); + when(fakeCachedArtifact.cache.getArtifactDirectory(any)) + .thenReturn(mockDirectory); + when(mockDirectory.existsSync()).thenReturn(false); + when(mockDirectory.createSync(recursive: true)) + .thenThrow(const FileSystemException()); + + expect(() => fakeCachedArtifact.update(<DevelopmentArtifact>{ + DevelopmentArtifact.android, + }), throwsA(isInstanceOf<ToolExit>())); + }, overrides: <Type, Generator>{ + FileSystem: () => MemoryFileSystem(), + }); } class FakeCachedArtifact extends EngineCachedArtifact { @@ -271,6 +292,7 @@ class MockFileSystem extends Mock implements FileSystem {} class MockFile extends Mock implements File {} +class MockDirectory extends Mock implements Directory {} class MockRandomAccessFile extends Mock implements RandomAccessFile {} class MockCachedArtifact extends Mock implements CachedArtifact {}