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

feat: v0.0.2 #1

Merged
merged 11 commits into from
Sep 18, 2021
30 changes: 16 additions & 14 deletions .github/workflows/lockpick.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,44 +19,46 @@ on:
jobs:
build:
runs-on: ubuntu-latest
container:
image: google/dart:2.14.2

steps:
- uses: actions/checkout@v2.3.4
- uses: subosito/flutter-action@v1.5.0
- uses: actions/checkout@v2

- name: Install Dependencies
run: flutter pub get
run: pub get

- name: Format
run: flutter format --set-exit-if-changed .
run: dartfmt --dry-run --set-exit-if-changed lib test

- name: Analyze
run: flutter analyze lib test

- name: Verify Build
run: flutter pub run test --run-skipped -t pull-request-only
run: dart analyze --fatal-infos --fatal-warnings .

- name: Run Tests
run: flutter test -x pull-request-only --no-pub --coverage --test-randomize-ordering-seed random
- name: Run tests
run: dart test --coverage=coverage && pub run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.packages --report-on=lib

- name: Check Code Coverage
uses: VeryGoodOpenSource/very_good_coverage@v1.1.1
with:
path: coverage/lcov.info
exclude: "**/*.g.dart **/*.gen.dart"

pana:
runs-on: ubuntu-latest
container:
image: google/dart:2.14.2

steps:
- uses: actions/checkout@v2.3.4
- uses: subosito/flutter-action@v1.5.0

- name: Install Dependencies
run: |
flutter packages get
flutter pub global activate pana 0.19.1
pub get
pub global activate pana 0.19.1

- name: Verify Pub Score
run: |
PANA=$(pana . --no-warning); PANA_SCORE=$(echo $PANA | sed -n "s/.*Points: \([0-9]*\)\/\([0-9]*\)./\1\/\2/p")
PANA=$(pub global run pana . --no-warning); PANA_SCORE=$(echo $PANA | sed -n "s/.*Points: \([0-9]*\)\/\([0-9]*\)./\1\/\2/p")
echo "score: $PANA_SCORE"
IFS='/'; read -a SCORE_ARR <<< "$PANA_SCORE"; SCORE=SCORE_ARR[0]; TOTAL=SCORE_ARR[1]
if (( $SCORE < $TOTAL )); then echo "minimum score not met!"; exit 1; fi
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
"version": "0.2.0",
"configurations": [
{
"name": "lockpick",
"name": "Run sync command",
"request": "launch",
"type": "dart",
"program": "bin/lockpick.dart",
"args": ["/Users/jeroen/Projects/work/jasje_leggen"]
"args": ["sync"]
}
]
}
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# CHANGELOG

This file is a manually maintained list of changes for each release. Feel
free to add your changes here when sending pull requests.

## 0.0.2 - 2021-09-18

- feat: improved cli implementation
- feat: add help menu

## 0.0.1 - 2021-09-17

- feat: initial proof of concept version
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,20 @@
[![style: very good analysis][very_good_analysis_badge]][very_good_analysis_link]
[![License: MIT][license_badge]][license_link]

A CLI for syncing Dart dependency versions between pubspec.yaml and pubspec.lock files.
A CLI for syncing Dart dependency versions between pubspec.yaml and pubspec.lock files. 🔒

## Usage

```sh
# Activate lockpick
pub global activate lockpick

# See usage information
lockpick --help

# Sync dependency versions in the current directory
lockpick sync ./
```

[license_badge]: https://img.shields.io/badge/license-MIT-blue.svg
[license_link]: https://opensource.org/licenses/MIT
Expand Down
78 changes: 12 additions & 66 deletions bin/lockpick.dart
Original file line number Diff line number Diff line change
@@ -1,71 +1,17 @@
import 'dart:io';

import 'package:lockpick/lockpick.dart';
import 'package:lockpick/src/logger/logger.dart';
import 'package:path/path.dart' as path;
import 'package:lockpick/src/command_runner.dart';
import 'package:universal_io/io.dart';

