diff --git a/packages/flutter_tools/lib/src/base/user_messages.dart b/packages/flutter_tools/lib/src/base/user_messages.dart index 5aa6f2ea1e1b2..8441db2a7df04 100644 --- a/packages/flutter_tools/lib/src/base/user_messages.dart +++ b/packages/flutter_tools/lib/src/base/user_messages.dart @@ -21,7 +21,7 @@ class UserMessages { // Messages used in FlutterValidator String flutterStatusInfo(String? channel, String? version, String os, String locale) => - 'Channel ${channel ?? 'unknown'}, ${version ?? 'Unknown'}, on $os, locale $locale'; + 'Channel ${channel ?? 'unknown'}, ${version ?? 'unknown version'}, on $os, locale $locale'; String flutterVersion(String version, String channel, String flutterRoot) => 'Flutter version $version on channel $channel at $flutterRoot'; String get flutterUnknownChannel => diff --git a/packages/flutter_tools/lib/src/commands/channel.dart b/packages/flutter_tools/lib/src/commands/channel.dart index 80d9bda409030..5a8695ed16438 100644 --- a/packages/flutter_tools/lib/src/commands/channel.dart +++ b/packages/flutter_tools/lib/src/commands/channel.dart @@ -53,13 +53,12 @@ class ChannelCommand extends FlutterCommand { Future _listChannels({ required bool showAll, required bool verbose }) async { // Beware: currentBranch could contain PII. See getBranchName(). - final String currentChannel = globals.flutterVersion.channel; + final String currentChannel = globals.flutterVersion.channel; // limited to known branch names + assert(kOfficialChannels.contains(currentChannel) || kObsoleteBranches.containsKey(currentChannel) || currentChannel == kUserBranch, 'potential PII leak in channel name: "$currentChannel"'); final String currentBranch = globals.flutterVersion.getBranchName(); final Set seenUnofficialChannels = {}; final List rawOutput = []; - showAll = showAll || currentChannel != currentBranch; - globals.printStatus('Flutter channels:'); final int result = await globals.processUtils.stream( ['git', 'branch', '-r'], @@ -74,8 +73,7 @@ class ChannelCommand extends FlutterCommand { throwToolExit('List channels failed: $result$details', exitCode: result); } - final List officialChannels = kOfficialChannels.toList(); - final List availableChannels = List.filled(officialChannels.length, false); + final Set availableChannels = {}; for (final String line in rawOutput) { final List split = line.split('/'); @@ -84,27 +82,25 @@ class ChannelCommand extends FlutterCommand { continue; } final String branch = split[1]; - if (split.length > 1) { - final int index = officialChannels.indexOf(branch); - - if (index != -1) { // Mark all available channels official channels from output - availableChannels[index] = true; - } else if (showAll && !seenUnofficialChannels.contains(branch)) { - // add other branches to seenUnofficialChannels if --all flag is given (to print later) - seenUnofficialChannels.add(branch); - } + if (kOfficialChannels.contains(branch)) { + availableChannels.add(branch); + } else if (showAll) { + seenUnofficialChannels.add(branch); } } + bool currentChannelIsOfficial = false; + // print all available official channels in sorted manner - for (int i = 0; i < officialChannels.length; i++) { + for (final String channel in kOfficialChannels) { // only print non-missing channels - if (availableChannels[i]) { + if (availableChannels.contains(channel)) { String currentIndicator = ' '; - if (officialChannels[i] == currentChannel) { + if (channel == currentChannel) { currentIndicator = '*'; + currentChannelIsOfficial = true; } - globals.printStatus('$currentIndicator ${officialChannels[i]}'); + globals.printStatus('$currentIndicator $channel (${kChannelDescriptions[channel]})'); } } @@ -117,9 +113,12 @@ class ChannelCommand extends FlutterCommand { globals.printStatus(' $branch'); } } + } else if (!currentChannelIsOfficial) { + globals.printStatus('* $currentBranch'); } - if (currentChannel == 'unknown') { + if (!currentChannelIsOfficial) { + assert(currentChannel == kUserBranch, 'Current channel is "$currentChannel", which is not an official branch. (Current branch is "$currentBranch".)'); globals.printStatus(''); globals.printStatus('Currently not on an official channel.'); } diff --git a/packages/flutter_tools/lib/src/commands/create_base.dart b/packages/flutter_tools/lib/src/commands/create_base.dart index c8dba571c5d5a..90c3fa00bbb82 100644 --- a/packages/flutter_tools/lib/src/commands/create_base.dart +++ b/packages/flutter_tools/lib/src/commands/create_base.dart @@ -407,8 +407,8 @@ abstract class CreateBase extends FlutterCommand { 'iosLanguage': iosLanguage, 'hasIosDevelopmentTeam': iosDevelopmentTeam != null && iosDevelopmentTeam.isNotEmpty, 'iosDevelopmentTeam': iosDevelopmentTeam ?? '', - 'flutterRevision': globals.flutterVersion.frameworkRevision, - 'flutterChannel': globals.flutterVersion.channel, + 'flutterRevision': escapeYamlString(globals.flutterVersion.frameworkRevision), + 'flutterChannel': escapeYamlString(globals.flutterVersion.getBranchName()), // may contain PII 'ios': ios, 'android': android, 'web': web, @@ -571,10 +571,11 @@ abstract class CreateBase extends FlutterCommand { final FlutterProjectMetadata metadata = FlutterProjectMetadata.explicit( file: metadataFile, versionRevision: globals.flutterVersion.frameworkRevision, - versionChannel: globals.flutterVersion.channel, + versionChannel: globals.flutterVersion.getBranchName(), // may contain PII projectType: projectType, migrateConfig: MigrateConfig(), - logger: globals.logger); + logger: globals.logger, + ); metadata.populate( platforms: platformsForMigrateConfig, projectDirectory: directory, diff --git a/packages/flutter_tools/lib/src/commands/downgrade.dart b/packages/flutter_tools/lib/src/commands/downgrade.dart index 8206c8dba63a0..a27482aa87902 100644 --- a/packages/flutter_tools/lib/src/commands/downgrade.dart +++ b/packages/flutter_tools/lib/src/commands/downgrade.dart @@ -47,15 +47,15 @@ class DowngradeCommand extends FlutterCommand { 'working-directory', hide: !verboseHelp, help: 'Override the downgrade working directory. ' - 'This is only intended to enable integration testing of the tool itself.' + 'This is only intended to enable integration testing of the tool itself. ' + 'It allows one to use the flutter tool from one checkout to downgrade a ' + 'different checkout.' ); argParser.addFlag( 'prompt', defaultsTo: true, hide: !verboseHelp, - help: 'Show the downgrade prompt. ' - 'The ability to disable this using "--no-prompt" is only provided for ' - 'integration testing of the tool itself.' + help: 'Show the downgrade prompt.' ); } @@ -99,8 +99,8 @@ class DowngradeCommand extends FlutterCommand { final Channel? channel = getChannelForName(currentChannel); if (channel == null) { throwToolExit( - 'Flutter is not currently on a known channel. Use "flutter channel " ' - 'to switch to an official channel.', + 'Flutter is not currently on a known channel. ' + 'Use "flutter channel" to switch to an official channel. ' ); } final PersistentToolState persistentToolState = _persistentToolState!; @@ -153,13 +153,14 @@ class DowngradeCommand extends FlutterCommand { } on ProcessException catch (error) { throwToolExit( 'Unable to downgrade Flutter: The tool could not update to the version ' - '$humanReadableVersion. This may be due to git not being installed or an ' - 'internal error. Please ensure that git is installed on your computer and ' - 'retry again.\nError: $error.' + '$humanReadableVersion.\n' + 'Error: $error' ); } try { await processUtils.run( + // The `--` bit (because it's followed by nothing) means that we don't actually change + // anything in the working tree, which avoids the need to first go into detached HEAD mode. ['git', 'checkout', currentChannel, '--'], throwOnError: true, workingDirectory: workingDirectory, @@ -167,9 +168,8 @@ class DowngradeCommand extends FlutterCommand { } on ProcessException catch (error) { throwToolExit( 'Unable to downgrade Flutter: The tool could not switch to the channel ' - '$currentChannel. This may be due to git not being installed or an ' - 'internal error. Please ensure that git is installed on your computer ' - 'and retry again.\nError: $error.' + '$currentChannel.\n' + 'Error: $error' ); } await FlutterVersion.resetFlutterVersionFreshnessCheck(); diff --git a/packages/flutter_tools/lib/src/doctor.dart b/packages/flutter_tools/lib/src/doctor.dart index 5744df33d781d..3978d0d77654f 100644 --- a/packages/flutter_tools/lib/src/doctor.dart +++ b/packages/flutter_tools/lib/src/doctor.dart @@ -577,14 +577,14 @@ class FlutterValidator extends DoctorValidator { ValidationMessage _getFlutterVersionMessage(String frameworkVersion, String versionChannel, String flutterRoot) { String flutterVersionMessage = _userMessages.flutterVersion(frameworkVersion, versionChannel, flutterRoot); - // The tool sets the channel as "unknown", if the current branch is on a - // "detached HEAD" state or doesn't have an upstream, and sets the - // frameworkVersion as "0.0.0-unknown" if "git describe" on HEAD doesn't - // produce an expected format to be parsed for the frameworkVersion. - if (versionChannel != 'unknown' && frameworkVersion != '0.0.0-unknown') { + // The tool sets the channel as kUserBranch, if the current branch is on a + // "detached HEAD" state, doesn't have an upstream, or is on a user branch, + // and sets the frameworkVersion as "0.0.0-unknown" if "git describe" on + // HEAD doesn't produce an expected format to be parsed for the frameworkVersion. + if (versionChannel != kUserBranch && frameworkVersion != '0.0.0-unknown') { return ValidationMessage(flutterVersionMessage); } - if (versionChannel == 'unknown') { + if (versionChannel == kUserBranch) { flutterVersionMessage = '$flutterVersionMessage\n${_userMessages.flutterUnknownChannel}'; } if (frameworkVersion == '0.0.0-unknown') { diff --git a/packages/flutter_tools/lib/src/flutter_project_metadata.dart b/packages/flutter_tools/lib/src/flutter_project_metadata.dart index c94693988b2ff..708f79fd5c72a 100644 --- a/packages/flutter_tools/lib/src/flutter_project_metadata.dart +++ b/packages/flutter_tools/lib/src/flutter_project_metadata.dart @@ -8,6 +8,7 @@ import 'base/file_system.dart'; import 'base/logger.dart'; import 'base/utils.dart'; import 'project.dart'; +import 'template.dart'; import 'version.dart'; enum FlutterProjectType implements CliEnum { @@ -172,11 +173,11 @@ class FlutterProjectMetadata { # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled. +# This file should be version controlled and should not be manually edited. version: - revision: $_versionRevision - channel: $_versionChannel + revision: ${escapeYamlString(_versionRevision ?? '')} + channel: ${escapeYamlString(_versionChannel ?? kUserBranch)} project_type: ${projectType == null ? '' : projectType!.cliName} ${migrateConfig.getOutputFileString()}'''; diff --git a/packages/flutter_tools/lib/src/globals.dart b/packages/flutter_tools/lib/src/globals.dart index bf3571bec5bfe..0f239393c7299 100644 --- a/packages/flutter_tools/lib/src/globals.dart +++ b/packages/flutter_tools/lib/src/globals.dart @@ -300,9 +300,6 @@ CustomDevicesConfig get customDevicesConfig => context.get( PreRunValidator get preRunValidator => context.get() ?? const NoOpPreRunValidator(); -// TODO(fujino): Migrate to 'main' https://github.com/flutter/flutter/issues/95041 -const String kDefaultFrameworkChannel = 'master'; - // Used to build RegExp instances which can detect the VM service message. final RegExp kVMServiceMessageRegExp = RegExp(r'The Dart VM service is listening on ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+)'); diff --git a/packages/flutter_tools/lib/src/template.dart b/packages/flutter_tools/lib/src/template.dart index c476e27a21526..19a8c948a7382 100644 --- a/packages/flutter_tools/lib/src/template.dart +++ b/packages/flutter_tools/lib/src/template.dart @@ -375,3 +375,24 @@ String _escapeKotlinKeywords(String androidIdentifier) { ).toList(); return correctedSegments.join('.'); } + +String escapeYamlString(String value) { + final StringBuffer result = StringBuffer(); + result.write('"'); + for (final int rune in value.runes) { + result.write( + switch (rune) { + 0x00 => r'\0', + 0x09 => r'\t', + 0x0A => r'\n', + 0x0D => r'\r', + 0x22 => r'\"', + 0x5C => r'\\', + < 0x20 => '\\x${rune.toRadixString(16).padLeft(2, "0")}', + _ => String.fromCharCode(rune), + } + ); + } + result.write('"'); + return result.toString(); +} diff --git a/packages/flutter_tools/lib/src/version.dart b/packages/flutter_tools/lib/src/version.dart index edb8b756fe895..bae196f14b0fe 100644 --- a/packages/flutter_tools/lib/src/version.dart +++ b/packages/flutter_tools/lib/src/version.dart @@ -22,6 +22,9 @@ const String _unknownFrameworkVersion = '0.0.0-unknown'; /// See `man gitrevisions` for more information. const String kGitTrackingUpstream = '@{upstream}'; +/// Replacement name when the branch is user-specific. +const String kUserBranch = '[user-branch]'; + /// This maps old branch names to the names of branches that replaced them. /// /// For example, in 2021 we deprecated the "dev" channel and transitioned "dev" @@ -40,12 +43,24 @@ enum Channel { // Beware: Keep order in accordance with stability const Set kOfficialChannels = { - globals.kDefaultFrameworkChannel, + 'master', 'main', 'beta', 'stable', }; +const Map kChannelDescriptions = { + 'master': 'latest development branch, for contributors', + 'main': 'latest development branch, follows master channel', + 'beta': 'updated monthly, recommended for experienced users', + 'stable': 'updated quarterly, for new users and for production app releases', +}; + +const Set kDevelopmentChannels = { + 'master', + 'main', +}; + /// Retrieve a human-readable name for a given [channel]. /// /// Requires [kOfficialChannels] to be correctly ordered. @@ -101,16 +116,7 @@ class FlutterVersion { String? _repositoryUrl; String? get repositoryUrl { - final String _ = channel; - return _repositoryUrl; - } - - String? _channel; - /// The channel is the upstream branch. - /// `master`, `dev`, `beta`, `stable`; or old ones, like `alpha`, `hackathon`, ... - String get channel { - String? channel = _channel; - if (channel == null) { + if (_repositoryUrl == null) { final String gitChannel = _runGit( 'git rev-parse --abbrev-ref --symbolic $kGitTrackingUpstream', globals.processUtils, @@ -124,14 +130,16 @@ class FlutterVersion { globals.processUtils, _workingDirectory, ); - channel = gitChannel.substring(slash + 1); - } else if (gitChannel.isEmpty) { - channel = 'unknown'; - } else { - channel = gitChannel; } - _channel = channel; } + return _repositoryUrl; + } + + /// The channel is the current branch if we recognize it, or "[user-branch]" (kUserBranch). + /// `master`, `beta`, `stable`; or old ones, like `alpha`, `hackathon`, `dev`, ... + String get channel { + final String channel = getBranchName(redactUnknownBranches: true); + assert(kOfficialChannels.contains(channel) || kObsoleteBranches.containsKey(channel) || channel == kUserBranch, 'Potential PII leak in channel name: "$channel"'); return channel; } @@ -296,16 +304,16 @@ class FlutterVersion { /// Return the branch name. /// /// If [redactUnknownBranches] is true and the branch is unknown, - /// the branch name will be returned as `'[user-branch]'`. + /// the branch name will be returned as `'[user-branch]'` ([kUserBranch]). String getBranchName({ bool redactUnknownBranches = false }) { _branch ??= () { - final String branch = _runGit('git rev-parse --abbrev-ref HEAD', globals.processUtils); - return branch == 'HEAD' ? channel : branch; + final String branch = _runGit('git symbolic-ref --short HEAD', globals.processUtils, _workingDirectory); + return branch == 'HEAD' ? '' : branch; }(); if (redactUnknownBranches || _branch!.isEmpty) { // Only return the branch names we know about; arbitrary branch names might contain PII. if (!kOfficialChannels.contains(_branch) && !kObsoleteBranches.containsKey(_branch)) { - return '[user-branch]'; + return kUserBranch; } } return _branch!; @@ -619,7 +627,7 @@ String _runSync(List command, { bool lenient = true }) { return ''; } -String _runGit(String command, ProcessUtils processUtils, [String? workingDirectory]) { +String _runGit(String command, ProcessUtils processUtils, String? workingDirectory) { return processUtils.runSync( command.split(' '), workingDirectory: workingDirectory ?? Cache.flutterRoot, @@ -709,8 +717,8 @@ class GitTagVersion { String gitRef = 'HEAD' }) { if (fetchTags) { - final String channel = _runGit('git rev-parse --abbrev-ref HEAD', processUtils, workingDirectory); - if (channel == 'dev' || channel == 'beta' || channel == 'stable') { + final String channel = _runGit('git symbolic-ref --short HEAD', processUtils, workingDirectory); + if (!kDevelopmentChannels.contains(channel) && kOfficialChannels.contains(channel)) { globals.printTrace('Skipping request to fetchTags - on well known channel $channel.'); } else { final String flutterGit = platform.environment['FLUTTER_GIT_URL'] ?? 'https://github.com/flutter/flutter.git'; @@ -918,8 +926,6 @@ class VersionFreshnessValidator { return const Duration(days: 365 ~/ 2); // Six months case 'beta': return const Duration(days: 7 * 8); // Eight weeks - case 'dev': - return const Duration(days: 7 * 4); // Four weeks default: return const Duration(days: 7 * 3); // Three weeks } diff --git a/packages/flutter_tools/test/commands.shard/hermetic/downgrade_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/downgrade_test.dart index 90b2e6ee3c0ee..5830675704521 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/downgrade_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/downgrade_test.dart @@ -41,7 +41,7 @@ void main() { }); testUsingContext('Downgrade exits on unknown channel', () async { - final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(); + final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(branch: 'WestSideStory'); // an unknown branch fileSystem.currentDirectory.childFile('.flutter_tool_state') .writeAsStringSync('{"last-active-master-version":"invalid"}'); final DowngradeCommand command = DowngradeCommand( @@ -58,7 +58,7 @@ void main() { }); testUsingContext('Downgrade exits on no recorded version', () async { - final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'beta'); + final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(branch: 'beta'); fileSystem.currentDirectory.childFile('.flutter_tool_state') .writeAsStringSync('{"last-active-master-version":"abcd"}'); final DowngradeCommand command = DowngradeCommand( @@ -86,7 +86,7 @@ void main() { }); testUsingContext('Downgrade exits on unknown recorded version', () async { - final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'master'); + final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(); fileSystem.currentDirectory.childFile('.flutter_tool_state') .writeAsStringSync('{"last-active-master-version":"invalid"}'); final DowngradeCommand command = DowngradeCommand( @@ -110,7 +110,7 @@ void main() { }); testUsingContext('Downgrade prompts for user input when terminal is attached - y', () async { - final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'master'); + final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(); stdio.hasTerminal = true; fileSystem.currentDirectory.childFile('.flutter_tool_state') .writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}'); @@ -131,7 +131,7 @@ void main() { }); testUsingContext('Downgrade prompts for user input when terminal is attached - n', () async { - final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'master'); + final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(); stdio.hasTerminal = true; fileSystem.currentDirectory.childFile('.flutter_tool_state') .writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}'); @@ -152,7 +152,7 @@ void main() { }); testUsingContext('Downgrade does not prompt when there is no terminal', () async { - final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'master'); + final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(); stdio.hasTerminal = false; fileSystem.currentDirectory.childFile('.flutter_tool_state') .writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}'); @@ -174,7 +174,7 @@ void main() { }); testUsingContext('Downgrade performs correct git commands', () async { - final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'master'); + final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(); stdio.hasTerminal = false; fileSystem.currentDirectory.childFile('.flutter_tool_state') .writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}'); diff --git a/packages/flutter_tools/test/commands.shard/hermetic/upgrade_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/upgrade_test.dart index 9d07f82170a87..2a1db24d57a75 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/upgrade_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/upgrade_test.dart @@ -114,7 +114,7 @@ void main() { expect(logger.statusText, contains("Transitioning from 'dev' to 'beta'...")); }, overrides: { FileSystem: () => fileSystem, - FlutterVersion: () => FakeFlutterVersion(channel: 'dev'), + FlutterVersion: () => FakeFlutterVersion(branch: 'dev'), Logger: () => logger, ProcessManager: () => processManager, }); @@ -197,7 +197,7 @@ void main() { ); }, overrides: { FileSystem: () => fileSystem, - FlutterVersion: () => FakeFlutterVersion(channel: 'master', frameworkVersion: startingTag, engineRevision: 'engine'), + FlutterVersion: () => FakeFlutterVersion(frameworkVersion: startingTag, engineRevision: 'engine'), Logger: () => logger, ProcessManager: () => processManager, }); @@ -264,7 +264,7 @@ void main() { ); }, overrides: { FileSystem: () => fileSystem, - FlutterVersion: () => FakeFlutterVersion(channel: 'beta', frameworkVersion: startingTag, engineRevision: 'engine'), + FlutterVersion: () => FakeFlutterVersion(branch: 'beta', frameworkVersion: startingTag, engineRevision: 'engine'), Logger: () => logger, ProcessManager: () => processManager, }); diff --git a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart index 726d0f0425c07..9069a35351744 100644 --- a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart +++ b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart @@ -78,7 +78,7 @@ void main() { projectDir = tempDir.childDirectory('flutter_project'); fakeFlutterVersion = FakeFlutterVersion( frameworkRevision: frameworkRevision, - channel: frameworkChannel, + branch: frameworkChannel, ); fakeProcessManager = FakeProcessManager.empty(); mockStdio = FakeStdio(); @@ -1269,8 +1269,8 @@ void main() { expectExists(versionPath); final String version = globals.fs.file(globals.fs.path.join(projectDir.path, versionPath)).readAsStringSync(); expect(version, contains('version:')); - expect(version, contains('revision: 12345678')); - expect(version, contains('channel: omega')); + expect(version, contains('revision: "12345678"')); + expect(version, contains('channel: "omega"')); // IntelliJ metadata final String intelliJSdkMetadataPath = globals.fs.path.join('.idea', 'libraries', 'Dart_SDK.xml'); @@ -1349,8 +1349,8 @@ void main() { expectExists(versionPath); final String version = globals.fs.file(globals.fs.path.join(projectDir.path, versionPath)).readAsStringSync(); expect(version, contains('version:')); - expect(version, contains('revision: 12345678')); - expect(version, contains('channel: omega')); + expect(version, contains('revision: "12345678"')); + expect(version, contains('channel: "omega"')); // IntelliJ metadata final String intelliJSdkMetadataPath = globals.fs.path.join('.idea', 'libraries', 'Dart_SDK.xml'); diff --git a/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart b/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart index ae507da6b5235..bddf42d0b3623 100644 --- a/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart +++ b/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart @@ -46,7 +46,7 @@ void main() { }); testUsingContext('throws on unknown tag, official branch, noforce', () async { - final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: 'beta'); + final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: 'beta'); const String upstreamRevision = ''; final FakeFlutterVersion latestVersion = FakeFlutterVersion(frameworkRevision: upstreamRevision); fakeCommandRunner.remoteVersion = latestVersion; @@ -66,7 +66,7 @@ void main() { }); testUsingContext('throws tool exit with uncommitted changes', () async { - final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: 'beta'); + final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: 'beta'); const String upstreamRevision = ''; final FakeFlutterVersion latestVersion = FakeFlutterVersion(frameworkRevision: upstreamRevision); fakeCommandRunner.remoteVersion = latestVersion; @@ -89,7 +89,7 @@ void main() { testUsingContext("Doesn't continue on known tag, beta branch, no force, already up-to-date", () async { const String revision = 'abc123'; final FakeFlutterVersion latestVersion = FakeFlutterVersion(frameworkRevision: revision); - final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: 'beta', frameworkRevision: revision); + final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: 'beta', frameworkRevision: revision); fakeCommandRunner.alreadyUpToDate = true; fakeCommandRunner.remoteVersion = latestVersion; @@ -116,7 +116,7 @@ void main() { const String upstreamVersion = '4.5.6'; final FakeFlutterVersion flutterVersion = FakeFlutterVersion( - channel: 'beta', + branch: 'beta', frameworkRevision: revision, frameworkRevisionShort: revision, frameworkVersion: version, @@ -287,7 +287,7 @@ void main() { const String upstreamVersion = '4.5.6'; final FakeFlutterVersion flutterVersion = FakeFlutterVersion( - channel: 'beta', + branch: 'beta', frameworkRevision: revision, frameworkVersion: version, ); @@ -348,7 +348,7 @@ void main() { testUsingContext('does not throw on unknown tag, official branch, force', () async { fakeCommandRunner.remoteVersion = FakeFlutterVersion(frameworkRevision: '1234'); - final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: 'beta'); + final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: 'beta'); final Future result = fakeCommandRunner.runCommand( force: true, @@ -366,7 +366,7 @@ void main() { }); testUsingContext('does not throw tool exit with uncommitted changes and force', () async { - final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: 'beta'); + final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: 'beta'); fakeCommandRunner.remoteVersion = FakeFlutterVersion(frameworkRevision: '1234'); fakeCommandRunner.willHaveUncommittedChanges = true; @@ -386,7 +386,7 @@ void main() { }); testUsingContext("Doesn't throw on known tag, beta branch, no force", () async { - final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: 'beta'); + final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: 'beta'); fakeCommandRunner.remoteVersion = FakeFlutterVersion(frameworkRevision: '1234'); final Future result = fakeCommandRunner.runCommand( diff --git a/packages/flutter_tools/test/general.shard/channel_test.dart b/packages/flutter_tools/test/general.shard/channel_test.dart index 5187fa76a3d40..f75c92fff2315 100644 --- a/packages/flutter_tools/test/general.shard/channel_test.dart +++ b/packages/flutter_tools/test/general.shard/channel_test.dart @@ -13,6 +13,7 @@ import 'package:flutter_tools/src/version.dart'; import '../src/common.dart'; import '../src/context.dart'; import '../src/fake_process_manager.dart'; +import '../src/fakes.dart' show FakeFlutterVersion; import '../src/test_flutter_command_runner.dart'; void main() { @@ -29,7 +30,16 @@ void main() { Future simpleChannelTest(List args) async { fakeProcessManager.addCommands(const [ - FakeCommand(command: ['git', 'branch', '-r'], stdout: ' branch-1\n branch-2'), + FakeCommand( + command: ['git', 'branch', '-r'], + stdout: + ' origin/branch-1\n' + ' origin/branch-2\n' + ' origin/master\n' + ' origin/main\n' + ' origin/stable\n' + ' origin/beta', + ), ]); final ChannelCommand command = ChannelCommand(); final CommandRunner runner = createTestCommandRunner(command); @@ -75,11 +85,13 @@ void main() { await runner.run(['channel']); expect(fakeProcessManager, hasNoRemainingExpectations); expect(testLogger.errorText, hasLength(0)); - // format the status text for a simpler assertion. - final Iterable rows = testLogger.statusText - .split('\n') - .map((String line) => line.substring(2)); // remove '* ' or ' ' from output - expect(rows, containsAllInOrder(kOfficialChannels)); + expect(testLogger.statusText, + 'Flutter channels:\n' + '* master (latest development branch, for contributors)\n' + ' main (latest development branch, follows master channel)\n' + ' beta (updated monthly, recommended for experienced users)\n' + ' stable (updated quarterly, for new users and for production app releases)\n', + ); // clear buffer for next process testLogger.clear(); @@ -99,13 +111,14 @@ void main() { await runner.run(['channel']); expect(fakeProcessManager, hasNoRemainingExpectations); - expect(rows, containsAllInOrder(kOfficialChannels)); expect(testLogger.errorText, hasLength(0)); - // format the status text for a simpler assertion. - final Iterable rows2 = testLogger.statusText - .split('\n') - .map((String line) => line.substring(2)); // remove '* ' or ' ' from output - expect(rows2, containsAllInOrder(kOfficialChannels)); + expect(testLogger.statusText, + 'Flutter channels:\n' + '* master (latest development branch, for contributors)\n' + ' main (latest development branch, follows master channel)\n' + ' beta (updated monthly, recommended for experienced users)\n' + ' stable (updated quarterly, for new users and for production app releases)\n', + ); // clear buffer for next process testLogger.clear(); @@ -114,10 +127,11 @@ void main() { fakeProcessManager.addCommand( const FakeCommand( command: ['git', 'branch', '-r'], - stdout: 'origin/beta\n' + stdout: 'origin/master\n' 'origin/dependabot/bundler\n' 'origin/v1.4.5-hotfixes\n' - 'origin/stable\n', + 'origin/stable\n' + 'origin/beta\n', ), ); @@ -158,18 +172,45 @@ void main() { expect(fakeProcessManager, hasNoRemainingExpectations); expect(testLogger.errorText, hasLength(0)); + expect(testLogger.statusText, + 'Flutter channels:\n' + '* beta (updated monthly, recommended for experienced users)\n' + ' stable (updated quarterly, for new users and for production app releases)\n' + ); + }, overrides: { + ProcessManager: () => fakeProcessManager, + FileSystem: () => MemoryFileSystem.test(), + FlutterVersion: () => FakeFlutterVersion(branch: 'beta'), + }); - // format the status text for a simpler assertion. - final Iterable rows = testLogger.statusText - .split('\n') - .map((String line) => line.trim()) - .where((String line) => line.isNotEmpty) - .skip(1); // remove `Flutter channels:` line + testUsingContext('handles custom branches', () async { + fakeProcessManager.addCommand( + const FakeCommand( + command: ['git', 'branch', '-r'], + stdout: 'origin/beta\n' + 'origin/stable\n' + 'origin/foo', + ), + ); + + final ChannelCommand command = ChannelCommand(); + final CommandRunner runner = createTestCommandRunner(command); + await runner.run(['channel']); - expect(rows, ['beta', 'stable', 'Currently not on an official channel.']); + expect(fakeProcessManager, hasNoRemainingExpectations); + expect(testLogger.errorText, hasLength(0)); + expect(testLogger.statusText, + 'Flutter channels:\n' + ' beta (updated monthly, recommended for experienced users)\n' + ' stable (updated quarterly, for new users and for production app releases)\n' + '* foo\n' + '\n' + 'Currently not on an official channel.\n', + ); }, overrides: { ProcessManager: () => fakeProcessManager, FileSystem: () => MemoryFileSystem.test(), + FlutterVersion: () => FakeFlutterVersion(branch: 'foo'), }); testUsingContext('removes duplicates', () async { @@ -189,18 +230,15 @@ void main() { expect(fakeProcessManager, hasNoRemainingExpectations); expect(testLogger.errorText, hasLength(0)); - - // format the status text for a simpler assertion. - final Iterable rows = testLogger.statusText - .split('\n') - .map((String line) => line.trim()) - .where((String line) => line.isNotEmpty) - .skip(1); // remove `Flutter channels:` line - - expect(rows, ['beta', 'stable', 'Currently not on an official channel.']); + expect(testLogger.statusText, + 'Flutter channels:\n' + '* beta (updated monthly, recommended for experienced users)\n' + ' stable (updated quarterly, for new users and for production app releases)\n' + ); }, overrides: { ProcessManager: () => fakeProcessManager, FileSystem: () => MemoryFileSystem.test(), + FlutterVersion: () => FakeFlutterVersion(branch: 'beta'), }); testUsingContext('can switch channels', () async { diff --git a/packages/flutter_tools/test/general.shard/features_test.dart b/packages/flutter_tools/test/general.shard/features_test.dart index df9d60375632a..f15220e90b542 100644 --- a/packages/flutter_tools/test/general.shard/features_test.dart +++ b/packages/flutter_tools/test/general.shard/features_test.dart @@ -33,7 +33,7 @@ void main() { FeatureFlags createFlags(String channel) { return FlutterFeatureFlags( - flutterVersion: FakeFlutterVersion(channel: channel), + flutterVersion: FakeFlutterVersion(branch: channel), config: testConfig, platform: platform, ); diff --git a/packages/flutter_tools/test/general.shard/flutter_validator_test.dart b/packages/flutter_tools/test/general.shard/flutter_validator_test.dart index 6a20dba80a8c7..f2cf86389a919 100644 --- a/packages/flutter_tools/test/general.shard/flutter_validator_test.dart +++ b/packages/flutter_tools/test/general.shard/flutter_validator_test.dart @@ -34,7 +34,7 @@ void main() { 'downloaded and exits with code 1', () async { final FakeFlutterVersion flutterVersion = FakeFlutterVersion( frameworkVersion: '1.0.0', - channel: 'beta', + branch: 'beta', ); final MemoryFileSystem fileSystem = MemoryFileSystem.test(); final Artifacts artifacts = Artifacts.test(); @@ -78,7 +78,7 @@ void main() { testWithoutContext('FlutterValidator shows an error message if Rosetta is needed', () async { final FakeFlutterVersion flutterVersion = FakeFlutterVersion( frameworkVersion: '1.0.0', - channel: 'beta', + branch: 'beta', ); final MemoryFileSystem fileSystem = MemoryFileSystem.test(); final Artifacts artifacts = Artifacts.test(); @@ -121,7 +121,7 @@ void main() { testWithoutContext('FlutterValidator does not run gen_snapshot binary check if it is not already downloaded', () async { final FakeFlutterVersion flutterVersion = FakeFlutterVersion( frameworkVersion: '1.0.0', - channel: 'beta', + branch: 'beta', ); final FlutterValidator flutterValidator = FlutterValidator( platform: FakePlatform( @@ -174,7 +174,7 @@ void main() { testWithoutContext('FlutterValidator shows mirrors on pub and flutter cloud storage', () async { final FakeFlutterVersion flutterVersion = FakeFlutterVersion( frameworkVersion: '1.0.0', - channel: 'beta', + branch: 'beta', ); final Platform platform = FakePlatform( operatingSystem: 'windows', @@ -218,7 +218,7 @@ void main() { ), flutterVersion: () => FakeFlutterVersion( frameworkVersion: '1.0.0', - channel: 'beta' + branch: 'beta' ), devToolsVersion: () => '2.8.0', userMessages: UserMessages(), @@ -247,8 +247,8 @@ void main() { final FlutterValidator flutterValidator = FlutterValidator( platform: FakePlatform(localeName: 'en_US.UTF-8'), flutterVersion: () => FakeFlutterVersion( + branch: 'unknown', frameworkVersion: '1.0.0', - // channel is unknown by default ), devToolsVersion: () => '2.8.0', userMessages: UserMessages(), @@ -261,10 +261,10 @@ void main() { expect(await flutterValidator.validate(), _matchDoctorValidation( validationType: ValidationType.partial, - statusInfo: 'Channel unknown, 1.0.0, on Linux, locale en_US.UTF-8', + statusInfo: 'Channel [user-branch], 1.0.0, on Linux, locale en_US.UTF-8', messages: containsAll([ const ValidationMessage.hint( - 'Flutter version 1.0.0 on channel unknown at /sdk/flutter\n' + 'Flutter version 1.0.0 on channel [user-branch] at /sdk/flutter\n' 'Currently on an unknown channel. Run `flutter channel` to switch to an official channel.\n' "If that doesn't fix the issue, reinstall Flutter by following instructions at https://flutter.dev/docs/get-started/install." ), @@ -281,7 +281,7 @@ void main() { platform: FakePlatform(localeName: 'en_US.UTF-8'), flutterVersion: () => FakeFlutterVersion( frameworkVersion: '0.0.0-unknown', - channel: 'beta', + branch: 'beta', ), devToolsVersion: () => '2.8.0', userMessages: UserMessages(), @@ -315,7 +315,7 @@ void main() { platform: FakePlatform(localeName: 'en_US.UTF-8'), flutterVersion: () => FakeFlutterVersion( frameworkVersion: '1.0.0', - channel: 'beta' + branch: 'beta' ), devToolsVersion: () => '2.8.0', userMessages: UserMessages(), @@ -338,7 +338,7 @@ void main() { platform: FakePlatform(localeName: 'en_US.UTF-8'), flutterVersion: () => FakeFlutterVersion( frameworkVersion: '1.0.0', - channel: 'beta', + branch: 'beta', repositoryUrl: 'https://githubmirror.com/flutter.git' ), devToolsVersion: () => '2.8.0', @@ -372,7 +372,7 @@ void main() { platform: FakePlatform(localeName: 'en_US.UTF-8'), flutterVersion: () => FakeFlutterVersion( frameworkVersion: '1.0.0', - channel: 'beta', + branch: 'beta', repositoryUrl: null, ), devToolsVersion: () => '2.8.0', @@ -406,7 +406,7 @@ void main() { platform: FakePlatform(localeName: 'en_US.UTF-8'), flutterVersion: () => FakeFlutterVersion( frameworkVersion: '1.0.0', - channel: 'beta' + branch: 'beta' ), devToolsVersion: () => '2.8.0', userMessages: UserMessages(), @@ -435,7 +435,7 @@ void main() { platform: FakePlatform(localeName: 'en_US.UTF-8'), flutterVersion: () => FakeFlutterVersion( frameworkVersion: '1.0.0', - channel: 'beta' + branch: 'beta' ), devToolsVersion: () => '2.8.0', userMessages: UserMessages(), @@ -472,7 +472,7 @@ void main() { platform: FakePlatform(operatingSystem: 'windows', localeName: 'en_US.UTF-8'), flutterVersion: () => FakeFlutterVersion( frameworkVersion: '1.0.0', - channel: 'beta' + branch: 'beta' ), devToolsVersion: () => '2.8.0', userMessages: UserMessages(), @@ -513,7 +513,7 @@ void main() { platform: FakePlatform(operatingSystem: 'windows', localeName: 'en_US.UTF-8'), flutterVersion: () => FakeFlutterVersion( frameworkVersion: '1.0.0', - channel: 'beta' + branch: 'beta' ), devToolsVersion: () => '2.8.0', userMessages: UserMessages(), @@ -546,7 +546,7 @@ void main() { platform: FakePlatform(localeName: 'en_US.UTF-8'), flutterVersion: () => FakeFlutterVersion( frameworkVersion: '1.0.0', - channel: 'beta' + branch: 'beta' ), devToolsVersion: () => '2.8.0', userMessages: UserMessages(), @@ -580,7 +580,7 @@ void main() { platform: FakePlatform(localeName: 'en_US.UTF-8'), flutterVersion: () => FakeFlutterVersion( frameworkVersion: '1.0.0', - channel: 'beta' + branch: 'beta' ), devToolsVersion: () => '2.8.0', userMessages: UserMessages(), diff --git a/packages/flutter_tools/test/general.shard/template_test.dart b/packages/flutter_tools/test/general.shard/template_test.dart index 368a5dc1f0ae9..4f3cc55334d66 100644 --- a/packages/flutter_tools/test/general.shard/template_test.dart +++ b/packages/flutter_tools/test/general.shard/template_test.dart @@ -194,6 +194,23 @@ void main() { expect(logger.statusText, isEmpty); }); }); + + testWithoutContext('escapeYamlString', () { + expect(escapeYamlString(''), r'""'); + expect(escapeYamlString('\x00\n\r\t\b'), r'"\0\n\r\t\x08"'); + expect(escapeYamlString('test'), r'"test"'); + expect(escapeYamlString('test\n test'), r'"test\n test"'); + expect(escapeYamlString('\x00\x01\x02\x0c\x19\xab'), r'"\0\x01\x02\x0c\x19«"'); + expect(escapeYamlString('"'), r'"\""'); + expect(escapeYamlString(r'\'), r'"\\"'); + expect(escapeYamlString('[user branch]'), r'"[user branch]"'); + expect(escapeYamlString('main'), r'"main"'); + expect(escapeYamlString('TEST_BRANCH'), r'"TEST_BRANCH"'); + expect(escapeYamlString(' '), r'" "'); + expect(escapeYamlString(' \n '), r'" \n "'); + expect(escapeYamlString('""'), r'"\"\""'); + expect(escapeYamlString('"\x01\u{0263A}\u{1F642}'), r'"\"\x01☺🙂"'); + }); } class FakeTemplateRenderer extends TemplateRenderer { diff --git a/packages/flutter_tools/test/general.shard/version_test.dart b/packages/flutter_tools/test/general.shard/version_test.dart index 861d90a8ef4ad..6fe00447e6c44 100644 --- a/packages/flutter_tools/test/general.shard/version_test.dart +++ b/packages/flutter_tools/test/general.shard/version_test.dart @@ -16,6 +16,7 @@ import 'package:test/fake.dart'; import '../src/common.dart'; import '../src/context.dart'; import '../src/fake_process_manager.dart'; +import '../src/fakes.dart' show FakeFlutterVersion; final SystemClock _testClock = SystemClock.fixed(DateTime(2015)); final DateTime _stampUpToDate = _testClock.ago(VersionFreshnessValidator.checkAgeConsideredUpToDate ~/ 2); @@ -67,6 +68,10 @@ void main() { command: ['git', 'describe', '--match', '*.*.*', '--long', '--tags', '1234abcd'], stdout: '0.1.2-3-1234abcd', ), + FakeCommand( + command: const ['git', 'symbolic-ref', '--short', 'HEAD'], + stdout: channel, + ), FakeCommand( command: const ['git', 'rev-parse', '--abbrev-ref', '--symbolic', '@{upstream}'], stdout: 'origin/$channel', @@ -94,10 +99,6 @@ void main() { command: const ['git', '-c', 'log.showSignature=false', 'log', 'HEAD', '-n', '1', '--pretty=format:%ad', '--date=iso'], stdout: getChannelUpToDateVersion().toString(), ), - FakeCommand( - command: const ['git', 'rev-parse', '--abbrev-ref', 'HEAD'], - stdout: channel, - ), ]); final FlutterVersion flutterVersion = globals.flutterVersion; @@ -129,7 +130,7 @@ void main() { }); testWithoutContext('prints nothing when Flutter installation looks out-of-date but is actually up-to-date', () async { - final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: channel); + final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: channel); final BufferLogger logger = BufferLogger.test(); final VersionCheckStamp stamp = VersionCheckStamp( lastTimeVersionWasChecked: _stampOutOfDate, @@ -150,7 +151,7 @@ void main() { }); testWithoutContext('does not ping server when version stamp is up-to-date', () async { - final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: channel); + final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: channel); final BufferLogger logger = BufferLogger.test(); final VersionCheckStamp stamp = VersionCheckStamp( lastTimeVersionWasChecked: _stampUpToDate, @@ -172,7 +173,7 @@ void main() { }); testWithoutContext('does not print warning if printed recently', () async { - final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: channel); + final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: channel); final BufferLogger logger = BufferLogger.test(); final VersionCheckStamp stamp = VersionCheckStamp( lastTimeVersionWasChecked: _stampUpToDate, @@ -194,7 +195,7 @@ void main() { }); testWithoutContext('pings server when version stamp is missing', () async { - final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: channel); + final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: channel); final BufferLogger logger = BufferLogger.test(); cache.versionStamp = '{}'; @@ -212,7 +213,7 @@ void main() { }); testWithoutContext('pings server when version stamp is out-of-date', () async { - final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: channel); + final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: channel); final BufferLogger logger = BufferLogger.test(); final VersionCheckStamp stamp = VersionCheckStamp( lastTimeVersionWasChecked: _stampOutOfDate, @@ -233,7 +234,7 @@ void main() { }); testWithoutContext('does not print warning when unable to connect to server if not out of date', () async { - final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: channel); + final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: channel); final BufferLogger logger = BufferLogger.test(); cache.versionStamp = '{}'; @@ -250,7 +251,7 @@ void main() { }); testWithoutContext('prints warning when unable to connect to server if really out of date', () async { - final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: channel); + final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: channel); final BufferLogger logger = BufferLogger.test(); final VersionCheckStamp stamp = VersionCheckStamp( lastTimeVersionWasChecked: _stampOutOfDate, @@ -329,7 +330,7 @@ void main() { if (flutterGitUrl != null) 'FLUTTER_GIT_URL': flutterGitUrl, }); return VersionUpstreamValidator( - version: FakeFlutterVersion(repositoryUrl: versionUpstreamUrl, channel: 'master'), + version: FakeFlutterVersion(repositoryUrl: versionUpstreamUrl), platform: testPlatform, ).run(); } @@ -413,17 +414,13 @@ void main() { stdout: '0.1.2-3-1234abcd', ), const FakeCommand( - command: ['git', 'rev-parse', '--abbrev-ref', '--symbolic', '@{upstream}'], - stdout: 'feature-branch', - ), - const FakeCommand( - command: ['git', 'rev-parse', '--abbrev-ref', 'HEAD'], + command: ['git', 'symbolic-ref', '--short', 'HEAD'], stdout: 'feature-branch', ), ]); final FlutterVersion flutterVersion = globals.flutterVersion; - expect(flutterVersion.channel, 'feature-branch'); + expect(flutterVersion.channel, '[user-branch]'); expect(flutterVersion.getVersionString(), 'feature-branch/1234abcd'); expect(flutterVersion.getBranchName(), 'feature-branch'); expect(flutterVersion.getVersionString(redactUnknownBranches: true), '[user-branch]/1234abcd'); @@ -455,7 +452,7 @@ void main() { expect(gitTagVersion.devVersion, null); expect(gitTagVersion.devPatch, null); - // Dev channel + // Beta channel gitTagVersion = GitTagVersion.parse('1.2.3-4.5.pre'); expect(gitTagVersion.frameworkVersionFor(hash), '1.2.3-4.5.pre'); expect(gitTagVersion.gitTag, '1.2.3-4.5.pre'); @@ -468,7 +465,7 @@ void main() { expect(gitTagVersion.devVersion, null); expect(gitTagVersion.devPatch, null); - // new tag release format, dev channel + // new tag release format, beta channel gitTagVersion = GitTagVersion.parse('1.2.3-4.5.pre-0-g$hash'); expect(gitTagVersion.frameworkVersionFor(hash), '1.2.3-4.5.pre'); expect(gitTagVersion.gitTag, '1.2.3-4.5.pre'); @@ -521,13 +518,13 @@ void main() { expect(gitTagVersion.frameworkVersionFor('abcd1234'), stableTag); }); - testUsingContext('determine favors stable tag over dev tag if both identify HEAD', () { + testUsingContext('determine favors stable tag over beta tag if both identify HEAD', () { const String stableTag = '1.2.3'; final FakeProcessManager fakeProcessManager = FakeProcessManager.list( [ const FakeCommand( command: ['git', 'tag', '--points-at', 'HEAD'], - // This tests the unlikely edge case where a dev release made it to stable without any cherry picks + // This tests the unlikely edge case where a beta release made it to stable without any cherry picks stdout: '1.2.3-6.0.pre\n$stableTag', ), ], @@ -589,11 +586,11 @@ void main() { expect(fakeProcessManager, hasNoRemainingExpectations); }); - testUsingContext('determine does not fetch tags on dev/stable/beta', () { + testUsingContext('determine does not fetch tags on beta', () { final FakeProcessManager fakeProcessManager = FakeProcessManager.list([ const FakeCommand( - command: ['git', 'rev-parse', '--abbrev-ref', 'HEAD'], - stdout: 'dev', + command: ['git', 'symbolic-ref', '--short', 'HEAD'], + stdout: 'beta', ), const FakeCommand( command: ['git', 'tag', '--points-at', 'HEAD'], @@ -616,7 +613,7 @@ void main() { testUsingContext('determine calls fetch --tags on master', () { final FakeProcessManager fakeProcessManager = FakeProcessManager.list([ const FakeCommand( - command: ['git', 'rev-parse', '--abbrev-ref', 'HEAD'], + command: ['git', 'symbolic-ref', '--short', 'HEAD'], stdout: 'master', ), const FakeCommand( @@ -643,7 +640,7 @@ void main() { testUsingContext('determine uses overridden git url', () { final FakeProcessManager fakeProcessManager = FakeProcessManager.list([ const FakeCommand( - command: ['git', 'rev-parse', '--abbrev-ref', 'HEAD'], + command: ['git', 'symbolic-ref', '--short', 'HEAD'], stdout: 'master', ), const FakeCommand( @@ -701,13 +698,3 @@ class FakeCache extends Fake implements Cache { } } } - -class FakeFlutterVersion extends Fake implements FlutterVersion { - FakeFlutterVersion({required this.channel, this.repositoryUrl}); - - @override - final String channel; - - @override - final String? repositoryUrl; -} diff --git a/packages/flutter_tools/test/integration.shard/downgrade_upgrade_integration_test.dart b/packages/flutter_tools/test/integration.shard/downgrade_upgrade_integration_test.dart index 3b8a49558f5ac..26ac8752cc1cf 100644 --- a/packages/flutter_tools/test/integration.shard/downgrade_upgrade_integration_test.dart +++ b/packages/flutter_tools/test/integration.shard/downgrade_upgrade_integration_test.dart @@ -11,7 +11,7 @@ import 'package:flutter_tools/src/base/terminal.dart'; import '../src/common.dart'; import 'test_utils.dart'; -const String _kInitialVersion = 'v1.9.1'; +const String _kInitialVersion = '3.0.0'; const String _kBranch = 'beta'; final Stdio stdio = Stdio(); @@ -80,6 +80,7 @@ void main() { printOnFailure('Step 4 - upgrade to the newest $_kBranch'); // This should update the persistent tool state with the sha for HEAD + // This is probably a source of flakes as it mutates system-global state. exitCode = await processUtils.stream([ flutterBin, 'upgrade', @@ -93,7 +94,7 @@ void main() { 'git', 'describe', '--match', - 'v*.*.*', + '*.*.*', '--long', '--tags', ], workingDirectory: testDirectory.path); @@ -114,7 +115,7 @@ void main() { 'git', 'describe', '--match', - 'v*.*.*', + '*.*.*', '--long', '--tags', ], workingDirectory: testDirectory.path); diff --git a/packages/flutter_tools/test/src/fakes.dart b/packages/flutter_tools/test/src/fakes.dart index 7760aea6a1396..30d379d7af505 100644 --- a/packages/flutter_tools/test/src/fakes.dart +++ b/packages/flutter_tools/test/src/fakes.dart @@ -324,7 +324,7 @@ class FakeBotDetector implements BotDetector { class FakeFlutterVersion implements FlutterVersion { FakeFlutterVersion({ - this.channel = 'unknown', + this.branch = 'master', this.dartSdkVersion = '12', this.devToolsVersion = '2.8.0', this.engineRevision = 'abcdefghijklmnopqrstuvwxyz', @@ -338,6 +338,8 @@ class FakeFlutterVersion implements FlutterVersion { this.gitTagVersion = const GitTagVersion.unknown(), }); + final String branch; + bool get didFetchTagsAndUpdate => _didFetchTagsAndUpdate; bool _didFetchTagsAndUpdate = false; @@ -345,7 +347,12 @@ class FakeFlutterVersion implements FlutterVersion { bool _didCheckFlutterVersionFreshness = false; @override - final String channel; + String get channel { + if (kOfficialChannels.contains(branch) || kObsoleteBranches.containsKey(branch)) { + return branch; + } + return kUserBranch; + } @override final String devToolsVersion; @@ -398,7 +405,10 @@ class FakeFlutterVersion implements FlutterVersion { @override String getBranchName({bool redactUnknownBranches = false}) { - return 'master'; + if (!redactUnknownBranches || kOfficialChannels.contains(branch) || kObsoleteBranches.containsKey(branch)) { + return branch; + } + return kUserBranch; } @override