Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
feat(very_good_flutter_plugin_hooks): define Dart and Very Good CLI c…
Browse files Browse the repository at this point in the history
…lasses (#149)
  • Loading branch information
alestiago authored Jan 30, 2024
1 parent b328e19 commit 2aa7e0c
Show file tree
Hide file tree
Showing 10 changed files with 724 additions and 1 deletion.
8 changes: 8 additions & 0 deletions brick/hooks/lib/src/cli/cli.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// Collection of command line interfaces (CLIs).
///
/// This library abstracts some CLIs to facilitate interacting with them.
library cli;

export 'command_line.dart';
export 'dart_cli.dart';
export 'very_good_cli.dart';
70 changes: 70 additions & 0 deletions brick/hooks/lib/src/cli/command_line.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import 'dart:async';
import 'dart:io';
import 'package:mason/mason.dart';
import 'package:meta/meta.dart';

/// [Process.run] function signature.
typedef RunProcess = Future<ProcessResult> Function(
String executable,
List<String> arguments, {
String? workingDirectory,
bool runInShell,
});

/// Starts a process and runs it non-interactively to completion.
///
/// Used for overriding the default [Process.run] implementation
/// during testing.
@visibleForTesting
RunProcess? runProcess;

/// Abstraction for running commands via command-line.
abstract class CommandLine {
/// Runs the specified [cmd] with the provided [args].
///
/// Throws a [ProcessException] if the process fails.
static Future<ProcessResult> run(
String cmd,
List<String> args, {
required Logger logger,
bool throwOnError = true,
String? workingDirectory,
}) async {
logger.detail('Running: $cmd with $args');
final runner = runProcess ?? Process.run;
final result = await runner(
cmd,
args,
workingDirectory: workingDirectory,
runInShell: true,
);
logger
..detail('stdout:\n${result.stdout}')
..detail('stderr:\n${result.stderr}');

if (throwOnError) {
_throwIfProcessFailed(result, cmd, args);
}
return result;
}

static void _throwIfProcessFailed(
ProcessResult pr,
String process,
List<String> args,
) {
if (pr.exitCode != 0) {
final values = {
'Standard out': pr.stdout.toString().trim(),
'Standard error': pr.stderr.toString().trim(),
}..removeWhere((k, v) => v.isEmpty);

var message = 'Unknown error';
if (values.isNotEmpty) {
message = values.entries.map((e) => '${e.key}:\n${e.value}').join('\n');
}

throw ProcessException(process, args, message, pr.exitCode);
}
}
}
62 changes: 62 additions & 0 deletions brick/hooks/lib/src/cli/dart_cli.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import 'package:mason/mason.dart';
import 'package:very_good_flutter_plugin_hooks/src/cli/cli.dart';

/// A wrapper around the Dart Command Line Interface (CLI).
///
/// The Dart CLI is part of the Dart SDK.
///
/// See also:
///
/// * [The Dart command-line tool documentation](https://dart.dev/tools/dart-tool)
/// * [The Dart command-line source code](https://github.com/dart-lang/sdk/tree/main/pkg/dartdev)
class DartCli {
const DartCli._();

/// A singleton instance of [DartCli].
static const instance = DartCli._();

static const _executableName = 'dart';

/// Determine whether dart is installed.
Future<bool> isInstalled({required Logger logger}) async {
try {
await CommandLine.run(
_executableName,
['--version'],
logger: logger,
);
return true;
} catch (_) {
return false;
}
}

/// Idiomatically format Dart source code.
Future<void> format({
required Logger logger,
String cwd = '.',
}) async {
await CommandLine.run(
_executableName,
['format'],
workingDirectory: cwd,
logger: logger,
);
}

/// Apply automated fixes to Dart source code.
///
/// Enabling [apply] applies the proposed changes.
Future<void> fix({
required Logger logger,
bool apply = false,
String cwd = '.',
}) async {
await CommandLine.run(
_executableName,
['fix', if (apply) '--apply'],
workingDirectory: cwd,
logger: logger,
);
}
}
47 changes: 47 additions & 0 deletions brick/hooks/lib/src/cli/very_good_cli.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import 'package:mason/mason.dart';
import 'package:very_good_flutter_plugin_hooks/src/cli/cli.dart';

/// A wrapper around the Very Good Command Line Interface (CLI).
///
/// See also:
///
/// * [The Very Good CLI documentation](https://cli.vgv.dev/)
class VeryGoodCli {
const VeryGoodCli._();

/// A singleton instance of [VeryGoodCli].
static const instance = VeryGoodCli._();

static const _executableName = 'very_good';

/// Determine whether dart is installed.
Future<bool> isInstalled({required Logger logger}) async {
try {
await CommandLine.run(
_executableName,
['--version'],
logger: logger,
);
return true;
} catch (_) {
return false;
}
}

/// Get packages in a Dart or Flutter project.
///
/// Enabling [recursive] installs dependencies recursively for all nested
/// packages.
Future<void> packagesGet({
required Logger logger,
String cwd = '.',
bool recursive = false,
}) async {
await CommandLine.run(
_executableName,
['packages', 'get', if (recursive) '--recursive'],
workingDirectory: cwd,
logger: logger,
);
}
}
2 changes: 2 additions & 0 deletions brick/hooks/lib/very_good_flutter_plugin_hooks.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/// Mason hooks for the Very Good Flutter Plugin brick.
library very_good_flutter_plugin_hooks;
3 changes: 2 additions & 1 deletion brick/hooks/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
name: very_good_flutter_plugins_hooks
name: very_good_flutter_plugin_hooks

environment:
sdk: ">=3.1.0 <4.0.0"

dependencies:
mason: ^0.1.0-dev.50
meta: ^1.11.0

dev_dependencies:
mocktail: ^1.0.0
Expand Down
Loading

0 comments on commit 2aa7e0c

Please sign in to comment.