diff --git a/.github/actions/prepare/action.yml b/.github/actions/prepare/action.yml index 159cc5b4..7ddccb1e 100644 --- a/.github/actions/prepare/action.yml +++ b/.github/actions/prepare/action.yml @@ -21,5 +21,5 @@ runs: shell: bash - name: Build Version - run: dart run grinder build-version + run: dart run build_runner build --delete-conflicting-outputs shell: bash diff --git a/CHANGELOG.md b/CHANGELOG.md index 9647e9dc..8c4ded66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## Unreleased + +* Added: `fvm use [version] --force` now skips install confirmation prompt by @mrgnhnt96 +* Added: Added flag to skip pub get on `install` and `use`, `--skip-pub-get` by @mrgnhnt96 +* Improvement: CI Flag now skips check update by @leoafarias +* Fix: Improve App Config and Project Config overrides by @leoafarias +* Fix: Incorrect check version update logic by @leoafarias +* Improvemnet: Better exception handling during mirror creation by @leoafarias + ## 3.0.12 * Adds skipping version mismatch handling when using force or running with a custom fvm version. [#653](https://github.com/leoafarias/fvm/issues/653) diff --git a/bin/main.dart b/bin/main.dart index 9408b5ae..7366ba49 100755 --- a/bin/main.dart +++ b/bin/main.dart @@ -7,7 +7,7 @@ import 'package:fvm/src/utils/context.dart'; import 'package:scope/scope.dart'; Future main(List args) async { - final scope = Scope()..value(contextKey, FVMContext.create()); + final scope = Scope()..value(contextKey, FVMContext.main); await _flushThenExit( await scope.run(() => FvmCommandRunner().run((args))), diff --git a/docs/next.config.js b/docs/next.config.js index c15c3b37..61814697 100644 --- a/docs/next.config.js +++ b/docs/next.config.js @@ -23,6 +23,11 @@ module.exports = withNextra({ destination: "/documentation/getting-started/faq", permanent: true, }, + { + source: "/docs/guides/global_version", + destination: "/documentation/guides/global-configuration", + permanent: true, + }, ]; }, }); diff --git a/lib/src/commands/config_command.dart b/lib/src/commands/config_command.dart index 864a08d0..420811ef 100644 --- a/lib/src/commands/config_command.dart +++ b/lib/src/commands/config_command.dart @@ -29,62 +29,45 @@ class ConfigCommand extends BaseCommand { @override Future run() async { // Flag if settings should be saved - var shouldSave = false; - var current = ConfigRepository.loadFile(); + final currentConfig = ConfigRepository.loadAppConfig(); + var updatedConfig = currentConfig; - if (wasParsed(ConfigKeys.flutterUrl.paramKey)) { - final flutterRepo = stringArg(ConfigKeys.flutterUrl.paramKey); - logger.info('Setting flutter repo to: ${yellow.wrap(flutterRepo)}'); - current.flutterUrl = flutterRepo; + void updateConfigKey(ConfigKeys key, T value) { + if (wasParsed(key.paramKey)) { + final updatedMap = AppConfig.fromMap({key.name: value}); + logger.info( + 'Setting ${key.paramKey} to: ${yellow.wrap(value.toString())}', + ); - shouldSave = true; - } - - if (wasParsed(ConfigKeys.gitCachePath.paramKey)) { - final gitCachePath = stringArg(ConfigKeys.gitCachePath.paramKey); - logger.info('Setting git cache path to: ${yellow.wrap(gitCachePath)}'); - current.gitCachePath = gitCachePath; - shouldSave = true; - } - - if (wasParsed(ConfigKeys.useGitCache.paramKey)) { - final gitCache = boolArg(ConfigKeys.useGitCache.paramKey); - logger.info( - 'Setting use git cache to: ${yellow.wrap(gitCache.toString())}', - ); - current.useGitCache = gitCache; - shouldSave = true; + logger.info(updatedMap.toString()); + updatedConfig = updatedConfig.merge(updatedMap); + } } - if (wasParsed(ConfigKeys.cachePath.paramKey)) { - final cachePath = stringArg(ConfigKeys.cachePath.paramKey); - logger.info('Setting fvm path to: ${yellow.wrap(cachePath)}'); - current.cachePath = cachePath; - shouldSave = true; + for (var key in ConfigKeys.values) { + updateConfigKey(key, argResults![key.paramKey]); } // Save - if (shouldSave) { + if (updatedConfig != currentConfig) { logger.info(''); final updateProgress = logger.progress('Saving settings'); // Update settings try { - ConfigRepository.save(current); + ConfigRepository.save(updatedConfig); } catch (error) { updateProgress.fail('Failed to save settings'); rethrow; } updateProgress.complete('Settings saved.'); } else { - // How do I scape a file.path? - logger ..info('FVM Configuration:') ..info('Located at ${ctx.configPath}') ..info(''); - final options = current.toMap(); + final options = currentConfig.toMap(); if (options.keys.isEmpty) { logger.info('No settings have been configured.'); diff --git a/lib/src/commands/install_command.dart b/lib/src/commands/install_command.dart index 859cbcfe..7b4845f0 100644 --- a/lib/src/commands/install_command.dart +++ b/lib/src/commands/install_command.dart @@ -30,8 +30,8 @@ class InstallCommand extends BaseCommand { ..addFlag( 'skip-pub-get', help: 'Skip resolving dependencies after switching Flutter SDK', - negatable: false, defaultsTo: false, + negatable: false, ); } @@ -65,7 +65,7 @@ class InstallCommand extends BaseCommand { project: project, force: true, skipSetup: !setup, - resolveDependencies: !skipPubGet, + runPubGetOnSdkChange: !skipPubGet, ); return ExitCode.success.code; diff --git a/lib/src/commands/list_command.dart b/lib/src/commands/list_command.dart index ceb47a04..fc7ee13d 100644 --- a/lib/src/commands/list_command.dart +++ b/lib/src/commands/list_command.dart @@ -1,13 +1,13 @@ import 'package:dart_console/dart_console.dart'; -import '../services/global_version_service.dart'; -import '../services/releases_service/models/release.model.dart'; -import '../services/releases_service/releases_client.dart'; -import '../utils/helpers.dart'; import 'package:mason_logger/mason_logger.dart'; import '../services/cache_service.dart'; +import '../services/global_version_service.dart'; import '../services/logger_service.dart'; +import '../services/releases_service/models/release.model.dart'; +import '../services/releases_service/releases_client.dart'; import '../utils/context.dart'; +import '../utils/helpers.dart'; import 'base_command.dart'; /// List installed SDK Versions @@ -71,7 +71,7 @@ class ListCommand extends BaseCommand { String flutterSdkVersion = version.flutterSdkVersion ?? ''; String getVersionOutput() { - if (version.notSetup) { + if (version.isNotSetup) { return flutterSdkVersion = '${yellow.wrap('Need setup')}'; } if (latestRelease != null && version.isChannel) { diff --git a/lib/src/commands/update_command.dart b/lib/src/commands/update_command.dart index 3afe0901..47a93873 100644 --- a/lib/src/commands/update_command.dart +++ b/lib/src/commands/update_command.dart @@ -6,7 +6,7 @@ import 'package:pub_updater/pub_updater.dart'; import '../services/logger_service.dart'; import '../utils/constants.dart'; -import '../version.g.dart'; +import '../version.dart'; class UpdateCommand extends Command { static const String commandName = 'update'; diff --git a/lib/src/commands/use_command.dart b/lib/src/commands/use_command.dart index 91a5f854..aa47ce77 100644 --- a/lib/src/commands/use_command.dart +++ b/lib/src/commands/use_command.dart @@ -46,8 +46,8 @@ class UseCommand extends BaseCommand { ..addFlag( 'skip-pub-get', help: 'Skip resolving dependencies after switching Flutter SDK', - negatable: false, defaultsTo: false, + negatable: false, ) ..addFlag( 'skip-setup', @@ -135,8 +135,8 @@ class UseCommand extends BaseCommand { project: project, force: forceOption, skipSetup: skipSetup, + runPubGetOnSdkChange: !skipPubGet, flavor: flavorOption, - resolveDependencies: !skipPubGet, ); return ExitCode.success.code; diff --git a/lib/src/models/cache_flutter_version_model.dart b/lib/src/models/cache_flutter_version_model.dart index 3d794dcf..7199b950 100644 --- a/lib/src/models/cache_flutter_version_model.dart +++ b/lib/src/models/cache_flutter_version_model.dart @@ -65,7 +65,10 @@ class CacheFlutterVersion extends FlutterVersion { } /// Verifies that cacheVersion has been setup - bool get notSetup => flutterSdkVersion == null; + bool get isNotSetup => flutterSdkVersion == null; + + /// Returns bool if version is setup + bool get isSetup => flutterSdkVersion != null; Future run( String command, { diff --git a/lib/src/models/config_model.dart b/lib/src/models/config_model.dart index 25cc4581..5a802225 100644 --- a/lib/src/models/config_model.dart +++ b/lib/src/models/config_model.dart @@ -1,181 +1,190 @@ // Use just for reference, should not change +import 'dart:convert'; import 'dart:io'; import 'package:args/args.dart'; -import 'package:jsonc/jsonc.dart'; +import 'package:dart_mappable/dart_mappable.dart'; import '../utils/change_case.dart'; import '../utils/constants.dart'; import '../utils/extensions.dart'; import '../utils/pretty_json.dart'; -class ConfigKeys { - final String key; +part 'config_model.mapper.dart'; - static const ConfigKeys cachePath = ConfigKeys('cache_path'); - static const ConfigKeys useGitCache = ConfigKeys('git_cache'); - static const ConfigKeys gitCachePath = ConfigKeys('git_cache_path'); - static const ConfigKeys flutterUrl = ConfigKeys('flutter_url'); - static const ConfigKeys priviledgedAccess = ConfigKeys('priviledged_access'); +@MappableEnum() +enum ConfigKeys { + cachePath(description: 'Path where $kPackageName will cache versions'), + useGitCache( + description: + 'Enable/Disable git cache globally, which is used for faster version installs.', + ), + gitCachePath(description: 'Path where local Git reference cache is stored'), + flutterUrl(description: 'Flutter repository Git URL to clone from'), - static const values = [ - cachePath, - useGitCache, - gitCachePath, - flutterUrl, - ]; + priviledgedAccess(description: 'Enable/Disable priviledged access for FVM'); - const ConfigKeys(this.key); + const ConfigKeys({required this.description}); - static ConfigKeys fromName(String name) { - return values.firstWhere((e) => e.key == name); - } + final String description; - static argResultsToMap(ArgResults argResults) { - final configMap = {}; + ChangeCase get _recase => ChangeCase(name); - for (final key in values) { - final value = argResults[key.paramKey]; - if (value != null) { - configMap[key.propKey] = value; - } - } + String get envKey => 'FVM_${_recase.constantCase}'; - return configMap; - } + String get paramKey => _recase.paramCase; + + String get propKey => _recase.camelCase; static injectArgParser(ArgParser argParser) { final configKeysFuncs = { - ConfigKeys.cachePath.key: () { + ConfigKeys.cachePath: () { argParser.addOption( ConfigKeys.cachePath.paramKey, - help: 'Path where $kPackageName will cache versions', + help: ConfigKeys.cachePath.description, ); }, - ConfigKeys.useGitCache.key: () { + ConfigKeys.useGitCache: () { argParser.addFlag( ConfigKeys.useGitCache.paramKey, - help: - 'Enable/Disable git cache globally, which is used for faster version installs.', + help: ConfigKeys.useGitCache.description, defaultsTo: true, negatable: true, ); }, - ConfigKeys.gitCachePath.key: () { + ConfigKeys.gitCachePath: () { argParser.addOption( ConfigKeys.gitCachePath.paramKey, - help: 'Path where local Git reference cache is stored', + help: ConfigKeys.gitCachePath.description, ); }, - ConfigKeys.flutterUrl.key: () { + ConfigKeys.flutterUrl: () { argParser.addOption( ConfigKeys.flutterUrl.paramKey, - help: 'Flutter repository Git URL to clone from', + help: ConfigKeys.flutterUrl.description, ); }, - ConfigKeys.priviledgedAccess.key: () { + ConfigKeys.priviledgedAccess: () { argParser.addFlag( ConfigKeys.priviledgedAccess.paramKey, - help: 'Enable/Disable priviledged access for FVM', + help: ConfigKeys.priviledgedAccess.description, defaultsTo: true, negatable: true, ); }, }; - for (final key in values) { - configKeysFuncs[key.key]?.call(); + for (final key in ConfigKeys.values) { + configKeysFuncs[key]?.call(); } } - - ChangeCase get _recase => ChangeCase(key); - - String get envKey => 'FVM_${_recase.constantCase}'; - String get paramKey => _recase.paramCase; - String get propKey => _recase.camelCase; - - @override - operator ==(Object other) => other is ConfigKeys && other.key == key; - - @override - int get hashCode => key.hashCode; } -class Config { +@MappableClass(ignoreNull: true) +abstract class BaseConfig with BaseConfigMappable { // If should use gitCache - bool? useGitCache; + final bool? useGitCache; - String? gitCachePath; + final String? gitCachePath; /// Flutter repo url - String? flutterUrl; + final String? flutterUrl; /// Directory where FVM is stored - String? cachePath; - - /// If FVM should run with priviledged access - bool? priviledgedAccess; + final String? cachePath; /// Constructor - Config({ + const BaseConfig({ required this.cachePath, required this.useGitCache, required this.gitCachePath, required this.flutterUrl, - required this.priviledgedAccess, }); +} + +@MappableClass(ignoreNull: true) +class EnvConfig extends BaseConfig with EnvConfigMappable { + static final fromMap = EnvConfigMapper.fromMap; + static final fromJson = EnvConfigMapper.fromJson; - factory Config.empty() { - return Config( + const EnvConfig({ + required super.cachePath, + required super.useGitCache, + required super.gitCachePath, + required super.flutterUrl, + }); + + static EnvConfig empty() { + return EnvConfig( cachePath: null, useGitCache: null, gitCachePath: null, flutterUrl: null, - priviledgedAccess: null, ); } +} - factory Config.fromMap(Map map) { - return Config( - cachePath: map[ConfigKeys.cachePath.propKey] as String?, - useGitCache: map[ConfigKeys.useGitCache.propKey] as bool?, - gitCachePath: map[ConfigKeys.gitCachePath.propKey] as String?, - flutterUrl: map[ConfigKeys.flutterUrl.propKey] as String?, - priviledgedAccess: map[ConfigKeys.priviledgedAccess.propKey] as bool?, - ); - } +@MappableClass(ignoreNull: true) +class FileConfig extends BaseConfig with FileConfigMappable { + /// If Vscode settings is not managed by FVM + final bool? updateVscodeSettings; - Map toMap() { - return { - if (cachePath != null) ConfigKeys.cachePath.propKey: cachePath, - if (useGitCache != null) ConfigKeys.useGitCache.propKey: useGitCache, - if (gitCachePath != null) ConfigKeys.gitCachePath.propKey: gitCachePath, - if (flutterUrl != null) ConfigKeys.flutterUrl.propKey: flutterUrl, - if (priviledgedAccess != null) - ConfigKeys.priviledgedAccess.propKey: priviledgedAccess, - }; - } -} + /// If FVM should update .gitignore + final bool? updateGitIgnore; -/// App config -class AppConfig extends Config { - /// Disables update notification - bool? disableUpdateCheck; - DateTime? lastUpdateCheck; + final bool? runPubGetOnSdkChanges; + + /// If FVM should run with priviledged access + final bool? priviledgedAccess; + + static final fromMap = FileConfigMapper.fromMap; + static final fromJson = FileConfigMapper.fromJson; /// Constructor - AppConfig({ - required this.disableUpdateCheck, - required this.lastUpdateCheck, + const FileConfig({ required super.cachePath, required super.useGitCache, required super.gitCachePath, required super.flutterUrl, - required super.priviledgedAccess, + required this.priviledgedAccess, + required this.runPubGetOnSdkChanges, + required this.updateVscodeSettings, + required this.updateGitIgnore, + }); + + void save(String path) { + final jsonContents = prettyJson(toMap()); + + path.file.write(jsonContents); + } +} + +@MappableClass(ignoreNull: true) +class AppConfig extends FileConfig with AppConfigMappable { + /// Disables update notification + + final bool? disableUpdateCheck; + final DateTime? lastUpdateCheck; + + static final fromMap = AppConfigMapper.fromMap; + static final fromJson = AppConfigMapper.fromJson; + + /// Constructor + const AppConfig({ + this.disableUpdateCheck, + this.lastUpdateCheck, + super.cachePath, + super.useGitCache, + super.gitCachePath, + super.flutterUrl, + super.priviledgedAccess, + super.runPubGetOnSdkChanges, + super.updateVscodeSettings, + super.updateGitIgnore, }); - factory AppConfig.empty() { + static AppConfig empty() { return AppConfig( disableUpdateCheck: null, lastUpdateCheck: null, @@ -184,29 +193,12 @@ class AppConfig extends Config { gitCachePath: null, flutterUrl: null, priviledgedAccess: null, + runPubGetOnSdkChanges: null, + updateVscodeSettings: null, + updateGitIgnore: null, ); } - factory AppConfig.fromMap(Map map) { - final envConfig = Config.fromMap(map); - - return AppConfig( - disableUpdateCheck: map['disableUpdateCheck'] as bool?, - lastUpdateCheck: map['lastUpdateCheck'] != null - ? DateTime.parse(map['lastUpdateCheck'] as String) - : null, - cachePath: envConfig.cachePath, - useGitCache: envConfig.useGitCache, - gitCachePath: envConfig.gitCachePath, - flutterUrl: envConfig.flutterUrl, - priviledgedAccess: envConfig.priviledgedAccess, - ); - } - - factory AppConfig.fromJson(String source) { - return AppConfig.fromMap(jsonc.decode(source) as Map); - } - static AppConfig? loadFromPath(String path) { final configFile = File(path); @@ -215,114 +207,82 @@ class AppConfig extends Config { : null; } - AppConfig copyWith({ - String? cachePath, - bool? useGitCache, - String? gitCachePath, - String? flutterUrl, - bool? disableUpdateCheck, - DateTime? lastUpdateCheck, - bool? priviledgedAccess, - }) { - return AppConfig( - disableUpdateCheck: disableUpdateCheck ?? this.disableUpdateCheck, - lastUpdateCheck: lastUpdateCheck ?? this.lastUpdateCheck, - cachePath: cachePath ?? this.cachePath, - useGitCache: useGitCache ?? this.useGitCache, - gitCachePath: gitCachePath ?? this.gitCachePath, - flutterUrl: flutterUrl ?? this.flutterUrl, - priviledgedAccess: priviledgedAccess ?? this.priviledgedAccess, - ); - } + AppConfig merge(BaseConfig? config) { + if (config == null) return this; + AppConfig newConfig; + if (config is EnvConfig) { + newConfig = AppConfig( + disableUpdateCheck: disableUpdateCheck, + cachePath: config.cachePath, + useGitCache: config.useGitCache, + gitCachePath: config.gitCachePath, + flutterUrl: config.flutterUrl, + ); + } - AppConfig merge(AppConfig? config) { - return copyWith( - cachePath: config?.cachePath, - useGitCache: config?.useGitCache, - gitCachePath: config?.gitCachePath, - flutterUrl: config?.flutterUrl, - disableUpdateCheck: config?.disableUpdateCheck, - lastUpdateCheck: config?.lastUpdateCheck, - priviledgedAccess: config?.priviledgedAccess, - ); - } + if (config is ProjectConfig) { + newConfig = AppConfig( + cachePath: config.cachePath, + useGitCache: config.useGitCache, + gitCachePath: config.gitCachePath, + flutterUrl: config.flutterUrl, + priviledgedAccess: config.priviledgedAccess, + runPubGetOnSdkChanges: config.runPubGetOnSdkChanges, + updateVscodeSettings: config.updateVscodeSettings, + updateGitIgnore: config.updateGitIgnore, + ); + } + + if (config is AppConfig) { + return copyWith.$merge(config); + } - AppConfig mergeConfig(Config? config) { - return copyWith( - cachePath: config?.cachePath, - useGitCache: config?.useGitCache, - gitCachePath: config?.gitCachePath, - flutterUrl: config?.flutterUrl, - priviledgedAccess: config?.priviledgedAccess, + newConfig = AppConfig( + cachePath: config.cachePath, + useGitCache: config.useGitCache, + gitCachePath: config.gitCachePath, + flutterUrl: config.flutterUrl, ); - } - @override - Map toMap() { - return { - ...super.toMap(), - if (disableUpdateCheck != null) 'disableUpdateCheck': disableUpdateCheck, - if (lastUpdateCheck != null) - 'lastUpdateCheck': lastUpdateCheck?.toIso8601String(), - }; + return copyWith.$merge(newConfig); } } /// Project config -class ProjectConfig extends Config { - /// Flutter SDK version configured - String? flutterSdkVersion; - - /// Flavors configured - Map? flavors; - - /// If Vscode settings is not managed by FVM - bool? _updateVscodeSettings; - - /// If FVM should update .gitignore - bool? _updateGitIgnore; - - /// If should run pub get on sdk change - bool? _runPubGetOnSdkChanges; +@MappableClass(ignoreNull: true) +class ProjectConfig extends FileConfig with ProjectConfigMappable { + final String? flutter; + final Map? flavors; /// Constructor - ProjectConfig({ + const ProjectConfig({ + this.flutter, + this.flavors, super.cachePath, super.useGitCache, super.gitCachePath, super.flutterUrl, super.priviledgedAccess, - this.flutterSdkVersion, - this.flavors, - bool? updateVscodeSettings, - bool? updateGitIgnore, - bool? runPubGetOnSdkChanges, - }) : _updateVscodeSettings = updateVscodeSettings, - _updateGitIgnore = updateGitIgnore, - _runPubGetOnSdkChanges = runPubGetOnSdkChanges; - - /// Returns ConfigDto from a map - factory ProjectConfig.fromMap(Map map) { - final envConfig = Config.fromMap(map); + super.runPubGetOnSdkChanges, + super.updateVscodeSettings, + super.updateGitIgnore, + }); + static ProjectConfig empty() { return ProjectConfig( - cachePath: envConfig.cachePath, - useGitCache: envConfig.useGitCache, - gitCachePath: envConfig.gitCachePath, - flutterUrl: envConfig.flutterUrl, - priviledgedAccess: envConfig.priviledgedAccess, - flutterSdkVersion: map['flutterSdkVersion'] ?? map['flutter'] as String?, - flavors: map['flavors'] != null ? Map.from(map['flavors'] as Map) : null, - updateVscodeSettings: map['updateVscodeSettings'] as bool?, - updateGitIgnore: map['updateGitIgnore'] as bool?, - runPubGetOnSdkChanges: map['runPubGetOnSdkChanges'] as bool?, + flutter: null, + flavors: null, + cachePath: null, + useGitCache: null, + gitCachePath: null, + flutterUrl: null, + priviledgedAccess: null, + runPubGetOnSdkChanges: null, + updateVscodeSettings: null, + updateGitIgnore: null, ); } - /// Returns ConfigDto from a json string - factory ProjectConfig.fromJson(String source) => - ProjectConfig.fromMap(jsonc.decode(source) as Map); - static ProjectConfig? loadFromPath(String path) { final configFile = File(path); @@ -331,93 +291,20 @@ class ProjectConfig extends Config { : null; } - /// Returns update vscode settings - bool? get updateVscodeSettings => _updateVscodeSettings; - - /// Returns update git ignore - bool? get updateGitIgnore => _updateGitIgnore; - - /// Returns run pub get on sdk changes - bool? get runPubGetOnSdkChanges => _runPubGetOnSdkChanges; - - /// Copies current config and overrides with new values - /// Returns a new ConfigDto - - ProjectConfig copyWith({ - String? cachePath, - String? flutterSdkVersion, - bool? useGitCache, - bool? updateVscodeSettings, - bool? updateGitIgnore, - bool? runPubGetOnSdkChanges, - bool? priviledgedAccess, - String? gitCachePath, - String? flutterUrl, - Map? flavors, - }) { - // merge map and override the keys - final mergedFlavors = { - if (this.flavors != null) ...?this.flavors, - // ignore: prefer-null-aware-spread - if (flavors != null) ...flavors, - }; - - return ProjectConfig( - cachePath: cachePath ?? this.cachePath, - useGitCache: useGitCache ?? this.useGitCache, - gitCachePath: gitCachePath ?? this.gitCachePath, - flutterUrl: flutterUrl ?? this.flutterUrl, - priviledgedAccess: priviledgedAccess ?? this.priviledgedAccess, - flutterSdkVersion: flutterSdkVersion ?? this.flutterSdkVersion, - flavors: mergedFlavors, - updateVscodeSettings: updateVscodeSettings ?? _updateVscodeSettings, - updateGitIgnore: updateGitIgnore ?? _updateGitIgnore, - runPubGetOnSdkChanges: runPubGetOnSdkChanges ?? _runPubGetOnSdkChanges, - ); + static ProjectConfig fromJson(String json) { + return ProjectConfig.fromMap(jsonDecode(json)); } - ProjectConfig merge(ProjectConfig config) { - return copyWith( - cachePath: config.cachePath, - flutterSdkVersion: config.flutterSdkVersion, - useGitCache: config.useGitCache, - updateVscodeSettings: config._updateVscodeSettings, - updateGitIgnore: config._updateGitIgnore, - runPubGetOnSdkChanges: config._runPubGetOnSdkChanges, - priviledgedAccess: config.priviledgedAccess, - gitCachePath: config.gitCachePath, - flutterUrl: config.flutterUrl, - flavors: config.flavors, - ); - } - - void save(String path) { - final jsonContents = prettyJson(toMap()); - - path.file.write(jsonContents); + static ProjectConfig fromMap(Map map) { + return ProjectConfigMapper.fromMap({ + ...map, + 'flutter': map['flutterSdkVersion'] ?? map['flutter'], + }); } Map toLegacyMap() { return { - if (flutterSdkVersion != null) 'flutterSdkVersion': flutterSdkVersion, - if (flavors != null && flavors!.isNotEmpty) 'flavors': flavors, - }; - } - - /// It checks each property for null prior to adding it to the map. - /// This is to ensure the returned map doesn't contain any null values. - /// Also, if [flavors] is not empty it adds it to the map. - - @override - Map toMap() { - return { - ...super.toMap(), - if (flutterSdkVersion != null) 'flutter': flutterSdkVersion, - if (_updateVscodeSettings != null) - 'updateVscodeSettings': _updateVscodeSettings, - if (_updateGitIgnore != null) 'updateGitIgnore': _updateGitIgnore, - if (_runPubGetOnSdkChanges != null) - 'runPubGetOnSdkChanges': _runPubGetOnSdkChanges, + if (flutter != null) 'flutterSdkVersion': flutter, if (flavors != null && flavors!.isNotEmpty) 'flavors': flavors, }; } diff --git a/lib/src/models/config_model.mapper.dart b/lib/src/models/config_model.mapper.dart new file mode 100644 index 00000000..9079f84b --- /dev/null +++ b/lib/src/models/config_model.mapper.dart @@ -0,0 +1,875 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, unnecessary_cast +// ignore_for_file: strict_raw_type, inference_failure_on_untyped_parameter + +part of 'config_model.dart'; + +class ConfigKeysMapper extends EnumMapper { + ConfigKeysMapper._(); + + static ConfigKeysMapper? _instance; + static ConfigKeysMapper ensureInitialized() { + if (_instance == null) { + MapperContainer.globals.use(_instance = ConfigKeysMapper._()); + } + return _instance!; + } + + static ConfigKeys fromValue(dynamic value) { + ensureInitialized(); + return MapperContainer.globals.fromValue(value); + } + + @override + ConfigKeys decode(dynamic value) { + switch (value) { + case 'cachePath': + return ConfigKeys.cachePath; + case 'useGitCache': + return ConfigKeys.useGitCache; + case 'gitCachePath': + return ConfigKeys.gitCachePath; + case 'flutterUrl': + return ConfigKeys.flutterUrl; + case 'priviledgedAccess': + return ConfigKeys.priviledgedAccess; + default: + throw MapperException.unknownEnumValue(value); + } + } + + @override + dynamic encode(ConfigKeys self) { + switch (self) { + case ConfigKeys.cachePath: + return 'cachePath'; + case ConfigKeys.useGitCache: + return 'useGitCache'; + case ConfigKeys.gitCachePath: + return 'gitCachePath'; + case ConfigKeys.flutterUrl: + return 'flutterUrl'; + case ConfigKeys.priviledgedAccess: + return 'priviledgedAccess'; + } + } +} + +extension ConfigKeysMapperExtension on ConfigKeys { + String toValue() { + ConfigKeysMapper.ensureInitialized(); + return MapperContainer.globals.toValue(this) as String; + } +} + +class BaseConfigMapper extends ClassMapperBase { + BaseConfigMapper._(); + + static BaseConfigMapper? _instance; + static BaseConfigMapper ensureInitialized() { + if (_instance == null) { + MapperContainer.globals.use(_instance = BaseConfigMapper._()); + EnvConfigMapper.ensureInitialized(); + FileConfigMapper.ensureInitialized(); + } + return _instance!; + } + + @override + final String id = 'BaseConfig'; + + static String? _$cachePath(BaseConfig v) => v.cachePath; + static const Field _f$cachePath = + Field('cachePath', _$cachePath); + static bool? _$useGitCache(BaseConfig v) => v.useGitCache; + static const Field _f$useGitCache = + Field('useGitCache', _$useGitCache); + static String? _$gitCachePath(BaseConfig v) => v.gitCachePath; + static const Field _f$gitCachePath = + Field('gitCachePath', _$gitCachePath); + static String? _$flutterUrl(BaseConfig v) => v.flutterUrl; + static const Field _f$flutterUrl = + Field('flutterUrl', _$flutterUrl); + + @override + final MappableFields fields = const { + #cachePath: _f$cachePath, + #useGitCache: _f$useGitCache, + #gitCachePath: _f$gitCachePath, + #flutterUrl: _f$flutterUrl, + }; + @override + final bool ignoreNull = true; + + static BaseConfig _instantiate(DecodingData data) { + throw MapperException.missingConstructor('BaseConfig'); + } + + @override + final Function instantiate = _instantiate; + + static BaseConfig fromMap(Map map) { + return ensureInitialized().decodeMap(map); + } + + static BaseConfig fromJson(String json) { + return ensureInitialized().decodeJson(json); + } +} + +mixin BaseConfigMappable { + String toJson(); + Map toMap(); + BaseConfigCopyWith get copyWith; +} + +abstract class BaseConfigCopyWith<$R, $In extends BaseConfig, $Out> + implements ClassCopyWith<$R, $In, $Out> { + $R call( + {String? cachePath, + bool? useGitCache, + String? gitCachePath, + String? flutterUrl}); + BaseConfigCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t); +} + +class EnvConfigMapper extends ClassMapperBase { + EnvConfigMapper._(); + + static EnvConfigMapper? _instance; + static EnvConfigMapper ensureInitialized() { + if (_instance == null) { + MapperContainer.globals.use(_instance = EnvConfigMapper._()); + BaseConfigMapper.ensureInitialized(); + } + return _instance!; + } + + @override + final String id = 'EnvConfig'; + + static String? _$cachePath(EnvConfig v) => v.cachePath; + static const Field _f$cachePath = + Field('cachePath', _$cachePath); + static bool? _$useGitCache(EnvConfig v) => v.useGitCache; + static const Field _f$useGitCache = + Field('useGitCache', _$useGitCache); + static String? _$gitCachePath(EnvConfig v) => v.gitCachePath; + static const Field _f$gitCachePath = + Field('gitCachePath', _$gitCachePath); + static String? _$flutterUrl(EnvConfig v) => v.flutterUrl; + static const Field _f$flutterUrl = + Field('flutterUrl', _$flutterUrl); + + @override + final MappableFields fields = const { + #cachePath: _f$cachePath, + #useGitCache: _f$useGitCache, + #gitCachePath: _f$gitCachePath, + #flutterUrl: _f$flutterUrl, + }; + @override + final bool ignoreNull = true; + + static EnvConfig _instantiate(DecodingData data) { + return EnvConfig( + cachePath: data.dec(_f$cachePath), + useGitCache: data.dec(_f$useGitCache), + gitCachePath: data.dec(_f$gitCachePath), + flutterUrl: data.dec(_f$flutterUrl)); + } + + @override + final Function instantiate = _instantiate; + + static EnvConfig fromMap(Map map) { + return ensureInitialized().decodeMap(map); + } + + static EnvConfig fromJson(String json) { + return ensureInitialized().decodeJson(json); + } +} + +mixin EnvConfigMappable { + String toJson() { + return EnvConfigMapper.ensureInitialized() + .encodeJson(this as EnvConfig); + } + + Map toMap() { + return EnvConfigMapper.ensureInitialized() + .encodeMap(this as EnvConfig); + } + + EnvConfigCopyWith get copyWith => + _EnvConfigCopyWithImpl(this as EnvConfig, $identity, $identity); + @override + String toString() { + return EnvConfigMapper.ensureInitialized() + .stringifyValue(this as EnvConfig); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (runtimeType == other.runtimeType && + EnvConfigMapper.ensureInitialized() + .isValueEqual(this as EnvConfig, other)); + } + + @override + int get hashCode { + return EnvConfigMapper.ensureInitialized().hashValue(this as EnvConfig); + } +} + +extension EnvConfigValueCopy<$R, $Out> on ObjectCopyWith<$R, EnvConfig, $Out> { + EnvConfigCopyWith<$R, EnvConfig, $Out> get $asEnvConfig => + $base.as((v, t, t2) => _EnvConfigCopyWithImpl(v, t, t2)); +} + +abstract class EnvConfigCopyWith<$R, $In extends EnvConfig, $Out> + implements BaseConfigCopyWith<$R, $In, $Out> { + @override + $R call( + {String? cachePath, + bool? useGitCache, + String? gitCachePath, + String? flutterUrl}); + EnvConfigCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t); +} + +class _EnvConfigCopyWithImpl<$R, $Out> + extends ClassCopyWithBase<$R, EnvConfig, $Out> + implements EnvConfigCopyWith<$R, EnvConfig, $Out> { + _EnvConfigCopyWithImpl(super.value, super.then, super.then2); + + @override + late final ClassMapperBase $mapper = + EnvConfigMapper.ensureInitialized(); + @override + $R call( + {Object? cachePath = $none, + Object? useGitCache = $none, + Object? gitCachePath = $none, + Object? flutterUrl = $none}) => + $apply(FieldCopyWithData({ + if (cachePath != $none) #cachePath: cachePath, + if (useGitCache != $none) #useGitCache: useGitCache, + if (gitCachePath != $none) #gitCachePath: gitCachePath, + if (flutterUrl != $none) #flutterUrl: flutterUrl + })); + @override + EnvConfig $make(CopyWithData data) => EnvConfig( + cachePath: data.get(#cachePath, or: $value.cachePath), + useGitCache: data.get(#useGitCache, or: $value.useGitCache), + gitCachePath: data.get(#gitCachePath, or: $value.gitCachePath), + flutterUrl: data.get(#flutterUrl, or: $value.flutterUrl)); + + @override + EnvConfigCopyWith<$R2, EnvConfig, $Out2> $chain<$R2, $Out2>( + Then<$Out2, $R2> t) => + _EnvConfigCopyWithImpl($value, $cast, t); +} + +class FileConfigMapper extends ClassMapperBase { + FileConfigMapper._(); + + static FileConfigMapper? _instance; + static FileConfigMapper ensureInitialized() { + if (_instance == null) { + MapperContainer.globals.use(_instance = FileConfigMapper._()); + BaseConfigMapper.ensureInitialized(); + AppConfigMapper.ensureInitialized(); + ProjectConfigMapper.ensureInitialized(); + } + return _instance!; + } + + @override + final String id = 'FileConfig'; + + static String? _$cachePath(FileConfig v) => v.cachePath; + static const Field _f$cachePath = + Field('cachePath', _$cachePath); + static bool? _$useGitCache(FileConfig v) => v.useGitCache; + static const Field _f$useGitCache = + Field('useGitCache', _$useGitCache); + static String? _$gitCachePath(FileConfig v) => v.gitCachePath; + static const Field _f$gitCachePath = + Field('gitCachePath', _$gitCachePath); + static String? _$flutterUrl(FileConfig v) => v.flutterUrl; + static const Field _f$flutterUrl = + Field('flutterUrl', _$flutterUrl); + static bool? _$priviledgedAccess(FileConfig v) => v.priviledgedAccess; + static const Field _f$priviledgedAccess = + Field('priviledgedAccess', _$priviledgedAccess); + static bool? _$runPubGetOnSdkChanges(FileConfig v) => v.runPubGetOnSdkChanges; + static const Field _f$runPubGetOnSdkChanges = + Field('runPubGetOnSdkChanges', _$runPubGetOnSdkChanges); + static bool? _$updateVscodeSettings(FileConfig v) => v.updateVscodeSettings; + static const Field _f$updateVscodeSettings = + Field('updateVscodeSettings', _$updateVscodeSettings); + static bool? _$updateGitIgnore(FileConfig v) => v.updateGitIgnore; + static const Field _f$updateGitIgnore = + Field('updateGitIgnore', _$updateGitIgnore); + + @override + final MappableFields fields = const { + #cachePath: _f$cachePath, + #useGitCache: _f$useGitCache, + #gitCachePath: _f$gitCachePath, + #flutterUrl: _f$flutterUrl, + #priviledgedAccess: _f$priviledgedAccess, + #runPubGetOnSdkChanges: _f$runPubGetOnSdkChanges, + #updateVscodeSettings: _f$updateVscodeSettings, + #updateGitIgnore: _f$updateGitIgnore, + }; + @override + final bool ignoreNull = true; + + static FileConfig _instantiate(DecodingData data) { + return FileConfig( + cachePath: data.dec(_f$cachePath), + useGitCache: data.dec(_f$useGitCache), + gitCachePath: data.dec(_f$gitCachePath), + flutterUrl: data.dec(_f$flutterUrl), + priviledgedAccess: data.dec(_f$priviledgedAccess), + runPubGetOnSdkChanges: data.dec(_f$runPubGetOnSdkChanges), + updateVscodeSettings: data.dec(_f$updateVscodeSettings), + updateGitIgnore: data.dec(_f$updateGitIgnore)); + } + + @override + final Function instantiate = _instantiate; + + static FileConfig fromMap(Map map) { + return ensureInitialized().decodeMap(map); + } + + static FileConfig fromJson(String json) { + return ensureInitialized().decodeJson(json); + } +} + +mixin FileConfigMappable { + String toJson() { + return FileConfigMapper.ensureInitialized() + .encodeJson(this as FileConfig); + } + + Map toMap() { + return FileConfigMapper.ensureInitialized() + .encodeMap(this as FileConfig); + } + + FileConfigCopyWith get copyWith => + _FileConfigCopyWithImpl(this as FileConfig, $identity, $identity); + @override + String toString() { + return FileConfigMapper.ensureInitialized() + .stringifyValue(this as FileConfig); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (runtimeType == other.runtimeType && + FileConfigMapper.ensureInitialized() + .isValueEqual(this as FileConfig, other)); + } + + @override + int get hashCode { + return FileConfigMapper.ensureInitialized().hashValue(this as FileConfig); + } +} + +extension FileConfigValueCopy<$R, $Out> + on ObjectCopyWith<$R, FileConfig, $Out> { + FileConfigCopyWith<$R, FileConfig, $Out> get $asFileConfig => + $base.as((v, t, t2) => _FileConfigCopyWithImpl(v, t, t2)); +} + +abstract class FileConfigCopyWith<$R, $In extends FileConfig, $Out> + implements BaseConfigCopyWith<$R, $In, $Out> { + @override + $R call( + {String? cachePath, + bool? useGitCache, + String? gitCachePath, + String? flutterUrl, + bool? priviledgedAccess, + bool? runPubGetOnSdkChanges, + bool? updateVscodeSettings, + bool? updateGitIgnore}); + FileConfigCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t); +} + +class _FileConfigCopyWithImpl<$R, $Out> + extends ClassCopyWithBase<$R, FileConfig, $Out> + implements FileConfigCopyWith<$R, FileConfig, $Out> { + _FileConfigCopyWithImpl(super.value, super.then, super.then2); + + @override + late final ClassMapperBase $mapper = + FileConfigMapper.ensureInitialized(); + @override + $R call( + {Object? cachePath = $none, + Object? useGitCache = $none, + Object? gitCachePath = $none, + Object? flutterUrl = $none, + Object? priviledgedAccess = $none, + Object? runPubGetOnSdkChanges = $none, + Object? updateVscodeSettings = $none, + Object? updateGitIgnore = $none}) => + $apply(FieldCopyWithData({ + if (cachePath != $none) #cachePath: cachePath, + if (useGitCache != $none) #useGitCache: useGitCache, + if (gitCachePath != $none) #gitCachePath: gitCachePath, + if (flutterUrl != $none) #flutterUrl: flutterUrl, + if (priviledgedAccess != $none) #priviledgedAccess: priviledgedAccess, + if (runPubGetOnSdkChanges != $none) + #runPubGetOnSdkChanges: runPubGetOnSdkChanges, + if (updateVscodeSettings != $none) + #updateVscodeSettings: updateVscodeSettings, + if (updateGitIgnore != $none) #updateGitIgnore: updateGitIgnore + })); + @override + FileConfig $make(CopyWithData data) => FileConfig( + cachePath: data.get(#cachePath, or: $value.cachePath), + useGitCache: data.get(#useGitCache, or: $value.useGitCache), + gitCachePath: data.get(#gitCachePath, or: $value.gitCachePath), + flutterUrl: data.get(#flutterUrl, or: $value.flutterUrl), + priviledgedAccess: + data.get(#priviledgedAccess, or: $value.priviledgedAccess), + runPubGetOnSdkChanges: + data.get(#runPubGetOnSdkChanges, or: $value.runPubGetOnSdkChanges), + updateVscodeSettings: + data.get(#updateVscodeSettings, or: $value.updateVscodeSettings), + updateGitIgnore: data.get(#updateGitIgnore, or: $value.updateGitIgnore)); + + @override + FileConfigCopyWith<$R2, FileConfig, $Out2> $chain<$R2, $Out2>( + Then<$Out2, $R2> t) => + _FileConfigCopyWithImpl($value, $cast, t); +} + +class AppConfigMapper extends ClassMapperBase { + AppConfigMapper._(); + + static AppConfigMapper? _instance; + static AppConfigMapper ensureInitialized() { + if (_instance == null) { + MapperContainer.globals.use(_instance = AppConfigMapper._()); + FileConfigMapper.ensureInitialized(); + } + return _instance!; + } + + @override + final String id = 'AppConfig'; + + static bool? _$disableUpdateCheck(AppConfig v) => v.disableUpdateCheck; + static const Field _f$disableUpdateCheck = + Field('disableUpdateCheck', _$disableUpdateCheck, opt: true); + static DateTime? _$lastUpdateCheck(AppConfig v) => v.lastUpdateCheck; + static const Field _f$lastUpdateCheck = + Field('lastUpdateCheck', _$lastUpdateCheck, opt: true); + static String? _$cachePath(AppConfig v) => v.cachePath; + static const Field _f$cachePath = + Field('cachePath', _$cachePath, opt: true); + static bool? _$useGitCache(AppConfig v) => v.useGitCache; + static const Field _f$useGitCache = + Field('useGitCache', _$useGitCache, opt: true); + static String? _$gitCachePath(AppConfig v) => v.gitCachePath; + static const Field _f$gitCachePath = + Field('gitCachePath', _$gitCachePath, opt: true); + static String? _$flutterUrl(AppConfig v) => v.flutterUrl; + static const Field _f$flutterUrl = + Field('flutterUrl', _$flutterUrl, opt: true); + static bool? _$priviledgedAccess(AppConfig v) => v.priviledgedAccess; + static const Field _f$priviledgedAccess = + Field('priviledgedAccess', _$priviledgedAccess, opt: true); + static bool? _$runPubGetOnSdkChanges(AppConfig v) => v.runPubGetOnSdkChanges; + static const Field _f$runPubGetOnSdkChanges = + Field('runPubGetOnSdkChanges', _$runPubGetOnSdkChanges, opt: true); + static bool? _$updateVscodeSettings(AppConfig v) => v.updateVscodeSettings; + static const Field _f$updateVscodeSettings = + Field('updateVscodeSettings', _$updateVscodeSettings, opt: true); + static bool? _$updateGitIgnore(AppConfig v) => v.updateGitIgnore; + static const Field _f$updateGitIgnore = + Field('updateGitIgnore', _$updateGitIgnore, opt: true); + + @override + final MappableFields fields = const { + #disableUpdateCheck: _f$disableUpdateCheck, + #lastUpdateCheck: _f$lastUpdateCheck, + #cachePath: _f$cachePath, + #useGitCache: _f$useGitCache, + #gitCachePath: _f$gitCachePath, + #flutterUrl: _f$flutterUrl, + #priviledgedAccess: _f$priviledgedAccess, + #runPubGetOnSdkChanges: _f$runPubGetOnSdkChanges, + #updateVscodeSettings: _f$updateVscodeSettings, + #updateGitIgnore: _f$updateGitIgnore, + }; + @override + final bool ignoreNull = true; + + static AppConfig _instantiate(DecodingData data) { + return AppConfig( + disableUpdateCheck: data.dec(_f$disableUpdateCheck), + lastUpdateCheck: data.dec(_f$lastUpdateCheck), + cachePath: data.dec(_f$cachePath), + useGitCache: data.dec(_f$useGitCache), + gitCachePath: data.dec(_f$gitCachePath), + flutterUrl: data.dec(_f$flutterUrl), + priviledgedAccess: data.dec(_f$priviledgedAccess), + runPubGetOnSdkChanges: data.dec(_f$runPubGetOnSdkChanges), + updateVscodeSettings: data.dec(_f$updateVscodeSettings), + updateGitIgnore: data.dec(_f$updateGitIgnore)); + } + + @override + final Function instantiate = _instantiate; + + static AppConfig fromMap(Map map) { + return ensureInitialized().decodeMap(map); + } + + static AppConfig fromJson(String json) { + return ensureInitialized().decodeJson(json); + } +} + +mixin AppConfigMappable { + String toJson() { + return AppConfigMapper.ensureInitialized() + .encodeJson(this as AppConfig); + } + + Map toMap() { + return AppConfigMapper.ensureInitialized() + .encodeMap(this as AppConfig); + } + + AppConfigCopyWith get copyWith => + _AppConfigCopyWithImpl(this as AppConfig, $identity, $identity); + @override + String toString() { + return AppConfigMapper.ensureInitialized() + .stringifyValue(this as AppConfig); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (runtimeType == other.runtimeType && + AppConfigMapper.ensureInitialized() + .isValueEqual(this as AppConfig, other)); + } + + @override + int get hashCode { + return AppConfigMapper.ensureInitialized().hashValue(this as AppConfig); + } +} + +extension AppConfigValueCopy<$R, $Out> on ObjectCopyWith<$R, AppConfig, $Out> { + AppConfigCopyWith<$R, AppConfig, $Out> get $asAppConfig => + $base.as((v, t, t2) => _AppConfigCopyWithImpl(v, t, t2)); +} + +abstract class AppConfigCopyWith<$R, $In extends AppConfig, $Out> + implements FileConfigCopyWith<$R, $In, $Out> { + @override + $R call( + {bool? disableUpdateCheck, + DateTime? lastUpdateCheck, + String? cachePath, + bool? useGitCache, + String? gitCachePath, + String? flutterUrl, + bool? priviledgedAccess, + bool? runPubGetOnSdkChanges, + bool? updateVscodeSettings, + bool? updateGitIgnore}); + AppConfigCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t); +} + +class _AppConfigCopyWithImpl<$R, $Out> + extends ClassCopyWithBase<$R, AppConfig, $Out> + implements AppConfigCopyWith<$R, AppConfig, $Out> { + _AppConfigCopyWithImpl(super.value, super.then, super.then2); + + @override + late final ClassMapperBase $mapper = + AppConfigMapper.ensureInitialized(); + @override + $R call( + {Object? disableUpdateCheck = $none, + Object? lastUpdateCheck = $none, + Object? cachePath = $none, + Object? useGitCache = $none, + Object? gitCachePath = $none, + Object? flutterUrl = $none, + Object? priviledgedAccess = $none, + Object? runPubGetOnSdkChanges = $none, + Object? updateVscodeSettings = $none, + Object? updateGitIgnore = $none}) => + $apply(FieldCopyWithData({ + if (disableUpdateCheck != $none) + #disableUpdateCheck: disableUpdateCheck, + if (lastUpdateCheck != $none) #lastUpdateCheck: lastUpdateCheck, + if (cachePath != $none) #cachePath: cachePath, + if (useGitCache != $none) #useGitCache: useGitCache, + if (gitCachePath != $none) #gitCachePath: gitCachePath, + if (flutterUrl != $none) #flutterUrl: flutterUrl, + if (priviledgedAccess != $none) #priviledgedAccess: priviledgedAccess, + if (runPubGetOnSdkChanges != $none) + #runPubGetOnSdkChanges: runPubGetOnSdkChanges, + if (updateVscodeSettings != $none) + #updateVscodeSettings: updateVscodeSettings, + if (updateGitIgnore != $none) #updateGitIgnore: updateGitIgnore + })); + @override + AppConfig $make(CopyWithData data) => AppConfig( + disableUpdateCheck: + data.get(#disableUpdateCheck, or: $value.disableUpdateCheck), + lastUpdateCheck: data.get(#lastUpdateCheck, or: $value.lastUpdateCheck), + cachePath: data.get(#cachePath, or: $value.cachePath), + useGitCache: data.get(#useGitCache, or: $value.useGitCache), + gitCachePath: data.get(#gitCachePath, or: $value.gitCachePath), + flutterUrl: data.get(#flutterUrl, or: $value.flutterUrl), + priviledgedAccess: + data.get(#priviledgedAccess, or: $value.priviledgedAccess), + runPubGetOnSdkChanges: + data.get(#runPubGetOnSdkChanges, or: $value.runPubGetOnSdkChanges), + updateVscodeSettings: + data.get(#updateVscodeSettings, or: $value.updateVscodeSettings), + updateGitIgnore: data.get(#updateGitIgnore, or: $value.updateGitIgnore)); + + @override + AppConfigCopyWith<$R2, AppConfig, $Out2> $chain<$R2, $Out2>( + Then<$Out2, $R2> t) => + _AppConfigCopyWithImpl($value, $cast, t); +} + +class ProjectConfigMapper extends ClassMapperBase { + ProjectConfigMapper._(); + + static ProjectConfigMapper? _instance; + static ProjectConfigMapper ensureInitialized() { + if (_instance == null) { + MapperContainer.globals.use(_instance = ProjectConfigMapper._()); + FileConfigMapper.ensureInitialized(); + } + return _instance!; + } + + @override + final String id = 'ProjectConfig'; + + static String? _$flutter(ProjectConfig v) => v.flutter; + static const Field _f$flutter = + Field('flutter', _$flutter, opt: true); + static Map? _$flavors(ProjectConfig v) => v.flavors; + static const Field> _f$flavors = + Field('flavors', _$flavors, opt: true); + static String? _$cachePath(ProjectConfig v) => v.cachePath; + static const Field _f$cachePath = + Field('cachePath', _$cachePath, opt: true); + static bool? _$useGitCache(ProjectConfig v) => v.useGitCache; + static const Field _f$useGitCache = + Field('useGitCache', _$useGitCache, opt: true); + static String? _$gitCachePath(ProjectConfig v) => v.gitCachePath; + static const Field _f$gitCachePath = + Field('gitCachePath', _$gitCachePath, opt: true); + static String? _$flutterUrl(ProjectConfig v) => v.flutterUrl; + static const Field _f$flutterUrl = + Field('flutterUrl', _$flutterUrl, opt: true); + static bool? _$priviledgedAccess(ProjectConfig v) => v.priviledgedAccess; + static const Field _f$priviledgedAccess = + Field('priviledgedAccess', _$priviledgedAccess, opt: true); + static bool? _$runPubGetOnSdkChanges(ProjectConfig v) => + v.runPubGetOnSdkChanges; + static const Field _f$runPubGetOnSdkChanges = + Field('runPubGetOnSdkChanges', _$runPubGetOnSdkChanges, opt: true); + static bool? _$updateVscodeSettings(ProjectConfig v) => + v.updateVscodeSettings; + static const Field _f$updateVscodeSettings = + Field('updateVscodeSettings', _$updateVscodeSettings, opt: true); + static bool? _$updateGitIgnore(ProjectConfig v) => v.updateGitIgnore; + static const Field _f$updateGitIgnore = + Field('updateGitIgnore', _$updateGitIgnore, opt: true); + + @override + final MappableFields fields = const { + #flutter: _f$flutter, + #flavors: _f$flavors, + #cachePath: _f$cachePath, + #useGitCache: _f$useGitCache, + #gitCachePath: _f$gitCachePath, + #flutterUrl: _f$flutterUrl, + #priviledgedAccess: _f$priviledgedAccess, + #runPubGetOnSdkChanges: _f$runPubGetOnSdkChanges, + #updateVscodeSettings: _f$updateVscodeSettings, + #updateGitIgnore: _f$updateGitIgnore, + }; + @override + final bool ignoreNull = true; + + static ProjectConfig _instantiate(DecodingData data) { + return ProjectConfig( + flutter: data.dec(_f$flutter), + flavors: data.dec(_f$flavors), + cachePath: data.dec(_f$cachePath), + useGitCache: data.dec(_f$useGitCache), + gitCachePath: data.dec(_f$gitCachePath), + flutterUrl: data.dec(_f$flutterUrl), + priviledgedAccess: data.dec(_f$priviledgedAccess), + runPubGetOnSdkChanges: data.dec(_f$runPubGetOnSdkChanges), + updateVscodeSettings: data.dec(_f$updateVscodeSettings), + updateGitIgnore: data.dec(_f$updateGitIgnore)); + } + + @override + final Function instantiate = _instantiate; + + static ProjectConfig fromMap(Map map) { + return ensureInitialized().decodeMap(map); + } + + static ProjectConfig fromJson(String json) { + return ensureInitialized().decodeJson(json); + } +} + +mixin ProjectConfigMappable { + String toJson() { + return ProjectConfigMapper.ensureInitialized() + .encodeJson(this as ProjectConfig); + } + + Map toMap() { + return ProjectConfigMapper.ensureInitialized() + .encodeMap(this as ProjectConfig); + } + + ProjectConfigCopyWith + get copyWith => _ProjectConfigCopyWithImpl( + this as ProjectConfig, $identity, $identity); + @override + String toString() { + return ProjectConfigMapper.ensureInitialized() + .stringifyValue(this as ProjectConfig); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (runtimeType == other.runtimeType && + ProjectConfigMapper.ensureInitialized() + .isValueEqual(this as ProjectConfig, other)); + } + + @override + int get hashCode { + return ProjectConfigMapper.ensureInitialized() + .hashValue(this as ProjectConfig); + } +} + +extension ProjectConfigValueCopy<$R, $Out> + on ObjectCopyWith<$R, ProjectConfig, $Out> { + ProjectConfigCopyWith<$R, ProjectConfig, $Out> get $asProjectConfig => + $base.as((v, t, t2) => _ProjectConfigCopyWithImpl(v, t, t2)); +} + +abstract class ProjectConfigCopyWith<$R, $In extends ProjectConfig, $Out> + implements FileConfigCopyWith<$R, $In, $Out> { + MapCopyWith<$R, String, String, ObjectCopyWith<$R, String, String>>? + get flavors; + @override + $R call( + {String? flutter, + Map? flavors, + String? cachePath, + bool? useGitCache, + String? gitCachePath, + String? flutterUrl, + bool? priviledgedAccess, + bool? runPubGetOnSdkChanges, + bool? updateVscodeSettings, + bool? updateGitIgnore}); + ProjectConfigCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t); +} + +class _ProjectConfigCopyWithImpl<$R, $Out> + extends ClassCopyWithBase<$R, ProjectConfig, $Out> + implements ProjectConfigCopyWith<$R, ProjectConfig, $Out> { + _ProjectConfigCopyWithImpl(super.value, super.then, super.then2); + + @override + late final ClassMapperBase $mapper = + ProjectConfigMapper.ensureInitialized(); + @override + MapCopyWith<$R, String, String, ObjectCopyWith<$R, String, String>>? + get flavors => $value.flavors != null + ? MapCopyWith( + $value.flavors!, + (v, t) => ObjectCopyWith(v, $identity, t), + (v) => call(flavors: v)) + : null; + @override + $R call( + {Object? flutter = $none, + Object? flavors = $none, + Object? cachePath = $none, + Object? useGitCache = $none, + Object? gitCachePath = $none, + Object? flutterUrl = $none, + Object? priviledgedAccess = $none, + Object? runPubGetOnSdkChanges = $none, + Object? updateVscodeSettings = $none, + Object? updateGitIgnore = $none}) => + $apply(FieldCopyWithData({ + if (flutter != $none) #flutter: flutter, + if (flavors != $none) #flavors: flavors, + if (cachePath != $none) #cachePath: cachePath, + if (useGitCache != $none) #useGitCache: useGitCache, + if (gitCachePath != $none) #gitCachePath: gitCachePath, + if (flutterUrl != $none) #flutterUrl: flutterUrl, + if (priviledgedAccess != $none) #priviledgedAccess: priviledgedAccess, + if (runPubGetOnSdkChanges != $none) + #runPubGetOnSdkChanges: runPubGetOnSdkChanges, + if (updateVscodeSettings != $none) + #updateVscodeSettings: updateVscodeSettings, + if (updateGitIgnore != $none) #updateGitIgnore: updateGitIgnore + })); + @override + ProjectConfig $make(CopyWithData data) => ProjectConfig( + flutter: data.get(#flutter, or: $value.flutter), + flavors: data.get(#flavors, or: $value.flavors), + cachePath: data.get(#cachePath, or: $value.cachePath), + useGitCache: data.get(#useGitCache, or: $value.useGitCache), + gitCachePath: data.get(#gitCachePath, or: $value.gitCachePath), + flutterUrl: data.get(#flutterUrl, or: $value.flutterUrl), + priviledgedAccess: + data.get(#priviledgedAccess, or: $value.priviledgedAccess), + runPubGetOnSdkChanges: + data.get(#runPubGetOnSdkChanges, or: $value.runPubGetOnSdkChanges), + updateVscodeSettings: + data.get(#updateVscodeSettings, or: $value.updateVscodeSettings), + updateGitIgnore: data.get(#updateGitIgnore, or: $value.updateGitIgnore)); + + @override + ProjectConfigCopyWith<$R2, ProjectConfig, $Out2> $chain<$R2, $Out2>( + Then<$Out2, $R2> t) => + _ProjectConfigCopyWithImpl($value, $cast, t); +} diff --git a/lib/src/models/project_model.dart b/lib/src/models/project_model.dart index 45b30967..ee719875 100644 --- a/lib/src/models/project_model.dart +++ b/lib/src/models/project_model.dart @@ -25,14 +25,16 @@ class Project { final PubSpec? pubspec; - const - /// Creates a new instance of [Project]. /// /// The [config] parameter represents the configuration of the project. /// The [path] parameter is the directory path of the project. /// The [pubspec] parameter represents the pubspec.yaml file of the project. - Project({required this.config, required this.path, required this.pubspec}); + const Project({ + required this.config, + required this.path, + required this.pubspec, + }); /// Loads the Flutter project from the given [path]. /// @@ -47,8 +49,8 @@ class Project { final legacyConfig = ProjectConfig.loadFromPath(legacyConfigFile); if (legacyConfig != null && config != null) { - final legacyVersion = legacyConfig.flutterSdkVersion; - final version = config.flutterSdkVersion; + final legacyVersion = legacyConfig.flutter; + final version = config.flutter; if (legacyVersion != version) { logger @@ -83,7 +85,7 @@ class Project { /// /// Returns `null` if no version is pinned. FlutterVersion? get pinnedVersion { - final sdkVersion = config?.flutterSdkVersion; + final sdkVersion = config?.flutter; if (sdkVersion != null) { return FlutterVersion.parse(sdkVersion); } diff --git a/lib/src/runner.dart b/lib/src/runner.dart index c4383799..c63086f0 100644 --- a/lib/src/runner.dart +++ b/lib/src/runner.dart @@ -25,7 +25,7 @@ import 'utils/constants.dart'; import 'utils/context.dart'; import 'utils/deprecation_util.dart'; import 'utils/exceptions.dart'; -import 'version.g.dart'; +import 'version.dart'; /// Command Runner for FVM class FvmCommandRunner extends CommandRunner { @@ -62,9 +62,11 @@ class FvmCommandRunner extends CommandRunner { /// user. Future _checkForUpdates() async { try { + final lastUpdateCheck = ctx.lastUpdateCheck ?? DateTime.now(); if (ctx.updateCheckDisabled) return null; - final oneDayAgo = DateTime.now().subtract(const Duration(days: 1)); - if (ctx.lastUpdateCheck?.isBefore(oneDayAgo) ?? false) { + final oneDay = lastUpdateCheck.add(const Duration(days: 1)); + + if (DateTime.now().isBefore(oneDay)) { return null; } diff --git a/lib/src/services/base_service.dart b/lib/src/services/base_service.dart index ea0b3012..783f4ba3 100644 --- a/lib/src/services/base_service.dart +++ b/lib/src/services/base_service.dart @@ -2,6 +2,7 @@ import '../utils/context.dart'; abstract class ContextService { final FVMContext? _context; + const ContextService(FVMContext? context) : _context = context; /// Gets context, if no context is passed will get from scope diff --git a/lib/src/services/config_repository.dart b/lib/src/services/config_repository.dart index 0ba003c8..bbd29aca 100644 --- a/lib/src/services/config_repository.dart +++ b/lib/src/services/config_repository.dart @@ -1,5 +1,7 @@ import 'dart:io'; +import 'package:path/path.dart' as path; + import '../models/config_model.dart'; import '../utils/constants.dart'; import '../utils/extensions.dart'; @@ -12,11 +14,21 @@ const String flutterGitUrl = 'FLUTTER_GIT_URL'; class ConfigRepository { const ConfigRepository._(); - static AppConfig loadFile() { + static AppConfig load({AppConfig? overrides}) { + final appConfig = loadAppConfig(); + final envConfig = _loadEnvironment(); + final projectConfig = _loadProjectConfig(); + + return appConfig.merge(envConfig).merge(projectConfig).merge(overrides); + } + + static AppConfig loadAppConfig() { final appConfig = AppConfig.loadFromPath(_configPath); - if (appConfig != null) return appConfig; + if (appConfig == null) { + save(AppConfig.empty()); + } - return AppConfig.empty(); + return AppConfig.loadFromPath(_configPath)!; } static void save(AppConfig config) { @@ -25,79 +37,81 @@ class ConfigRepository { _configPath.file.write(jsonContents); } + static ProjectConfig? _loadProjectConfig({Directory? directory}) { + // Get directory, defined root or current + directory ??= Directory.current; + + // Checks if the directory is root + final isRootDir = path.rootPrefix(directory.path) == directory.path; + + // Gets project from directory + final projectConfig = ProjectConfig.loadFromPath(directory.path); + + // If project has a config return it + if (projectConfig != null) return projectConfig; + + // Return working directory if has reached root + if (isRootDir) return null; + + return _loadProjectConfig(directory: directory.parent); + } + static void update({ String? cachePath, - bool? useGitCache, String? gitCachePath, String? flutterUrl, bool? disableUpdateCheck, DateTime? lastUpdateCheck, + bool? priviledgedAccess, + bool? useGitCache, }) { - final currentConfig = loadFile(); - final newConfig = currentConfig.copyWith( + final currentConfig = loadAppConfig(); + final newConfig = AppConfig( + disableUpdateCheck: disableUpdateCheck, + lastUpdateCheck: lastUpdateCheck, cachePath: cachePath, useGitCache: useGitCache, gitCachePath: gitCachePath, flutterUrl: flutterUrl, - disableUpdateCheck: disableUpdateCheck, - lastUpdateCheck: lastUpdateCheck, + priviledgedAccess: priviledgedAccess, ); - save(newConfig); + save(currentConfig.copyWith.$merge(newConfig)); } - static Config loadEnv() { + static EnvConfig _loadEnvironment() { final environments = Platform.environment; - bool? gitCache; - String? gitCachePath; - String? flutterUrl; - String? cachePath; - bool? priviledgedAccess; + var config = EnvConfig.empty(); // Default to Flutter's environment variable if present; can still be overridden if (environments.containsKey(flutterGitUrl)) { - flutterUrl = environments[flutterGitUrl]; + config = config.copyWith(flutterUrl: environments[flutterGitUrl]); } - for (final variable in ConfigKeys.values) { - final value = environments[variable.envKey]; + for (final envVar in ConfigKeys.values) { + final value = environments[envVar.envKey]; final legacyFvmHome = environments['FVM_HOME']; - if (variable == ConfigKeys.cachePath) { - cachePath = value ?? legacyFvmHome; - break; + if (envVar == ConfigKeys.cachePath) { + config = config.copyWith(cachePath: value ?? legacyFvmHome); } if (value == null) continue; - if (variable == ConfigKeys.useGitCache) { - gitCache = stringToBool(value); - break; + if (envVar == ConfigKeys.useGitCache) { + config = config.copyWith(useGitCache: stringToBool(value)); } - if (variable == ConfigKeys.gitCachePath) { - gitCachePath = value; - break; + if (envVar == ConfigKeys.gitCachePath) { + config = config.copyWith(gitCachePath: value); } - if (variable == ConfigKeys.flutterUrl) { - flutterUrl = value; - break; - } - - if (variable == ConfigKeys.priviledgedAccess) { - priviledgedAccess = stringToBool(value); - break; + if (envVar == ConfigKeys.flutterUrl) { + config = config.copyWith(flutterUrl: value); } } - return Config( - cachePath: cachePath, - useGitCache: gitCache, - gitCachePath: gitCachePath, - flutterUrl: flutterUrl, - priviledgedAccess: priviledgedAccess, - ); + return config; } static String get _configPath => kAppConfigFile; diff --git a/lib/src/services/project_service.dart b/lib/src/services/project_service.dart index 4288dd7f..a403d593 100644 --- a/lib/src/services/project_service.dart +++ b/lib/src/services/project_service.dart @@ -8,6 +8,7 @@ import '../utils/context.dart'; import '../utils/extensions.dart'; import '../utils/pretty_json.dart'; import 'base_service.dart'; +import 'logger_service.dart'; /// Flutter Project Services /// APIs for interacting with local Flutter projects @@ -32,6 +33,8 @@ class ProjectService extends ContextService { // Get directory, defined root or current directory ??= Directory(context.workingDirectory); + logger.detail('Searching for project in ${directory.path}'); + // Checks if the directory is root final isRootDir = path.rootPrefix(directory.path) == directory.path; @@ -39,10 +42,18 @@ class ProjectService extends ContextService { final project = Project.loadFromPath(directory.path); // If project has a config return it - if (project.hasConfig && project.hasPubspec) return project; + if (project.hasConfig && project.hasPubspec) { + logger.detail('Found project in ${project.path}'); + + return project; + } // Return working directory if has reached root - if (isRootDir) return Project.loadFromPath(context.workingDirectory); + if (isRootDir) { + logger.detail('No project found in ${context.workingDirectory}'); + + return Project.loadFromPath(context.workingDirectory); + } return findAncestor(directory: directory.parent); } @@ -73,14 +84,16 @@ class ProjectService extends ContextService { String? flutterSdkVersion, bool? updateVscodeSettings, }) { - final newConfig = project.config ?? ProjectConfig(); + final currentConfig = project.config ?? ProjectConfig.empty(); - final config = newConfig.copyWith( - flutterSdkVersion: flutterSdkVersion, - updateVscodeSettings: updateVscodeSettings, + final newConfig = ProjectConfig( + flutter: flutterSdkVersion, flavors: flavors, + updateVscodeSettings: updateVscodeSettings, ); + final config = currentConfig.copyWith.$merge(newConfig); + // Update flavors final configFile = project.configPath.file; final legacyConfigFile = project.legacyConfigPath.file; diff --git a/lib/src/services/releases_service/releases_client.dart b/lib/src/services/releases_service/releases_client.dart index 7f180340..472ebc27 100644 --- a/lib/src/services/releases_service/releases_client.dart +++ b/lib/src/services/releases_service/releases_client.dart @@ -28,7 +28,6 @@ String getReleasesUrl(String platform) { class FlutterReleases { static Releases? _cacheReleasesRes; - const FlutterReleases._(); /// Gets Flutter SDK Releases diff --git a/lib/src/utils/constants.dart b/lib/src/utils/constants.dart index 17b18430..0d9baa50 100644 --- a/lib/src/utils/constants.dart +++ b/lib/src/utils/constants.dart @@ -78,3 +78,25 @@ String get _configHome { // same as XDG specification would specify as fallback. return join(kUserHome, '.config'); } + +/// List of common CI environment variables +const kCiEnvironmentVariables = [ + // General CI indicator, used by many CI providers + 'CI', + // Travis CI + 'TRAVIS', + // CircleCI + 'CIRCLECI', + // GitHub Actions + 'GITHUB_ACTIONS', + // GitLab CI + 'GITLAB_CI', + // Jenkins + 'JENKINS_URL', + // Bamboo + 'BAMBOO_BUILD_NUMBER', + // TeamCity + 'TEAMCITY_VERSION', + // Azure Pipelines + 'TF_BUILD', +]; diff --git a/lib/src/utils/context.dart b/lib/src/utils/context.dart index 2b5ede1b..0e220a7e 100644 --- a/lib/src/utils/context.dart +++ b/lib/src/utils/context.dart @@ -5,6 +5,7 @@ import 'package:path/path.dart'; import 'package:scope/scope.dart'; import '../models/config_model.dart'; +import '../services/base_service.dart'; import '../services/cache_service.dart'; import '../services/config_repository.dart'; import '../services/flutter_service.dart'; @@ -19,8 +20,8 @@ final contextKey = ScopeKey(); /// /// Generators are allowed to return `null`, in which case the context will /// store the `null` value as the value for that type. -// ignore: avoid-dynamic -typedef Generator = dynamic Function(FVMContext context); + +typedef Generator = T Function(FVMContext context); FVMContext get ctx => use(contextKey, withDefault: () => FVMContext.main); @@ -38,11 +39,14 @@ class FVMContext { /// Flag to determine if context is running in a test final bool isTest; + /// Generators for dependencies + final Map? generators; + /// App config final AppConfig config; - /// Generators for dependencies - final Map? generators; + /// Environment variables + final Map environment; /// Generated values final Map _dependencies = {}; @@ -51,28 +55,24 @@ class FVMContext { String? id, AppConfig? configOverrides, String? workingDirectory, - Map overrides = const {}, + Map generatorOverrides = const {}, + Map? environmentOverrides, bool isTest = false, }) { workingDirectory ??= Directory.current.path; - // Load config from file in config path - final projectConfig = ProjectConfig.loadFromPath(workingDirectory); - final envConfig = ConfigRepository.loadEnv(); - - final appConfig = ConfigRepository.loadFile() - .mergeConfig(envConfig) - .mergeConfig(projectConfig); + // Load all configs + final config = ConfigRepository.load(overrides: configOverrides); - // Merge config from file with env config - final config = appConfig.merge(configOverrides); + final level = isTest ? Level.error : Level.info; - final level = isTest ? Level.warning : Level.info; + final environment = {...Platform.environment, ...?environmentOverrides}; return FVMContext._( id: id ?? 'MAIN', workingDirectory: workingDirectory, config: config, + environment: environment, generators: { LoggerService: (context) => LoggerService( level: level, @@ -82,7 +82,7 @@ class FVMContext { FlutterService: FlutterService.new, CacheService: CacheService.new, GlobalVersionService: GlobalVersionService.new, - ...overrides, + ...generatorOverrides, }, isTest: isTest, ); @@ -94,18 +94,25 @@ class FVMContext { required this.id, required this.workingDirectory, required this.config, + required this.environment, this.generators = const {}, this.isTest = false, }); - /// Environment variables - Map get environment => Platform.environment; - /// Directory where FVM is stored String get fvmDir => config.cachePath ?? kAppDirHome; /// Flag to determine if should use git cache - bool get gitCache => config.useGitCache ?? true; + bool get gitCache { + return config.useGitCache != null ? config.useGitCache! : true; + } + + /// Run pub get on sdk changes + bool get runPubGetOnSdkChanges { + return config.runPubGetOnSdkChanges != null + ? config.runPubGetOnSdkChanges! + : true; + } String get gitCachePath { // If git cache is not overriden use default based on fvmDir @@ -121,10 +128,16 @@ class FVMContext { DateTime? get lastUpdateCheck => config.lastUpdateCheck; /// Flutter SDK Path - bool get updateCheckDisabled => config.disableUpdateCheck ?? false; + bool get updateCheckDisabled { + return config.disableUpdateCheck != null + ? config.disableUpdateCheck! + : false; + } /// Priviledged access - bool get priviledgedAccess => config.priviledgedAccess ?? true; + bool get priviledgedAccess { + return config.priviledgedAccess != null ? config.priviledgedAccess! : true; + } /// Where Default Flutter SDK is stored String get globalCacheLink => join(fvmDir, 'default'); @@ -138,6 +151,12 @@ class FVMContext { /// Config path String get configPath => kAppConfigFile; + /// Checks if the current environment is a Continuous Integration (CI) environment. + /// This is done by checking for common CI environment variables. + bool get isCI { + return kCiEnvironmentVariables.any(Platform.environment.containsKey); + } + T get() { if (_dependencies.containsKey(T)) { return _dependencies[T] as T; diff --git a/lib/src/utils/deprecation_util.dart b/lib/src/utils/deprecation_util.dart index 8db92a7b..d2022dd7 100644 --- a/lib/src/utils/deprecation_util.dart +++ b/lib/src/utils/deprecation_util.dart @@ -1,45 +1,12 @@ -import 'dart:convert'; import 'dart:io'; import 'package:mason_logger/mason_logger.dart'; -import 'package:path/path.dart'; import '../models/config_model.dart'; -import '../services/config_repository.dart'; import '../services/logger_service.dart'; -import 'constants.dart'; -import 'context.dart'; void deprecationWorkflow() { _warnDeprecatedEnvVars(); - final fvmDir = ctx.fvmDir; - final legacySettingsFile = File(join(fvmDir, '.settings')); - - if (!legacySettingsFile.existsSync()) { - return; - } - - final payload = legacySettingsFile.readAsStringSync(); - try { - final settings = jsonDecode(payload); - final settingsCachePath = settings['cachePath'] as String?; - if (settingsCachePath != null && settingsCachePath != fvmDir) { - var appConfig = ConfigRepository.loadFile(); - appConfig = appConfig.copyWith(cachePath: fvmDir); - ConfigRepository.save(appConfig); - legacySettingsFile.deleteSync(recursive: true); - logger.success( - 'We have moved the settings file ${legacySettingsFile.path}' - 'Your settings have been migrated to $kAppConfigFile' - 'Your cachePath is now $settingsCachePath. FVM will exit now. Please run the command again.', - ); - // Exit to prevent execution with wrong cache path - exit(ExitCode.success.code); - } - } catch (_) { - logger.warn('Could not parse legacy settings file'); - legacySettingsFile.deleteSync(recursive: true); - } } // TODO: Removed on future version of the app diff --git a/lib/src/version.dart b/lib/src/version.dart new file mode 100644 index 00000000..a28987a6 --- /dev/null +++ b/lib/src/version.dart @@ -0,0 +1,2 @@ +// Generated code. Do not modify. +const packageVersion = '3.0.10'; diff --git a/lib/src/version.g.dart b/lib/src/version.g.dart deleted file mode 100644 index 5e8ece4c..00000000 --- a/lib/src/version.g.dart +++ /dev/null @@ -1,3 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -const packageVersion = '3.0.12'; diff --git a/lib/src/workflows/resolve_dependencies.workflow.dart b/lib/src/workflows/resolve_dependencies.workflow.dart index 509a1c51..018d40f3 100644 --- a/lib/src/workflows/resolve_dependencies.workflow.dart +++ b/lib/src/workflows/resolve_dependencies.workflow.dart @@ -5,6 +5,7 @@ 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 '../utils/context.dart'; import '../utils/exceptions.dart'; Future resolveDependenciesWorkflow( @@ -12,15 +13,13 @@ Future resolveDependenciesWorkflow( CacheFlutterVersion version, { required bool force, }) async { - if (version.notSetup) return; + if (version.isNotSetup) return; if (project.dartToolVersion == version.flutterSdkVersion) { return; } - final runPubGetOnSdkChanges = project.config?.runPubGetOnSdkChanges ?? true; - - if (!runPubGetOnSdkChanges) { + if (!ctx.runPubGetOnSdkChanges) { logger ..info('Skipping "pub get" because of config setting.') ..spacer; diff --git a/lib/src/workflows/use_version.workflow.dart b/lib/src/workflows/use_version.workflow.dart index 0956a56d..5dfb5b87 100644 --- a/lib/src/workflows/use_version.workflow.dart +++ b/lib/src/workflows/use_version.workflow.dart @@ -27,7 +27,7 @@ Future useVersionWorkflow({ required Project project, bool force = false, bool skipSetup = false, - bool resolveDependencies = true, + bool runPubGetOnSdkChange = true, String? flavor, }) async { // If project use check that is Flutter project @@ -47,7 +47,7 @@ Future useVersionWorkflow({ ..detail('Project path: ${project.path}') ..detail(''); - if (!skipSetup && version.notSetup) { + if (!skipSetup && version.isNotSetup) { await setupFlutterWorkflow(version); } @@ -62,7 +62,7 @@ Future useVersionWorkflow({ await _checkGitignore(updatedProject, force: force); - if (resolveDependencies) { + if (runPubGetOnSdkChange) { await resolveDependenciesWorkflow(updatedProject, version, force: force); } diff --git a/pubspec.lock b/pubspec.lock index 3430c4fc..fb25e9b6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -17,6 +17,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.13.0" + ansicolor: + dependency: transitive + description: + name: ansicolor + sha256: "8bf17a8ff6ea17499e40a2d2542c2f481cd7615760c6d34065cb22bfd22e6880" + url: "https://pub.dev" + source: hosted + version: "2.0.2" archive: dependency: transitive description: @@ -49,6 +57,86 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + url: "https://pub.dev" + source: hosted + version: "4.0.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" + url: "https://pub.dev" + source: hosted + version: "2.4.8" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" + url: "https://pub.dev" + source: hosted + version: "7.3.0" + build_verify: + dependency: "direct dev" + description: + name: build_verify + sha256: abbb9b9eda076854ac1678d284c053a5ec608e64da741d0801f56d4bbea27e23 + url: "https://pub.dev" + source: hosted + version: "3.1.0" + build_version: + dependency: "direct dev" + description: + name: build_version + sha256: "4e8eafbf722eac3bd60c8d38f108c04bd69b80100f8792b32be3407725c7fa6a" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: fedde275e0a6b798c3296963c5cd224e3e1b55d0e478d5b7e65e6b540f363a0e + url: "https://pub.dev" + source: hosted + version: "8.9.1" characters: dependency: transitive description: @@ -97,6 +185,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 + url: "https://pub.dev" + source: hosted + version: "4.10.0" collection: dependency: transitive description: @@ -145,6 +241,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + dart_mappable: + dependency: "direct main" + description: + name: dart_mappable + sha256: "7b6d38ae95f1ae8ffa65df9a5464f14b56c2de94699a035202ca4cd3a0ba249e" + url: "https://pub.dev" + source: hosted + version: "4.2.0" + dart_mappable_builder: + dependency: "direct dev" + description: + name: dart_mappable_builder + sha256: "98c058f7e80a98ea42d357d888ed1648d96bedac8b16872b58fc7024faefcdfe" + url: "https://pub.dev" + source: hosted + version: "4.2.0" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" + url: "https://pub.dev" + source: hosted + version: "2.3.2" date_format: dependency: "direct main" description: @@ -169,6 +289,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.4" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" frontend_server_client: dependency: transitive description: @@ -193,6 +321,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + graphs: + dependency: transitive + description: + name: graphs + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" + source: hosted + version: "2.3.1" grinder: dependency: "direct dev" description: @@ -481,6 +617,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" source_map_stack_trace: dependency: transitive description: @@ -521,6 +665,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" string_scanner: dependency: transitive description: @@ -569,6 +721,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" tint: dependency: "direct main" description: @@ -577,6 +737,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + type_plus: + dependency: transitive + description: + name: type_plus + sha256: "2e33cfac2e129297d5874567bdf7587502ec359881e9318551e014d91b02f84a" + url: "https://pub.dev" + source: hosted + version: "2.1.0" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e1b1282a..2c7ee21d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: fvm description: A simple cli to manage Flutter SDK versions per project. Support channels, releases, and local cache for fast switching between versions. -version: 3.0.12 +version: 3.0.10 homepage: https://github.com/leoafarias/fvm environment: @@ -28,6 +28,8 @@ dependencies: stack_trace: ^1.11.1 pubspec: ^2.3.0 jsonc: ^0.0.3 + dart_mappable: ^4.2.0 + dev_dependencies: cli_pkg: ^2.5.0 @@ -37,4 +39,8 @@ dev_dependencies: crypto: ^3.0.3 http: ^1.1.0 dart_code_metrics_presets: ^2.9.0 + build_runner: ^2.4.8 + dart_mappable_builder: ^4.2.0 + build_verify: ^3.1.0 + build_version: ^2.1.1 diff --git a/test/commands/flutter_command_test.dart b/test/commands/flutter_command_test.dart index 69432cd2..85778f70 100644 --- a/test/commands/flutter_command_test.dart +++ b/test/commands/flutter_command_test.dart @@ -28,7 +28,7 @@ void main() { expect(project.pinnedVersion?.name, channel); expect( - cacheVersion?.notSetup, + cacheVersion?.isNotSetup, false, reason: 'Version should be setup', ); diff --git a/test/complete_workflow_test.dart b/test/complete_workflow_test.dart index e9c81845..6c43c8ad 100644 --- a/test/complete_workflow_test.dart +++ b/test/complete_workflow_test.dart @@ -29,7 +29,7 @@ void main() { expect(existingChannel, channel); expect( - cacheVersion?.notSetup, + cacheVersion?.isNotSetup, true, reason: 'Version should not be setup', ); @@ -63,7 +63,7 @@ void main() { expect(project.pinnedVersion?.name, channel); expect( - cacheVersion?.notSetup, + cacheVersion?.isNotSetup, true, reason: 'Version should not be setup', ); diff --git a/test/ensure_build_test.dart b/test/ensure_build_test.dart new file mode 100644 index 00000000..df5b8253 --- /dev/null +++ b/test/ensure_build_test.dart @@ -0,0 +1,6 @@ +import 'package:build_verify/build_verify.dart'; +import 'package:test/test.dart'; + +void main() { + test('ensure_build', expectBuildClean); +} diff --git a/test/utils/helpers_test.dart b/test/utils/helpers_test.dart index a7923f3e..67319107 100644 --- a/test/utils/helpers_test.dart +++ b/test/utils/helpers_test.dart @@ -1,7 +1,7 @@ import 'dart:io'; import 'package:fvm/src/utils/helpers.dart'; -import 'package:fvm/src/version.g.dart'; +import 'package:fvm/src/version.dart'; import 'package:path/path.dart'; import 'package:test/test.dart'; import 'package:yaml/yaml.dart'; diff --git a/tool/grind.dart b/tool/grind.dart index f25c3c83..312f500b 100644 --- a/tool/grind.dart +++ b/tool/grind.dart @@ -5,8 +5,6 @@ import 'package:cli_pkg/cli_pkg.dart' as pkg; import 'package:fvm/src/utils/http.dart'; import 'package:grinder/grinder.dart'; import 'package:path/path.dart' as path; -import 'package:pub_semver/pub_semver.dart'; -import 'package:pubspec/pubspec.dart'; import '../test/testing_helpers/prepare_test_environment.dart'; import 'homebrew.dart'; @@ -29,39 +27,6 @@ void main(List args) { grind(args); } -@Task('Builds the version file') -Future buildVersion() async { - final args = context.invocation.arguments; - final versionArg = args.getOption('version'); - - final pubspec = await PubSpec.load(Directory.current); - Version? version = pubspec.version; - - if (versionArg != null) { - version = Version.parse(versionArg); - } - - if (version != pubspec.version) { - var newPubSpec = pubspec.copy(version: version); - await newPubSpec.save(Directory.current); - } - - final versionFile = File( - path.join(Directory.current.path, 'lib', 'src', 'version.g.dart'), - ); - - if (!versionFile.existsSync()) { - versionFile.createSync(recursive: true); - } - - String fileContent = '// GENERATED CODE - DO NOT MODIFY BY HAND\n\n'; - fileContent += "const packageVersion = '$version';\n"; - - versionFile.writeAsStringSync(fileContent); - - log('Version $version written to version.g.dart'); -} - @Task('Get all releases') Future getReleases() async { String owner = 'leoafarias'; @@ -88,7 +53,6 @@ Future getReleases() async { } @Task('Prepare test environment') -@Depends(buildVersion) void testSetup() { final testDir = Directory(getTempTestDir()); if (testDir.existsSync()) {