-
Notifications
You must be signed in to change notification settings - Fork 152
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: re-write cutler to be more testable
I removed the 'rebase' command for now since it was dead. 'rebase' should be re-written later to just print the commands needed since having it actually drive the rebase was a dream. I separated "Repo" from "Checkout" and removed the global config object. I moved to using a global logger and package scoped to match other packages. I added a bunch of tests. This still doesn't have 100% coverage but it should be 100% testable now.
- Loading branch information
Showing
16 changed files
with
498 additions
and
393 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1 @@ | ||
include: package:very_good_analysis/analysis_options.5.0.0.yaml | ||
linter: | ||
rules: | ||
# avoid_print can be removed now that we have a logger. | ||
avoid_print: false | ||
include: package:very_good_analysis/analysis_options.5.0.0.yaml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,109 +1,12 @@ | ||
import 'dart:io'; | ||
|
||
import 'package:args/args.dart'; | ||
import 'package:args/command_runner.dart'; | ||
import 'package:cutler/commands/commands.dart'; | ||
import 'package:cutler/config.dart'; | ||
import 'package:cutler/model.dart'; | ||
import 'package:mason_logger/mason_logger.dart'; | ||
import 'package:path/path.dart' as p; | ||
|
||
class Cutler extends CommandRunner<int> { | ||
Cutler({Logger? logger}) | ||
: _logger = logger ?? Logger(), | ||
super('cutler', 'A tool for maintaining forks of Flutter.') { | ||
addCommand(RebaseCommand(logger: _logger)); | ||
addCommand(VersionsCommand(logger: _logger)); | ||
|
||
argParser | ||
..addFlag('verbose', abbr: 'v') | ||
..addOption( | ||
'root', | ||
help: 'Directory in which to find checkouts.', | ||
) | ||
..addOption( | ||
'flutter-channel', | ||
defaultsTo: 'stable', | ||
help: 'Upstream channel to propose rebasing onto.', | ||
) | ||
..addFlag('dry-run', defaultsTo: true, help: 'Do not actually run git.') | ||
..addFlag('update', defaultsTo: true, help: 'Update checkouts.'); | ||
} | ||
|
||
final Logger _logger; | ||
|
||
Iterable<String> missingDirectories(String rootDir) { | ||
return Repo.values.map((repo) => '$rootDir/${repo.path}').where( | ||
(path) => !Directory(path).existsSync(), | ||
); | ||
} | ||
|
||
// This behavior belongs in the Dart SDK somewhere. | ||
String findPackageRoot() { | ||
// e.g. `dart run bin/cutler.dart` | ||
final scriptPath = Platform.script.path; | ||
if (scriptPath.endsWith('.dart')) { | ||
final cutlerBin = p.dirname(Platform.script.path); | ||
return p.dirname(cutlerBin); | ||
} | ||
// `dart run` pre-compiles into a snapshot and then runs, e.g. | ||
// .../packages/cutler/.dart_tool/pub/bin/cutler/cutler.dart-3.0.2.snapshot | ||
if (scriptPath.endsWith('.snapshot') && scriptPath.contains('.dart_tool')) { | ||
return scriptPath.split('.dart_tool').first; | ||
} | ||
throw UnimplementedError('Could not find package root.'); | ||
} | ||
|
||
String fallbackRootDir() { | ||
final cutlerRoot = findPackageRoot(); | ||
final packagesDir = p.dirname(cutlerRoot); | ||
final shorebirdDir = p.dirname(packagesDir); | ||
final fallbackDirectories = <String>[ | ||
Directory.current.path, | ||
p.dirname(shorebirdDir), | ||
// Internal checkouts use a _shorebird wrapper directory. | ||
p.dirname(p.dirname(shorebirdDir)), | ||
]; | ||
for (final directory in fallbackDirectories) { | ||
if (missingDirectories(directory).isEmpty) { | ||
print('Using $directory as checkouts root.'); | ||
return directory; | ||
} | ||
} | ||
_logger.err('Failed to find a valid checkouts root, tried:\n' | ||
'${fallbackDirectories.join('\n')}'); | ||
return ''; // Returning an invalid directory will cause validation to fail. | ||
} | ||
|
||
@override | ||
ArgResults parse(Iterable<String> args) { | ||
final results = super.parse(args); | ||
|
||
final rootDir = results['root'] as String? ?? fallbackRootDir(); | ||
|
||
final missingDirs = missingDirectories(rootDir); | ||
if (missingDirs.isNotEmpty) { | ||
_logger | ||
..err('Could not find a valid checkouts root.') | ||
..err('--root must be a directory containing the ' | ||
'following:\n${Repo.values.map((r) => r.path).join('\n')}') | ||
..err('Missing directories:\n${missingDirs.join('\n')}'); | ||
exit(1); | ||
} | ||
|
||
config = Config( | ||
checkoutsRoot: expandUser(rootDir), | ||
verbose: results['verbose'] as bool, | ||
dryRun: results['dry-run'] as bool, | ||
doUpdate: results['update'] as bool, | ||
flutterChannel: results['flutter-channel'] as String, | ||
); | ||
|
||
return results; | ||
} | ||
} | ||
import 'package:cutler/cutler.dart'; | ||
import 'package:cutler/logger.dart'; | ||
import 'package:scoped/scoped.dart'; | ||
|
||
void main(List<String> args) { | ||
print(Platform.script.path); | ||
Cutler().run(args); | ||
runScoped( | ||
() => Cutler().run(args), | ||
values: { | ||
loggerRef, | ||
}, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,45 @@ | ||
import 'package:args/command_runner.dart'; | ||
import 'package:cutler/checkout.dart'; | ||
import 'package:cutler/config.dart'; | ||
import 'package:cutler/git_extensions.dart'; | ||
import 'package:cutler/model.dart'; | ||
import 'package:mason_logger/mason_logger.dart'; | ||
import 'package:cutler/cutler.dart'; | ||
import 'package:cutler/logger.dart'; | ||
|
||
/// Base class for Cutler subcommands. | ||
abstract class CutlerCommand extends Command<int> { | ||
/// Constructs a new [CutlerCommand]. | ||
CutlerCommand({ | ||
required this.logger, | ||
}); | ||
CutlerCommand(); | ||
|
||
/// The logger to use for this command. | ||
final Logger logger; | ||
/// The global config, set during argument parsing. | ||
Config get config => (runner! as Cutler).config; | ||
|
||
/// The checkout objects | ||
late final Checkouts checkouts; | ||
|
||
/// The Flutter checkout. | ||
Checkout get flutter => checkouts.flutter; | ||
|
||
/// The Engine checkout. | ||
Checkout get engine => checkouts.engine; | ||
|
||
/// The Shorebird checkout. | ||
Checkout get shorebird => checkouts.shorebird; | ||
|
||
/// The Buildroot checkout. | ||
Checkout get buildroot => checkouts.buildroot; | ||
|
||
/// The Dart checkout. | ||
Checkout get dart => checkouts.dart; | ||
|
||
/// Update the repos if needed. | ||
void updateReposIfNeeded(Config config) { | ||
if (config.doUpdate) { | ||
final progress = logger.progress('Updating checkouts...'); | ||
for (final repo in Repo.values) { | ||
progress.update('Updating ${repo.name}'); | ||
repo.fetchAll(); | ||
} | ||
progress.complete('Checkouts updated!'); | ||
if (!config.doUpdate) { | ||
return; | ||
} | ||
final progress = logger.progress('Updating checkouts...'); | ||
for (final checkout in checkouts.values) { | ||
progress.update('Updating ${checkout.name}'); | ||
checkout.fetchAll(); | ||
} | ||
progress.complete('Checkouts updated!'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1 @@ | ||
export 'rebase_command.dart'; | ||
export 'versions_command.dart'; |
Oops, something went wrong.