run method
Runs this command.
The return value is wrapped in a Future if necessary and returned by
CommandRunner.runCommand.
Implementation
@override
Future<void> run() async {
final headless = _headless;
// --no-ui implies --yes (no interactive prompt in headless mode)
final yesFlag = (argResults!['yes'] as bool) || headless;
final projectDir = findNitroProjectRoot();
if (projectDir == null) {
stderr.writeln(headless ? '[nitro:error] No Nitro project found.' : '❌ No Nitro project found.');
exit(1);
}
final pubspec = File(p.join(projectDir.path, 'pubspec.yaml'));
String pluginName = 'unknown';
for (final line in pubspec.readAsLinesSync()) {
if (line.startsWith('name: ')) {
pluginName = line.replaceFirst('name: ', '').trim();
break;
}
}
Directory.current = projectDir;
// ── Preflight: detect managed content removed by manual edits ─────────────
final issues = detectManagedContentIssues(baseDir: projectDir.path);
if (issues.isNotEmpty) {
stderr.writeln('');
if (headless) {
stderr.writeln('[nitro:warn] managed content missing from plugin files:');
for (final issue in issues) {
stderr.writeln('[nitro:warn] ${issue.file}: ${issue.description}');
}
stderr.writeln('[nitro:info] proceeding with re-injection (--no-ui implies --yes)');
} else {
stderr.writeln(' \x1B[1;33m⚠ nitrogen link detected managed content missing from plugin files:\x1B[0m');
stderr.writeln('');
final byFile = <String, List<String>>{};
for (final issue in issues) {
byFile.putIfAbsent(issue.file, () => []).add(issue.description);
}
for (final entry in byFile.entries) {
stderr.writeln(' \x1B[1;37m${entry.key}\x1B[0m');
for (final desc in entry.value) {
stderr.writeln(' \x1B[33m• $desc\x1B[0m');
}
}
stderr.writeln('');
stderr.writeln(' These sections are managed by nitrogen link.');
stderr.writeln(' Re-running link will restore them automatically.');
if (!yesFlag) {
stderr.write('\n Re-inject missing sections? [Y/n] ');
final answer = (stdin.readLineSync() ?? '').trim().toLowerCase();
if (answer == 'n' || answer == 'no') {
stderr.writeln('\n Skipped. Run `nitrogen link --yes` to suppress this prompt.');
return;
}
} else {
stderr.writeln(' (--yes flag set — proceeding without confirmation)');
}
stderr.writeln('');
}
}
if (headless) {
await _runHeadless(pluginName, projectDir.path);
} else {
final result = LinkResult();
await runApp(LinkView(pluginName: pluginName, result: result));
if (result.success) {
stdout.writeln('\n \x1B[1;32m✨ $pluginName linked\x1B[0m');
}
}
}