Skip to content

Commit

Permalink
add!: proper sub commands for bump and log commands (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
marvin-kolja authored Jan 31, 2024
1 parent ac25b19 commit e1e59c7
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 33 deletions.
3 changes: 3 additions & 0 deletions lib/src/cli/cider_cli.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,7 @@ class CiderCli extends CommandRunner<int> {
@override
Future<int> run(Iterable<String> args) =>
ErrorInterceptor(console).run(() => super.run(args));

@override
void printUsage() => console.out.writeln(usage);
}
51 changes: 24 additions & 27 deletions lib/src/cli/command/bump_command.dart
Original file line number Diff line number Diff line change
@@ -1,44 +1,41 @@
import 'package:args/command_runner.dart';
import 'package:cider/src/project.dart';
import 'package:cider/src/cli/command/bump_sub_command.dart';
import 'package:cider/src/cli/command/cider_command.dart';
import 'package:version_manipulation/mutations.dart';

enum BumpType {
breaking(BumpBreaking(), 'Bump the breaking version'),
major(BumpMajor(), 'Bump the major version'),
minor(BumpMinor(), 'Bump the minor version'),
patch(BumpPatch(), 'Bump the patch version'),
build(BumpBuild(), 'Bump the build version'),
pre(BumpPreRelease(), 'Bump the pre-release version'),
release(Release(), 'Bump the release version');

const BumpType(this.mutation, this.description);

final VersionMutation mutation;
final String description;
}

class BumpCommand extends CiderCommand {
BumpCommand(super.printer) {
mutations.keys.forEach(argParser.addCommand);
argParser
..addFlag('keep-build', help: 'Keep the existing build')
..addFlag('bump-build', help: 'Also bump the build')
..addOption('build',
help: 'Sets the build to the given value', defaultsTo: '')
..addOption('pre',
help: 'Sets the pre-release to the given value', defaultsTo: '');
for (final type in BumpType.values) {
addSubcommand(
BumpSubCommand(type.name, type.description, type.mutation, printer),
);
}
}

static const mutations = <String, VersionMutation>{
'breaking': BumpBreaking(),
'build': BumpBuild(),
'major': BumpMajor(),
'minor': BumpMinor(),
'patch': BumpPatch(),
'pre': BumpPreRelease(),
'release': Release(),
};

@override
final name = 'bump';
@override
final description = 'Bump project version';

@override
Future<int> exec(Project project) async {
final part = argResults!.command?.name ??
(throw ArgumentError('Version part must be specified'));
final result = await project.bumpVersion(mutations[part]!,
keepBuild: argResults!['keep-build'],
bumpBuild: argResults!['bump-build'],
build: argResults!['build'],
pre: argResults!['pre']);
printer.out.writeln(result);
return 0;
throw UsageException(
'Bump command can only be used with subcommands', usage);
}
}
37 changes: 37 additions & 0 deletions lib/src/cli/command/bump_sub_command.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:cider/src/cli/console.dart';
import 'package:cider/src/project.dart';
import 'package:cider/src/cli/command/cider_command.dart';
import 'package:version_manipulation/mutations.dart';

class BumpSubCommand extends CiderCommand {
BumpSubCommand(this.name, this.description, this.mutation, Console printer)
: super(printer) {
argParser
..addFlag('keep-build', help: 'Keep the existing build')
..addFlag('bump-build', help: 'Also bump the build')
..addOption('build',
help: 'Sets the build to the given value', defaultsTo: '')
..addOption('pre',
help: 'Sets the pre-release to the given value', defaultsTo: '');
}

@override
final String name;

@override
final String description;

final VersionMutation mutation;

@override
Future<int> exec(Project project) async {
final result = await project.bumpVersion(mutation,
keepBuild: argResults!['keep-build'],
bumpBuild: argResults!['bump-build'],
build: argResults!['build'],
pre: argResults!['pre']);
printer.out.writeln(result);

return 0;
}
}
3 changes: 3 additions & 0 deletions lib/src/cli/command/cider_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ abstract class CiderCommand extends Command<int> {
tagTemplate: tagTemplate,
keepEmptyUnreleased: keepEmptyUnreleased);
}

