Skip to content

Commit c3baa22

Browse files
authored
feat(cli): Re-implement celest upgrade (#296)
Re-implements the upgrade command to account for installations via `pub global`.
1 parent 918e3d4 commit c3baa22

23 files changed

+180
-93
lines changed

apps/cli/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## 1.0.9-wip
22

33
- chore: Remove unused native assets code
4+
- feat: Re-implement `celest upgrade`
45

56
## 1.0.8
67

apps/cli/bin/celest.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ void main(List<String> args) async {
1010
..addCommand(StartCommand())
1111
..addCommand(BuildCommand())
1212
..addCommand(AnalysisServerCommand())
13-
// TODO(dnys1): Re-implement the upgrade command
14-
// ..addCommand(UpgradeCommand())
13+
..addCommand(UpgradeCommand())
1514
..addCommand(UninstallCommand())
1615
..addCommand(PrecacheCommand());
1716

apps/cli/fixtures/fixtures_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import 'package:celest_cli/src/project/project_linker.dart';
2828
import 'package:celest_cli/src/pub/pub_action.dart';
2929
import 'package:celest_cli/src/sdk/dart_sdk.dart';
3030
import 'package:celest_cli/src/sdk/sdk_finder.dart';
31-
import 'package:celest_cli/src/utils/cli.dart';
31+
import 'package:celest_cli/src/utils/process.dart';
3232
import 'package:celest_cli/src/utils/recase.dart';
3333
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
3434
import 'package:file/file.dart';

apps/cli/lib/celest_cli.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export 'src/cli.dart';
1+
export 'src/cli/cli.dart';
22
export 'src/commands/analysis_server_command.dart';
33
export 'src/commands/build_command.dart';
44
export 'src/commands/init_command.dart';
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import 'package:celest_cli/src/context.dart';
2+
3+
enum CliRuntime {
4+
pubGlobal,
5+
aot,
6+
local;
7+
8+
static CliRuntime get current {
9+
if (fileSystem.path.fromUri(platform.script).endsWith('.snapshot')) {
10+
return pubGlobal;
11+
} else if (platform.executable.contains('dart')) {
12+
return local;
13+
} else {
14+
return aot;
15+
}
16+
}
17+
}

apps/cli/lib/src/commands/build_command.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import 'package:celest_cli/src/commands/celest_command.dart';
2-
import 'package:celest_cli/src/commands/project_init.dart';
3-
import 'package:celest_cli/src/commands/project_migrate.dart';
42
import 'package:celest_cli/src/context.dart';
53
import 'package:celest_cli/src/frontend/celest_frontend.dart';
4+
import 'package:celest_cli/src/init/project_init.dart';
5+
import 'package:celest_cli/src/init/project_migrate.dart';
66
import 'package:mason_logger/src/mason_logger.dart';
77

88
final class BuildCommand extends CelestCommand with Configure, Migrate {

apps/cli/lib/src/commands/celest_command.dart

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@ import 'dart:convert';
33
import 'dart:io';
44

55
import 'package:args/command_runner.dart';
6+
import 'package:celest_cli/src/cli/cli_runtime.dart';
67
import 'package:celest_cli/src/context.dart';
78
import 'package:celest_cli/src/models.dart';
9+
import 'package:celest_cli/src/releases/celest_release_info.dart';
810
import 'package:celest_cli/src/releases/latest_release.dart';
911
import 'package:celest_cli/src/sdk/dart_sdk.dart';
10-
import 'package:cli_util/cli_util.dart';
12+
import 'package:celest_cli/src/version.dart';
13+
import 'package:collection/collection.dart';
1114
import 'package:http/http.dart' as http;
1215
import 'package:logging/logging.dart';
1316
import 'package:meta/meta.dart';
14-
import 'package:path/path.dart' as p;
1517
import 'package:pub_semver/pub_semver.dart';
1618

1719
/// Base class for all commands in this package providing common functionality.
@@ -24,16 +26,6 @@ abstract base class CelestCommand extends Command<int> {
2426
/// Whether verbose logging is enabled.
2527
bool get verbose => globalResults?['verbose'] as bool? ?? false;
2628

27-
/// The path to the Flutter SDK, if installed.
28-
late final String? flutterRoot = () {
29-
final dartSdkPath = getSdkPath();
30-
final flutterBin = p.dirname(p.dirname(dartSdkPath));
31-
if (File(p.join(flutterBin, 'flutter')).existsSync()) {
32-
return p.dirname(flutterBin);
33-
}
34-
return null;
35-
}();
36-
3729
/// Resolves the latest version information from `pub.dev`.
3830
Future<PubVersionInfo?> resolveVersionInfo(String package) async {
3931
// Get the currently published version of the package.
@@ -66,23 +58,57 @@ abstract base class CelestCommand extends Command<int> {
6658
return PubVersionInfo(semvers..sort());
6759
}
6860

69-
Future<void> checkForLatestVersion() async {
61+
Future<void> checkForLatestVersion({bool? includeDev}) async {
62+
final (latestVersion, _) = await getLatestVersion(includeDev: includeDev);
63+
if (latestVersion < currentVersion) {
64+
cliLogger.warn(
65+
'A new version of Celest is available! Run `celest upgrade` '
66+
'to get the latest changes.',
67+
);
68+
}
69+
}
70+
71+
Future<(Version, CelestReleaseInfo?)> getLatestVersion({
72+
bool? includeDev,
73+
}) async {
74+
includeDev ??= currentVersion.isPreRelease;
7075
try {
71-
final latestRelease = await performance.trace(
76+
final (latestVersion, releaseInfo) = await performance.trace(
7277
'CelestCommand',
7378
'retrieveLatestRelease',
74-
() =>
75-
retrieveLatestRelease(version).timeout(const Duration(seconds: 3)),
79+
() => switch (CliRuntime.current) {
80+
CliRuntime.aot => retrieveLatestRelease(includeDev: includeDev!)
81+
.then((release) => (release.version, release)),
82+
CliRuntime.local => Future.value((currentVersion, null)),
83+
CliRuntime.pubGlobal => _latestVersionPub(includeDev: includeDev!)
84+
.then((version) => (version, null)),
85+
}
86+
.timeout(const Duration(seconds: 3)),
7687
);
77-
if (latestRelease.version > Version.parse(version)) {
78-
cliLogger.warn(
79-
'A new version of Celest is available! Run `celest upgrade` '
80-
'to get the latest changes.',
81-
);
82-
}
88+
return (latestVersion, releaseInfo);
8389
} on Object catch (e, st) {
8490
performance.captureError(e, stackTrace: st);
91+
return (currentVersion, null);
92+
}
93+
}
94+
95+
Future<Version> _latestVersionPub({
96+
bool includeDev = false,
97+
}) async {
98+
final versionInfo = await resolveVersionInfo('celest_cli');
99+
if (versionInfo == null) {
100+
throw Exception(
101+
'Failed to resolve version information for celest_cli.',
102+
);
85103
}
104+
return maxBy(
105+
[
106+
currentVersion,
107+
versionInfo.latestVersion,
108+
if (includeDev) versionInfo.latestPrerelease,
109+
].nonNulls,
110+
(v) => v,
111+
)!;
86112
}
87113

88114
@override

apps/cli/lib/src/commands/init_command.dart

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import 'dart:io';
22

3+
import 'package:celest_cli/src/cli/cli_runtime.dart';
34
import 'package:celest_cli/src/commands/celest_command.dart';
4-
import 'package:celest_cli/src/commands/project_init.dart';
55
import 'package:celest_cli/src/context.dart';
6+
import 'package:celest_cli/src/init/project_init.dart';
67
import 'package:mason_logger/mason_logger.dart';
78

89
final class InitCommand extends CelestCommand with Configure, ProjectCreator {
@@ -22,32 +23,29 @@ final class InitCommand extends CelestCommand with Configure, ProjectCreator {
2223

2324
/// Precache assets in the background.
2425
Future<void> _precacheInBackground() async {
25-
final List<String> command;
26-
if (fileSystem.path.fromUri(platform.script).endsWith('.snapshot')) {
27-
command = <String>[
28-
platform.resolvedExecutable,
29-
'pub',
30-
'global',
31-
'run',
32-
'celest_cli:celest',
33-
'precache',
34-
projectPaths.projectRoot,
35-
];
36-
} else if (platform.executable.contains('dart')) {
37-
command = <String>[
38-
platform.resolvedExecutable,
39-
'run',
40-
platform.script.toFilePath(),
41-
'precache',
42-
projectPaths.projectRoot,
43-
];
44-
} else {
45-
command = <String>[
46-
platform.resolvedExecutable,
47-
'precache',
48-
projectPaths.projectRoot,
49-
];
50-
}
26+
final command = switch (CliRuntime.current) {
27+
CliRuntime.pubGlobal => <String>[
28+
platform.resolvedExecutable,
29+
'pub',
30+
'global',
31+
'run',
32+
'celest_cli:celest',
33+
'precache',
34+
projectPaths.projectRoot,
35+
],
36+
CliRuntime.local => <String>[
37+
platform.resolvedExecutable,
38+
'run',
39+
platform.script.toFilePath(),
40+
'precache',
41+
projectPaths.projectRoot,
42+
],
43+
CliRuntime.aot => <String>[
44+
platform.resolvedExecutable,
45+
'precache',
46+
projectPaths.projectRoot,
47+
],
48+
};
5149
try {
5250
logger.fine('Precaching assets in background...');
5351
await processManager.start(
@@ -71,11 +69,11 @@ final class InitCommand extends CelestCommand with Configure, ProjectCreator {
7169

7270
final projectRoot = projectPaths.projectRoot;
7371

74-
var command = 'celest start';
7572
// `celest start` can be run from either the project root, the attached
7673
// Flutter app's root if there is one, or any subdirectory therof.
7774
//
7875
// If we're in none of those, then add a `cd` command to the start messsage.
76+
var command = 'celest start';
7977
final currentDir = fileSystem.currentDirectory.path;
8078
final appRoot = celestProject.parentProject?.path ?? projectRoot;
8179
if (!p.equals(appRoot, currentDir) && !p.isWithin(appRoot, currentDir)) {

apps/cli/lib/src/commands/start_command.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import 'package:celest_cli/src/commands/celest_command.dart';
2-
import 'package:celest_cli/src/commands/project_init.dart';
3-
import 'package:celest_cli/src/commands/project_migrate.dart';
42
import 'package:celest_cli/src/context.dart';
53
import 'package:celest_cli/src/frontend/celest_frontend.dart';
64
import 'package:celest_cli/src/frontend/child_process.dart';
5+
import 'package:celest_cli/src/init/project_init.dart';
6+
import 'package:celest_cli/src/init/project_migrate.dart';
77
import 'package:mason_logger/mason_logger.dart';
88

99
final class StartCommand extends CelestCommand

0 commit comments

Comments
 (0)