Skip to content

Commit

Permalink
[flutter_migrate] Start command and executables (#2735)
Browse files Browse the repository at this point in the history
* [flutter_migrate] Start command

* Sync with upstream changes

* Integrate with compute and add E2E tests

* E2E tests passing

* Resolve hangs, add help messages

* Use CommandRunner

* Cleanup hooks to prevent hang

* Formatting

* Softer requirements on test matching to ignore order

* Null safety, address minor comments

* Address comments

* Cleanup and logging improvements

* format, normalize

* Kick tests

* Fix tests

* Improve win test robustness

* Windows perms copyall

* Fix directory typo bug

* takeown command in CI

* Add logging for windows

* windows command debug logging

* Skip running on unsupported flutter versions

* Add main.dart

* Bots memory, dynamic flutter executable

* Different temp dir

* Takeown of main.dart

* test adjustments

* Analyzer

* Increase resources to dart_unit_tests

* Remove logging
  • Loading branch information
GaryQian authored Dec 27, 2022
1 parent a978884 commit e425eea
Show file tree
Hide file tree
Showing 15 changed files with 1,109 additions and 49 deletions.
28 changes: 14 additions & 14 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,19 +128,6 @@ task:
- else
- echo "Only run in presubmit"
- fi
- name: dart_unit_tests
env:
matrix:
CHANNEL: "master"
CHANNEL: "stable"
unit_test_script:
- ./script/tool_runner.sh test --exclude=script/configs/dart_unit_tests_exceptions.yaml
pathified_unit_test_script:
# Run tests with path-based dependencies to ensure that publishing
# the changes won't break tests of other packages in the repository
# that depend on it.
- ./script/tool_runner.sh make-deps-path-based --target-dependencies-with-non-breaking-updates
- $PLUGIN_TOOL_COMMAND test --run-on-dirty-packages --exclude=script/configs/dart_unit_tests_exceptions.yaml
- name: analyze
env:
matrix:
Expand Down Expand Up @@ -256,7 +243,7 @@ task:
zone: us-central1-a
namespace: default
cpu: 4
memory: 12G
memory: 16G
matrix:
### Android tasks ###
- name: android-platform_tests
Expand Down Expand Up @@ -320,6 +307,19 @@ task:
- cd ../..
- flutter packages get
- dart testing/web_benchmarks_test.dart
- name: dart_unit_tests
env:
matrix:
CHANNEL: "master"
CHANNEL: "stable"
unit_test_script:
- ./script/tool_runner.sh test --exclude=script/configs/dart_unit_tests_exceptions.yaml
pathified_unit_test_script:
# Run tests with path-based dependencies to ensure that publishing
# the changes won't break tests of other packages in the repository
# that depend on it.
- ./script/tool_runner.sh make-deps-path-based --target-dependencies-with-non-breaking-updates
- $PLUGIN_TOOL_COMMAND test --run-on-dirty-packages --exclude=script/configs/dart_unit_tests_exceptions.yaml

# ARM macOS tasks.
task:
Expand Down
6 changes: 5 additions & 1 deletion packages/flutter_migrate/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ any migrations that are broken.

## Usage

The core command sequence to use is `start`, `apply`.
To run the tool enter the root directory of your flutter project and run:

`dart run <path_to_flutter_migrate_package>/bin/flutter_migrate.dart <subcommand> [parameters]`

The core subcommand sequence to use is `start`, `apply`.

* `start` will generate a migration that will be staged in the `migration_staging_directory`
in your project home. This command may take some time to complete depending on network speed.
Expand Down
9 changes: 9 additions & 0 deletions packages/flutter_migrate/bin/flutter_migrate.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter_migrate/executable.dart' as executable;

void main(List<String> args) {
executable.main(args);
}
95 changes: 95 additions & 0 deletions packages/flutter_migrate/lib/executable.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:io' as io;

import 'package:args/args.dart';
import 'package:args/command_runner.dart';

import 'src/base/command.dart';
import 'src/base/file_system.dart';
import 'src/base_dependencies.dart';

import 'src/commands/abandon.dart';
import 'src/commands/apply.dart';
import 'src/commands/start.dart';
import 'src/commands/status.dart';

Future<void> main(List<String> args) async {
final bool veryVerbose = args.contains('-vv');
final bool verbose =
args.contains('-v') || args.contains('--verbose') || veryVerbose;

final MigrateBaseDependencies baseDependencies = MigrateBaseDependencies();

final List<MigrateCommand> commands = <MigrateCommand>[
MigrateStartCommand(
verbose: verbose,
logger: baseDependencies.logger,
fileSystem: baseDependencies.fileSystem,
processManager: baseDependencies.processManager,
),
MigrateStatusCommand(
verbose: verbose,
logger: baseDependencies.logger,
fileSystem: baseDependencies.fileSystem,
processManager: baseDependencies.processManager,
),
MigrateAbandonCommand(
logger: baseDependencies.logger,
fileSystem: baseDependencies.fileSystem,
terminal: baseDependencies.terminal,
processManager: baseDependencies.processManager),
MigrateApplyCommand(
verbose: verbose,
logger: baseDependencies.logger,
fileSystem: baseDependencies.fileSystem,
terminal: baseDependencies.terminal,
processManager: baseDependencies.processManager),
];

final MigrateCommandRunner runner = MigrateCommandRunner();

commands.forEach(runner.addCommand);
await runner.run(args);

await _exit(0, baseDependencies,
shutdownHooks: baseDependencies.fileSystem.shutdownHooks);
await baseDependencies.fileSystem.dispose();
}

/// Simple extension of a CommandRunner to provide migrate specific global flags.
class MigrateCommandRunner extends CommandRunner<void> {
MigrateCommandRunner()
: super(
'flutter',
'Migrates legacy flutter projects to modern versions.',
) {
argParser.addFlag('verbose',
abbr: 'v',
negatable: false,
help: 'Noisy logging, including all shell commands executed.');
}

@override
ArgParser get argParser => _argParser;
final ArgParser _argParser = ArgParser();
}

Future<int> _exit(int code, MigrateBaseDependencies baseDependencies,
{required ShutdownHooks shutdownHooks}) async {
// Run shutdown hooks before flushing logs
await shutdownHooks.runShutdownHooks(baseDependencies.logger);

final Completer<void> completer = Completer<void>();

// Give the task / timer queue one cycle through before we hard exit.
Timer.run(() {
io.exit(code);
});

await completer.future;
return code;
}
15 changes: 15 additions & 0 deletions packages/flutter_migrate/lib/src/base/command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@

import 'package:args/command_runner.dart';

import 'logger.dart';
import 'project.dart';

enum ExitStatus {
success,
warning,
fail,
killed,
}

const String flutterNoPubspecMessage = 'Error: No pubspec.yaml file found.\n'
'This command should be run from the root of your Flutter project.';

class CommandResult {
const CommandResult(this.exitStatus);

Expand Down Expand Up @@ -50,6 +56,7 @@ abstract class MigrateCommand extends Command<void> {
@override
Future<void> run() async {
await runCommand();
return;
}

Future<CommandResult> runCommand();
Expand All @@ -71,4 +78,12 @@ abstract class MigrateCommand extends Command<void> {

/// Gets the parsed command-line option named [name] as an `int`.
int? intArg(String name) => argResults?[name] as int?;

bool validateWorkingDirectory(FlutterProject project, Logger logger) {
if (!project.pubspecFile.existsSync()) {
logger.printError(flutterNoPubspecMessage);
return false;
}
return true;
}
}
87 changes: 87 additions & 0 deletions packages/flutter_migrate/lib/src/base_dependencies.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:io';

import 'package:process/process.dart';

import 'base/common.dart';
import 'base/file_system.dart';
import 'base/io.dart';
import 'base/logger.dart';
import 'base/signals.dart';
import 'base/terminal.dart';

/// Initializes the boilerplate dependencies needed by the migrate tool.
class MigrateBaseDependencies {
MigrateBaseDependencies() {
processManager = const LocalProcessManager();
fileSystem = LocalFileSystem(
LocalSignals.instance, Signals.defaultExitSignals, ShutdownHooks());

stdio = Stdio();
terminal = AnsiTerminal(stdio: stdio);

final LoggerFactory loggerFactory = LoggerFactory(
outputPreferences: OutputPreferences(
wrapText: stdio.hasTerminal,
showColor: stdout.supportsAnsiEscapes,
stdio: stdio,
),
terminal: terminal,
stdio: stdio,
);
logger = loggerFactory.createLogger(
windows: isWindows,
);
}

late final ProcessManager processManager;
late final LocalFileSystem fileSystem;
late final Stdio stdio;
late final Terminal terminal;
late final Logger logger;
}

/// An abstraction for instantiation of the correct logger type.
///
/// Our logger class hierarchy and runtime requirements are overly complicated.
class LoggerFactory {
LoggerFactory({
required Terminal terminal,
required Stdio stdio,
required OutputPreferences outputPreferences,
StopwatchFactory stopwatchFactory = const StopwatchFactory(),
}) : _terminal = terminal,
_stdio = stdio,
_stopwatchFactory = stopwatchFactory,
_outputPreferences = outputPreferences;

final Terminal _terminal;
final Stdio _stdio;
final StopwatchFactory _stopwatchFactory;
final OutputPreferences _outputPreferences;

/// Create the appropriate logger for the current platform and configuration.
Logger createLogger({
required bool windows,
}) {
Logger logger;
if (windows) {
logger = WindowsStdoutLogger(
terminal: _terminal,
stdio: _stdio,
outputPreferences: _outputPreferences,
stopwatchFactory: _stopwatchFactory,
);
} else {
logger = StdoutLogger(
terminal: _terminal,
stdio: _stdio,
outputPreferences: _outputPreferences,
stopwatchFactory: _stopwatchFactory);
}
return logger;
}
}
10 changes: 9 additions & 1 deletion packages/flutter_migrate/lib/src/commands/abandon.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class MigrateAbandonCommand extends MigrateCommand {
required this.fileSystem,
required this.terminal,
required ProcessManager processManager,
this.standalone = false,
}) : migrateUtils = MigrateUtils(
logger: logger,
fileSystem: fileSystem,
Expand Down Expand Up @@ -60,6 +61,8 @@ class MigrateAbandonCommand extends MigrateCommand {

final MigrateUtils migrateUtils;

final bool standalone;

@override
final String name = 'abandon';

Expand All @@ -75,7 +78,12 @@ class MigrateAbandonCommand extends MigrateCommand {
? FlutterProject.current(fileSystem)
: flutterProjectFactory
.fromDirectory(fileSystem.directory(projectDirectory));
final bool isSubcommand = boolArg('flutter-subcommand') ?? false;
final bool isSubcommand = boolArg('flutter-subcommand') ?? !standalone;

if (!validateWorkingDirectory(project, logger)) {
return const CommandResult(ExitStatus.fail);
}

Directory stagingDirectory =
project.directory.childDirectory(kDefaultMigrateStagingDirectoryName);
final String? customStagingDirectoryPath = stringArg('staging-directory');
Expand Down
11 changes: 9 additions & 2 deletions packages/flutter_migrate/lib/src/commands/apply.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class MigrateApplyCommand extends MigrateCommand {
required this.fileSystem,
required this.terminal,
required ProcessManager processManager,
this.standalone = false,
}) : _verbose = verbose,
_processManager = processManager,
migrateUtils = MigrateUtils(
Expand Down Expand Up @@ -76,6 +77,8 @@ class MigrateApplyCommand extends MigrateCommand {

final MigrateUtils migrateUtils;

final bool standalone;

@override
final String name = 'apply';

Expand All @@ -98,12 +101,16 @@ class MigrateApplyCommand extends MigrateCommand {
final FlutterToolsEnvironment environment =
await FlutterToolsEnvironment.initializeFlutterToolsEnvironment(
_processManager, logger);
final bool isSubcommand = boolArg('flutter-subcommand') ?? false;
final bool isSubcommand = boolArg('flutter-subcommand') ?? !standalone;

if (!validateWorkingDirectory(project, logger)) {
return CommandResult.fail();
}

if (!await gitRepoExists(project.directory.path, logger, migrateUtils)) {
logger.printStatus('No git repo found. Please run in a project with an '
'initialized git repo or initialize one with:');
printCommandText('git init', logger, standalone: null);
printCommand('git init', logger);
return const CommandResult(ExitStatus.fail);
}

Expand Down
Loading

0 comments on commit e425eea

Please sign in to comment.