Detect Flutter SDK location relative to Dart SDK (#3045)
* Detect Flutter SDK location relative to Dart SDK
If the Dart SDK is present inside the Flutter SDK in sub-folder
`bin/cache/dart-sdk/`, then we no-longer require the environment
variable `FLUTTER_ROOT` to be specified. Instead we simply derive
the location of the Flutter SDK from the location of the Dart SDK.
We still allow the environment variable `FLUTTER_ROOT` to override
the otherwise automatically detected Flutter SDK location.
* Check that "version" file is present before deciding that we have found a Flutter SDK
diff --git a/lib/src/sdk/flutter.dart b/lib/src/sdk/flutter.dart
index d74adde..3c8411f 100644
--- a/lib/src/sdk/flutter.dart
+++ b/lib/src/sdk/flutter.dart
@@ -20,25 +20,67 @@
@override
Version get firstPubVersion => Version.parse('1.19.0');
- static final bool _isAvailable =
- Platform.environment.containsKey('FLUTTER_ROOT');
- static final String _rootDirectory = Platform.environment['FLUTTER_ROOT'];
+ // We only consider the Flutter SDK to present if we find a root directory
+ // and the root directory contains a valid 'version' file.
+ static final bool _isAvailable = _rootDirectory != null && _version != null;
+ static final String _rootDirectory = () {
+ // If FLUTTER_ROOT is specified, then this always points to the Flutter SDK
+ if (Platform.environment.containsKey('FLUTTER_ROOT')) {
+ return Platform.environment['FLUTTER_ROOT'];
+ }
+
+ // We can try to find the Flutter SDK relative to the Dart SDK.
+ // We know that the Dart SDK is always present, this is found relative to
+ // the `dart` executable, for details see: lib/src/sdk/dart.dart
+ //
+ // Once we have the location of the Dart SDK, we can look at its parent
+ // directories, if going 3 levels-up and down `bin/cache/dart-sdk/` is equal
+ // to the Dart SDK root, then it's probably because we are located inside
+ // the Flutter SDK, at: `$FLUTTER_ROOT/bin/cache/dart-sdk`
+ final parts = p.split(sdk.rootDirectory);
+ if (parts.length > 3) {
+ // Go 3-levels up from the Dart SDK root
+ final flutterSdk = p.joinAll(parts.take(parts.length - 3));
+ // If going down 'bin/cache/dart-sdk/' yields the same path as the Dart
+ // SDK has, then it's probably because the Dart SDK is located inside
+ // the Flutter SDK.
+ final dartRootFromFlutterSdk = p.join(
+ flutterSdk,
+ 'bin',
+ 'cache',
+ 'dart-sdk',
+ );
+ if (p.equals(sdk.rootDirectory, dartRootFromFlutterSdk)) {
+ return flutterSdk;
+ }
+ }
+
+ return null;
+ }();
+ static final Version _version = () {
+ if (_rootDirectory == null) return null;
+
+ try {
+ return Version.parse(
+ readTextFile(p.join(_rootDirectory, 'version')).trim(),
+ );
+ } on IOException {
+ return null; // I guess the file doesn't exist
+ } on FormatException {
+ return null; // I guess the file has the wrong format
+ }
+ }();
@override
String get installMessage =>
- 'Flutter users should run `flutter pub get` instead of `pub get`.';
+ 'Flutter users should run `flutter pub get` instead of `dart pub get`.';
@override
Version get version {
- if (!_isAvailable) return null;
-
- _version ??=
- Version.parse(readTextFile(p.join(_rootDirectory, 'version')).trim());
+ if (!isAvailable) return null;
return _version;
}
- Version _version;
-
@override
String packagePath(String name) {
if (!isAvailable) return null;
diff --git a/test/sdk_test.dart b/test/sdk_test.dart
index e1d311b..93ebdac 100644
--- a/test/sdk_test.dart
+++ b/test/sdk_test.dart
@@ -133,7 +133,7 @@
Because myapp depends on foo any from sdk which doesn't exist (the
Flutter SDK is not available), version solving failed.
- Flutter users should run `flutter pub get` instead of `pub
+ Flutter users should run `flutter pub get` instead of `dart pub
get`.
"""), exitCode: exit_codes.UNAVAILABLE);
});
diff --git a/test/version_solver_test.dart b/test/version_solver_test.dart
index 44d0399..41003bb 100644
--- a/test/version_solver_test.dart
+++ b/test/version_solver_test.dart
@@ -1458,7 +1458,7 @@
await expectResolves(error: equalsIgnoringWhitespace('''
Because myapp requires the Flutter SDK, version solving failed.
- Flutter users should run `flutter pub get` instead of `pub get`.
+ Flutter users should run `flutter pub get` instead of `dart pub get`.
'''));
});
@@ -1474,7 +1474,7 @@
Because myapp depends on foo any which requires the Flutter SDK, version
solving failed.
- Flutter users should run `flutter pub get` instead of `pub get`.
+ Flutter users should run `flutter pub get` instead of `dart pub get`.
'''));
});
@@ -1502,7 +1502,7 @@
await expectResolves(error: equalsIgnoringWhitespace('''
Because myapp requires the Flutter SDK, version solving failed.
- Flutter users should run `flutter pub get` instead of `pub get`.
+ Flutter users should run `flutter pub get` instead of `dart pub get`.
'''));
});
});