run method
Runs this command.
The return value is wrapped in a Future if necessary and returned by
CommandRunner.runCommand.
Implementation
@override
Future<int> run() async {
try {
final result = historyStore.prune();
if (result.warning case final warning?) {
diagnostics('Warning: $warning');
}
} catch (error) {
diagnostics('Warning: Failed to prune applied history: $error');
}
final projectName = argResults!.rest.singleOrNull;
if (projectName == null) {
return _error(
ExitReporter.usageError,
'MISSING_PROJECT_NAME',
'Missing required project name.',
missingDecisions: const ['projectName'],
);
}
_interrupted = false;
final interruptSubscription = _watchSigint
? ProcessSignal.sigint.watch().listen((_) => _interrupted = true)
: null;
final probeRoot = doctorProbe == null
? await Directory.systemTemp.createTemp('flutterstart-create-probe-')
: null;
try {
final probe =
doctorProbe ??
DoctorProbe(
processRunner: const ProcessRunner(),
stagingRoot: probeRoot!.path,
);
final report = await probe.probe();
final preflight = doctorBlockingConditions(report);
if (preflight.isNotEmpty) {
return _error(
ExitReporter.environmentPreflightFailure,
'ENVIRONMENT_PREFLIGHT_FAILURE',
preflight.join('; '),
);
}
final lock = recipeLock ?? await loadRecipeLock();
final blueprint = await _collectBlueprint(projectName, lock, report);
if (blueprint == null) return _collectionExitCode;
final flutterVersion = report.flutterVersion.value;
final dartVersion = report.dartVersion.value;
if (flutterVersion == null || dartVersion == null) {
return _error(
ExitReporter.environmentPreflightFailure,
'TOOLCHAIN_VERSION_UNOBSERVED',
'Flutter and Dart versions must be observed before planning.',
);
}
final resolvedCatalog = catalog ?? await loadCatalog();
final baseCompatibility = validateBlueprint(
blueprint: blueprint,
flutterVersion: flutterVersion,
dartVersion: dartVersion,
lock: lock,
);
// Catalog-driven rules layer onto the same CompatibilityResult
// contract the 0.1 engine already returns (FR-029-FR-033; a v1
// Blueprint has no selections, so this contributes zero findings).
final catalogCompatibility = validateBlueprintAgainstCatalog(
blueprint: blueprint,
catalog: resolvedCatalog,
flutterVersion: flutterVersion,
dartVersion: dartVersion,
lock: lock,
);
final compatibility = CompatibilityResult([
...baseCompatibility.findings,
...catalogCompatibility.findings,
]);
for (final warning in compatibility.warnings) {
diagnostics('Warning [${warning.code}]: ${warning.message}');
}
if (compatibility.hasBlockers) {
return _error(
ExitReporter.blueprintInvalidOrCompatibilityBlocker,
'COMPATIBILITY_BLOCKER',
compatibility.blockers.map((finding) => finding.message).join('; '),
);
}
final destination = Directory(
blueprint.destination,
).absolute.uri.normalizePath().toFilePath();
try {
return await withSessionLock(
destination,
() => _plan(
blueprint,
lock,
report,
destination,
compatibility,
resolvedCatalog,
),
baseDir: sessionLockBaseDir,
);
} on SessionLockHeldException catch (error) {
return _error(error.exitCode, 'SESSION_LOCK_HELD', error.message);
}
} finally {
await interruptSubscription?.cancel();
if (probeRoot?.existsSync() ?? false) {
probeRoot!.deleteSync(recursive: true);
}
}
}