From 881ba38af2793118713d42975577c84f47a9e591 Mon Sep 17 00:00:00 2001 From: leoafarias Date: Sat, 20 Jun 2020 09:32:24 -0400 Subject: [PATCH 1/3] Changes to process runners, and improved version validation --- .gitignore | 5 ++-- README.md | 5 ++-- coverage.json | 0 coverage_badge.svg | 6 ++--- lib/commands/flutter.dart | 4 ++-- lib/commands/install.dart | 16 +++++++++++-- lib/commands/remove.dart | 13 +++++------ lib/commands/use.dart | 8 +++---- lib/utils/flutter_tools.dart | 37 ++++++++++++++++-------------- lib/utils/guards.dart | 14 ----------- lib/utils/helpers.dart | 27 ++++++++++++++-------- lib/utils/version_installer.dart | 31 +++++++++++++++---------- pubspec.yaml | 1 + test/fvm_test.dart | 19 ++++++++------- test/utils/flutter_tools_test.dart | 4 ++-- 15 files changed, 105 insertions(+), 85 deletions(-) create mode 100644 coverage.json diff --git a/.gitignore b/.gitignore index 8e9041b1..2d9dd3fd 100644 --- a/.gitignore +++ b/.gitignore @@ -16,9 +16,6 @@ doc/api/ # Test Coverage test/.test_coverage.dart -# Link url to flutter version for tests -fvm - # IntelliJ related *.iml *.ipr @@ -31,4 +28,6 @@ fvm .settings/ .vscode/ coverage/lcov.info + +# FVM during tests .fvm diff --git a/README.md b/README.md index 5a35a97d..8c8efa97 100644 --- a/README.md +++ b/README.md @@ -40,12 +40,13 @@ And then, for information on each command: FVM gives you the ability to install many Flutter **releases** or **channels**. +- `version` - use `stable` to install the Stable channel and `v1.8.0` or `1.17.0-dev.3.1` to install the release. +- `--skip-setup` - will skip Flutter setup after install + ```bash > fvm install ``` -Version - use `master` to install the Master channel and `v1.8.0` or `1.17.0-dev.3.1` to install the release. - #### Project Config SDK Version If your project is already configured to use an specifc version. Run `install` without any arguments will make sure the proper version is installed for the project. diff --git a/coverage.json b/coverage.json new file mode 100644 index 00000000..e69de29b diff --git a/coverage_badge.svg b/coverage_badge.svg index a6f4e712..cfe3b880 100644 --- a/coverage_badge.svg +++ b/coverage_badge.svg @@ -8,13 +8,13 @@ - + coverage coverage - 75% - 75% + 74% + 74% diff --git a/lib/commands/flutter.dart b/lib/commands/flutter.dart index 4b99c26e..5a7f6d03 100644 --- a/lib/commands/flutter.dart +++ b/lib/commands/flutter.dart @@ -23,9 +23,9 @@ class FlutterCommand extends Command { @override Future run() async { Guards.isFlutterProject(); - final flutterSdkPath = getFlutterSdkExecPath(); + final flutterExec = getFlutterSdkExec(); - await processRunner(flutterSdkPath, argResults.arguments, + await flutterCmd(flutterExec, argResults.arguments, workingDirectory: kWorkingDirectory.path); } } diff --git a/lib/commands/install.dart b/lib/commands/install.dart index be889c29..e7085886 100644 --- a/lib/commands/install.dart +++ b/lib/commands/install.dart @@ -1,6 +1,7 @@ import 'package:args/command_runner.dart'; import 'package:fvm/exceptions.dart'; import 'package:fvm/utils/guards.dart'; +import 'package:fvm/utils/helpers.dart'; import 'package:fvm/utils/project_config.dart'; import 'package:fvm/utils/version_installer.dart'; @@ -15,7 +16,14 @@ class InstallCommand extends Command { final description = 'Installs Flutter SDK Version'; /// Constructor - InstallCommand(); + InstallCommand() { + argParser + ..addFlag( + 'skip-setup', + help: 'Skips Flutter setup after install', + negatable: false, + ); + } @override void run() async { @@ -32,6 +40,10 @@ class InstallCommand extends Command { version = argResults.arguments[0].toLowerCase(); } - await installFlutterVersion(version); + final skipSetup = argResults['skip-setup'] == true; + + final flutterVersion = await inferFlutterVersion(version); + + await installFlutterVersion(flutterVersion, skipSetup: skipSetup); } } diff --git a/lib/commands/remove.dart b/lib/commands/remove.dart index 544054a0..6c5eb04b 100644 --- a/lib/commands/remove.dart +++ b/lib/commands/remove.dart @@ -1,7 +1,7 @@ import 'package:args/command_runner.dart'; import 'package:fvm/utils/flutter_tools.dart'; import 'package:fvm/utils/helpers.dart'; -import 'package:fvm/utils/logger.dart'; +import 'package:fvm/utils/print.dart'; /// Removes Flutter SDK class RemoveCommand extends Command { @@ -27,17 +27,16 @@ class RemoveCommand extends Command { @override void run() async { final version = argResults.arguments[0].toLowerCase(); - - final isValidInstall = isFlutterVersionInstalled(version); + final flutterVersion = await inferFlutterVersion(version); + final isValidInstall = isFlutterVersionInstalled(flutterVersion); if (!isValidInstall) { - throw Exception('Flutter SDK: $version is not installed'); + throw Exception('Flutter SDK: $flutterVersion is not installed'); } - final progress = logger.progress('Removing $version'); + Print.success('Removing $flutterVersion'); try { - flutterSdkRemove(version); - finishProgress(progress); + flutterSdkRemove(flutterVersion); } on Exception { rethrow; } diff --git a/lib/commands/use.dart b/lib/commands/use.dart index f67cdeb3..2b2b3d9b 100644 --- a/lib/commands/use.dart +++ b/lib/commands/use.dart @@ -35,19 +35,19 @@ class UseCommand extends Command { throw Exception('Please provide a version. fvm use '); } // Make sure is valid Flutter version - await Guards.isFlutterVersion(version); + final flutterVersion = await inferFlutterVersion(version); // If project use check that is Flutter project if (!useGlobally) Guards.isFlutterProject(); // Make sure version is installed - await checkAndInstallVersion(version); + await checkAndInstallVersion(flutterVersion); if (useGlobally) { // Sets version as the global - setAsGlobalVersion(version); + setAsGlobalVersion(flutterVersion); } else { // Updates the project config with version - setAsProjectVersion(version); + setAsProjectVersion(flutterVersion); } } } diff --git a/lib/utils/flutter_tools.dart b/lib/utils/flutter_tools.dart index 417ef096..4cb11547 100644 --- a/lib/utils/flutter_tools.dart +++ b/lib/utils/flutter_tools.dart @@ -1,42 +1,37 @@ import 'dart:io'; import 'package:fvm/constants.dart'; +import 'package:fvm/exceptions.dart'; import 'package:fvm/utils/git.dart'; import 'package:fvm/utils/helpers.dart'; +import 'package:fvm/utils/logger.dart'; import 'package:fvm/utils/print.dart'; +import 'package:process_run/cmd_run.dart'; +import 'package:process_run/process_run.dart'; import 'package:path/path.dart' as path; -import 'package:io/io.dart'; /// Runs a process -Future processRunner(String cmd, List args, +Future flutterCmd(String exec, List args, {String workingDirectory}) async { - final manager = ProcessManager(); - - var pr = await manager.spawn(cmd, args, workingDirectory: workingDirectory); - final exitCode = await pr.exitCode; - - exit(exitCode); + var pr = await run(exec, args, + workingDirectory: workingDirectory, stdout: stdout, stderr: stderr); + exitCode = pr.exitCode; } /// Clones Flutter SDK from Version Number or Channel /// Returns exists:true if comes from cache or false if its new fetch. -Future flutterVersionClone( +Future gitCloneCmd( String version, ) async { final versionDirectory = Directory(path.join(kVersionsDir.path, version)); - if (!isFlutterChannel(version)) { - version = await inferFlutterVersion(version); - } - - // If it's installed correctly just return and use cached - if (isInstalledCorrectly(version)) return; - await versionDirectory.create(recursive: true); final args = [ 'clone', '--progress', + '--depth', + '1', '--single-branch', '-b', version, @@ -45,12 +40,20 @@ Future flutterVersionClone( kFlutterRepo, versionDirectory.path ]; - await processRunner('git', args); + + final process = await run('git', args, + stdout: stdout, stderr: stderr, verbose: logger.isVerbose); + + if (process.exitCode != 0) { + throw ExceptionCouldNotClone( + 'Could not install Flutter version: $version.'); + } } /// Gets SDK Version Future flutterSdkVersion(String branch) async { final branchDirectory = Directory(path.join(kVersionsDir.path, branch)); + if (!branchDirectory.existsSync()) { throw Exception('Could not get version from SDK that is not installed'); } diff --git a/lib/utils/guards.dart b/lib/utils/guards.dart index 5a29c8b7..19101d04 100644 --- a/lib/utils/guards.dart +++ b/lib/utils/guards.dart @@ -2,9 +2,7 @@ import 'dart:io'; import 'package:fvm/constants.dart'; -import 'package:fvm/exceptions.dart'; import 'package:fvm/utils/git.dart'; -import 'package:fvm/utils/helpers.dart'; /// Guards class Guards { @@ -25,16 +23,4 @@ class Guards { 'You need Git Installed to run fvm. Go to https://git-scm.com/downloads'); } } - - /// Make sure version is valid - static Future isFlutterVersion(String version) async { - // Check if its a channel - if (isFlutterChannel(version)) return; - // Check if ts a version - final flutterVersion = await inferFlutterVersion(version); - if (flutterVersion == null) { - throw ExceptionNotValidVersion( - '"$version" is not a valid Flutter SDK version'); - } - } } diff --git a/lib/utils/helpers.dart b/lib/utils/helpers.dart index 8011e21f..14176a18 100644 --- a/lib/utils/helpers.dart +++ b/lib/utils/helpers.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:fvm/constants.dart'; import 'package:fvm/exceptions.dart'; import 'package:fvm/utils/confirm.dart'; -import 'package:fvm/utils/logger.dart'; import 'package:fvm/utils/print.dart'; import 'package:fvm/utils/project_config.dart'; import 'package:fvm/utils/version_installer.dart'; @@ -13,14 +12,22 @@ import 'package:fvm/utils/flutter_tools.dart'; /// Returns true if it's a valid Flutter version number Future inferFlutterVersion(String version) async { final versions = await flutterListAllSdks(); + version = version.toLowerCase(); + + // Return if its flutter chacnnel + if (isFlutterChannel(version)) return version; + if ((versions).contains(version)) { return version; } final prefixedVersion = 'v$version'; + if ((versions).contains(prefixedVersion)) { return prefixedVersion; } - throw ExceptionNotValidVersion('"$version" is not a valid version'); + + throw ExceptionNotValidVersion( + '"$version" is not a valid Flutter SDK version'); } /// Returns true if it's a valid Flutter channel @@ -40,9 +47,7 @@ Future checkAndInstallVersion(String version) async { // Install if input is confirmed if (await confirm('Would you like to install it?')) { - final installProgress = logger.progress('Installing $version'); await installFlutterVersion(version); - finishProgress(installProgress); } else { // If do not install exist exit(0); @@ -72,12 +77,16 @@ bool isCurrentVersion(String version) { } /// The Flutter SDK Path referenced on FVM -String getFlutterSdkPath() { - final config = readProjectConfig(); - return path.join(kVersionsDir.path, config.flutterSdkVersion); +String getFlutterSdkPath({String version}) { + var sdkVersion = version; + if (version == null) { + final config = readProjectConfig(); + sdkVersion = config.flutterSdkVersion; + } + return path.join(kVersionsDir.path, sdkVersion); } -String getFlutterSdkExecPath() { - return path.join(getFlutterSdkPath(), 'bin', +String getFlutterSdkExec({String version}) { + return path.join(getFlutterSdkPath(version: version), 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter'); } diff --git a/lib/utils/version_installer.dart b/lib/utils/version_installer.dart index 5567a9cf..cdb348c2 100644 --- a/lib/utils/version_installer.dart +++ b/lib/utils/version_installer.dart @@ -1,21 +1,28 @@ import 'package:fvm/exceptions.dart'; import 'package:fvm/utils/flutter_tools.dart'; -import 'package:fvm/utils/logger.dart'; -import 'package:io/ansi.dart'; +import 'package:fvm/utils/helpers.dart'; +import 'package:fvm/utils/print.dart'; -Future installFlutterVersion( - String flutterVersion, -) async { - if (flutterVersion == null) { +Future installFlutterVersion(String version, + {bool skipSetup = false}) async { + if (version == null) { throw ExceptionMissingChannelVersion(); } - final version = flutterVersion.toLowerCase(); - final progress = logger.progress(green.wrap('Downloading $version')); - // Skips line in progress - print(''); + // If it's installed correctly just return and use cached + if (isInstalledCorrectly(version)) { + Print.success('Version: $version - already installed.'); + return; + } + + Print.success('Installing Version: $version:'); - await flutterVersionClone(version); + await gitCloneCmd(version); - finishProgress(progress); + // Skips Flutter sdk setup + if (skipSetup) return; + Print.success('Setting up Flutter sdk'); + Print.info('If you want to skip this next time use "--skip-setup"'); + final flutterExec = getFlutterSdkExec(version: version); + await flutterCmd(flutterExec, ['doctor']); } diff --git a/pubspec.yaml b/pubspec.yaml index 70823ce7..6c381c4b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,6 +15,7 @@ dependencies: console: ^3.1.0 io: ^0.3.3 path: ^1.6.4 + process_run: ^0.10.10+1 dev_dependencies: pedantic: ^1.8.0 diff --git a/test/fvm_test.dart b/test/fvm_test.dart index 3ff876b0..b21e6cb8 100644 --- a/test/fvm_test.dart +++ b/test/fvm_test.dart @@ -3,6 +3,7 @@ import 'package:fvm/commands/install.dart'; import 'package:fvm/commands/runner.dart'; import 'package:fvm/exceptions.dart'; import 'package:fvm/fvm.dart'; +import 'package:fvm/utils/helpers.dart'; import 'package:test/test.dart'; import 'package:path/path.dart' as path; import 'package:fvm/constants.dart'; @@ -30,7 +31,7 @@ void main() { }); test('Install Channel', () async { try { - await fvmRunner(['install', channel, '--verbose']); + await fvmRunner(['install', channel, '--verbose', '--skip-setup']); final existingChannel = await flutterSdkVersion(channel); final correct = isInstalledCorrectly(channel); final installedVersions = flutterListInstalledSdks(); @@ -100,16 +101,18 @@ void main() { group('Release Flow', () { test('Install Release', () async { try { - await fvmRunner(['install', release, '--verbose']); - final existingRelease = await flutterSdkVersion(release); - final correct = isInstalledCorrectly(release); + await fvmRunner(['install', release, '--verbose', '--skip-setup']); + final version = await inferFlutterVersion(release); + final existingRelease = await flutterSdkVersion(version); + + final correct = isInstalledCorrectly(version); final installedVersions = flutterListInstalledSdks(); - final installExists = installedVersions.contains(release); + final installExists = installedVersions.contains(version); expect(installExists, true, reason: 'Install does not exist'); expect(correct, true, reason: 'Not Installed Correctly'); - expect(existingRelease, 'v$release'); + expect(existingRelease, version); } on Exception catch (e) { fail('Exception thrown, $e'); } @@ -123,8 +126,8 @@ void main() { final linkExists = kProjectFvmSdkSymlink.existsSync(); final targetBin = kProjectFvmSdkSymlink.targetSync(); - - final releaseBin = path.join(kVersionsDir.path, release); + final version = await inferFlutterVersion(release); + final releaseBin = path.join(kVersionsDir.path, version); expect(targetBin == releaseBin, true); expect(linkExists, true); diff --git a/test/utils/flutter_tools_test.dart b/test/utils/flutter_tools_test.dart index e9e6615f..b23c6d7a 100644 --- a/test/utils/flutter_tools_test.dart +++ b/test/utils/flutter_tools_test.dart @@ -12,10 +12,10 @@ void main() { final invalidVersion = 'INVALID_VERSION'; try { - await flutterVersionClone(invalidVersion); + await gitCloneCmd(invalidVersion); fail('Exception not thrown'); } on Exception catch (e) { - expect(e, const TypeMatcher()); + expect(e, const TypeMatcher()); } }); test('Checks that install is not correct', () async { From ab5250e4e725615c2fdd7d101fded0945a736ba2 Mon Sep 17 00:00:00 2001 From: leoafarias Date: Sat, 20 Jun 2020 09:34:51 -0400 Subject: [PATCH 2/3] Changed command for flutter setup --- lib/utils/version_installer.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/version_installer.dart b/lib/utils/version_installer.dart index cdb348c2..887e69bd 100644 --- a/lib/utils/version_installer.dart +++ b/lib/utils/version_installer.dart @@ -24,5 +24,5 @@ Future installFlutterVersion(String version, Print.success('Setting up Flutter sdk'); Print.info('If you want to skip this next time use "--skip-setup"'); final flutterExec = getFlutterSdkExec(version: version); - await flutterCmd(flutterExec, ['doctor']); + await flutterCmd(flutterExec, ['--version']); } From f28438f08c60f4726bc4575b359e629d541e6592 Mon Sep 17 00:00:00 2001 From: leoafarias Date: Sat, 20 Jun 2020 09:40:08 -0400 Subject: [PATCH 3/3] Test coverage update --- coverage_badge.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coverage_badge.svg b/coverage_badge.svg index cfe3b880..f6e16c2f 100644 --- a/coverage_badge.svg +++ b/coverage_badge.svg @@ -8,7 +8,7 @@ - +