Future<void> main(List<String> args) async {
log('--- Lockpick CLI ---');

final workingDirectory = resolveDirectory(args.isEmpty ? null : args.first);

// Check and change working directory.
if (!workingDirectory.isCurrent) {
if (!workingDirectory.existsSync()) {
throw Exception(
'Working directory "${workingDirectory.path}" does not exist.',
);
}

log('Changing working directory to "${workingDirectory.path}".');
Directory.current = workingDirectory;
}

// Throw error if working directory does not contain a "pubspec.yaml" file.
if (!workingDirectory.containsFile('pubspec.yaml')) {
throw Exception(
'Current directory ("${workingDirectory.path}") does not contain '
'a "pubspec.yaml" file.',
);
}

// Throw error if working directory does not contain a "pubspec.lock" file.
if (!workingDirectory.containsFile('pubspec.lock')) {
throw Exception(
'Current directory ("${workingDirectory.path}") does not contain '
'a "pubspec.lock" file.',
);
}

await LockpickCli(
launchConfig: LaunchConfig(
yamlFile: File(path.join(workingDirectory.path, 'pubspec.yaml')),
lockFile: File(path.join(workingDirectory.path, 'pubspec.lock')),
),
).run();
}

Directory resolveDirectory(String? pathArg) {
if (pathArg == null) {
return Directory.current;
} else {
if (path.isAbsolute(pathArg)) {
return Directory(pathArg);
} else {
return Directory(
path.absolute(
path.join(
path.current,
pathArg,
),
),
);
}
}
await _flushThenExit(await LockpickCommandRunner().run(args));
}

extension on Directory {
bool get isCurrent => absolute.path == Directory.current.absolute.path;
bool containsFile(String name) =>
listSync().any((entity) => path.split(entity.path).last == name);
/// Flushes the stdout and stderr streams, then exits the program with the given
/// status code.
///
/// This returns a Future that will never complete, since the program will have
/// exited already. This is useful to prevent Future chains from proceeding
/// after you've decided to exit.
Future _flushThenExit(int status) {
return Future.wait<void>([stdout.close(), stderr.close()])
.then<void>((_) => exit(status));
}
12 changes: 12 additions & 0 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## Usage

```sh
# Activate lockpick
pub global activate lockpick

# See usage information
lockpick --help

# Sync dependency versions in the current directory
lockpick sync ./
```
13 changes: 10 additions & 3 deletions lib/lockpick.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
/// A CLI for syncing Dart dependency versions between pubspec.yaml and
/// pubspec.lock files. 🔒
///
/// ```sh
/// # Activate lockpick
/// pub global activate lockpick
///
/// # See usage information
/// lockpick --help
/// ```
library lockpick;

export 'src/lockpick.dart';
export 'src/models/models.dart';
79 changes: 79 additions & 0 deletions lib/src/command_runner.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:io/ansi.dart';
import 'package:io/io.dart';
import 'package:lockpick/src/commands/commands.dart';
import 'package:lockpick/src/extensions/extensions.dart';
import 'package:lockpick/src/version.dart';
import 'package:mason/mason.dart';

/// {@template lockpick_command_runner}
/// A CLI for syncing Dart dependency versions between pubspec.yaml and
/// pubspec.lock files.
/// {@endtemplate}
class LockpickCommandRunner extends CommandRunner<int> {
/// {@macro lockpick_command_runner}
LockpickCommandRunner({
Logger? logger,
}) : _logger = logger ?? Logger(),
super(
'lockpick',
'A CLI for syncing Dart dependency versions '
'between pubspec.yaml and pubspec.lock files. 🔒',
) {
argParser
..addFlag(
'version',
negatable: false,
help: 'Print the current version of lockpick.',
)
..addVerboseFlag();
addCommand(SyncCommand(logger: logger));
}

/// Standard timeout duration for the CLI.
static const timeout = Duration(milliseconds: 500);

final Logger _logger;

@override
Future<int> run(Iterable<String> args) async {
try {
final _argResults = parse(args);
return await runCommand(_argResults) ?? ExitCode.success.code;
} on FormatException catch (e, stackTrace) {
_logger
..err(e.message)
..err('$stackTrace')
..info('')
..info(usage);
return ExitCode.usage.code;
} on UsageException catch (e) {
_logger
..err(e.message)
..info('')
..info(usage);
return ExitCode.usage.code;
} catch (e, st) {
_logger
..err(styleBold.wrap('Unexpected error occurred'))
..err(e.toString())
..err(lightGray.wrap(st.toString()));
return ExitCode.software.code;
}
}

@override
Future<int?> runCommand(ArgResults topLevelResults) async {
if (topLevelResults['version'] == true) {
_logger.info('lockpick version: $packageVersion');
return ExitCode.success.code;
} else {
final exitCode = await super.runCommand(topLevelResults);
if (exitCode == ExitCode.success.code) {
_logger.success('Done!');
}
return exitCode;
}
}
}
1 change: 1 addition & 0 deletions lib/src/commands/commands.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'sync.dart';