diff --git a/dev/tools/lib/repository.dart b/dev/tools/lib/repository.dart index 5e6f98f1904..64c052fb853 100644 --- a/dev/tools/lib/repository.dart +++ b/dev/tools/lib/repository.dart @@ -317,8 +317,8 @@ abstract class Repository { ); git.run( - ['cherry-pick', '--no-commit', commit], - 'attempt to cherry-pick $commit without committing', + ['cherry-pick', commit], + 'cherry-pick $commit', workingDirectory: checkoutDirectory.path, ); } diff --git a/dev/tools/lib/start.dart b/dev/tools/lib/start.dart index ff9e06654df..b9237d1996e 100644 --- a/dev/tools/lib/start.dart +++ b/dev/tools/lib/start.dart @@ -216,7 +216,10 @@ class StartCommand extends Command { stdio.printTrace( 'Attempt to cherrypick $revision ${success ? 'succeeded' : 'failed'}', ); - if (!success) { + if (success) { + engine.cherryPick(revision); + cherrypick.state = pb.CherrypickState.COMPLETED; + } else { cherrypick.state = pb.CherrypickState.PENDING_WITH_CONFLICT; } } @@ -253,10 +256,16 @@ class StartCommand extends Command { for (final pb.Cherrypick cherrypick in frameworkCherrypicks) { final String revision = cherrypick.trunkRevision; - final bool result = framework.canCherryPick(revision); + final bool success = framework.canCherryPick(revision); stdio.printTrace( - 'Attempt to cherrypick $cherrypick ${result ? 'succeeded' : 'failed'}', + 'Attempt to cherrypick $cherrypick ${success ? 'succeeded' : 'failed'}', ); + if (success) { + framework.cherryPick(revision); + cherrypick.state = pb.CherrypickState.COMPLETED; + } else { + cherrypick.state = pb.CherrypickState.PENDING_WITH_CONFLICT; + } } final String frameworkHead = framework.reverseParse('HEAD'); diff --git a/dev/tools/test/repository_test.dart b/dev/tools/test/repository_test.dart new file mode 100644 index 00000000000..87363f2af29 --- /dev/null +++ b/dev/tools/test/repository_test.dart @@ -0,0 +1,172 @@ +// 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:dev_tools/repository.dart'; +import 'package:file/memory.dart'; +import 'package:platform/platform.dart'; + +import '../../../packages/flutter_tools/test/src/fake_process_manager.dart'; + +import './common.dart'; + +void main() { + group('repository', () { + test('canCherryPick returns true if git cherry-pick returns 0', () { + const LocalPlatform platform = LocalPlatform(); + const String rootDir = '/'; + const String commit = 'abc123'; + + final TestStdio stdio = TestStdio(); + final MemoryFileSystem fileSystem = MemoryFileSystem.test(); + final FakeProcessManager processManager = + FakeProcessManager.list([ + FakeCommand(command: [ + 'git', + 'clone', + '--origin', + 'upstream', + '--', + FrameworkRepository.defaultUpstream, + fileSystem.path + .join(rootDir, 'flutter_conductor_checkouts', 'framework'), + ]), + const FakeCommand(command: [ + 'git', + 'rev-parse', + 'HEAD', + ], stdout: commit), + const FakeCommand(command: [ + 'git', + 'status', + '--porcelain', + ]), + const FakeCommand(command: [ + 'git', + 'cherry-pick', + '--no-commit', + commit, + ], exitCode: 0), + const FakeCommand(command: [ + 'git', + 'reset', + 'HEAD', + '--hard', + ]), + ]); + final Checkouts checkouts = Checkouts( + fileSystem: fileSystem, + parentDirectory: fileSystem.directory(rootDir), + platform: platform, + processManager: processManager, + stdio: stdio, + ); + final Repository repository = FrameworkRepository(checkouts); + expect(repository.canCherryPick(commit), true); + }); + + test('canCherryPick returns false if git cherry-pick returns non-zero', () { + const LocalPlatform platform = LocalPlatform(); + const String rootDir = '/'; + const String commit = 'abc123'; + + final TestStdio stdio = TestStdio(); + final MemoryFileSystem fileSystem = MemoryFileSystem.test(); + final FakeProcessManager processManager = + FakeProcessManager.list([ + FakeCommand(command: [ + 'git', + 'clone', + '--origin', + 'upstream', + '--', + FrameworkRepository.defaultUpstream, + fileSystem.path + .join(rootDir, 'flutter_conductor_checkouts', 'framework'), + ]), + const FakeCommand(command: [ + 'git', + 'rev-parse', + 'HEAD', + ], stdout: commit), + const FakeCommand(command: [ + 'git', + 'status', + '--porcelain', + ]), + const FakeCommand(command: [ + 'git', + 'cherry-pick', + '--no-commit', + commit, + ], exitCode: 1), + const FakeCommand(command: [ + 'git', + 'diff', + ]), + const FakeCommand(command: [ + 'git', + 'reset', + 'HEAD', + '--hard', + ]), + ]); + final Checkouts checkouts = Checkouts( + fileSystem: fileSystem, + parentDirectory: fileSystem.directory(rootDir), + platform: platform, + processManager: processManager, + stdio: stdio, + ); + final Repository repository = FrameworkRepository(checkouts); + expect(repository.canCherryPick(commit), false); + }); + + test('cherryPick() applies the commit', () { + const LocalPlatform platform = LocalPlatform(); + const String rootDir = '/'; + const String commit = 'abc123'; + + final TestStdio stdio = TestStdio(); + final MemoryFileSystem fileSystem = MemoryFileSystem.test(); + final FakeProcessManager processManager = + FakeProcessManager.list([ + FakeCommand(command: [ + 'git', + 'clone', + '--origin', + 'upstream', + '--', + FrameworkRepository.defaultUpstream, + fileSystem.path + .join(rootDir, 'flutter_conductor_checkouts', 'framework'), + ]), + const FakeCommand(command: [ + 'git', + 'rev-parse', + 'HEAD', + ], stdout: commit), + const FakeCommand(command: [ + 'git', + 'status', + '--porcelain', + ]), + const FakeCommand(command: [ + 'git', + 'cherry-pick', + commit, + ]), + ]); + final Checkouts checkouts = Checkouts( + fileSystem: fileSystem, + parentDirectory: fileSystem.directory(rootDir), + platform: platform, + processManager: processManager, + stdio: stdio, + ); + final Repository repository = FrameworkRepository(checkouts); + repository.cherryPick(commit); + expect(processManager.hasRemainingExpectations, false); + }); + }); +}