@override
printUsage() => printer.out.writeln(usage);
}

extension _Map on Map {
Expand Down
27 changes: 24 additions & 3 deletions lib/src/cli/command/log_command.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
import 'package:args/command_runner.dart';
import 'package:cider/src/cli/command/cider_command.dart';
import 'package:cider/src/cli/command/log_sub_command.dart';
import 'package:cider/src/project.dart';

enum LogType {
fix('Add a new bug fix to the changelog'),
add('Add a new feature to the changelog'),
change('Add a new change to the changelog'),
deprecate('Add a new deprecation to the changelog'),
remove('Add a new removal to the changelog'),
security('Add a new security fix to the changelog');

const LogType(this.description);

final String description;
}

class LogCommand extends CiderCommand {
LogCommand(super.printer);
LogCommand(super.printer) {
for (final type in LogType.values) {
addSubcommand(
LogSubCommand(type.name, type.description, type, printer),
);
}
}

@override
final name = 'log';
Expand All @@ -12,7 +33,7 @@ class LogCommand extends CiderCommand {

@override
Future<int> exec(Project project) async {
await project.addUnreleased(argResults!.rest.first, argResults!.rest[1]);
return 0;
throw UsageException(
'Log command can only be used with subcommands', usage);
}
}
24 changes: 24 additions & 0 deletions lib/src/cli/command/log_sub_command.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import 'package:cider/src/cli/command/log_command.dart';
import 'package:cider/src/cli/console.dart';
import 'package:cider/src/project.dart';
import 'package:cider/src/cli/command/cider_command.dart';

class LogSubCommand extends CiderCommand {
LogSubCommand(this.name, this.description, this.type, Console printer)
: super(printer);

@override
final String name;

@override
final String description;

final LogType type;

@override
Future<int> exec(Project project) async {
await project.addUnreleased(type.name, argResults!.rest.first);

return 0;
}
}
30 changes: 27 additions & 3 deletions test/functional_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import 'package:path/path.dart' as path;
import 'package:pubspec_parse/pubspec_parse.dart';
import 'package:test/test.dart';

import 'subcommands_usage.expect.dart';

void main() {
late Directory temp;
final out = BufferChannel();
Expand Down Expand Up @@ -232,14 +234,36 @@ I love my dog.
expect(err.buffer.toString().trim(),
'The next version must be higher than the current one.');
});
test('version part must be specified', () async {
test('incorrect usage', () async {
final code = await run(['bump']);
expect(code, 65);
expect(err.buffer.toString().trim(), 'Version part must be specified');
expect(code, 64);
expect(err.buffer.toString().trim().split('\n').first,
'Usage: cider bump <subcommand> [arguments]');
});
test('help usage', () async {
final code = await run(['bump', '--help']);
expect(code, 0);
expect(err.buffer.toString(), isEmpty);
expectSubcommandsUsage(out.buffer.toString(), command: 'bump');
});
});
});

group('Log', () {
test('incorrect usage', () async {
final code = await run(['log']);
expect(code, 64);
expect(err.buffer.toString().trim().split('\n').first,
'Usage: cider log <subcommand> [arguments]');
});
test('help usage', () async {
final code = await run(['log', '--help']);
expect(code, 0);
expect(err.buffer.toString(), isEmpty);
expectSubcommandsUsage(out.buffer.toString(), command: 'log');
});
});

group('Find Root', () {
test('valid root', () async {
final code = await cli.run(['version']);
Expand Down
10 changes: 10 additions & 0 deletions test/subcommands_usage.expect.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'package:test/test.dart';

void expectSubcommandsUsage(String output, {String? command}) {
if (command != null) {
expect(output, contains('Usage: cider $command <subcommand> [arguments]'));
}
expect(output, contains('-h, --help Print this usage information.'));
expect(output, contains('Available subcommands:'));
expect(output, contains('Run "cider help" to see global options.'));
}

0 comments on commit e1e59c7

Please sign in to comment.