diff --git a/lib/src/commands/config_command.dart b/lib/src/commands/config_command.dart index 80fe31f7..de5f0022 100644 --- a/lib/src/commands/config_command.dart +++ b/lib/src/commands/config_command.dart @@ -1,10 +1,10 @@ -import '../../constants.dart'; -import '../../fvm.dart'; -import '../services/config_repository.dart'; -import '../services/logger_service.dart'; import 'package:io/ansi.dart'; import 'package:io/io.dart'; +import '../../fvm.dart'; +import '../services/config_repository.dart'; +import '../services/logger_service.dart'; +import '../utils/constants.dart'; import '../utils/context.dart'; import 'base_command.dart'; diff --git a/lib/src/commands/dart_command.dart b/lib/src/commands/dart_command.dart index 7cb6b56c..3df03b6f 100644 --- a/lib/src/commands/dart_command.dart +++ b/lib/src/commands/dart_command.dart @@ -1,9 +1,9 @@ import 'package:args/args.dart'; -import '../../constants.dart'; -import '../../fvm.dart'; -import '../utils/commands.dart'; +import '../../fvm.dart'; import '../services/logger_service.dart'; +import '../utils/commands.dart'; +import '../utils/constants.dart'; import '../workflows/ensure_cache.workflow.dart'; import 'base_command.dart'; @@ -40,6 +40,7 @@ class DartCommand extends BaseCommand { // Running null will default to dart version on path } final results = await runDart(args, version: cacheVersion); + return results.exitCode; } } diff --git a/lib/src/commands/doctor_command.dart b/lib/src/commands/doctor_command.dart index 0f96e6dd..6c76c278 100644 --- a/lib/src/commands/doctor_command.dart +++ b/lib/src/commands/doctor_command.dart @@ -2,16 +2,16 @@ import 'dart:convert'; import 'dart:io'; import 'package:dart_console/dart_console.dart'; -import '../../constants.dart'; -import '../../exceptions.dart'; -import '../../fvm.dart'; -import '../utils/console_utils.dart'; -import '../utils/context.dart'; -import '../utils/which.dart'; import 'package:io/io.dart'; import 'package:path/path.dart'; +import '../../fvm.dart'; import '../services/logger_service.dart'; +import '../utils/console_utils.dart'; +import '../utils/constants.dart'; +import '../utils/context.dart'; +import '../utils/exceptions.dart'; +import '../utils/which.dart'; import 'base_command.dart'; /// Information about fvm environment @@ -155,10 +155,7 @@ class DoctorCommand extends BaseCommand { ]); } } else { - table.insertRow([ - kIntelliJ, - 'No .idea folder found', - ]); + table.insertRow([kIntelliJ, 'No .idea folder found']); } logger.write(table.toString()); diff --git a/lib/src/commands/exec_command.dart b/lib/src/commands/exec_command.dart index 38231cf8..e4b5334b 100644 --- a/lib/src/commands/exec_command.dart +++ b/lib/src/commands/exec_command.dart @@ -1,10 +1,10 @@ import 'package:args/args.dart'; import 'package:args/command_runner.dart'; -import '../../constants.dart'; -import '../../fvm.dart'; +import '../../fvm.dart'; import '../services/logger_service.dart'; import '../utils/commands.dart'; +import '../utils/constants.dart'; import '../workflows/ensure_cache.workflow.dart'; import 'base_command.dart'; diff --git a/lib/src/commands/flutter_command.dart b/lib/src/commands/flutter_command.dart index 48ace5f9..560de3f4 100644 --- a/lib/src/commands/flutter_command.dart +++ b/lib/src/commands/flutter_command.dart @@ -1,10 +1,10 @@ import 'package:args/args.dart'; -import '../../constants.dart'; -import '../../exceptions.dart'; + import '../../fvm.dart'; import '../services/logger_service.dart'; - import '../utils/commands.dart'; +import '../utils/constants.dart'; +import '../utils/exceptions.dart'; import '../workflows/ensure_cache.workflow.dart'; import 'base_command.dart'; @@ -56,6 +56,7 @@ class FlutterCommand extends BaseCommand { // Running null will default to flutter version on paths } final results = await runFlutter(args, version: cacheVersion); + return results.exitCode; } } diff --git a/lib/src/commands/global_command.dart b/lib/src/commands/global_command.dart index 3358f532..b220ce49 100644 --- a/lib/src/commands/global_command.dart +++ b/lib/src/commands/global_command.dart @@ -1,16 +1,16 @@ -import '../../constants.dart'; +import 'package:mason_logger/mason_logger.dart'; +import 'package:tint/tint.dart'; + import '../models/cache_flutter_version_model.dart'; +import '../services/cache_service.dart'; import '../services/global_version_service.dart'; import '../services/logger_service.dart'; import '../services/project_service.dart'; import '../utils/console_utils.dart'; +import '../utils/constants.dart'; import '../utils/context.dart'; import '../utils/helpers.dart'; import '../utils/which.dart'; -import 'package:mason_logger/mason_logger.dart'; -import 'package:tint/tint.dart'; - -import '../services/cache_service.dart'; import '../workflows/ensure_cache.workflow.dart'; import 'base_command.dart'; diff --git a/lib/src/commands/install_command.dart b/lib/src/commands/install_command.dart index 120e453a..dc2427e7 100644 --- a/lib/src/commands/install_command.dart +++ b/lib/src/commands/install_command.dart @@ -1,11 +1,11 @@ import 'dart:async'; -import '../workflows/setup_flutter.workflow.dart'; import 'package:io/io.dart'; -import '../../exceptions.dart'; import '../services/project_service.dart'; +import '../utils/exceptions.dart'; import '../workflows/ensure_cache.workflow.dart'; +import '../workflows/setup_flutter.workflow.dart'; import 'base_command.dart'; /// Installs Flutter SDK @@ -20,8 +20,8 @@ class InstallCommand extends BaseCommand { InstallCommand() { argParser.addFlag( 'setup', - help: 'Builds SDK after install after install', abbr: 's', + help: 'Builds SDK after install after install', defaultsTo: false, negatable: false, ); diff --git a/lib/src/commands/remove_command.dart b/lib/src/commands/remove_command.dart index df75331b..764d2732 100644 --- a/lib/src/commands/remove_command.dart +++ b/lib/src/commands/remove_command.dart @@ -1,13 +1,13 @@ import 'dart:io'; -import '../../constants.dart'; -import '../utils/context.dart'; import 'package:io/io.dart'; import '../models/flutter_version_model.dart'; import '../services/cache_service.dart'; import '../services/logger_service.dart'; import '../utils/console_utils.dart'; +import '../utils/constants.dart'; +import '../utils/context.dart'; import 'base_command.dart'; /// Removes Flutter SDK @@ -21,8 +21,8 @@ class RemoveCommand extends BaseCommand { RemoveCommand() { argParser.addFlag( 'all', - help: 'Removes all versions', abbr: 'a', + help: 'Removes all versions', negatable: false, ); } @@ -48,6 +48,7 @@ class RemoveCommand extends BaseCommand { ); } } + return ExitCode.success.code; } @@ -65,6 +66,7 @@ class RemoveCommand extends BaseCommand { // Check if version is installed if (cacheVersion == null) { logger.info('Flutter SDK: $validVersion is not installed'); + return ExitCode.success.code; } diff --git a/lib/src/commands/update_command.dart b/lib/src/commands/update_command.dart index 1f235177..d2c76e4d 100644 --- a/lib/src/commands/update_command.dart +++ b/lib/src/commands/update_command.dart @@ -4,8 +4,8 @@ import 'package:args/command_runner.dart'; import 'package:mason_logger/mason_logger.dart'; import 'package:pub_updater/pub_updater.dart'; -import '../../constants.dart'; import '../services/logger_service.dart'; +import '../utils/constants.dart'; import '../version.g.dart'; class UpdateCommand extends Command { diff --git a/lib/src/models/cache_flutter_version_model.dart b/lib/src/models/cache_flutter_version_model.dart index f0a90a12..3d794dcf 100644 --- a/lib/src/models/cache_flutter_version_model.dart +++ b/lib/src/models/cache_flutter_version_model.dart @@ -1,13 +1,13 @@ import 'dart:io'; -import 'flutter_version_model.dart'; +import 'package:path/path.dart'; + import '../utils/commands.dart'; import '../utils/compare_semver.dart'; +import '../utils/constants.dart'; import '../utils/extensions.dart'; import '../utils/helpers.dart'; -import 'package:path/path.dart'; - -import '../../constants.dart'; +import 'flutter_version_model.dart'; /// Cache Version model class CacheFlutterVersion extends FlutterVersion { @@ -41,6 +41,7 @@ class CacheFlutterVersion extends FlutterVersion { /// Get old bin path /// Before version 1.17.5 dart path was bin/cache/dart-sdk/bin if (hasOldBinPath) return join(_dartSdkCache, 'bin'); + return binPath; } @@ -53,11 +54,13 @@ class CacheFlutterVersion extends FlutterVersion { /// Gets Flutter SDK version from CacheVersion sync String? get flutterSdkVersion { final versionFile = join(directory, 'version'); + return versionFile.file.read()?.trim(); } String? get dartSdkVersion { final versionFile = join(_dartSdkCache, 'version'); + return versionFile.file.read()?.trim(); } diff --git a/lib/src/models/config_model.dart b/lib/src/models/config_model.dart index b9fb1a6d..33030bea 100644 --- a/lib/src/models/config_model.dart +++ b/lib/src/models/config_model.dart @@ -4,8 +4,9 @@ import 'dart:convert'; import 'dart:io'; import 'package:args/args.dart'; -import '../../constants.dart'; + import '../utils/change_case.dart'; +import '../utils/constants.dart'; import '../utils/extensions.dart'; import '../utils/pretty_json.dart'; diff --git a/lib/src/models/flutter_version_model.dart b/lib/src/models/flutter_version_model.dart index bf045571..005db212 100644 --- a/lib/src/models/flutter_version_model.dart +++ b/lib/src/models/flutter_version_model.dart @@ -1,8 +1,7 @@ import '../utils/compare_semver.dart'; +import '../utils/constants.dart'; import '../utils/extensions.dart'; import '../utils/git_utils.dart'; - -import '../../constants.dart'; import '../utils/helpers.dart'; /// Provides a structured way to handle Flutter SDK versions. @@ -121,6 +120,7 @@ class FlutterVersion { int compareTo(FlutterVersion other) { final otherVersion = assignVersionWeight(other.version); final versionWeight = assignVersionWeight(version); + return compareSemver(versionWeight, otherVersion); } diff --git a/lib/src/models/project_model.dart b/lib/src/models/project_model.dart index 3b5ad744..e7d5305f 100644 --- a/lib/src/models/project_model.dart +++ b/lib/src/models/project_model.dart @@ -5,7 +5,7 @@ import 'package:path/path.dart'; import 'package:pub_semver/pub_semver.dart'; import 'package:pubspec/pubspec.dart'; -import '../../constants.dart'; +import '../utils/constants.dart'; import '../utils/extensions.dart'; import 'config_model.dart'; import 'flutter_version_model.dart'; diff --git a/lib/src/runner.dart b/lib/src/runner.dart index a8683ae1..21684117 100644 --- a/lib/src/runner.dart +++ b/lib/src/runner.dart @@ -3,29 +3,29 @@ import 'dart:io'; import 'package:args/args.dart'; import 'package:args/command_runner.dart'; -import '../constants.dart'; -import 'commands/global_command.dart'; -import 'commands/update_command.dart'; -import 'services/config_repository.dart'; -import 'services/logger_service.dart'; -import 'utils/context.dart'; -import 'utils/deprecation_util.dart'; import 'package:mason_logger/mason_logger.dart'; import 'package:pub_updater/pub_updater.dart'; import 'package:stack_trace/stack_trace.dart'; -import '../exceptions.dart'; import 'commands/config_command.dart'; import 'commands/dart_command.dart'; import 'commands/doctor_command.dart'; import 'commands/exec_command.dart'; import 'commands/flutter_command.dart'; +import 'commands/global_command.dart'; import 'commands/install_command.dart'; import 'commands/list_command.dart'; import 'commands/releases_command.dart'; import 'commands/remove_command.dart'; import 'commands/spawn_command.dart'; +import 'commands/update_command.dart'; import 'commands/use_command.dart'; +import 'services/config_repository.dart'; +import 'services/logger_service.dart'; +import 'utils/constants.dart'; +import 'utils/context.dart'; +import 'utils/deprecation_util.dart'; +import 'utils/exceptions.dart'; import 'version.g.dart'; /// Command Runner for FVM @@ -41,8 +41,8 @@ class FvmCommandRunner extends CommandRunner { ..addFlag( 'version', abbr: 'v', - negatable: false, help: 'Print the current version.', + negatable: false, ); addCommand(InstallCommand()); addCommand(UseCommand()); @@ -142,6 +142,7 @@ class FvmCommandRunner extends CommandRunner { "Try running with sudo or administrator priviledges.\n" "If you are on Windows, you can turn on developer mode: https://bit.ly/3vxRr2M", ); + return ExitCode.noPerm.code; } @@ -179,6 +180,7 @@ class FvmCommandRunner extends CommandRunner { ..err(err.toString()); _printTrace(stackTrace); + return ExitCode.unavailable.code; } finally { // Add spacer after the last line always diff --git a/lib/src/services/cache_service.dart b/lib/src/services/cache_service.dart index 514065c8..3c94b435 100644 --- a/lib/src/services/cache_service.dart +++ b/lib/src/services/cache_service.dart @@ -1,14 +1,14 @@ import 'dart:io'; -import '../../exceptions.dart'; -import 'base_service.dart'; -import '../utils/context.dart'; -import '../utils/extensions.dart'; import 'package:io/io.dart'; import 'package:path/path.dart' as path; import '../models/cache_flutter_version_model.dart'; import '../models/flutter_version_model.dart'; +import '../utils/context.dart'; +import '../utils/exceptions.dart'; +import '../utils/extensions.dart'; +import 'base_service.dart'; enum CacheIntegrity { valid, @@ -34,6 +34,7 @@ class CacheService extends ContextService { if (version.isChannel) return true; // If sdkVersion is not available return true if (version.flutterSdkVersion == null) return true; + return version.flutterSdkVersion == version.version; } @@ -45,6 +46,7 @@ class CacheService extends ContextService { final versionDir = getVersionCacheDir(version.name); // Return null if version does not exist if (!versionDir.existsSync()) return null; + return CacheFlutterVersion(version, directory: versionDir.path); } diff --git a/lib/src/services/config_repository.dart b/lib/src/services/config_repository.dart index 89eece38..1203937d 100644 --- a/lib/src/services/config_repository.dart +++ b/lib/src/services/config_repository.dart @@ -1,9 +1,8 @@ import 'dart:io'; -import '../../constants.dart'; -import '../utils/helpers.dart'; - import '../../fvm.dart'; +import '../utils/constants.dart'; +import '../utils/helpers.dart'; const String flutterGitUrl = 'FLUTTER_GIT_URL'; diff --git a/lib/src/services/flutter_service.dart b/lib/src/services/flutter_service.dart index 1e863762..1e1f5110 100644 --- a/lib/src/services/flutter_service.dart +++ b/lib/src/services/flutter_service.dart @@ -2,19 +2,19 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'base_service.dart'; -import 'logger_service.dart'; -import 'releases_service/releases_client.dart'; -import '../utils/context.dart'; -import '../utils/parsers/git_clone_update_printer.dart'; import 'package:git/git.dart'; import 'package:io/io.dart' as io; import 'package:mason_logger/mason_logger.dart'; -import '../../exceptions.dart'; import '../../fvm.dart'; import '../models/flutter_version_model.dart'; import '../utils/commands.dart'; +import '../utils/context.dart'; +import '../utils/exceptions.dart'; +import '../utils/parsers/git_clone_update_printer.dart'; +import 'base_service.dart'; +import 'logger_service.dart'; +import 'releases_service/releases_client.dart'; /// Helpers and tools to interact with Flutter sdk class FlutterService extends ContextService { @@ -152,6 +152,7 @@ class FlutterService extends ContextService { if (commitSha == null) { return false; } + return commit.contains(commitSha); } @@ -164,6 +165,7 @@ class FlutterService extends ContextService { } final tags = await getTags(); + return tags.where((t) => t == tag).isNotEmpty; } diff --git a/lib/src/services/releases_service/releases_client.dart b/lib/src/services/releases_service/releases_client.dart index adfee8b3..753a1610 100644 --- a/lib/src/services/releases_service/releases_client.dart +++ b/lib/src/services/releases_service/releases_client.dart @@ -1,12 +1,11 @@ import 'dart:io'; -import 'models/channels.model.dart'; -import 'models/release.model.dart'; +import '../../utils/exceptions.dart'; import '../../utils/http.dart'; - -import '../../../exceptions.dart'; import '../logger_service.dart'; +import 'models/channels.model.dart'; import 'models/flutter_releases.model.dart'; +import 'models/release.model.dart'; final _envVars = Platform.environment; final _storageUrl = 'https://storage.googleapis.com'; @@ -46,9 +45,11 @@ class FlutterReleases { final response = await fetch(releasesUrl); _cacheReleasesRes = Releases.fromJson(response); + return await Future.value(_cacheReleasesRes); } on Exception catch (err) { logger.detail(err.toString()); + return _getFromFlutterUrl(platform); } } @@ -57,6 +58,7 @@ class FlutterReleases { try { final response = await fetch(getFlutterReleasesUrl(platform)); _cacheReleasesRes = Releases.fromJson(response); + return await Future.value(_cacheReleasesRes); } on Exception { throw AppException( @@ -73,12 +75,14 @@ class FlutterReleases { FlutterChannel channel, ) async { final releases = await get(); + return releases.getLatestChannelRelease(channel.name); } /// Returns a [FlutterChannel] from a [version] static Future getReleaseFromVersion(String version) async { final releases = await get(); + return releases.getReleaseFromVersion(version); } } diff --git a/lib/src/utils/cli_util.dart b/lib/src/utils/cli_util.dart index c4d62530..f839e903 100644 --- a/lib/src/utils/cli_util.dart +++ b/lib/src/utils/cli_util.dart @@ -6,9 +6,10 @@ import 'dart:io'; -import '../../constants.dart'; import 'package:path/path.dart' as path; +import 'constants.dart'; + /// Return the path to the current Dart SDK. String getSdkPath() => path.dirname(path.dirname(Platform.resolvedExecutable)); @@ -33,6 +34,7 @@ String get _configHome { if (xdgConfigHome != null) { return xdgConfigHome; } + // XDG Base Directory Specification says to use $HOME/.config/ when // $XDG_CONFIG_HOME isn't defined. return path.join(kUserHome, '.config'); diff --git a/lib/src/utils/console_utils.dart b/lib/src/utils/console_utils.dart index a7421e61..24762bc4 100644 --- a/lib/src/utils/console_utils.dart +++ b/lib/src/utils/console_utils.dart @@ -1,8 +1,8 @@ import 'package:dart_console/dart_console.dart'; -import '../models/cache_flutter_version_model.dart'; -import '../../exceptions.dart'; +import '../models/cache_flutter_version_model.dart'; import '../services/logger_service.dart'; +import 'exceptions.dart'; Table createTable([List columns = const []]) { final table = Table() @@ -14,6 +14,7 @@ Table createTable([List columns = const []]) { for (final column in columns) { table.insertColumn(header: column, alignment: TextAlignment.left); } + return table; } diff --git a/lib/constants.dart b/lib/src/utils/constants.dart similarity index 100% rename from lib/constants.dart rename to lib/src/utils/constants.dart diff --git a/lib/src/utils/context.dart b/lib/src/utils/context.dart index e8614c1b..3a3866ec 100644 --- a/lib/src/utils/context.dart +++ b/lib/src/utils/context.dart @@ -1,15 +1,15 @@ import 'dart:io'; -import '../services/config_repository.dart'; -import '../services/flutter_service.dart'; -import '../services/global_version_service.dart'; -import '../services/logger_service.dart'; import 'package:mason_logger/mason_logger.dart'; import 'package:path/path.dart'; import 'package:scope/scope.dart'; -import '../../constants.dart'; import '../../fvm.dart'; +import '../services/config_repository.dart'; +import '../services/flutter_service.dart'; +import '../services/global_version_service.dart'; +import '../services/logger_service.dart'; +import 'constants.dart'; final contextKey = ScopeKey(); diff --git a/lib/src/utils/deprecation_util.dart b/lib/src/utils/deprecation_util.dart index b4b165df..489bfaf8 100644 --- a/lib/src/utils/deprecation_util.dart +++ b/lib/src/utils/deprecation_util.dart @@ -1,13 +1,14 @@ import 'dart:convert'; import 'dart:io'; -import '../../constants.dart'; +import 'package:mason_logger/mason_logger.dart'; +import 'package:path/path.dart'; + import '../../fvm.dart'; import '../services/config_repository.dart'; import '../services/logger_service.dart'; +import 'constants.dart'; import 'context.dart'; -import 'package:mason_logger/mason_logger.dart'; -import 'package:path/path.dart'; void deprecationWorkflow() { _warnDeprecatedEnvVars(); @@ -87,6 +88,7 @@ void _warnDeprecatedEnvVars() { if (!confirmation) { exit(ExitCode.success.code); } + return; } diff --git a/lib/exceptions.dart b/lib/src/utils/exceptions.dart similarity index 100% rename from lib/exceptions.dart rename to lib/src/utils/exceptions.dart diff --git a/lib/src/utils/helpers.dart b/lib/src/utils/helpers.dart index d9322b18..ae9b255b 100644 --- a/lib/src/utils/helpers.dart +++ b/lib/src/utils/helpers.dart @@ -1,11 +1,11 @@ import 'dart:io'; import 'package:date_format/date_format.dart'; -import 'git_utils.dart'; import 'package:pub_semver/pub_semver.dart'; -import '../../constants.dart'; import '../services/logger_service.dart'; +import 'constants.dart'; +import 'git_utils.dart'; /// Checks if [name] is a channel diff --git a/lib/src/workflows/ensure_cache.workflow.dart b/lib/src/workflows/ensure_cache.workflow.dart index cbea0290..e0909458 100644 --- a/lib/src/workflows/ensure_cache.workflow.dart +++ b/lib/src/workflows/ensure_cache.workflow.dart @@ -2,13 +2,13 @@ import 'dart:io'; import 'package:mason_logger/mason_logger.dart'; -import '../../exceptions.dart'; import '../models/cache_flutter_version_model.dart'; import '../models/flutter_version_model.dart'; import '../services/cache_service.dart'; import '../services/flutter_service.dart'; import '../services/logger_service.dart'; import '../utils/context.dart'; +import '../utils/exceptions.dart'; import '../utils/helpers.dart'; /// Ensures that the specified Flutter SDK version is cached locally. diff --git a/lib/src/workflows/resolve_dependencies.workflow.dart b/lib/src/workflows/resolve_dependencies.workflow.dart index ae7de1f1..a11ded2a 100644 --- a/lib/src/workflows/resolve_dependencies.workflow.dart +++ b/lib/src/workflows/resolve_dependencies.workflow.dart @@ -1,10 +1,11 @@ import 'dart:io'; -import '../../exceptions.dart'; +import 'package:mason_logger/mason_logger.dart'; + import '../models/cache_flutter_version_model.dart'; import '../models/project_model.dart'; import '../services/logger_service.dart'; -import 'package:mason_logger/mason_logger.dart'; +import '../utils/exceptions.dart'; Future resolveDependenciesWorkflow( Project project, diff --git a/lib/src/workflows/use_version.workflow.dart b/lib/src/workflows/use_version.workflow.dart index 04f3a145..ad6ca9bc 100644 --- a/lib/src/workflows/use_version.workflow.dart +++ b/lib/src/workflows/use_version.workflow.dart @@ -7,13 +7,13 @@ import 'package:mason_logger/mason_logger.dart'; import 'package:path/path.dart'; import 'package:pub_semver/pub_semver.dart'; -import '../../constants.dart'; -import '../../exceptions.dart'; import '../models/cache_flutter_version_model.dart'; import '../models/project_model.dart'; import '../services/logger_service.dart'; import '../services/project_service.dart'; +import '../utils/constants.dart'; import '../utils/context.dart'; +import '../utils/exceptions.dart'; import '../utils/extensions.dart'; import '../utils/helpers.dart'; import '../utils/pretty_json.dart'; diff --git a/test/testing_helpers/prepare_test_environment.dart b/test/testing_helpers/prepare_test_environment.dart index 40cc34a1..36ff9684 100644 --- a/test/testing_helpers/prepare_test_environment.dart +++ b/test/testing_helpers/prepare_test_environment.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:fvm/constants.dart'; +import 'package:fvm/src/utils/constants.dart'; import 'package:fvm/src/utils/context.dart'; import 'package:io/io.dart'; import 'package:path/path.dart';