execute method
Executes the command with the provided arguments.
Returns an integer exit code (0 for success).
Implementation
@override
Future<int> execute(List<String> arguments) async {
final ArgResults results;
try {
results = _argParser.parse(arguments);
} on FormatException catch (e) {
throw ValidationException(
'Error: ${e.message}\n\nUsage:\n flutter_setup create [<project_name>] [--template <name>] [--force]',
);
}
final bool forceFlag = results['force'] as bool? ?? false;
final bool isInteractive = results.rest.isEmpty;
CreateProjectRequest request;
if (!isInteractive) {
// Non-interactive path from CLI flags/arguments
final projectName = results.rest.first;
final templateName = results['template'] as String? ?? 'default';
request = CreateProjectRequest(
projectName: projectName,
templateName: templateName,
force: forceFlag,
);
} else {
// Interactive prompting path when no project name argument is passed
request = _promptForProjectRequest(force: forceFlag);
}
// Common validation and destination checks
Validators.validateFlutterProjectName(request.projectName);
String targetPath = workingDirectory != null
? p.join(workingDirectory!, request.projectName)
: request.projectName;
bool force = request.force;
while (Directory(targetPath).existsSync() || File(targetPath).existsSync()) {
if (force) {
// Delete existing directory contents BEFORE running flutter create
final targetDir = Directory(targetPath);
if (targetDir.existsSync()) {
try {
targetDir.deleteSync(recursive: true);
} catch (e) {
throw CliException('Failed to clear target directory "$targetPath": $e');
}
} else if (File(targetPath).existsSync()) {
File(targetPath).deleteSync();
}
break;
}
if (!isInteractive) {
throw DestinationConflictException(
targetPath,
customMessage:
'Target directory "$targetPath" already exists. Use --force to overwrite.',
);
}
_output.warning('Directory "$targetPath" already exists.');
final choice = _prompter.askChoice(
'Action',
['Cancel', 'Overwrite', 'Choose a different name'],
defaultValue: 'Cancel',
);
if (choice == 'Cancel') {
throw DestinationConflictException(
targetPath,
customMessage: 'Project generation cancelled by user.',
);
} else if (choice == 'Overwrite') {
force = true;
} else {
// Prompt for a different name and validate
final newRequest = _promptForProjectRequest(force: force);
Validators.validateFlutterProjectName(newRequest.projectName);
request = newRequest;
targetPath = request.projectName;
}
}
final template = _repository.getTemplate(request.templateName);
_output.info('Creating Flutter project "${request.projectName}"...');
final context = GeneratorContext(
projectName: request.projectName,
template: template,
targetDirectory: targetPath,
);
final GenerationResult result;
try {
result = await _generator.generate(context);
} on PackageInstallException catch (e) {
_output.error('Error: Failed to install package "${e.packageName}".');
_output.error('Reason: ${e.errorDetails}\n');
if (e.installedBeforeFailure.isNotEmpty) {
_output.info('Successfully installed before failure: ${e.installedBeforeFailure.join(', ')}');
}
return e.exitCode;
} on CliException catch (e) {
_output.error('Project generation failed: ${e.message}');
return e.exitCode;
} catch (e) {
_output.error('An unexpected error occurred during generation: $e');
return 1;
}
// Success summary
_output.success('Flutter project created');
_output.success('Applied template "${template.name}"');
_output.success(
'Generated ${result.renderResult.createdFiles.length} files, ${result.renderResult.createdFolders.length} folders',
);
if (result.installResult.installedDependencies.isNotEmpty) {
_output.success(
'Installed dependencies (${result.installResult.installedDependencies.length})',
);
}
if (result.installResult.installedDevDependencies.isNotEmpty) {
_output.success(
'Installed dev dependencies (${result.installResult.installedDevDependencies.length})',
);
}
_output.success('Dependencies resolved (flutter pub get)');
if (result.discoveredAssetsCount > 0) {
_output.success('Assets discovered (${result.discoveredAssetsCount})');
_output.success('pubspec.yaml updated');
_output.success(
'Assets class generated (${result.assetsClassPath ?? "lib/core/constants/assets.dart"})',
);
} else {
_output.info('⊘ No assets found in template — skipping asset registration');
}
_output.info('\nProject ready at ./${request.projectName}');
return 0;
}