mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Migrate apply (#102787)
This commit is contained in:
parent
e1aad362df
commit
696110ba46
@ -11,6 +11,7 @@ import '../base/terminal.dart';
|
|||||||
import '../migrate/migrate_utils.dart';
|
import '../migrate/migrate_utils.dart';
|
||||||
import '../runner/flutter_command.dart';
|
import '../runner/flutter_command.dart';
|
||||||
import 'migrate_abandon.dart';
|
import 'migrate_abandon.dart';
|
||||||
|
import 'migrate_apply.dart';
|
||||||
import 'migrate_status.dart';
|
import 'migrate_status.dart';
|
||||||
|
|
||||||
/// Base command for the migration tool.
|
/// Base command for the migration tool.
|
||||||
@ -37,6 +38,14 @@ class MigrateCommand extends FlutterCommand {
|
|||||||
platform: platform,
|
platform: platform,
|
||||||
processManager: processManager
|
processManager: processManager
|
||||||
));
|
));
|
||||||
|
addSubcommand(MigrateApplyCommand(
|
||||||
|
verbose: verbose,
|
||||||
|
logger: logger,
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
terminal: terminal,
|
||||||
|
platform: platform,
|
||||||
|
processManager: processManager
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
final Logger logger;
|
final Logger logger;
|
||||||
|
204
packages/flutter_tools/lib/src/commands/migrate_apply.dart
Normal file
204
packages/flutter_tools/lib/src/commands/migrate_apply.dart
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
// Copyright 2014 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:process/process.dart';
|
||||||
|
|
||||||
|
import '../base/file_system.dart';
|
||||||
|
import '../base/logger.dart';
|
||||||
|
import '../base/platform.dart';
|
||||||
|
import '../base/terminal.dart';
|
||||||
|
import '../flutter_project_metadata.dart';
|
||||||
|
import '../migrate/migrate_manifest.dart';
|
||||||
|
import '../migrate/migrate_update_locks.dart';
|
||||||
|
import '../migrate/migrate_utils.dart';
|
||||||
|
import '../project.dart';
|
||||||
|
import '../runner/flutter_command.dart';
|
||||||
|
import '../version.dart';
|
||||||
|
import 'migrate.dart';
|
||||||
|
|
||||||
|
/// Migrate subcommand that checks the migrate working directory for unresolved conflicts and
|
||||||
|
/// applies the staged changes to the project.
|
||||||
|
class MigrateApplyCommand extends FlutterCommand {
|
||||||
|
MigrateApplyCommand({
|
||||||
|
bool verbose = false,
|
||||||
|
required this.logger,
|
||||||
|
required this.fileSystem,
|
||||||
|
required this.terminal,
|
||||||
|
required Platform platform,
|
||||||
|
required ProcessManager processManager,
|
||||||
|
}) : _verbose = verbose,
|
||||||
|
migrateUtils = MigrateUtils(
|
||||||
|
logger: logger,
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
platform: platform,
|
||||||
|
processManager: processManager,
|
||||||
|
) {
|
||||||
|
requiresPubspecYaml();
|
||||||
|
argParser.addOption(
|
||||||
|
'staging-directory',
|
||||||
|
help: 'Specifies the custom migration working directory used to stage '
|
||||||
|
'and edit proposed changes. This path can be absolute or relative '
|
||||||
|
'to the flutter project root. This defaults to '
|
||||||
|
'`$kDefaultMigrateStagingDirectoryName`',
|
||||||
|
valueHelp: 'path',
|
||||||
|
);
|
||||||
|
argParser.addOption(
|
||||||
|
'project-directory',
|
||||||
|
help: 'The root directory of the flutter project. This defaults to the '
|
||||||
|
'current working directory if omitted.',
|
||||||
|
valueHelp: 'path',
|
||||||
|
);
|
||||||
|
argParser.addFlag(
|
||||||
|
'force',
|
||||||
|
abbr: 'f',
|
||||||
|
help: 'Ignore unresolved merge conflicts and uncommitted changes and '
|
||||||
|
'apply staged changes by force.',
|
||||||
|
);
|
||||||
|
argParser.addFlag(
|
||||||
|
'keep-working-directory',
|
||||||
|
help: 'Do not delete the working directory.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final bool _verbose;
|
||||||
|
|
||||||
|
final Logger logger;
|
||||||
|
|
||||||
|
final FileSystem fileSystem;
|
||||||
|
|
||||||
|
final Terminal terminal;
|
||||||
|
|
||||||
|
final MigrateUtils migrateUtils;
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String name = 'apply';
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String description = r'Accepts the changes produced by `$ flutter '
|
||||||
|
'migrate start` and copies the changed files into '
|
||||||
|
'your project files. All merge conflicts should '
|
||||||
|
'be resolved before apply will complete '
|
||||||
|
'successfully. If conflicts still exist, this '
|
||||||
|
'command will print the remaining conflicted files.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get category => FlutterCommandCategory.project;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{};
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<FlutterCommandResult> runCommand() async {
|
||||||
|
final String? projectDirectory = stringArg('project-directory');
|
||||||
|
final FlutterProjectFactory flutterProjectFactory = FlutterProjectFactory(logger: logger, fileSystem: fileSystem);
|
||||||
|
final FlutterProject project = projectDirectory == null
|
||||||
|
? FlutterProject.current()
|
||||||
|
: flutterProjectFactory.fromDirectory(fileSystem.directory(projectDirectory));
|
||||||
|
|
||||||
|
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);
|
||||||
|
return const FlutterCommandResult(ExitStatus.fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
final bool force = boolArg('force') ?? false;
|
||||||
|
|
||||||
|
Directory stagingDirectory = project.directory.childDirectory(kDefaultMigrateStagingDirectoryName);
|
||||||
|
final String? customStagingDirectoryPath = stringArg('staging-directory');
|
||||||
|
if (customStagingDirectoryPath != null) {
|
||||||
|
if (fileSystem.path.isAbsolute(customStagingDirectoryPath)) {
|
||||||
|
stagingDirectory = fileSystem.directory(customStagingDirectoryPath);
|
||||||
|
} else {
|
||||||
|
stagingDirectory = project.directory.childDirectory(customStagingDirectoryPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!stagingDirectory.existsSync()) {
|
||||||
|
logger.printStatus('No migration in progress at $stagingDirectory. Please run:');
|
||||||
|
printCommandText('flutter migrate start', logger);
|
||||||
|
return const FlutterCommandResult(ExitStatus.fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
final File manifestFile = MigrateManifest.getManifestFileFromDirectory(stagingDirectory);
|
||||||
|
final MigrateManifest manifest = MigrateManifest.fromFile(manifestFile);
|
||||||
|
if (!checkAndPrintMigrateStatus(manifest, stagingDirectory, warnConflict: true, logger: logger) && !force) {
|
||||||
|
logger.printStatus('Conflicting files found. Resolve these conflicts and try again.');
|
||||||
|
logger.printStatus('Guided conflict resolution wizard:');
|
||||||
|
printCommandText('flutter migrate resolve-conflicts', logger);
|
||||||
|
return const FlutterCommandResult(ExitStatus.fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await hasUncommittedChanges(project.directory.path, logger, migrateUtils) && !force) {
|
||||||
|
return const FlutterCommandResult(ExitStatus.fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.printStatus('Applying migration.');
|
||||||
|
// Copy files from working directory to project root
|
||||||
|
final List<String> allFilesToCopy = <String>[];
|
||||||
|
allFilesToCopy.addAll(manifest.mergedFiles);
|
||||||
|
allFilesToCopy.addAll(manifest.conflictFiles);
|
||||||
|
allFilesToCopy.addAll(manifest.addedFiles);
|
||||||
|
if (allFilesToCopy.isNotEmpty && _verbose) {
|
||||||
|
logger.printStatus('Modifying ${allFilesToCopy.length} files.', indent: 2);
|
||||||
|
}
|
||||||
|
for (final String localPath in allFilesToCopy) {
|
||||||
|
if (_verbose) {
|
||||||
|
logger.printStatus('Writing $localPath');
|
||||||
|
}
|
||||||
|
final File workingFile = stagingDirectory.childFile(localPath);
|
||||||
|
final File targetFile = project.directory.childFile(localPath);
|
||||||
|
if (!workingFile.existsSync()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!targetFile.existsSync()) {
|
||||||
|
targetFile.createSync(recursive: true);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
targetFile.writeAsStringSync(workingFile.readAsStringSync(), flush: true);
|
||||||
|
} on FileSystemException {
|
||||||
|
targetFile.writeAsBytesSync(workingFile.readAsBytesSync(), flush: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Delete files slated for deletion.
|
||||||
|
if (manifest.deletedFiles.isNotEmpty) {
|
||||||
|
logger.printStatus('Deleting ${manifest.deletedFiles.length} files.', indent: 2);
|
||||||
|
}
|
||||||
|
for (final String localPath in manifest.deletedFiles) {
|
||||||
|
final File targetFile = FlutterProject.current().directory.childFile(localPath);
|
||||||
|
targetFile.deleteSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the migrate config files to reflect latest migration.
|
||||||
|
if (_verbose) {
|
||||||
|
logger.printStatus('Updating .migrate_configs');
|
||||||
|
}
|
||||||
|
final FlutterProjectMetadata metadata = FlutterProjectMetadata(project.directory.childFile('.metadata'), logger);
|
||||||
|
final FlutterVersion version = FlutterVersion(workingDirectory: project.directory.absolute.path);
|
||||||
|
|
||||||
|
final String currentGitHash = version.frameworkRevision;
|
||||||
|
metadata.migrateConfig.populate(
|
||||||
|
projectDirectory: project.directory,
|
||||||
|
currentRevision: currentGitHash,
|
||||||
|
logger: logger,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Clean up the working directory
|
||||||
|
final bool keepWorkingDirectory = boolArg('keep-working-directory') ?? false;
|
||||||
|
if (!keepWorkingDirectory) {
|
||||||
|
stagingDirectory.deleteSync(recursive: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect pub dependency locking. Run flutter pub upgrade --major-versions
|
||||||
|
await updatePubspecDependencies(project, migrateUtils, logger, terminal);
|
||||||
|
|
||||||
|
// Detect gradle lockfiles in android directory. Delete lockfiles and regenerate with ./gradlew tasks (any gradle task that requires a build).
|
||||||
|
await updateGradleDependencyLocking(project, migrateUtils, logger, terminal, _verbose, fileSystem);
|
||||||
|
|
||||||
|
logger.printStatus('Migration complete. You may use commands like `git '
|
||||||
|
'status`, `git diff` and `git restore <file>` to continue '
|
||||||
|
'working with the migrated files.');
|
||||||
|
return const FlutterCommandResult(ExitStatus.success);
|
||||||
|
}
|
||||||
|
}
|
116
packages/flutter_tools/lib/src/migrate/migrate_update_locks.dart
Normal file
116
packages/flutter_tools/lib/src/migrate/migrate_update_locks.dart
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// Copyright 2014 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 '../base/file_system.dart';
|
||||||
|
import '../base/logger.dart';
|
||||||
|
import '../base/terminal.dart';
|
||||||
|
import '../project.dart';
|
||||||
|
import 'migrate_utils.dart';
|
||||||
|
|
||||||
|
/// Checks if the project uses pubspec dependency locking and prompts if
|
||||||
|
/// the pub upgrade should be run.
|
||||||
|
Future<void> updatePubspecDependencies(
|
||||||
|
FlutterProject flutterProject,
|
||||||
|
MigrateUtils migrateUtils,
|
||||||
|
Logger logger,
|
||||||
|
Terminal terminal
|
||||||
|
) async {
|
||||||
|
final File pubspecFile = flutterProject.directory.childFile('pubspec.yaml');
|
||||||
|
if (!pubspecFile.existsSync()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!pubspecFile.readAsStringSync().contains('# THIS LINE IS AUTOGENERATED')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.printStatus('\nDart dependency locking detected in pubspec.yaml.');
|
||||||
|
terminal.usesTerminalUi = true;
|
||||||
|
String selection = 'y';
|
||||||
|
selection = await terminal.promptForCharInput(
|
||||||
|
<String>['y', 'n'],
|
||||||
|
logger: logger,
|
||||||
|
prompt: 'Do you want the tool to run `flutter pub upgrade --major-versions`? (y)es, (n)o',
|
||||||
|
defaultChoiceIndex: 1,
|
||||||
|
);
|
||||||
|
if (selection == 'y') {
|
||||||
|
// Runs `flutter pub upgrade --major-versions`
|
||||||
|
await migrateUtils.flutterPubUpgrade(flutterProject.directory.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if gradle dependency locking is used and prompts the developer to
|
||||||
|
/// remove and back up the gradle dependency lockfile.
|
||||||
|
Future<void> updateGradleDependencyLocking(
|
||||||
|
FlutterProject flutterProject,
|
||||||
|
MigrateUtils migrateUtils,
|
||||||
|
Logger logger,
|
||||||
|
Terminal terminal,
|
||||||
|
bool verbose,
|
||||||
|
FileSystem fileSystem
|
||||||
|
) async {
|
||||||
|
final Directory androidDir = flutterProject.directory.childDirectory('android');
|
||||||
|
if (!androidDir.existsSync()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final List<FileSystemEntity> androidFiles = androidDir.listSync();
|
||||||
|
final List<File> lockfiles = <File>[];
|
||||||
|
final List<String> backedUpFilePaths = <String>[];
|
||||||
|
for (final FileSystemEntity entity in androidFiles) {
|
||||||
|
if (entity is! File) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final File file = entity.absolute;
|
||||||
|
// Don't re-handle backed up lockfiles.
|
||||||
|
if (file.path.contains('_backup_')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// lockfiles generated by gradle start with this prefix.
|
||||||
|
if (file.readAsStringSync().startsWith(
|
||||||
|
'# This is a Gradle generated file for dependency locking.\n# '
|
||||||
|
'Manual edits can break the build and are not advised.\n# This '
|
||||||
|
'file is expected to be part of source control.')) {
|
||||||
|
lockfiles.add(file);
|
||||||
|
}
|
||||||
|
} on FileSystemException {
|
||||||
|
if (verbose) {
|
||||||
|
logger.printStatus('Unable to check ${file.path}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lockfiles.isNotEmpty) {
|
||||||
|
logger.printStatus('\nGradle dependency locking detected.');
|
||||||
|
logger.printStatus('Flutter can backup the lockfiles and regenerate updated '
|
||||||
|
'lockfiles.');
|
||||||
|
terminal.usesTerminalUi = true;
|
||||||
|
String selection = 'y';
|
||||||
|
selection = await terminal.promptForCharInput(
|
||||||
|
<String>['y', 'n'],
|
||||||
|
logger: logger,
|
||||||
|
prompt: 'Do you want the tool to update locked dependencies? (y)es, (n)o',
|
||||||
|
defaultChoiceIndex: 1,
|
||||||
|
);
|
||||||
|
if (selection == 'y') {
|
||||||
|
for (final File file in lockfiles) {
|
||||||
|
int counter = 0;
|
||||||
|
while (true) {
|
||||||
|
final String newPath = '${file.absolute.path}_backup_$counter';
|
||||||
|
if (!fileSystem.file(newPath).existsSync()) {
|
||||||
|
file.renameSync(newPath);
|
||||||
|
backedUpFilePaths.add(newPath);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Runs `./gradlew tasks`in the project's android directory.
|
||||||
|
await migrateUtils.gradlewTasks(flutterProject.directory.childDirectory('android').path);
|
||||||
|
logger.printStatus('Old lockfiles renamed to:');
|
||||||
|
for (final String path in backedUpFilePaths) {
|
||||||
|
logger.printStatus(path, color: TerminalColor.grey, indent: 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,231 @@
|
|||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
// @dart = 2.8
|
||||||
|
|
||||||
|
import 'package:flutter_tools/src/base/file_system.dart';
|
||||||
|
import 'package:flutter_tools/src/base/logger.dart';
|
||||||
|
import 'package:flutter_tools/src/base/platform.dart';
|
||||||
|
import 'package:flutter_tools/src/base/terminal.dart';
|
||||||
|
import 'package:flutter_tools/src/cache.dart';
|
||||||
|
import 'package:flutter_tools/src/commands/migrate.dart';
|
||||||
|
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||||
|
import 'package:flutter_tools/src/migrate/migrate_utils.dart';
|
||||||
|
|
||||||
|
import '../../src/common.dart';
|
||||||
|
import '../../src/context.dart';
|
||||||
|
import '../../src/test_flutter_command_runner.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
FileSystem fileSystem;
|
||||||
|
BufferLogger logger;
|
||||||
|
Platform platform;
|
||||||
|
Terminal terminal;
|
||||||
|
ProcessManager processManager;
|
||||||
|
Directory appDir;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
fileSystem = globals.localFileSystem;
|
||||||
|
appDir = fileSystem.systemTempDirectory.createTempSync('apptestdir');
|
||||||
|
logger = BufferLogger.test();
|
||||||
|
platform = FakePlatform();
|
||||||
|
terminal = Terminal.test();
|
||||||
|
processManager = globals.processManager;
|
||||||
|
});
|
||||||
|
|
||||||
|
setUpAll(() {
|
||||||
|
Cache.disableLocking();
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDown(() async {
|
||||||
|
tryToDelete(appDir);
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('Apply produces all outputs', () async {
|
||||||
|
final MigrateCommand command = MigrateCommand(
|
||||||
|
verbose: true,
|
||||||
|
logger: logger,
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
terminal: terminal,
|
||||||
|
platform: platform,
|
||||||
|
processManager: processManager,
|
||||||
|
);
|
||||||
|
final Directory workingDir = appDir.childDirectory(kDefaultMigrateStagingDirectoryName);
|
||||||
|
appDir.childFile('lib/main.dart').createSync(recursive: true);
|
||||||
|
final File pubspecOriginal = appDir.childFile('pubspec.yaml');
|
||||||
|
pubspecOriginal.createSync();
|
||||||
|
pubspecOriginal.writeAsStringSync('''
|
||||||
|
name: originalname
|
||||||
|
description: A new Flutter project.
|
||||||
|
version: 1.0.0+1
|
||||||
|
environment:
|
||||||
|
sdk: '>=2.18.0-58.0.dev <3.0.0'
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
dev_dependencies:
|
||||||
|
flutter_test:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
uses-material-design: true''', flush: true);
|
||||||
|
|
||||||
|
final File gitignore = appDir.childFile('.gitignore');
|
||||||
|
gitignore.createSync();
|
||||||
|
gitignore.writeAsStringSync(kDefaultMigrateStagingDirectoryName, flush: true);
|
||||||
|
|
||||||
|
logger.clear();
|
||||||
|
await createTestCommandRunner(command).run(
|
||||||
|
<String>[
|
||||||
|
'migrate',
|
||||||
|
'apply',
|
||||||
|
'--staging-directory=${workingDir.path}',
|
||||||
|
'--project-directory=${appDir.path}',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
expect(logger.statusText, contains('Project is not a git repo. Please initialize a git repo and try again.'));
|
||||||
|
|
||||||
|
await processManager.run(<String>['git', 'init'], workingDirectory: appDir.path);
|
||||||
|
|
||||||
|
logger.clear();
|
||||||
|
await createTestCommandRunner(command).run(
|
||||||
|
<String>[
|
||||||
|
'migrate',
|
||||||
|
'apply',
|
||||||
|
'--staging-directory=${workingDir.path}',
|
||||||
|
'--project-directory=${appDir.path}',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
expect(logger.statusText, contains('No migration in progress'));
|
||||||
|
|
||||||
|
final File pubspecModified = workingDir.childFile('pubspec.yaml');
|
||||||
|
pubspecModified.createSync(recursive: true);
|
||||||
|
pubspecModified.writeAsStringSync('''
|
||||||
|
name: newname
|
||||||
|
description: new description of the test project
|
||||||
|
version: 1.0.0+1
|
||||||
|
environment:
|
||||||
|
sdk: '>=2.18.0-58.0.dev <3.0.0'
|
||||||
|
dependencies:
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
dev_dependencies:
|
||||||
|
flutter_test:
|
||||||
|
sdk: flutter
|
||||||
|
flutter:
|
||||||
|
uses-material-design: false
|
||||||
|
# EXTRALINE:''', flush: true);
|
||||||
|
|
||||||
|
final File addedFile = workingDir.childFile('added.file');
|
||||||
|
addedFile.createSync(recursive: true);
|
||||||
|
addedFile.writeAsStringSync('new file contents');
|
||||||
|
|
||||||
|
final File manifestFile = workingDir.childFile('.migrate_manifest');
|
||||||
|
manifestFile.createSync(recursive: true);
|
||||||
|
manifestFile.writeAsStringSync('''
|
||||||
|
merged_files:
|
||||||
|
- pubspec.yaml
|
||||||
|
conflict_files:
|
||||||
|
- conflict/conflict.file
|
||||||
|
added_files:
|
||||||
|
- added.file
|
||||||
|
deleted_files:
|
||||||
|
''');
|
||||||
|
|
||||||
|
// Add conflict file
|
||||||
|
final File conflictFile = workingDir.childDirectory('conflict').childFile('conflict.file');
|
||||||
|
conflictFile.createSync(recursive: true);
|
||||||
|
conflictFile.writeAsStringSync('''
|
||||||
|
line1
|
||||||
|
<<<<<<< /conflcit/conflict.file
|
||||||
|
line2
|
||||||
|
=======
|
||||||
|
linetwo
|
||||||
|
>>>>>>> /var/folders/md/gm0zgfcj07vcsj6jkh_mp_wh00ff02/T/flutter_tools.4Xdep8/generatedTargetTemplatetlN44S/conflict/conflict.file
|
||||||
|
line3
|
||||||
|
''', flush: true);
|
||||||
|
|
||||||
|
final File conflictFileOriginal = appDir.childDirectory('conflict').childFile('conflict.file');
|
||||||
|
conflictFileOriginal.createSync(recursive: true);
|
||||||
|
conflictFileOriginal.writeAsStringSync('''
|
||||||
|
line1
|
||||||
|
line2
|
||||||
|
line3
|
||||||
|
''', flush: true);
|
||||||
|
|
||||||
|
logger.clear();
|
||||||
|
await createTestCommandRunner(command).run(
|
||||||
|
<String>[
|
||||||
|
'migrate',
|
||||||
|
'apply',
|
||||||
|
'--staging-directory=${workingDir.path}',
|
||||||
|
'--project-directory=${appDir.path}',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
expect(logger.statusText, contains(r'''
|
||||||
|
Added files:
|
||||||
|
- added.file
|
||||||
|
Modified files:
|
||||||
|
- pubspec.yaml
|
||||||
|
Unable to apply migration. The following files in the migration working directory still have unresolved conflicts:
|
||||||
|
- conflict/conflict.file
|
||||||
|
Conflicting files found. Resolve these conflicts and try again.
|
||||||
|
Guided conflict resolution wizard:
|
||||||
|
|
||||||
|
$ flutter migrate resolve-conflicts'''));
|
||||||
|
|
||||||
|
conflictFile.writeAsStringSync('''
|
||||||
|
line1
|
||||||
|
linetwo
|
||||||
|
line3
|
||||||
|
''', flush: true);
|
||||||
|
|
||||||
|
logger.clear();
|
||||||
|
await createTestCommandRunner(command).run(
|
||||||
|
<String>[
|
||||||
|
'migrate',
|
||||||
|
'apply',
|
||||||
|
'--staging-directory=${workingDir.path}',
|
||||||
|
'--project-directory=${appDir.path}',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
expect(logger.statusText, contains('There are uncommitted changes in your project. Please git commit, abandon, or stash your changes before trying again.'));
|
||||||
|
|
||||||
|
await processManager.run(<String>['git', 'add', '.'], workingDirectory: appDir.path);
|
||||||
|
await processManager.run(<String>['git', 'commit', '-m', 'Initial commit'], workingDirectory: appDir.path);
|
||||||
|
|
||||||
|
logger.clear();
|
||||||
|
await createTestCommandRunner(command).run(
|
||||||
|
<String>[
|
||||||
|
'migrate',
|
||||||
|
'apply',
|
||||||
|
'--staging-directory=${workingDir.path}',
|
||||||
|
'--project-directory=${appDir.path}',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
expect(logger.statusText, contains(r'''
|
||||||
|
Added files:
|
||||||
|
- added.file
|
||||||
|
Modified files:
|
||||||
|
- conflict/conflict.file
|
||||||
|
- pubspec.yaml
|
||||||
|
|
||||||
|
Applying migration.
|
||||||
|
Modifying 3 files.
|
||||||
|
Writing pubspec.yaml
|
||||||
|
Writing conflict/conflict.file
|
||||||
|
Writing added.file
|
||||||
|
Updating .migrate_configs
|
||||||
|
Migration complete. You may use commands like `git status`, `git diff` and `git restore <file>` to continue working with the migrated files.'''));
|
||||||
|
|
||||||
|
expect(pubspecOriginal.readAsStringSync(), contains('# EXTRALINE'));
|
||||||
|
expect(conflictFileOriginal.readAsStringSync(), contains('linetwo'));
|
||||||
|
expect(appDir.childFile('added.file').existsSync(), true);
|
||||||
|
expect(appDir.childFile('added.file').readAsStringSync(), contains('new file contents'));
|
||||||
|
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
FileSystem: () => fileSystem,
|
||||||
|
ProcessManager: () => processManager,
|
||||||
|
Platform: () => platform,
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user