Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 19 additions & 14 deletions packages/flutterfire_cli/lib/src/commands/update.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ class UpdateCommand extends FlutterFireCommand {
final String name = 'update';

@override
final String description =
'Update the version of firebase plugins in your pubspec '
final String description = 'Update the version of firebase plugins in your pubspec '
'to the latest version and clean your workspace to ensure that everything '
'works properly.';

Expand All @@ -80,6 +79,8 @@ class UpdateCommand extends FlutterFireCommand {
commandRequiresFlutterApp();

await updateFlutterFirePackages(
cleanBaseCommand: flutterApp!.cleanBaseCommand,
pubBaseCommand: flutterApp!.pubBaseCommand,
flutterAppPath: flutterApp!.package.path,
logger: logger,
);
Expand All @@ -98,30 +99,34 @@ typedef ProcessRunner = Future<ProcessResult> Function(
/// Cleans the workspace and upgrades every FlutterFire plugin the app depends
/// on to its latest major version.
Future<void> updateFlutterFirePackages({
String? cleanBaseCommand = 'flutter',
String pubBaseCommand = 'flutter',
required String flutterAppPath,
required Logger logger,
ProcessRunner runProcess = Process.run,
}) async {
/// `runInShell` is required on Windows: the Flutter CLI is `flutter.bat`
/// there, and `Process.run` does not resolve it through `PATHEXT`.
/// See https://github.com/dart-lang/sdk/issues/31291
Future<ProcessResult> runFlutter(List<String> arguments) {
Future<ProcessResult> runCommand(String command, List<String> arguments) {
return runProcess(
'flutter',
command,
arguments,
workingDirectory: flutterAppPath,
runInShell: true,
);
}

logger.stdout('Cleaning up current workspace ...');
// A failed clean (a locked "build" directory, for instance) is not worth
// giving up the update over, but it should not pass unnoticed either.
final cleanResult = await runFlutter(['clean']);
if (cleanResult.exitCode != 0) {
logger.stderr(
FlutterCommandException('flutter clean', cleanResult).toString(),
);
if (cleanBaseCommand case final command?) {
// A failed clean (a locked "build" directory, for instance) is not worth
// giving up the update over, but it should not pass unnoticed either.
final cleanResult = await runCommand(command, ['clean']);
if (cleanResult.exitCode != 0) {
logger.stderr(
FlutterCommandException('flutter clean', cleanResult).toString(),
);
}
}

final pubspecLock = File(path.join(flutterAppPath, 'pubspec.lock'));
Expand All @@ -141,11 +146,11 @@ Future<void> updateFlutterFirePackages({
for (final package in flutterfirePackages) {
// We run each package individually because chaining them
// will fail at the first package not in the pubspec.
await runFlutter(['pub', 'upgrade', '--major-versions', package]);
await runCommand(pubBaseCommand, ['pub', 'upgrade', '--major-versions', package]);
}

logger.stdout("Running 'flutter pub get'...");
final pubGetResult = await runFlutter(['pub', 'get']);
logger.stdout("Running '$pubBaseCommand pub get'...");
final pubGetResult = await runCommand(pubBaseCommand, ['pub', 'get']);
if (pubGetResult.exitCode != 0) {
throw FlutterCommandException('flutter pub get', pubGetResult);
}
Expand Down
36 changes: 33 additions & 3 deletions packages/flutterfire_cli/lib/src/common/package.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,10 @@ class Package {

/// Returns whether this package is a Flutter app.
/// This is determined by ensuring all the following conditions are met:
/// a) the package depends on the Flutter SDK.
/// a) the package depends on the Flutter SDK or is a Flutter compatible package.
/// b) the package does not define itself as a Flutter plugin inside pubspec.yaml.
/// c) a lib/main.dart file exists in the package.
bool get isFlutterApp {
// Must directly depend on the Flutter SDK.
// Must directly depend on the Flutter SDK or be a Flutter compatible package.
if (!isFlutterPackage) return false;

// Must not have a Flutter plugin definition in it's pubspec.yaml.
Expand All @@ -90,7 +89,38 @@ class Package {
return true;
}

/// Returns whether this package is a runtime package.
///
/// These are packages that are compatible with Flutter plugins, even
/// if they don't depend on the Flutter SDK directly.
///
/// This is determined by evaluating [runtimePackageChecks] against this package.
late final bool isRuntimePackage =
runtimePackageChecks.any((check) => check(this));

bool get isRuntimeApp {
// Must not be a Flutter package.
if (isFlutterApp) return false;

// Must be a runtime package.
if (!isRuntimePackage) return false;

return true;
}

/// Returns whether this package is a Flutter plugin.
/// This is determined by whether the pubspec contains a flutter.plugin definition.
bool get isFlutterPlugin => pubSpec.flutter?.containsKey('plugin') ?? false;
}

/// A list of checks that determine whether a package is a runtime package.
///
/// This is used to determine if a package is compatible with Flutter plugins,
/// even if it doesn't depend on the Flutter SDK directly.
final List<bool Function(Package)> runtimePackageChecks = [
// The Jaspr framework supports flutter-like development and is compatible
// with Flutter plugins, so we check for any package that lists Jaspr as a
// dependency.
(pkg) => pkg.dependencies.contains('jaspr'),
// Additional checks may be added here.
];
Loading
Loading