Skip to content

Commit f975471

Browse files
authored
fix(dart_frog_cli): run update check on sigint (#368)
1 parent b90ce81 commit f975471

File tree

4 files changed

+65
-14
lines changed

4 files changed

+65
-14
lines changed

packages/dart_frog_cli/lib/src/command_runner.dart

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:io' as io;
2+
13
import 'package:args/args.dart';
24
import 'package:args/command_runner.dart';
35
import 'package:dart_frog_cli/src/commands/commands.dart';
@@ -6,6 +8,9 @@ import 'package:dart_frog_cli/src/version.dart';
68
import 'package:mason/mason.dart' hide packageVersion;
79
import 'package:pub_updater/pub_updater.dart';
810

11+
/// Typedef for [io.exit].
12+
typedef Exit = dynamic Function(int exitCode);
13+
914
/// The package name.
1015
const packageName = 'dart_frog_cli';
1116

@@ -24,8 +29,12 @@ class DartFrogCommandRunner extends CommandRunner<int> {
2429
DartFrogCommandRunner({
2530
Logger? logger,
2631
PubUpdater? pubUpdater,
32+
io.ProcessSignal? sigint,
33+
Exit? exit,
2734
}) : _logger = logger ?? Logger(),
2835
_pubUpdater = pubUpdater ?? PubUpdater(),
36+
_sigint = sigint ?? io.ProcessSignal.sigint,
37+
_exit = exit ?? io.exit,
2938
super(executableName, executableDescription) {
3039
argParser.addFlags();
3140
addCommand(BuildCommand(logger: _logger));
@@ -36,12 +45,16 @@ class DartFrogCommandRunner extends CommandRunner<int> {
3645

3746
final Logger _logger;
3847
final PubUpdater _pubUpdater;
48+
final io.ProcessSignal _sigint;
49+
final Exit _exit;
3950

4051
@override
4152
Future<int> run(Iterable<String> args) async {
4253
final argResults = parse(args);
4354
late final int exitCode;
4455

56+
_sigint.watch().listen(_onSigint);
57+
4558
try {
4659
exitCode = await runCommand(argResults) ?? ExitCode.success.code;
4760
} catch (error) {
@@ -54,11 +67,25 @@ class DartFrogCommandRunner extends CommandRunner<int> {
5467
return exitCode;
5568
}
5669

70+
Future<void> _onSigint(io.ProcessSignal signal) async {
71+
await _checkForUpdates();
72+
_exit(0);
73+
}
74+
5775
Future<void> _checkForUpdates() async {
76+
_logger.detail('[updater] checking for updates...');
5877
try {
5978
final latestVersion = await _pubUpdater.getLatestVersion(packageName);
79+
_logger.detail('[updater] latest version is $latestVersion.');
80+
6081
final isUpToDate = packageVersion == latestVersion;
82+
if (isUpToDate) {
83+
_logger.detail('[updater] no updates available.');
84+
return;
85+
}
86+
6187
if (!isUpToDate) {
88+
_logger.detail('[updater] update available.');
6289
final changelogLink = lightCyan.wrap(
6390
styleUnderlined.wrap(
6491
link(
@@ -77,7 +104,13 @@ ${lightYellow.wrap('Changelog:')} $changelogLink
77104
Run ${lightCyan.wrap('$executableName update')} to update''',
78105
);
79106
}
80-
} catch (_) {}
107+
} catch (error, stackTrace) {
108+
_logger.detail(
109+
'[updater] update check error.\n$error\n$stackTrace',
110+
);
111+
} finally {
112+
_logger.detail('[updater] update check complete.');
113+
}
81114
}
82115

83116
@override

packages/dart_frog_cli/lib/src/commands/dev/dev.dart

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -213,14 +213,12 @@ class DevCommand extends DartFrogCommand {
213213
logger.detail('[process] killing process...');
214214
if (_isWindows) {
215215
logger.detail('[process] taskkill /F /T /PID ${process.pid}');
216-
final result = await _runProcess(
217-
'taskkill',
218-
['/F', '/T', '/PID', '${process.pid}'],
219-
);
220-
logger.detail('[process] exit(${result.exitCode})');
221-
return _exit(result.exitCode);
216+
await _runProcess('taskkill', ['/F', '/T', '/PID', '${process.pid}']);
217+
} else {
218+
logger.detail('[process] process.kill()...');
219+
process.kill();
222220
}
223-
process.kill();
221+
logger.detail('[process] killing process complete.');
224222
}
225223
}
226224

packages/dart_frog_cli/test/src/command_runner_test.dart

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// ignore_for_file: no_adjacent_strings_in_list
22
import 'dart:async';
3+
import 'dart:io';
34

45
import 'package:dart_frog_cli/src/command_runner.dart';
56
import 'package:dart_frog_cli/src/version.dart';
@@ -12,6 +13,8 @@ class _MockLogger extends Mock implements Logger {}
1213

1314
class _MockPubUpdater extends Mock implements PubUpdater {}
1415

16+
class _MockProcessSignal extends Mock implements ProcessSignal {}
17+
1518
const expectedUsage = [
1619
'A fast, minimalistic backend framework for Dart.\n'
1720
'\n'
@@ -51,19 +54,25 @@ void main() {
5154
late Logger logger;
5255
late PubUpdater pubUpdater;
5356
late DartFrogCommandRunner commandRunner;
57+
late ProcessSignal sigint;
5458

5559
setUp(() {
5660
printLogs = [];
5761
logger = _MockLogger();
5862
pubUpdater = _MockPubUpdater();
63+
sigint = _MockProcessSignal();
5964

6065
when(
6166
() => pubUpdater.getLatestVersion(any()),
6267
).thenAnswer((_) async => packageVersion);
6368

69+
when(() => sigint.watch()).thenAnswer((_) => const Stream.empty());
70+
6471
commandRunner = DartFrogCommandRunner(
6572
logger: logger,
6673
pubUpdater: pubUpdater,
74+
exit: (_) {},
75+
sigint: sigint,
6776
);
6877
});
6978

@@ -73,6 +82,20 @@ void main() {
7382
});
7483

7584
group('run', () {
85+
test('checks for updates on sigint', () async {
86+
final exitCalls = <int>[];
87+
commandRunner = DartFrogCommandRunner(
88+
logger: logger,
89+
pubUpdater: pubUpdater,
90+
exit: exitCalls.add,
91+
sigint: sigint,
92+
);
93+
when(() => sigint.watch()).thenAnswer((_) => Stream.value(sigint));
94+
await commandRunner.run(['--version']);
95+
expect(exitCalls, equals([0]));
96+
verify(() => pubUpdater.getLatestVersion(any())).called(2);
97+
});
98+
7699
test('prompts for update when newer version exists', () async {
77100
when(
78101
() => pubUpdater.getLatestVersion(any()),
@@ -136,9 +159,8 @@ void main() {
136159
test(
137160
'sets correct log level.',
138161
overridePrint(() async {
139-
final logger = Logger();
140-
await DartFrogCommandRunner(logger: logger).run(['--verbose']);
141-
expect(logger.level, equals(Level.verbose));
162+
await commandRunner.run(['--verbose']);
163+
verify(() => logger.level = Level.verbose).called(1);
142164
}),
143165
);
144166

packages/dart_frog_cli/test/src/commands/dev/dev_test.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ void main() {
6767
process = _MockProcess();
6868
processResult = _MockProcessResult();
6969
sigint = _MockProcessSignal();
70+
when(() => sigint.watch()).thenAnswer((_) => const Stream.empty());
7071
generatorTarget = _MockRestorableDirectoryGeneratorTarget();
7172
command = DevCommand(
7273
logger: logger,
@@ -531,7 +532,6 @@ void main() {
531532
const processId = 42;
532533
final generatorHooks = _MockGeneratorHooks();
533534
final processRunCalls = <List<String>>[];
534-
int? exitCode;
535535
when(
536536
() => generatorHooks.preGen(
537537
vars: any(named: 'vars'),
@@ -554,7 +554,6 @@ void main() {
554554
when(() => process.stdout).thenAnswer((_) => const Stream.empty());
555555
when(() => process.stderr).thenAnswer((_) => const Stream.empty());
556556
when(() => process.pid).thenReturn(processId);
557-
when(() => processResult.exitCode).thenReturn(ExitCode.success.code);
558557
when(
559558
() => directoryWatcher.events,
560559
).thenAnswer((_) => StreamController<WatchEvent>().stream);
@@ -581,7 +580,6 @@ void main() {
581580
)..testArgResults = argResults;
582581
command.run().ignore();
583582
await untilCalled(() => process.pid);
584-
expect(exitCode, equals(ExitCode.success.code));
585583
expect(
586584
processRunCalls,
587585
equals([

0 commit comments

Comments
 (0)