Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flag to exit with error instead of asking for interaction #712

Merged
merged 18 commits into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 3.2.0

* Adds support for skipping input requests by @Rexios80. Input requests are skipped when:
* The `--fvm-skip-input` flag is passed
* Running in CI
* Exits with `ExitCode.unavailable` if the request to install a Flutter version is denied by @Rexios80

## 3.1.7

* Display the configured version in the `fvm list` command by @digoreis
Expand Down
11 changes: 10 additions & 1 deletion bin/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,16 @@ import 'package:fvm/src/utils/context.dart';
import 'package:scope/scope.dart';

Future<void> main(List<String> args) async {
final scope = Scope()..value(contextKey, FVMContext.create(args: args));
final editableArgs = List<String>.from(args);
final skipInput = editableArgs.remove('--fvm-skip-input');
final scope = Scope()
..value(
contextKey,
FVMContext.create(
args: editableArgs,
skipInput: skipInput,
),
);

await _flushThenExit(
await scope.run(() async => FvmCommandRunner().run((args))),
Expand Down
2 changes: 2 additions & 0 deletions docs/pages/documentation/guides/basic-commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ Sets a specific Flutter SDK version for a project, ensuring environment consiste
- `-s, --skip-setup`: Omits Flutter setup post-installation for expedited process.
- `--skip-pub-get`: Skips resolving dependencies (`flutter pub get`) after switching Flutter SDK.

- `--fvm-skip-input`: Skips requests for user input and uses default values.

### Examples

**Setting a Specific Version**:
Expand Down
27 changes: 24 additions & 3 deletions lib/src/services/logger_service.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:io';

import 'package:dart_console/dart_console.dart';
import 'package:interact/interact.dart' as interact;
Expand Down Expand Up @@ -63,19 +64,39 @@ class LoggerService extends ContextService {
return progress;
}

bool confirm(String? message, {bool? defaultValue}) {
bool confirm(String? message, {bool? defaultValue, bool? ciDefaultValue}) {
// When running tests, always return true.
if (context.isTest) return true;

if (context.skipInput) {
if (ciDefaultValue != null) {
return ciDefaultValue;
} else if (defaultValue != null) {
return defaultValue;
}
exit(ExitCode.usage.code);
}

return interact.Confirm(prompt: message ?? '', defaultValue: defaultValue)
.interact();
}

String select(String? message, {required List<String> options}) {
String select(
String? message, {
required List<String> options,
int? defaultSelection,
}) {
if (context.skipInput) {
if (defaultSelection != null) {
return options[defaultSelection];
}
exit(ExitCode.usage.code);
}

final selection = interact.Select(
prompt: message ?? '',
options: options,
initialIndex: 0,
initialIndex: defaultSelection ?? 0,
).interact();

return options[selection];
Expand Down
11 changes: 10 additions & 1 deletion lib/src/utils/context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class FVMContext with FVMContextMappable {

final List<String> args;

/// True if the `--fvm-skip-input` flag was passed to the command
final bool _skipInput;

/// Generated values
final Map<Type, dynamic> _dependencies = {};

Expand All @@ -68,13 +71,15 @@ class FVMContext with FVMContextMappable {
required this.config,
required this.environment,
required this.args,
required bool skipInput,
required this.generators,
this.isTest = false,
});
}) : _skipInput = skipInput;

static FVMContext create({
String? id,
List<String>? args,
bool? skipInput,
AppConfig? configOverrides,
String? workingDirectory,
Map<Type, dynamic>? generatorOverrides,
Expand All @@ -96,6 +101,7 @@ class FVMContext with FVMContextMappable {
config: config,
environment: environment,
args: args ?? [],
skipInput: skipInput ?? false,
generators: {
LoggerService: (context) => LoggerService(
level: level,
Expand Down Expand Up @@ -189,6 +195,9 @@ class FVMContext with FVMContextMappable {
return kCiEnvironmentVariables.any(Platform.environment.containsKey);
}

@MappableField()
bool get skipInput => isCI || _skipInput;

T get<T>() {
if (_dependencies.containsKey(T)) {
return _dependencies[T] as T;
Expand Down
13 changes: 13 additions & 0 deletions lib/src/utils/context.mapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ class FVMContextMapper extends ClassMapperBase<FVMContext> {
Field('environment', _$environment);
static List<String> _$args(FVMContext v) => v.args;
static const Field<FVMContext, List<String>> _f$args = Field('args', _$args);
static bool _$_skipInput(FVMContext v) => v._skipInput;
static const Field<FVMContext, bool> _f$_skipInput =
Field('_skipInput', _$_skipInput, key: 'skipInput');
static Map<Type, ContextService Function(FVMContext)> _$generators(
FVMContext v) =>
v.generators;
Expand Down Expand Up @@ -83,6 +86,9 @@ class FVMContextMapper extends ClassMapperBase<FVMContext> {
Field('configPath', _$configPath);
static bool _$isCI(FVMContext v) => v.isCI;
static const Field<FVMContext, bool> _f$isCI = Field('isCI', _$isCI);
static bool _$skipInput(FVMContext v) => v.skipInput;
static const Field<FVMContext, bool> _f$skipInput =
Field('skipInput', _$skipInput);

@override
final MappableFields<FVMContext> fields = const {
Expand All @@ -91,6 +97,7 @@ class FVMContextMapper extends ClassMapperBase<FVMContext> {
#config: _f$config,
#environment: _f$environment,
#args: _f$args,
#_skipInput: _f$_skipInput,
#generators: _f$generators,
#isTest: _f$isTest,
#fvmDir: _f$fvmDir,
Expand All @@ -107,6 +114,7 @@ class FVMContextMapper extends ClassMapperBase<FVMContext> {
#versionsCachePath: _f$versionsCachePath,
#configPath: _f$configPath,
#isCI: _f$isCI,
#skipInput: _f$skipInput,
};

static FVMContext _instantiate(DecodingData data) {
Expand All @@ -116,6 +124,7 @@ class FVMContextMapper extends ClassMapperBase<FVMContext> {
config: data.dec(_f$config),
environment: data.dec(_f$environment),
args: data.dec(_f$args),
skipInput: data.dec(_f$_skipInput),
generators: data.dec(_f$generators),
isTest: data.dec(_f$isTest));
}
Expand Down Expand Up @@ -187,6 +196,7 @@ abstract class FVMContextCopyWith<$R, $In extends FVMContext, $Out>
AppConfig? config,
Map<String, String>? environment,
List<String>? args,
bool? skipInput,
Map<Type, ContextService Function(FVMContext)>? generators,
bool? isTest});
FVMContextCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(Then<$Out2, $R2> t);
Expand Down Expand Up @@ -230,6 +240,7 @@ class _FVMContextCopyWithImpl<$R, $Out>
AppConfig? config,
Map<String, String>? environment,
List<String>? args,
bool? skipInput,
Map<Type, ContextService Function(FVMContext)>? generators,
bool? isTest}) =>
$apply(FieldCopyWithData({
Expand All @@ -238,6 +249,7 @@ class _FVMContextCopyWithImpl<$R, $Out>
if (config != null) #config: config,
if (environment != null) #environment: environment,
if (args != null) #args: args,
if (skipInput != null) #skipInput: skipInput,
if (generators != null) #generators: generators,
if (isTest != null) #isTest: isTest
}));
Expand All @@ -249,6 +261,7 @@ class _FVMContextCopyWithImpl<$R, $Out>
config: data.get(#config, or: $value.config),
environment: data.get(#environment, or: $value.environment),
args: data.get(#args, or: $value.args),
skipInput: data.get(#skipInput, or: $value._skipInput),
generators: data.get(#generators, or: $value.generators),
isTest: data.get(#isTest, or: $value.isTest));

Expand Down
3 changes: 2 additions & 1 deletion lib/src/workflows/ensure_cache.workflow.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,11 @@ Future<CacheFlutterVersion> ensureCacheWorkflow(
final shouldInstallConfirmed = logger.confirm(
'Would you like to install it now?',
defaultValue: true,
ciDefaultValue: false,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was the reason I added this

);

if (!shouldInstallConfirmed) {
exit(ExitCode.success.code);
exit(ExitCode.unavailable.code);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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.1.7
version: 3.2.0
homepage: https://github.com/leoafarias/fvm

environment:
Expand Down
Loading