From f47eac9c5868e57cc2398d9fc3f05e8317ba36d2 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 23 Sep 2021 11:52:51 -0400 Subject: [PATCH] changed subprocesses to async from sync (#89668) * changed subprocess to async from sync --- dev/conductor/dart_test.yaml | 6 + dev/conductor/lib/candidates.dart | 10 +- dev/conductor/lib/codesign.dart | 80 +++--- dev/conductor/lib/git.dart | 16 +- dev/conductor/lib/next.dart | 41 ++-- dev/conductor/lib/repository.dart | 310 +++++++++++++----------- dev/conductor/lib/roll_dev.dart | 30 +-- dev/conductor/lib/start.dart | 66 ++--- dev/conductor/test/codesign_test.dart | 16 +- dev/conductor/test/repository_test.dart | 36 +-- dev/conductor/test/roll_dev_test.dart | 26 +- 11 files changed, 335 insertions(+), 302 deletions(-) create mode 100644 dev/conductor/dart_test.yaml diff --git a/dev/conductor/dart_test.yaml b/dev/conductor/dart_test.yaml new file mode 100644 index 00000000000..ea3283fe598 --- /dev/null +++ b/dev/conductor/dart_test.yaml @@ -0,0 +1,6 @@ +# codesign_integration_test takes longer than the default timeout which is 30s +# since it has to clone both the engine and framework repos, and that test is running +# asynchronously. The async function is being awaited more than 30s which counts as inactivity +# The default timeout needs to be extended to accomodate codesign_integration_test + +timeout: 5m diff --git a/dev/conductor/lib/candidates.dart b/dev/conductor/lib/candidates.dart index 6dde6766839..cf4711b717a 100644 --- a/dev/conductor/lib/candidates.dart +++ b/dev/conductor/lib/candidates.dart @@ -38,9 +38,9 @@ class CandidatesCommand extends Command { String get description => 'List release candidates.'; @override - void run() { + Future run() async { final ArgResults results = argResults!; - git.run( + await git.run( ['fetch', results[kRemote] as String], 'Fetch from remote ${results[kRemote]}', workingDirectory: flutterRoot.path, @@ -52,10 +52,10 @@ class CandidatesCommand extends Command { upstreamPath: flutterRoot.path, ); - final Version currentVersion = framework.flutterVersion(); + final Version currentVersion = await framework.flutterVersion(); stdio.printStatus('currentVersion = $currentVersion'); - final List branches = git.getOutput( + final List branches = (await git.getOutput( [ 'branch', '--no-color', @@ -65,7 +65,7 @@ class CandidatesCommand extends Command { ], 'List all remote branches', workingDirectory: flutterRoot.path, - ).split('\n'); + )).split('\n'); // Pattern for extracting only the branch name via sub-group 1 final RegExp remotePattern = RegExp('${results[kRemote]}\\/(.*)'); diff --git a/dev/conductor/lib/codesign.dart b/dev/conductor/lib/codesign.dart index 057e9020425..7622551b33a 100644 --- a/dev/conductor/lib/codesign.dart +++ b/dev/conductor/lib/codesign.dart @@ -38,9 +38,9 @@ class CodesignCommand extends Command { platform = checkouts.platform, stdio = checkouts.stdio, processManager = checkouts.processManager { - if (framework != null) { - _framework = framework; - } + if (framework != null) { + _framework = framework; + } argParser.addFlag( kVerify, help: @@ -89,7 +89,7 @@ class CodesignCommand extends Command { 'For codesigning and verifying the signatures of engine binaries.'; @override - void run() { + Future run() async { if (!platform.isMacOS) { throw ConductorException( 'Error! Expected operating system "macos", actual operating system is: ' @@ -112,21 +112,21 @@ class CodesignCommand extends Command { 'the desired revision and run that version of the conductor.\n'); revision = argResults![kRevision] as String; } else { - revision = (processManager.runSync( + revision = ((await processManager.run( ['git', 'rev-parse', 'HEAD'], - workingDirectory: framework.checkoutDirectory.path, - ).stdout as String).trim(); + workingDirectory: (await framework.checkoutDirectory).path, + )).stdout as String).trim(); assert(revision.isNotEmpty); } - framework.checkout(revision); + await framework.checkout(revision); // Ensure artifacts present - framework.runFlutter(['precache', '--android', '--ios', '--macos']); + await framework.runFlutter(['precache', '--android', '--ios', '--macos']); - verifyExist(); + await verifyExist(); if (argResults![kSignatures] as bool) { - verifySignatures(); + await verifySignatures(); } } @@ -134,7 +134,8 @@ class CodesignCommand extends Command { /// /// This list should be kept in sync with the actual contents of Flutter's /// cache. - List get binariesWithEntitlements { + Future> get binariesWithEntitlements async { + final String frameworkCacheDirectory = await framework.cacheDirectory; return [ 'artifacts/engine/android-arm-profile/darwin-x64/gen_snapshot', 'artifacts/engine/android-arm-release/darwin-x64/gen_snapshot', @@ -165,7 +166,7 @@ class CodesignCommand extends Command { 'dart-sdk/bin/utils/gen_snapshot', ] .map((String relativePath) => - fileSystem.path.join(framework.cacheDirectory, relativePath)) + fileSystem.path.join(frameworkCacheDirectory, relativePath)) .toList(); } @@ -173,7 +174,8 @@ class CodesignCommand extends Command { /// /// This list should be kept in sync with the actual contents of Flutter's /// cache. - List get binariesWithoutEntitlements { + Future> get binariesWithoutEntitlements async { + final String frameworkCacheDirectory = await framework.cacheDirectory; return [ 'artifacts/engine/darwin-x64-profile/FlutterMacOS.framework/Versions/A/FlutterMacOS', 'artifacts/engine/darwin-x64-release/FlutterMacOS.framework/Versions/A/FlutterMacOS', @@ -188,7 +190,7 @@ class CodesignCommand extends Command { 'artifacts/ios-deploy/ios-deploy', ] .map((String relativePath) => - fileSystem.path.join(framework.cacheDirectory, relativePath)) + fileSystem.path.join(frameworkCacheDirectory, relativePath)) .toList(); } @@ -200,12 +202,13 @@ class CodesignCommand extends Command { /// [binariesWithEntitlements] or [binariesWithoutEntitlements] lists should /// be updated accordingly. @visibleForTesting - void verifyExist() { + Future verifyExist() async { final Set foundFiles = {}; - for (final String binaryPath in findBinaryPaths(framework.cacheDirectory)) { - if (binariesWithEntitlements.contains(binaryPath)) { + for (final String binaryPath + in await findBinaryPaths(await framework.cacheDirectory)) { + if ((await binariesWithEntitlements).contains(binaryPath)) { foundFiles.add(binaryPath); - } else if (binariesWithoutEntitlements.contains(binaryPath)) { + } else if ((await binariesWithoutEntitlements).contains(binaryPath)) { foundFiles.add(binaryPath); } else { throw ConductorException( @@ -214,7 +217,7 @@ class CodesignCommand extends Command { } final List allExpectedFiles = - binariesWithEntitlements + binariesWithoutEntitlements; + (await binariesWithEntitlements) + (await binariesWithoutEntitlements); if (foundFiles.length < allExpectedFiles.length) { final List unfoundFiles = allExpectedFiles .where( @@ -237,19 +240,19 @@ class CodesignCommand extends Command { /// Verify code signatures and entitlements of all binaries in the cache. @visibleForTesting - void verifySignatures() { + Future verifySignatures() async { final List unsignedBinaries = []; final List wrongEntitlementBinaries = []; final List unexpectedBinaries = []; - - for (final String binaryPath in findBinaryPaths(framework.cacheDirectory)) { + for (final String binaryPath + in await findBinaryPaths(await framework.cacheDirectory)) { bool verifySignature = false; bool verifyEntitlements = false; - if (binariesWithEntitlements.contains(binaryPath)) { + if ((await binariesWithEntitlements).contains(binaryPath)) { verifySignature = true; verifyEntitlements = true; } - if (binariesWithoutEntitlements.contains(binaryPath)) { + if ((await binariesWithoutEntitlements).contains(binaryPath)) { verifySignature = true; } if (!verifySignature && !verifyEntitlements) { @@ -258,7 +261,7 @@ class CodesignCommand extends Command { continue; } stdio.printTrace('Verifying the code signature of $binaryPath'); - final io.ProcessResult codeSignResult = processManager.runSync( + final io.ProcessResult codeSignResult = await processManager.run( [ 'codesign', '-vvv', @@ -275,7 +278,7 @@ class CodesignCommand extends Command { } if (verifyEntitlements) { stdio.printTrace('Verifying entitlements of $binaryPath'); - if (!hasExpectedEntitlements(binaryPath)) { + if (!(await hasExpectedEntitlements(binaryPath))) { wrongEntitlementBinaries.add(binaryPath); } } @@ -330,11 +333,12 @@ class CodesignCommand extends Command { List? _allBinaryPaths; /// Find every binary file in the given [rootDirectory]. - List findBinaryPaths(String rootDirectory) { + Future> findBinaryPaths(String rootDirectory) async { if (_allBinaryPaths != null) { return _allBinaryPaths!; } - final io.ProcessResult result = processManager.runSync( + final List allBinaryPaths = []; + final io.ProcessResult result = await processManager.run( [ 'find', rootDirectory, @@ -346,13 +350,19 @@ class CodesignCommand extends Command { .split('\n') .where((String s) => s.isNotEmpty) .toList(); - _allBinaryPaths = allFiles.where(isBinary).toList(); + + await Future.forEach(allFiles, (String filePath) async { + if (await isBinary(filePath)) { + allBinaryPaths.add(filePath); + } + }); + _allBinaryPaths = allBinaryPaths; return _allBinaryPaths!; } /// Check mime-type of file at [filePath] to determine if it is binary. - bool isBinary(String filePath) { - final io.ProcessResult result = processManager.runSync( + Future isBinary(String filePath) async { + final io.ProcessResult result = await processManager.run( [ 'file', '--mime-type', @@ -364,8 +374,8 @@ class CodesignCommand extends Command { } /// Check if the binary has the expected entitlements. - bool hasExpectedEntitlements(String binaryPath) { - final io.ProcessResult entitlementResult = processManager.runSync( + Future hasExpectedEntitlements(String binaryPath) async { + final io.ProcessResult entitlementResult = await processManager.run( [ 'codesign', '--display', @@ -386,7 +396,7 @@ class CodesignCommand extends Command { final String output = entitlementResult.stdout as String; for (final String entitlement in expectedEntitlements) { final bool entitlementExpected = - binariesWithEntitlements.contains(binaryPath); + (await binariesWithEntitlements).contains(binaryPath); if (output.contains(entitlement) != entitlementExpected) { stdio.printError( 'File "$binaryPath" ${entitlementExpected ? 'does not have expected' : 'has unexpected'} ' diff --git a/dev/conductor/lib/git.dart b/dev/conductor/lib/git.dart index f81de2d3ec7..d0a257f5a72 100644 --- a/dev/conductor/lib/git.dart +++ b/dev/conductor/lib/git.dart @@ -14,34 +14,34 @@ class Git { final ProcessManager processManager; - String getOutput( + Future getOutput( List args, String explanation, { required String workingDirectory, bool allowFailures = false, - }) { - final ProcessResult result = _run(args, workingDirectory); + }) async { + final ProcessResult result = await _run(args, workingDirectory); if (result.exitCode == 0) { return stdoutToString(result.stdout); } _reportFailureAndExit(args, workingDirectory, result, explanation); } - int run( + Future run( List args, String explanation, { bool allowNonZeroExitCode = false, required String workingDirectory, - }) { - final ProcessResult result = _run(args, workingDirectory); + }) async { + final ProcessResult result = await _run(args, workingDirectory); if (result.exitCode != 0 && !allowNonZeroExitCode) { _reportFailureAndExit(args, workingDirectory, result, explanation); } return result.exitCode; } - ProcessResult _run(List args, String workingDirectory) { - return processManager.runSync( + Future _run(List args, String workingDirectory) async { + return processManager.run( ['git', ...args], workingDirectory: workingDirectory, environment: {'GIT_TRACE': '1'}, diff --git a/dev/conductor/lib/next.dart b/dev/conductor/lib/next.dart index 4cb356d50e0..0b98049bad8 100644 --- a/dev/conductor/lib/next.dart +++ b/dev/conductor/lib/next.dart @@ -47,8 +47,8 @@ class NextCommand extends Command { String get description => 'Proceed to the next release phase.'; @override - void run() { - runNext( + Future run() async { + await runNext( autoAccept: argResults![kYesFlag] as bool, checkouts: checkouts, force: argResults![kForceFlag] as bool, @@ -74,12 +74,12 @@ bool prompt(String message, Stdio stdio) { } @visibleForTesting -void runNext({ +Future runNext({ required bool autoAccept, required bool force, required Checkouts checkouts, required File stateFile, -}) { +}) async { final Stdio stdio = checkouts.stdio; const List finishedStates = [ CherrypickState.COMPLETED, @@ -106,10 +106,11 @@ void runNext({ previousCheckoutLocation: state.engine.checkoutPath, ); // check if the candidate branch is enabled in .ci.yaml - if (!engine.ciYaml.enabledBranches.contains(state.engine.candidateBranch)) { - engine.ciYaml.enableBranch(state.engine.candidateBranch); + final CiYaml engineCiYaml = await engine.ciYaml; + if (!engineCiYaml.enabledBranches.contains(state.engine.candidateBranch)) { + engineCiYaml.enableBranch(state.engine.candidateBranch); // commit - final String revision = engine.commit( + final String revision = await engine.commit( 'add branch ${state.engine.candidateBranch} to enabled_branches in .ci.yaml', addFirst: true, ); @@ -158,7 +159,7 @@ void runNext({ } } - engine.pushRef( + await engine.pushRef( fromRef: 'HEAD', // Explicitly create new branch toRef: 'refs/heads/${state.engine.workingBranch}', @@ -211,7 +212,7 @@ void runNext({ previousCheckoutLocation: state.engine.checkoutPath, ); - final String engineRevision = engine.reverseParse('HEAD'); + final String engineRevision = await engine.reverseParse('HEAD'); final Remote upstream = Remote( name: RemoteName.upstream, @@ -225,10 +226,10 @@ void runNext({ ); // Check if the current candidate branch is enabled - if (!framework.ciYaml.enabledBranches.contains(state.framework.candidateBranch)) { - framework.ciYaml.enableBranch(state.framework.candidateBranch); + if (!(await framework.ciYaml).enabledBranches.contains(state.framework.candidateBranch)) { + (await framework.ciYaml).enableBranch(state.framework.candidateBranch); // commit - final String revision = framework.commit( + final String revision = await framework.commit( 'add branch ${state.framework.candidateBranch} to enabled_branches in .ci.yaml', addFirst: true, ); @@ -240,9 +241,9 @@ void runNext({ } stdio.printStatus('Rolling new engine hash $engineRevision to framework checkout...'); - final bool needsCommit = framework.updateEngineRevision(engineRevision); + final bool needsCommit = await framework.updateEngineRevision(engineRevision); if (needsCommit) { - final String revision = framework.commit( + final String revision = await framework.commit( 'Update Engine revision to $engineRevision for ${state.releaseChannel} release ${state.releaseVersion}', addFirst: true, ); @@ -293,7 +294,7 @@ void runNext({ } } - framework.pushRef( + await framework.pushRef( fromRef: 'HEAD', // Explicitly create new branch toRef: 'refs/heads/${state.framework.workingBranch}', @@ -314,7 +315,7 @@ void runNext({ upstreamRemote: upstream, previousCheckoutLocation: state.framework.checkoutPath, ); - final String headRevision = framework.reverseParse('HEAD'); + final String headRevision = await framework.reverseParse('HEAD'); if (autoAccept == false) { final bool response = prompt( 'Are you ready to tag commit $headRevision as ${state.releaseVersion}\n' @@ -327,7 +328,7 @@ void runNext({ return; } } - framework.tag(headRevision, state.releaseVersion, upstream.name); + await framework.tag(headRevision, state.releaseVersion, upstream.name); break; case pb.ReleasePhase.PUBLISH_CHANNEL: final Remote upstream = Remote( @@ -341,10 +342,10 @@ void runNext({ upstreamRemote: upstream, previousCheckoutLocation: state.framework.checkoutPath, ); - final String headRevision = framework.reverseParse('HEAD'); + final String headRevision = await framework.reverseParse('HEAD'); if (autoAccept == false) { // dryRun: true means print out git command - framework.pushRef( + await framework.pushRef( fromRef: headRevision, toRef: state.releaseChannel, remote: state.framework.upstream.url, @@ -362,7 +363,7 @@ void runNext({ return; } } - framework.pushRef( + await framework.pushRef( fromRef: headRevision, toRef: state.releaseChannel, remote: state.framework.upstream.url, diff --git a/dev/conductor/lib/repository.dart b/dev/conductor/lib/repository.dart index 0aedf5ca6e3..38256c83ab5 100644 --- a/dev/conductor/lib/repository.dart +++ b/dev/conductor/lib/repository.dart @@ -58,34 +58,11 @@ abstract class Repository { required this.parentDirectory, this.initialRef, this.localUpstream = false, - String? previousCheckoutLocation, + this.previousCheckoutLocation, this.mirrorRemote, }) : git = Git(processManager), assert(localUpstream != null), - assert(upstreamRemote.url.isNotEmpty) { - if (previousCheckoutLocation != null) { - _checkoutDirectory = fileSystem.directory(previousCheckoutLocation); - if (!_checkoutDirectory!.existsSync()) { - throw ConductorException( - 'Provided previousCheckoutLocation $previousCheckoutLocation does not exist on disk!'); - } - if (initialRef != null) { - assert(initialRef != ''); - git.run( - ['fetch', upstreamRemote.name], - 'Fetch ${upstreamRemote.name} to ensure we have latest refs', - workingDirectory: _checkoutDirectory!.path, - ); - // Note: if [initialRef] is a remote ref the checkout will be left in a - // detached HEAD state. - git.run( - ['checkout', initialRef!], - 'Checking out initialRef $initialRef', - workingDirectory: _checkoutDirectory!.path, - ); - } - } - } + assert(upstreamRemote.url.isNotEmpty); final String name; final Remote upstreamRemote; @@ -109,22 +86,47 @@ abstract class Repository { final bool localUpstream; Directory? _checkoutDirectory; + String? previousCheckoutLocation; /// Directory for the repository checkout. /// /// Since cloning a repository takes a long time, we do not ensure it is /// cloned on the filesystem until this getter is accessed. - Directory get checkoutDirectory { + Future get checkoutDirectory async { if (_checkoutDirectory != null) { return _checkoutDirectory!; } + if (previousCheckoutLocation != null) { + _checkoutDirectory = fileSystem.directory(previousCheckoutLocation); + if (!_checkoutDirectory!.existsSync()) { + throw ConductorException( + 'Provided previousCheckoutLocation $previousCheckoutLocation does not exist on disk!'); + } + if (initialRef != null) { + assert(initialRef != ''); + await git.run( + ['fetch', upstreamRemote.name], + 'Fetch ${upstreamRemote.name} to ensure we have latest refs', + workingDirectory: _checkoutDirectory!.path, + ); + // Note: if [initialRef] is a remote ref the checkout will be left in a + // detached HEAD state. + await git.run( + ['checkout', initialRef!], + 'Checking out initialRef $initialRef', + workingDirectory: _checkoutDirectory!.path, + ); + } + return _checkoutDirectory!; + } + _checkoutDirectory = parentDirectory.childDirectory(name); - lazilyInitialize(_checkoutDirectory!); + await lazilyInitialize(_checkoutDirectory!); return _checkoutDirectory!; } /// Ensure the repository is cloned to disk and initialized with proper state. - void lazilyInitialize(Directory checkoutDirectory) { + Future lazilyInitialize(Directory checkoutDirectory) async { if (checkoutDirectory.existsSync()) { stdio.printTrace('Deleting $name from ${checkoutDirectory.path}...'); checkoutDirectory.deleteSync(recursive: true); @@ -133,7 +135,7 @@ abstract class Repository { stdio.printTrace( 'Cloning $name from ${upstreamRemote.url} to ${checkoutDirectory.path}...', ); - git.run( + await git.run( [ 'clone', '--origin', @@ -146,12 +148,12 @@ abstract class Repository { workingDirectory: parentDirectory.path, ); if (mirrorRemote != null) { - git.run( + await git.run( ['remote', 'add', mirrorRemote!.name, mirrorRemote!.url], 'Adding remote ${mirrorRemote!.url} as ${mirrorRemote!.name}', workingDirectory: checkoutDirectory.path, ); - git.run( + await git.run( ['fetch', mirrorRemote!.name], 'Fetching git remote ${mirrorRemote!.name}', workingDirectory: checkoutDirectory.path, @@ -161,7 +163,7 @@ abstract class Repository { // These branches must exist locally for the repo that depends on it // to fetch and push to. for (final String channel in kReleaseChannels) { - git.run( + await git.run( ['checkout', channel, '--'], 'check out branch $channel locally', workingDirectory: checkoutDirectory.path, @@ -170,82 +172,82 @@ abstract class Repository { } if (initialRef != null) { - git.run( + await git.run( ['checkout', '${upstreamRemote.name}/$initialRef'], 'Checking out initialRef $initialRef', workingDirectory: checkoutDirectory.path, ); } - final String revision = reverseParse('HEAD'); + final String revision = await reverseParse('HEAD'); stdio.printTrace( 'Repository $name is checked out at revision "$revision".', ); } /// The URL of the remote named [remoteName]. - String remoteUrl(String remoteName) { + Future remoteUrl(String remoteName) async { assert(remoteName != null); return git.getOutput( ['remote', 'get-url', remoteName], 'verify the URL of the $remoteName remote', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); } /// Verify the repository's git checkout is clean. - bool gitCheckoutClean() { - final String output = git.getOutput( + Future gitCheckoutClean() async { + final String output = await git.getOutput( ['status', '--porcelain'], 'check that the git checkout is clean', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); return output == ''; } /// Return the revision for the branch point between two refs. - String branchPoint(String firstRef, String secondRef) { - return git.getOutput( + Future branchPoint(String firstRef, String secondRef) async { + return (await git.getOutput( ['merge-base', firstRef, secondRef], 'determine the merge base between $firstRef and $secondRef', - workingDirectory: checkoutDirectory.path, - ).trim(); + workingDirectory: (await checkoutDirectory).path, + )).trim(); } /// Fetch all branches and associated commits and tags from [remoteName]. - void fetch(String remoteName) { - git.run( + Future fetch(String remoteName) async { + await git.run( ['fetch', remoteName, '--tags'], 'fetch $remoteName --tags', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); } /// Create (and checkout) a new branch based on the current HEAD. /// /// Runs `git checkout -b $branchName`. - void newBranch(String branchName) { - git.run( + Future newBranch(String branchName) async { + await git.run( ['checkout', '-b', branchName], 'create & checkout new branch $branchName', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); } /// Check out the given ref. - void checkout(String ref) { - git.run( + Future checkout(String ref) async { + await git.run( ['checkout', ref], 'checkout ref', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); } /// Obtain the version tag at the tip of a release branch. - String getFullTag( + Future getFullTag( String remoteName, String branchName, { bool exact = true, - }) { + }) async { // includes both stable (e.g. 1.2.3) and dev tags (e.g. 1.2.3-4.5.pre) const String glob = '*.*.*'; // describe the latest dev release @@ -260,34 +262,33 @@ abstract class Repository { ref, ], 'obtain last released version number', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); } /// List commits in reverse chronological order. - List revList(List args) { - return git - .getOutput(['rev-list', ...args], + Future> revList(List args) async { + return (await git.getOutput(['rev-list', ...args], 'rev-list with args ${args.join(' ')}', - workingDirectory: checkoutDirectory.path) + workingDirectory: (await checkoutDirectory).path)) .trim() .split('\n'); } /// Look up the commit for [ref]. - String reverseParse(String ref) { - final String revisionHash = git.getOutput( + Future reverseParse(String ref) async { + final String revisionHash = await git.getOutput( ['rev-parse', ref], 'look up the commit for the ref $ref', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); assert(revisionHash.isNotEmpty); return revisionHash; } /// Determines if one ref is an ancestor for another. - bool isAncestor(String possibleAncestor, String possibleDescendant) { - final int exitcode = git.run( + Future isAncestor(String possibleAncestor, String possibleDescendant) async { + final int exitcode = await git.run( [ 'merge-base', '--is-ancestor', @@ -296,83 +297,83 @@ abstract class Repository { ], 'verify $possibleAncestor is a direct ancestor of $possibleDescendant.', allowNonZeroExitCode: true, - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); return exitcode == 0; } /// Determines if a given commit has a tag. - bool isCommitTagged(String commit) { - final int exitcode = git.run( + Future isCommitTagged(String commit) async { + final int exitcode = await git.run( ['describe', '--exact-match', '--tags', commit], 'verify $commit is already tagged', allowNonZeroExitCode: true, - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); return exitcode == 0; } /// Determines if a commit will cherry-pick to current HEAD without conflict. - bool canCherryPick(String commit) { + Future canCherryPick(String commit) async { assert( - gitCheckoutClean(), - 'cannot cherry-pick because git checkout ${checkoutDirectory.path} is not clean', + await gitCheckoutClean(), + 'cannot cherry-pick because git checkout ${(await checkoutDirectory).path} is not clean', ); - final int exitcode = git.run( + final int exitcode = await git.run( ['cherry-pick', '--no-commit', commit], 'attempt to cherry-pick $commit without committing', allowNonZeroExitCode: true, - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); final bool result = exitcode == 0; if (result == false) { - stdio.printError(git.getOutput( + stdio.printError(await git.getOutput( ['diff'], 'get diff of failed cherry-pick', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, )); } - reset('HEAD'); + await reset('HEAD'); return result; } /// Cherry-pick a [commit] to the current HEAD. /// /// This method will throw a [GitException] if the command fails. - void cherryPick(String commit) { + Future cherryPick(String commit) async { assert( - gitCheckoutClean(), - 'cannot cherry-pick because git checkout ${checkoutDirectory.path} is not clean', + await gitCheckoutClean(), + 'cannot cherry-pick because git checkout ${(await checkoutDirectory).path} is not clean', ); - git.run( + await git.run( ['cherry-pick', commit], 'cherry-pick $commit', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); } /// Resets repository HEAD to [ref]. - void reset(String ref) { - git.run( + Future reset(String ref) async { + await git.run( ['reset', ref, '--hard'], 'reset to $ref', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); } /// Push [commit] to the release channel [branch]. - void pushRef({ + Future pushRef({ required String fromRef, required String remote, required String toRef, bool force = false, bool dryRun = false, - }) { + }) async { final List args = [ 'push', if (force) '--force', @@ -386,47 +387,48 @@ abstract class Repository { if (dryRun) { stdio.printStatus('About to execute command: `$command`'); } else { - git.run( + await git.run( args, 'update the release branch with the commit', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); stdio.printStatus('Executed command: `$command`'); } } - String commit( + Future commit( String message, { bool addFirst = false, - }) { + }) async { assert(!message.contains("'")); - final bool hasChanges = git.getOutput( + final bool hasChanges = (await git.getOutput( ['status', '--porcelain'], 'check for uncommitted changes', - workingDirectory: checkoutDirectory.path, - ).trim().isNotEmpty; + workingDirectory: (await checkoutDirectory).path, + )).trim().isNotEmpty; if (!hasChanges) { - throw ConductorException('Tried to commit with message $message but no changes were present'); + throw ConductorException( + 'Tried to commit with message $message but no changes were present'); } if (addFirst) { - git.run( + await git.run( ['add', '--all'], 'add all changes to the index', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); } - git.run( + await git.run( ['commit', "--message='$message'"], 'commit changes', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); return reverseParse('HEAD'); } /// Create an empty commit and return the revision. @visibleForTesting - String authorEmptyCommit([String message = 'An empty commit']) { - git.run( + Future authorEmptyCommit([String message = 'An empty commit']) async { + await git.run( [ '-c', 'user.name=Conductor', @@ -438,7 +440,7 @@ abstract class Repository { "'$message'", ], 'create an empty commit', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); return reverseParse('HEAD'); } @@ -450,7 +452,7 @@ abstract class Repository { /// /// This method is for testing purposes. @visibleForTesting - Repository cloneRepository(String cloneName); + Future cloneRepository(String cloneName); } class FrameworkRepository extends Repository { @@ -500,57 +502,66 @@ class FrameworkRepository extends Repository { } final Checkouts checkouts; - late final CiYaml ciYaml = CiYaml(checkoutDirectory.childFile('.ci.yaml')); static const String defaultUpstream = 'https://github.com/flutter/flutter.git'; static const String defaultBranch = 'master'; - String get cacheDirectory => fileSystem.path.join( - checkoutDirectory.path, - 'bin', - 'cache', - ); + Future get ciYaml async { + final CiYaml ciYaml = + CiYaml((await checkoutDirectory).childFile('.ci.yaml')); + return ciYaml; + } + + Future get cacheDirectory async { + return fileSystem.path.join( + (await checkoutDirectory).path, + 'bin', + 'cache', + ); + } /// Tag [commit] and push the tag to the remote. - void tag(String commit, String tagName, String remote) { + Future tag(String commit, String tagName, String remote) async { assert(commit.isNotEmpty); assert(tagName.isNotEmpty); assert(remote.isNotEmpty); stdio.printStatus('About to tag commit $commit as $tagName...'); - git.run( + await git.run( ['tag', tagName, commit], 'tag the commit with the version label', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); stdio.printStatus('Tagging successful.'); stdio.printStatus('About to push $tagName to remote $remote...'); - git.run( + await git.run( ['push', remote, tagName], 'publish the tag to the repo', - workingDirectory: checkoutDirectory.path, + workingDirectory: (await checkoutDirectory).path, ); stdio.printStatus('Tag push successful.'); } @override - Repository cloneRepository(String? cloneName) { + Future cloneRepository(String? cloneName) async { assert(localUpstream); cloneName ??= 'clone-of-$name'; return FrameworkRepository( checkouts, name: cloneName, upstreamRemote: Remote( - name: RemoteName.upstream, url: 'file://${checkoutDirectory.path}/'), + name: RemoteName.upstream, + url: 'file://${(await checkoutDirectory).path}/'), ); } - void _ensureToolReady() { - final File toolsStamp = - fileSystem.directory(cacheDirectory).childFile('flutter_tools.stamp'); + Future _ensureToolReady() async { + final File toolsStamp = fileSystem + .directory(await cacheDirectory) + .childFile('flutter_tools.stamp'); if (toolsStamp.existsSync()) { final String toolsStampHash = toolsStamp.readAsStringSync().trim(); - final String repoHeadHash = reverseParse('HEAD'); + final String repoHeadHash = await reverseParse('HEAD'); if (toolsStampHash == repoHeadHash) { return; } @@ -558,39 +569,38 @@ class FrameworkRepository extends Repository { stdio.printTrace('Building tool...'); // Build tool - processManager.runSync([ - fileSystem.path.join(checkoutDirectory.path, 'bin', 'flutter'), + await processManager.run([ + fileSystem.path.join((await checkoutDirectory).path, 'bin', 'flutter'), 'help', ]); } - io.ProcessResult runFlutter(List args) { - _ensureToolReady(); - - return processManager.runSync([ - fileSystem.path.join(checkoutDirectory.path, 'bin', 'flutter'), + Future runFlutter(List args) async { + await _ensureToolReady(); + return processManager.run([ + fileSystem.path.join((await checkoutDirectory).path, 'bin', 'flutter'), ...args, ]); } @override - void checkout(String ref) { - super.checkout(ref); + Future checkout(String ref) async { + await super.checkout(ref); // The tool will overwrite old cached artifacts, but not delete unused // artifacts from a previous version. Thus, delete the entire cache and // re-populate. - final Directory cache = fileSystem.directory(cacheDirectory); + final Directory cache = fileSystem.directory(await cacheDirectory); if (cache.existsSync()) { stdio.printTrace('Deleting cache...'); cache.deleteSync(recursive: true); } - _ensureToolReady(); + await _ensureToolReady(); } - Version flutterVersion() { + Future flutterVersion() async { // Check version final io.ProcessResult result = - runFlutter(['--version', '--machine']); + await runFlutter(['--version', '--machine']); final Map versionJson = jsonDecode( stdoutToString(result.stdout), ) as Map; @@ -600,12 +610,12 @@ class FrameworkRepository extends Repository { /// Update this framework's engine version file. /// /// Returns [true] if the version file was updated and a commit is needed. - bool updateEngineRevision( + Future updateEngineRevision( String newEngine, { @visibleForTesting File? engineVersionFile, - }) { + }) async { assert(newEngine.isNotEmpty); - engineVersionFile ??= checkoutDirectory + engineVersionFile ??= (await checkoutDirectory) .childDirectory('bin') .childDirectory('internal') .childFile('engine.version'); @@ -649,33 +659,33 @@ class HostFrameworkRepository extends FrameworkRepository { } @override - Directory get checkoutDirectory => _checkoutDirectory!; + Future get checkoutDirectory async => _checkoutDirectory!; @override - void newBranch(String branchName) { + Future newBranch(String branchName) async { throw ConductorException( 'newBranch not implemented for the host repository'); } @override - void checkout(String ref) { + Future checkout(String ref) async { throw ConductorException( 'checkout not implemented for the host repository'); } @override - String cherryPick(String commit) { + Future cherryPick(String commit) async { throw ConductorException( 'cherryPick not implemented for the host repository'); } @override - String reset(String ref) { + Future reset(String ref) async { throw ConductorException('reset not implemented for the host repository'); } @override - void tag(String commit, String tagName, String remote) { + Future tag(String commit, String tagName, String remote) async { throw ConductorException('tag not implemented for the host repository'); } @@ -691,7 +701,7 @@ class HostFrameworkRepository extends FrameworkRepository { } @override - String authorEmptyCommit([String message = 'An empty commit']) { + Future authorEmptyCommit([String message = 'An empty commit']) async { throw ConductorException( 'authorEmptyCommit not implemented for the host repository', ); @@ -724,18 +734,21 @@ class EngineRepository extends Repository { final Checkouts checkouts; - late final CiYaml ciYaml = CiYaml(checkoutDirectory.childFile('.ci.yaml')); + Future get ciYaml async { + final CiYaml ciYaml = CiYaml((await checkoutDirectory).childFile('.ci.yaml')); + return ciYaml; + } static const String defaultUpstream = 'https://github.com/flutter/engine.git'; static const String defaultBranch = 'master'; /// Update the `dart_revision` entry in the DEPS file. - void updateDartRevision( + Future updateDartRevision( String newRevision, { @visibleForTesting File? depsFile, - }) { + }) async { assert(newRevision.length == 40); - depsFile ??= checkoutDirectory.childFile('DEPS'); + depsFile ??= (await checkoutDirectory).childFile('DEPS'); final String fileContent = depsFile.readAsStringSync(); final RegExp dartPattern = RegExp("[ ]+'dart_revision': '([a-z0-9]{40})',"); final Iterable allMatches = @@ -755,14 +768,15 @@ class EngineRepository extends Repository { } @override - Repository cloneRepository(String? cloneName) { + Future cloneRepository(String? cloneName) async { assert(localUpstream); cloneName ??= 'clone-of-$name'; return EngineRepository( checkouts, name: cloneName, upstreamRemote: Remote( - name: RemoteName.upstream, url: 'file://${checkoutDirectory.path}/'), + name: RemoteName.upstream, + url: 'file://${(await checkoutDirectory).path}/'), ); } } diff --git a/dev/conductor/lib/roll_dev.dart b/dev/conductor/lib/roll_dev.dart index a5eaa504ed1..3598f93e85c 100644 --- a/dev/conductor/lib/roll_dev.dart +++ b/dev/conductor/lib/roll_dev.dart @@ -90,8 +90,8 @@ class RollDevCommand extends Command { 'For publishing a dev release without cherry picks.'; @override - void run() { - rollDev( + Future run() async { + await rollDev( argResults: argResults!, repository: FrameworkRepository(checkouts), stdio: stdio, @@ -104,12 +104,12 @@ class RollDevCommand extends Command { /// /// Returns true if publishing was successful, else false. @visibleForTesting -bool rollDev({ +Future rollDev({ required String usage, required ArgResults argResults, required Stdio stdio, required FrameworkRepository repository, -}) { +}) async { final String remoteName = argResults[kRemoteName] as String; final String? level = argResults[kIncrement] as String?; final String candidateBranch = argResults[kCandidateBranch] as String; @@ -124,30 +124,30 @@ bool rollDev({ 'and roll a new dev build.\n$usage'); } - final String remoteUrl = repository.remoteUrl(remoteName); + final String remoteUrl = await repository.remoteUrl(remoteName); - if (!repository.gitCheckoutClean()) { + if (!(await repository.gitCheckoutClean())) { throw Exception( 'Your git repository is not clean. Try running "git clean -fd". Warning, ' 'this will delete files! Run with -n to find out which ones.'); } - repository.fetch(remoteName); + await repository.fetch(remoteName); // Verify [commit] is valid - final String commit = repository.reverseParse(candidateBranch); + final String commit = await repository.reverseParse(candidateBranch); stdio.printStatus('remoteName is $remoteName'); // Get the name of the last dev release final Version lastVersion = Version.fromString( - repository.getFullTag(remoteName, 'dev'), + await repository.getFullTag(remoteName, 'dev'), ); final Version version = skipTagging ? lastVersion : Version.fromCandidateBranch(candidateBranch); final String tagName = version.toString(); - if (repository.reverseParse(lastVersion.toString()).contains(commit.trim())) { + if ((await repository.reverseParse(lastVersion.toString())).contains(commit.trim())) { throw Exception( 'Commit $commit is already on the dev branch as $lastVersion.'); } @@ -157,18 +157,18 @@ bool rollDev({ return false; } - if (skipTagging && !repository.isCommitTagged(commit)) { + if (skipTagging && !(await repository.isCommitTagged(commit))) { throw Exception( 'The $kSkipTagging flag is only supported for tagged commits.'); } - if (!force && !repository.isAncestor(commit, lastVersion.toString())) { + if (!force && !(await repository.isAncestor(commit, lastVersion.toString()))) { throw Exception( 'The previous dev tag $lastVersion is not a direct ancestor of $commit.\n' 'The flag "$kForce" is required to force push a new release past a cherry-pick.'); } - final String hash = repository.reverseParse(commit); + final String hash = await repository.reverseParse(commit); // [commit] can be a prefix for [hash]. assert(hash.startsWith(commit)); @@ -188,10 +188,10 @@ bool rollDev({ } if (!skipTagging) { - repository.tag(commit, version.toString(), remoteName); + await repository.tag(commit, version.toString(), remoteName); } - repository.pushRef( + await repository.pushRef( fromRef: commit, remote: remoteName, toRef: 'dev', diff --git a/dev/conductor/lib/start.dart b/dev/conductor/lib/start.dart index abe5584ab23..a1c672c84ee 100644 --- a/dev/conductor/lib/start.dart +++ b/dev/conductor/lib/start.dart @@ -101,14 +101,6 @@ class StartCommand extends Command { 'n': 'Indicates a hotfix to a dev or beta release.', }, ); - final Git git = Git(processManager); - conductorVersion = git.getOutput( - ['rev-parse', 'HEAD'], - 'look up the current revision.', - workingDirectory: flutterRoot.path, - ).trim(); - - assert(conductorVersion.isNotEmpty); } final Checkouts checkouts; @@ -132,7 +124,15 @@ class StartCommand extends Command { String get description => 'Initialize a new Flutter release.'; @override - void run() { + Future run() async { + final Git git = Git(processManager); + conductorVersion = (await git.getOutput( + ['rev-parse', 'HEAD'], + 'look up the current revision.', + workingDirectory: flutterRoot.path, + )).trim(); + + assert(conductorVersion.isNotEmpty); final ArgResults argumentResults = argResults!; if (!platform.isMacOS && !platform.isLinux) { throw ConductorException( @@ -231,42 +231,42 @@ class StartCommand extends Command { // Create a new branch so that we don't accidentally push to upstream // candidateBranch. final String workingBranchName = 'cherrypicks-$candidateBranch'; - engine.newBranch(workingBranchName); + await engine.newBranch(workingBranchName); if (dartRevision != null && dartRevision.isNotEmpty) { - engine.updateDartRevision(dartRevision); - engine.commit('Update Dart SDK to $dartRevision', addFirst: true); + await engine.updateDartRevision(dartRevision); + await engine.commit('Update Dart SDK to $dartRevision', addFirst: true); } - final List engineCherrypicks = _sortCherrypicks( + final List engineCherrypicks = (await _sortCherrypicks( repository: engine, cherrypicks: engineCherrypickRevisions, upstreamRef: EngineRepository.defaultBranch, releaseRef: candidateBranch, - ).map((String revision) => pb.Cherrypick( + )).map((String revision) => pb.Cherrypick( trunkRevision: revision, state: pb.CherrypickState.PENDING, )).toList(); for (final pb.Cherrypick cherrypick in engineCherrypicks) { final String revision = cherrypick.trunkRevision; - final bool success = engine.canCherryPick(revision); + final bool success = await engine.canCherryPick(revision); stdio.printTrace( 'Attempt to cherrypick $revision ${success ? 'succeeded' : 'failed'}', ); if (success) { - engine.cherryPick(revision); + await engine.cherryPick(revision); cherrypick.state = pb.CherrypickState.COMPLETED; } else { cherrypick.state = pb.CherrypickState.PENDING_WITH_CONFLICT; } } - final String engineHead = engine.reverseParse('HEAD'); + final String engineHead = await engine.reverseParse('HEAD'); state.engine = pb.Repository( candidateBranch: candidateBranch, workingBranch: workingBranchName, startingGitHead: engineHead, currentGitHead: engineHead, - checkoutPath: engine.checkoutDirectory.path, + checkoutPath: (await engine.checkoutDirectory).path, cherrypicks: engineCherrypicks, dartRevision: dartRevision, upstream: pb.Remote(name: 'upstream', url: engine.upstreamRemote.url), @@ -284,25 +284,25 @@ class StartCommand extends Command { url: frameworkMirror, ), ); - framework.newBranch(workingBranchName); - final List frameworkCherrypicks = _sortCherrypicks( + await framework.newBranch(workingBranchName); + final List frameworkCherrypicks = (await _sortCherrypicks( repository: framework, cherrypicks: frameworkCherrypickRevisions, upstreamRef: FrameworkRepository.defaultBranch, releaseRef: candidateBranch, - ).map((String revision) => pb.Cherrypick( + )).map((String revision) => pb.Cherrypick( trunkRevision: revision, state: pb.CherrypickState.PENDING, )).toList(); for (final pb.Cherrypick cherrypick in frameworkCherrypicks) { final String revision = cherrypick.trunkRevision; - final bool success = framework.canCherryPick(revision); + final bool success = await framework.canCherryPick(revision); stdio.printTrace( 'Attempt to cherrypick $cherrypick ${success ? 'succeeded' : 'failed'}', ); if (success) { - framework.cherryPick(revision); + await framework.cherryPick(revision); cherrypick.state = pb.CherrypickState.COMPLETED; } else { cherrypick.state = pb.CherrypickState.PENDING_WITH_CONFLICT; @@ -310,7 +310,9 @@ class StartCommand extends Command { } // Get framework version - final Version lastVersion = Version.fromString(framework.getFullTag(framework.upstreamRemote.name, candidateBranch, exact: false)); + final Version lastVersion = Version.fromString(await framework.getFullTag( + framework.upstreamRemote.name, candidateBranch, + exact: false)); Version nextVersion; if (incrementLetter == 'm') { nextVersion = Version.fromCandidateBranch(candidateBranch); @@ -333,13 +335,13 @@ class StartCommand extends Command { } state.releaseVersion = nextVersion.toString(); - final String frameworkHead = framework.reverseParse('HEAD'); + final String frameworkHead = await framework.reverseParse('HEAD'); state.framework = pb.Repository( candidateBranch: candidateBranch, workingBranch: workingBranchName, startingGitHead: frameworkHead, currentGitHead: frameworkHead, - checkoutPath: framework.checkoutDirectory.path, + checkoutPath: (await framework.checkoutDirectory).path, cherrypicks: frameworkCherrypicks, upstream: pb.Remote(name: 'upstream', url: framework.upstreamRemote.url), mirror: pb.Remote(name: 'mirror', url: framework.mirrorRemote!.url), @@ -357,12 +359,12 @@ class StartCommand extends Command { } // To minimize merge conflicts, sort the commits by rev-list order. - List _sortCherrypicks({ + Future> _sortCherrypicks({ required Repository repository, required List cherrypicks, required String upstreamRef, required String releaseRef, - }) { + }) async { if (cherrypicks.isEmpty) { return cherrypicks; } @@ -375,7 +377,7 @@ class StartCommand extends Command { final List sortedCherrypicks = []; for (final String cherrypick in cherrypicks) { try { - final String fullRef = repository.reverseParse(cherrypick); + final String fullRef = await repository.reverseParse(cherrypick); validatedCherrypicks.add(fullRef); } on GitException { // Catch this exception so that we can validate the rest. @@ -383,16 +385,16 @@ class StartCommand extends Command { } } - final String branchPoint = repository.branchPoint( + final String branchPoint = await repository.branchPoint( '${repository.upstreamRemote.name}/$upstreamRef', '${repository.upstreamRemote.name}/$releaseRef', ); // `git rev-list` returns newest first, so reverse this list - final List upstreamRevlist = repository.revList([ + final List upstreamRevlist = (await repository.revList([ '--ancestry-path', '$branchPoint..$upstreamRef', - ]).reversed.toList(); + ])).reversed.toList(); stdio.printStatus('upstreamRevList:\n${upstreamRevlist.join('\n')}\n'); stdio.printStatus('validatedCherrypicks:\n${validatedCherrypicks.join('\n')}\n'); diff --git a/dev/conductor/test/codesign_test.dart b/dev/conductor/test/codesign_test.dart index 91b4b0d6b2e..24b3e0d02ea 100644 --- a/dev/conductor/test/codesign_test.dart +++ b/dev/conductor/test/codesign_test.dart @@ -56,8 +56,8 @@ void main() { ); final FakeCodesignCommand command = FakeCodesignCommand( checkouts: checkouts, - binariesWithEntitlements: binariesWithEntitlements, - binariesWithoutEntitlements: binariesWithoutEntitlements, + binariesWithEntitlements: Future>.value(binariesWithEntitlements), + binariesWithoutEntitlements: Future>.value(binariesWithoutEntitlements), flutterRoot: fileSystem.directory(flutterRoot), ); runner = CommandRunner('codesign-test', '') @@ -326,8 +326,8 @@ void main() { ), ...codesignCheckCommands, ]); - expect( - () async => runner.run(['codesign', '--$kVerify', '--$kRevision', revision]), + await expectLater( + () => runner.run(['codesign', '--$kVerify', '--$kRevision', revision]), throwsExceptionWith('Test failed because unsigned binaries detected.'), ); expect(processManager.hasRemainingExpectations, false); @@ -413,8 +413,8 @@ void main() { ), ...codesignCheckCommands, ]); - expect( - () async => runner.run(['codesign', '--$kVerify', '--$kRevision', revision]), + await expectLater( + () => runner.run(['codesign', '--$kVerify', '--$kRevision', revision]), throwsExceptionWith('Test failed because files found with the wrong entitlements'), ); expect(processManager.hasRemainingExpectations, false); @@ -495,8 +495,8 @@ class FakeCodesignCommand extends CodesignCommand { }) : super(checkouts: checkouts, flutterRoot: flutterRoot); @override - final List binariesWithEntitlements; + final Future> binariesWithEntitlements; @override - final List binariesWithoutEntitlements; + final Future> binariesWithoutEntitlements; } diff --git a/dev/conductor/test/repository_test.dart b/dev/conductor/test/repository_test.dart index 04fb23a5f9a..f52c0e5c43d 100644 --- a/dev/conductor/test/repository_test.dart +++ b/dev/conductor/test/repository_test.dart @@ -25,7 +25,7 @@ void main() { ); }); - test('canCherryPick returns true if git cherry-pick returns 0', () { + test('canCherryPick returns true if git cherry-pick returns 0', () async { const String commit = 'abc123'; final TestStdio stdio = TestStdio(); @@ -73,10 +73,10 @@ void main() { stdio: stdio, ); final Repository repository = FrameworkRepository(checkouts); - expect(repository.canCherryPick(commit), true); + expect(await repository.canCherryPick(commit), true); }); - test('canCherryPick returns false if git cherry-pick returns non-zero', () { + test('canCherryPick returns false if git cherry-pick returns non-zero', () async { const String commit = 'abc123'; final TestStdio stdio = TestStdio(); @@ -128,10 +128,10 @@ void main() { stdio: stdio, ); final Repository repository = FrameworkRepository(checkouts); - expect(repository.canCherryPick(commit), false); + expect(await repository.canCherryPick(commit), false); }); - test('cherryPick() applies the commit', () { + test('cherryPick() applies the commit', () async { const String commit = 'abc123'; final TestStdio stdio = TestStdio(); @@ -172,11 +172,11 @@ void main() { stdio: stdio, ); final Repository repository = FrameworkRepository(checkouts); - repository.cherryPick(commit); + await repository.cherryPick(commit); expect(processManager.hasRemainingExpectations, false); }); - test('updateDartRevision() updates the DEPS file', () { + test('updateDartRevision() updates the DEPS file', () async { const String previousDartRevision = '171876a4e6cf56ee6da1f97d203926bd7afda7ef'; const String nextDartRevision = 'f6c91128be6b77aef8351e1e3a9d07c85bc2e46e'; final TestStdio stdio = TestStdio(); @@ -194,7 +194,7 @@ void main() { final EngineRepository repo = EngineRepository(checkouts); final File depsFile = fileSystem.file('/DEPS'); depsFile.writeAsStringSync(generateMockDeps(previousDartRevision)); - repo.updateDartRevision(nextDartRevision, depsFile: depsFile); + await repo.updateDartRevision(nextDartRevision, depsFile: depsFile); final String updatedDepsFileContent = depsFile.readAsStringSync(); expect(updatedDepsFileContent, generateMockDeps(nextDartRevision)); }); @@ -219,7 +219,7 @@ void main() { vars = { }'''); expect( - () => repo.updateDartRevision(nextDartRevision, depsFile: depsFile), + () async => repo.updateDartRevision(nextDartRevision, depsFile: depsFile), throwsExceptionWith('Unexpected content in the DEPS file at'), ); }); @@ -278,7 +278,7 @@ vars = { final EngineRepository repo = EngineRepository(checkouts); expect( - () => repo.commit(message), + () async => repo.commit(message), throwsExceptionWith('Tried to commit with message $message but no changes were present'), ); }); @@ -338,7 +338,7 @@ vars = { repo.commit(message); }); - test('updateEngineRevision() returns false if newCommit is the same as version file', () { + test('updateEngineRevision() returns false if newCommit is the same as version file', () async { const String commit1 = 'abc123'; const String commit2 = 'def456'; final TestStdio stdio = TestStdio(); @@ -371,7 +371,7 @@ vars = { ); final FrameworkRepository repo = FrameworkRepository(checkouts); - final bool didUpdate = repo.updateEngineRevision(commit2, engineVersionFile: engineVersionFile); + final bool didUpdate = await repo.updateEngineRevision(commit2, engineVersionFile: engineVersionFile); expect(didUpdate, false); }); @@ -385,7 +385,7 @@ vars = { ); }); - test('ciYaml.enableBranch() will prepend the given branch to the yaml list of enabled_branches', () { + test('ciYaml.enableBranch() will prepend the given branch to the yaml list of enabled_branches', () async { const String commit1 = 'abc123'; final TestStdio stdio = TestStdio(); final MemoryFileSystem fileSystem = MemoryFileSystem.test(); @@ -430,18 +430,18 @@ enabled_branches: final FrameworkRepository framework = FrameworkRepository(checkouts); expect( - framework.ciYaml.enabledBranches, + (await framework.ciYaml).enabledBranches, ['master', 'dev', 'beta', 'stable'], ); - framework.ciYaml.enableBranch('foo'); + (await framework.ciYaml).enableBranch('foo'); expect( - framework.ciYaml.enabledBranches, + (await framework.ciYaml).enabledBranches, ['foo', 'master', 'dev', 'beta', 'stable'], ); expect( - framework.ciYaml.stringContents, + (await framework.ciYaml).stringContents, ''' # Friendly note @@ -498,7 +498,7 @@ enabled_branches: final FrameworkRepository framework = FrameworkRepository(checkouts); expect( - () => framework.ciYaml.enableBranch('master'), + () async => (await framework.ciYaml).enableBranch('master'), throwsExceptionWith('.ci.yaml already contains the branch master'), ); }); diff --git a/dev/conductor/test/roll_dev_test.dart b/dev/conductor/test/roll_dev_test.dart index acac496a921..001fd6cad48 100644 --- a/dev/conductor/test/roll_dev_test.dart +++ b/dev/conductor/test/roll_dev_test.dart @@ -51,7 +51,7 @@ void main() { remote: remote, ); expect( - () => rollDev( + () async => rollDev( argResults: fakeArgResults, repository: repo, stdio: stdio, @@ -95,7 +95,7 @@ void main() { remote: remote, ); expect( - () => rollDev( + () async => rollDev( argResults: fakeArgResults, repository: repo, stdio: stdio, @@ -105,7 +105,7 @@ void main() { ); }); - test('does not reset or tag if --just-print is specified', () { + test('does not reset or tag if --just-print is specified', () async { processManager.addCommands([ const FakeCommand(command: [ 'git', @@ -166,7 +166,7 @@ void main() { justPrint: true, ); expect( - rollDev( + await rollDev( usage: usage, argResults: fakeArgResults, repository: repo, @@ -249,7 +249,7 @@ void main() { skipTagging: true, ); expect( - () => rollDev( + () async => rollDev( usage: usage, argResults: fakeArgResults, repository: repo, @@ -320,7 +320,7 @@ void main() { justPrint: true, ); expect( - () => rollDev( + () async => rollDev( usage: usage, argResults: fakeArgResults, repository: repo, @@ -403,7 +403,7 @@ void main() { const String errorMessage = 'The previous dev tag $lastVersion is not a ' 'direct ancestor of $commit.'; expect( - () => rollDev( + () async => rollDev( argResults: fakeArgResults, repository: repo, stdio: stdio, @@ -413,7 +413,7 @@ void main() { ); }); - test('does not tag but updates branch if --skip-tagging provided', () { + test('does not tag but updates branch if --skip-tagging provided', () async { processManager.addCommands([ const FakeCommand(command: [ 'git', @@ -498,7 +498,7 @@ void main() { skipTagging: true, ); expect( - rollDev( + await rollDev( usage: usage, argResults: fakeArgResults, repository: repo, @@ -508,7 +508,7 @@ void main() { ); }); - test('successfully tags and publishes release', () { + test('successfully tags and publishes release', () async { processManager.addCommands([ const FakeCommand(command: [ 'git', @@ -597,7 +597,7 @@ void main() { remote: remote, ); expect( - rollDev( + await rollDev( usage: usage, argResults: fakeArgResults, repository: repo, @@ -607,7 +607,7 @@ void main() { ); }); - test('successfully publishes release with --force', () { + test('successfully publishes release with --force', () async { processManager.addCommands([ const FakeCommand(command: [ 'git', @@ -692,7 +692,7 @@ void main() { force: true, ); expect( - rollDev( + await rollDev( argResults: fakeArgResults, repository: repo, stdio: stdio,