diff --git a/packages/flutter_tools/lib/src/commands/create_base.dart b/packages/flutter_tools/lib/src/commands/create_base.dart index 67dd988012..17e70ce5a1 100644 --- a/packages/flutter_tools/lib/src/commands/create_base.dart +++ b/packages/flutter_tools/lib/src/commands/create_base.dart @@ -669,8 +669,18 @@ abstract class CreateBase extends FlutterCommand { 'templates', 'template_manifest.json', ); + final String manifestFileContents; + try { + manifestFileContents = globals.fs.file(manifestPath).readAsStringSync(); + } on FileSystemException catch (e) { + throwToolExit( + 'Unable to read the template manifest at path "$manifestPath".\n' + 'Make sure that your user account has sufficient permissions to read this file.\n' + 'Exception details: $e', + ); + } final Map manifest = json.decode( - globals.fs.file(manifestPath).readAsStringSync(), + manifestFileContents, ) as Map; return Set.from( (manifest['files']! as List).cast().map( diff --git a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart index 106115991c..a8975081ae 100644 --- a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart +++ b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart @@ -7,6 +7,7 @@ import 'dart:convert'; import 'dart:io' as io; import 'package:args/command_runner.dart'; +import 'package:file/file.dart'; import 'package:file/memory.dart'; import 'package:file_testing/file_testing.dart'; import 'package:flutter_tools/src/android/gradle_utils.dart' show templateAndroidGradlePluginVersion, templateAndroidGradlePluginVersionForModule, templateDefaultGradleVersion; @@ -3749,6 +3750,40 @@ void main() { expect(rawManifestJson.contains(expectedDescription), isTrue); }); + + testUsingContext('flutter create should tool exit if the template manifest cannot be read', () async { + globals.fs.file(globals.fs.path.join( + Cache.flutterRoot!, + 'packages', + 'flutter_tools', + 'templates', + 'template_manifest.json', + )).createSync(recursive: true); + + final CreateCommand command = CreateCommand(); + final CommandRunner runner = createTestCommandRunner(command); + + await expectLater( + runner.run([ + 'create', + '--no-pub', + '--template=plugin', + '--project-name=test', + projectDir.path, + ]), + throwsToolExit(message: 'Unable to read the template manifest at path'), + ); + }, overrides: { + FileSystem: () => MemoryFileSystem.test( + opHandle: (String context, FileSystemOp operation) { + if (operation == FileSystemOp.read && context.contains('template_manifest.json')) { + throw io.PathNotFoundException( + context, const OSError(), 'Cannot open file'); + } + }, + ), + ProcessManager: () => fakeProcessManager, + }); } Future _createProject(