Unverified Commit 9c7a9e77 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Give channel descriptions in `flutter channel`, use branch instead of upstream...

Give channel descriptions in `flutter channel`, use branch instead of upstream for channel name (#126936)

## How we determine the channel name

Historically, we used the current branch's upstream to figure out the current channel name. I have no idea why. I traced it back to https://github.com/flutter/flutter/pull/446/files where @abarth implement this and I reviewed that PR and left no comment on it at the time.

I think this is confusing. You can be on a branch and it tells you that your channel is different. That seems weird.

This PR changes the logic to uses the current branch as the channel name.

## How we display channels

The main reason this PR exists is to add channel descriptions to the `flutter channel` list:

```
ianh@burmese:~/dev/flutter/packages/flutter_tools$ flutter channel
Flutter channels:
  master (tip of tree, for contributors)
  main (tip of tree, follows master channel)
  beta (updated monthly, recommended for experienced users)
  stable (updated quarterly, for new users and for production app releases)
* foo_bar

Currently not on an official channel.
ianh@burmese:~/dev/flutter/packages/flutter_tools$
```

## Other changes

I made a few other changes while I was at it:

* If you're not on an official channel, we used to imply `--show-all`, but now we don't, we just show the official channels plus yours. This avoids flooding the screen in the case the user is on a weird channel and just wants to know what channel they're on.
* I made the tool more consistent about how it handles unofficial branches. Now it's always `[user branch]`.
* I slightly adjusted how unknown versions are rendered so it's clearer the version is unknown rather than just having the word "Unknown" floating in the output without context.
* Simplified some of the code.
* Made some of the tests more strict (checking all output rather than just some aspects of it).
* Changed the MockFlutterVersion to implement the FlutterVersion API more strictly.
* I made sure we escape the output to `.metadata` to avoid potential injection bugs (previously we just inlined the version and channel name verbatim with no escaping, which is super sketchy).
* Tweaked the help text for the `downgrade` command to be clearer.
* Removed some misleading text in some error messages.
* Made the `.metadata` generator consistent with the template file.
* Removed some obsolete code to do with the `dev` branch.

## Reviewer notes

I'm worried that there are implications to some of these changes that I am not aware of, so please don't assume I know what I'm doing when reviewing this code. :-)
parent 25d2f90a
...@@ -21,7 +21,7 @@ class UserMessages { ...@@ -21,7 +21,7 @@ class UserMessages {
// Messages used in FlutterValidator // Messages used in FlutterValidator
String flutterStatusInfo(String? channel, String? version, String os, String locale) => 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) => String flutterVersion(String version, String channel, String flutterRoot) =>
'Flutter version $version on channel $channel at $flutterRoot'; 'Flutter version $version on channel $channel at $flutterRoot';
String get flutterUnknownChannel => String get flutterUnknownChannel =>
......
...@@ -53,13 +53,12 @@ class ChannelCommand extends FlutterCommand { ...@@ -53,13 +53,12 @@ class ChannelCommand extends FlutterCommand {
Future<void> _listChannels({ required bool showAll, required bool verbose }) async { Future<void> _listChannels({ required bool showAll, required bool verbose }) async {
// Beware: currentBranch could contain PII. See getBranchName(). // 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 String currentBranch = globals.flutterVersion.getBranchName();
final Set<String> seenUnofficialChannels = <String>{}; final Set<String> seenUnofficialChannels = <String>{};
final List<String> rawOutput = <String>[]; final List<String> rawOutput = <String>[];
showAll = showAll || currentChannel != currentBranch;
globals.printStatus('Flutter channels:'); globals.printStatus('Flutter channels:');
final int result = await globals.processUtils.stream( final int result = await globals.processUtils.stream(
<String>['git', 'branch', '-r'], <String>['git', 'branch', '-r'],
...@@ -74,8 +73,7 @@ class ChannelCommand extends FlutterCommand { ...@@ -74,8 +73,7 @@ class ChannelCommand extends FlutterCommand {
throwToolExit('List channels failed: $result$details', exitCode: result); throwToolExit('List channels failed: $result$details', exitCode: result);
} }
final List<String> officialChannels = kOfficialChannels.toList(); final Set<String> availableChannels = <String>{};
final List<bool> availableChannels = List<bool>.filled(officialChannels.length, false);
for (final String line in rawOutput) { for (final String line in rawOutput) {
final List<String> split = line.split('/'); final List<String> split = line.split('/');
...@@ -84,27 +82,25 @@ class ChannelCommand extends FlutterCommand { ...@@ -84,27 +82,25 @@ class ChannelCommand extends FlutterCommand {
continue; continue;
} }
final String branch = split[1]; final String branch = split[1];
if (split.length > 1) { if (kOfficialChannels.contains(branch)) {
final int index = officialChannels.indexOf(branch); availableChannels.add(branch);
} else if (showAll) {
if (index != -1) { // Mark all available channels official channels from output seenUnofficialChannels.add(branch);
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);
}
} }
} }
bool currentChannelIsOfficial = false;
// print all available official channels in sorted manner // 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 // only print non-missing channels
if (availableChannels[i]) { if (availableChannels.contains(channel)) {
String currentIndicator = ' '; String currentIndicator = ' ';
if (officialChannels[i] == currentChannel) { if (channel == currentChannel) {
currentIndicator = '*'; currentIndicator = '*';
currentChannelIsOfficial = true;
} }
globals.printStatus('$currentIndicator ${officialChannels[i]}'); globals.printStatus('$currentIndicator $channel (${kChannelDescriptions[channel]})');
} }
} }
...@@ -117,9 +113,12 @@ class ChannelCommand extends FlutterCommand { ...@@ -117,9 +113,12 @@ class ChannelCommand extends FlutterCommand {
globals.printStatus(' $branch'); 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('');
globals.printStatus('Currently not on an official channel.'); globals.printStatus('Currently not on an official channel.');
} }
......
...@@ -407,8 +407,8 @@ abstract class CreateBase extends FlutterCommand { ...@@ -407,8 +407,8 @@ abstract class CreateBase extends FlutterCommand {
'iosLanguage': iosLanguage, 'iosLanguage': iosLanguage,
'hasIosDevelopmentTeam': iosDevelopmentTeam != null && iosDevelopmentTeam.isNotEmpty, 'hasIosDevelopmentTeam': iosDevelopmentTeam != null && iosDevelopmentTeam.isNotEmpty,
'iosDevelopmentTeam': iosDevelopmentTeam ?? '', 'iosDevelopmentTeam': iosDevelopmentTeam ?? '',
'flutterRevision': globals.flutterVersion.frameworkRevision, 'flutterRevision': escapeYamlString(globals.flutterVersion.frameworkRevision),
'flutterChannel': globals.flutterVersion.channel, 'flutterChannel': escapeYamlString(globals.flutterVersion.getBranchName()), // may contain PII
'ios': ios, 'ios': ios,
'android': android, 'android': android,
'web': web, 'web': web,
...@@ -571,10 +571,11 @@ abstract class CreateBase extends FlutterCommand { ...@@ -571,10 +571,11 @@ abstract class CreateBase extends FlutterCommand {
final FlutterProjectMetadata metadata = FlutterProjectMetadata.explicit( final FlutterProjectMetadata metadata = FlutterProjectMetadata.explicit(
file: metadataFile, file: metadataFile,
versionRevision: globals.flutterVersion.frameworkRevision, versionRevision: globals.flutterVersion.frameworkRevision,
versionChannel: globals.flutterVersion.channel, versionChannel: globals.flutterVersion.getBranchName(), // may contain PII
projectType: projectType, projectType: projectType,
migrateConfig: MigrateConfig(), migrateConfig: MigrateConfig(),
logger: globals.logger); logger: globals.logger,
);
metadata.populate( metadata.populate(
platforms: platformsForMigrateConfig, platforms: platformsForMigrateConfig,
projectDirectory: directory, projectDirectory: directory,
......
...@@ -47,15 +47,15 @@ class DowngradeCommand extends FlutterCommand { ...@@ -47,15 +47,15 @@ class DowngradeCommand extends FlutterCommand {
'working-directory', 'working-directory',
hide: !verboseHelp, hide: !verboseHelp,
help: 'Override the downgrade working directory. ' 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( argParser.addFlag(
'prompt', 'prompt',
defaultsTo: true, defaultsTo: true,
hide: !verboseHelp, hide: !verboseHelp,
help: 'Show the downgrade prompt. ' help: 'Show the downgrade prompt.'
'The ability to disable this using "--no-prompt" is only provided for '
'integration testing of the tool itself.'
); );
} }
...@@ -99,8 +99,8 @@ class DowngradeCommand extends FlutterCommand { ...@@ -99,8 +99,8 @@ class DowngradeCommand extends FlutterCommand {
final Channel? channel = getChannelForName(currentChannel); final Channel? channel = getChannelForName(currentChannel);
if (channel == null) { if (channel == null) {
throwToolExit( throwToolExit(
'Flutter is not currently on a known channel. Use "flutter channel <name>" ' 'Flutter is not currently on a known channel. '
'to switch to an official channel.', 'Use "flutter channel" to switch to an official channel. '
); );
} }
final PersistentToolState persistentToolState = _persistentToolState!; final PersistentToolState persistentToolState = _persistentToolState!;
...@@ -153,13 +153,14 @@ class DowngradeCommand extends FlutterCommand { ...@@ -153,13 +153,14 @@ class DowngradeCommand extends FlutterCommand {
} on ProcessException catch (error) { } on ProcessException catch (error) {
throwToolExit( throwToolExit(
'Unable to downgrade Flutter: The tool could not update to the version ' 'Unable to downgrade Flutter: The tool could not update to the version '
'$humanReadableVersion. This may be due to git not being installed or an ' '$humanReadableVersion.\n'
'internal error. Please ensure that git is installed on your computer and ' 'Error: $error'
'retry again.\nError: $error.'
); );
} }
try { try {
await processUtils.run( 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.
<String>['git', 'checkout', currentChannel, '--'], <String>['git', 'checkout', currentChannel, '--'],
throwOnError: true, throwOnError: true,
workingDirectory: workingDirectory, workingDirectory: workingDirectory,
...@@ -167,9 +168,8 @@ class DowngradeCommand extends FlutterCommand { ...@@ -167,9 +168,8 @@ class DowngradeCommand extends FlutterCommand {
} on ProcessException catch (error) { } on ProcessException catch (error) {
throwToolExit( throwToolExit(
'Unable to downgrade Flutter: The tool could not switch to the channel ' 'Unable to downgrade Flutter: The tool could not switch to the channel '
'$currentChannel. This may be due to git not being installed or an ' '$currentChannel.\n'
'internal error. Please ensure that git is installed on your computer ' 'Error: $error'
'and retry again.\nError: $error.'
); );
} }
await FlutterVersion.resetFlutterVersionFreshnessCheck(); await FlutterVersion.resetFlutterVersionFreshnessCheck();
......
...@@ -577,14 +577,14 @@ class FlutterValidator extends DoctorValidator { ...@@ -577,14 +577,14 @@ class FlutterValidator extends DoctorValidator {
ValidationMessage _getFlutterVersionMessage(String frameworkVersion, String versionChannel, String flutterRoot) { ValidationMessage _getFlutterVersionMessage(String frameworkVersion, String versionChannel, String flutterRoot) {
String flutterVersionMessage = _userMessages.flutterVersion(frameworkVersion, versionChannel, flutterRoot); String flutterVersionMessage = _userMessages.flutterVersion(frameworkVersion, versionChannel, flutterRoot);
// The tool sets the channel as "unknown", if the current branch is on a // The tool sets the channel as kUserBranch, if the current branch is on a
// "detached HEAD" state or doesn't have an upstream, and sets the // "detached HEAD" state, doesn't have an upstream, or is on a user branch,
// frameworkVersion as "0.0.0-unknown" if "git describe" on HEAD doesn't // and sets the frameworkVersion as "0.0.0-unknown" if "git describe" on
// produce an expected format to be parsed for the frameworkVersion. // HEAD doesn't produce an expected format to be parsed for the frameworkVersion.
if (versionChannel != 'unknown' && frameworkVersion != '0.0.0-unknown') { if (versionChannel != kUserBranch && frameworkVersion != '0.0.0-unknown') {
return ValidationMessage(flutterVersionMessage); return ValidationMessage(flutterVersionMessage);
} }
if (versionChannel == 'unknown') { if (versionChannel == kUserBranch) {
flutterVersionMessage = '$flutterVersionMessage\n${_userMessages.flutterUnknownChannel}'; flutterVersionMessage = '$flutterVersionMessage\n${_userMessages.flutterUnknownChannel}';
} }
if (frameworkVersion == '0.0.0-unknown') { if (frameworkVersion == '0.0.0-unknown') {
......
...@@ -8,6 +8,7 @@ import 'base/file_system.dart'; ...@@ -8,6 +8,7 @@ import 'base/file_system.dart';
import 'base/logger.dart'; import 'base/logger.dart';
import 'base/utils.dart'; import 'base/utils.dart';
import 'project.dart'; import 'project.dart';
import 'template.dart';
import 'version.dart'; import 'version.dart';
enum FlutterProjectType implements CliEnum { enum FlutterProjectType implements CliEnum {
...@@ -172,11 +173,11 @@ class FlutterProjectMetadata { ...@@ -172,11 +173,11 @@ class FlutterProjectMetadata {
# This file tracks properties of this Flutter project. # This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc. # 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: version:
revision: $_versionRevision revision: ${escapeYamlString(_versionRevision ?? '')}
channel: $_versionChannel channel: ${escapeYamlString(_versionChannel ?? kUserBranch)}
project_type: ${projectType == null ? '' : projectType!.cliName} project_type: ${projectType == null ? '' : projectType!.cliName}
${migrateConfig.getOutputFileString()}'''; ${migrateConfig.getOutputFileString()}''';
......
...@@ -300,9 +300,6 @@ CustomDevicesConfig get customDevicesConfig => context.get<CustomDevicesConfig>( ...@@ -300,9 +300,6 @@ CustomDevicesConfig get customDevicesConfig => context.get<CustomDevicesConfig>(
PreRunValidator get preRunValidator => context.get<PreRunValidator>() ?? const NoOpPreRunValidator(); PreRunValidator get preRunValidator => context.get<PreRunValidator>() ?? 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. // 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:/=_\-\.\[\]]+)'); final RegExp kVMServiceMessageRegExp = RegExp(r'The Dart VM service is listening on ((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+)');
......
...@@ -375,3 +375,24 @@ String _escapeKotlinKeywords(String androidIdentifier) { ...@@ -375,3 +375,24 @@ String _escapeKotlinKeywords(String androidIdentifier) {
).toList(); ).toList();
return correctedSegments.join('.'); 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();
}
...@@ -22,6 +22,9 @@ const String _unknownFrameworkVersion = '0.0.0-unknown'; ...@@ -22,6 +22,9 @@ const String _unknownFrameworkVersion = '0.0.0-unknown';
/// See `man gitrevisions` for more information. /// See `man gitrevisions` for more information.
const String kGitTrackingUpstream = '@{upstream}'; 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. /// 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" /// For example, in 2021 we deprecated the "dev" channel and transitioned "dev"
...@@ -40,12 +43,24 @@ enum Channel { ...@@ -40,12 +43,24 @@ enum Channel {
// Beware: Keep order in accordance with stability // Beware: Keep order in accordance with stability
const Set<String> kOfficialChannels = <String>{ const Set<String> kOfficialChannels = <String>{
globals.kDefaultFrameworkChannel, 'master',
'main', 'main',
'beta', 'beta',
'stable', 'stable',
}; };
const Map<String, String> kChannelDescriptions = <String, String>{
'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<String> kDevelopmentChannels = <String>{
'master',
'main',
};
/// Retrieve a human-readable name for a given [channel]. /// Retrieve a human-readable name for a given [channel].
/// ///
/// Requires [kOfficialChannels] to be correctly ordered. /// Requires [kOfficialChannels] to be correctly ordered.
...@@ -101,16 +116,7 @@ class FlutterVersion { ...@@ -101,16 +116,7 @@ class FlutterVersion {
String? _repositoryUrl; String? _repositoryUrl;
String? get repositoryUrl { String? get repositoryUrl {
final String _ = channel; if (_repositoryUrl == null) {
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) {
final String gitChannel = _runGit( final String gitChannel = _runGit(
'git rev-parse --abbrev-ref --symbolic $kGitTrackingUpstream', 'git rev-parse --abbrev-ref --symbolic $kGitTrackingUpstream',
globals.processUtils, globals.processUtils,
...@@ -124,14 +130,16 @@ class FlutterVersion { ...@@ -124,14 +130,16 @@ class FlutterVersion {
globals.processUtils, globals.processUtils,
_workingDirectory, _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; return channel;
} }
...@@ -296,16 +304,16 @@ class FlutterVersion { ...@@ -296,16 +304,16 @@ class FlutterVersion {
/// Return the branch name. /// Return the branch name.
/// ///
/// If [redactUnknownBranches] is true and the branch is unknown, /// 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 }) { String getBranchName({ bool redactUnknownBranches = false }) {
_branch ??= () { _branch ??= () {
final String branch = _runGit('git rev-parse --abbrev-ref HEAD', globals.processUtils); final String branch = _runGit('git symbolic-ref --short HEAD', globals.processUtils, _workingDirectory);
return branch == 'HEAD' ? channel : branch; return branch == 'HEAD' ? '' : branch;
}(); }();
if (redactUnknownBranches || _branch!.isEmpty) { if (redactUnknownBranches || _branch!.isEmpty) {
// Only return the branch names we know about; arbitrary branch names might contain PII. // Only return the branch names we know about; arbitrary branch names might contain PII.
if (!kOfficialChannels.contains(_branch) && !kObsoleteBranches.containsKey(_branch)) { if (!kOfficialChannels.contains(_branch) && !kObsoleteBranches.containsKey(_branch)) {
return '[user-branch]'; return kUserBranch;
} }
} }
return _branch!; return _branch!;
...@@ -619,7 +627,7 @@ String _runSync(List<String> command, { bool lenient = true }) { ...@@ -619,7 +627,7 @@ String _runSync(List<String> command, { bool lenient = true }) {
return ''; return '';
} }
String _runGit(String command, ProcessUtils processUtils, [String? workingDirectory]) { String _runGit(String command, ProcessUtils processUtils, String? workingDirectory) {
return processUtils.runSync( return processUtils.runSync(
command.split(' '), command.split(' '),
workingDirectory: workingDirectory ?? Cache.flutterRoot, workingDirectory: workingDirectory ?? Cache.flutterRoot,
...@@ -709,8 +717,8 @@ class GitTagVersion { ...@@ -709,8 +717,8 @@ class GitTagVersion {
String gitRef = 'HEAD' String gitRef = 'HEAD'
}) { }) {
if (fetchTags) { if (fetchTags) {
final String channel = _runGit('git rev-parse --abbrev-ref HEAD', processUtils, workingDirectory); final String channel = _runGit('git symbolic-ref --short HEAD', processUtils, workingDirectory);
if (channel == 'dev' || channel == 'beta' || channel == 'stable') { if (!kDevelopmentChannels.contains(channel) && kOfficialChannels.contains(channel)) {
globals.printTrace('Skipping request to fetchTags - on well known channel $channel.'); globals.printTrace('Skipping request to fetchTags - on well known channel $channel.');
} else { } else {
final String flutterGit = platform.environment['FLUTTER_GIT_URL'] ?? 'https://github.com/flutter/flutter.git'; final String flutterGit = platform.environment['FLUTTER_GIT_URL'] ?? 'https://github.com/flutter/flutter.git';
...@@ -918,8 +926,6 @@ class VersionFreshnessValidator { ...@@ -918,8 +926,6 @@ class VersionFreshnessValidator {
return const Duration(days: 365 ~/ 2); // Six months return const Duration(days: 365 ~/ 2); // Six months
case 'beta': case 'beta':
return const Duration(days: 7 * 8); // Eight weeks return const Duration(days: 7 * 8); // Eight weeks
case 'dev':
return const Duration(days: 7 * 4); // Four weeks
default: default:
return const Duration(days: 7 * 3); // Three weeks return const Duration(days: 7 * 3); // Three weeks
} }
......
...@@ -41,7 +41,7 @@ void main() { ...@@ -41,7 +41,7 @@ void main() {
}); });
testUsingContext('Downgrade exits on unknown channel', () async { 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') fileSystem.currentDirectory.childFile('.flutter_tool_state')
.writeAsStringSync('{"last-active-master-version":"invalid"}'); .writeAsStringSync('{"last-active-master-version":"invalid"}');
final DowngradeCommand command = DowngradeCommand( final DowngradeCommand command = DowngradeCommand(
...@@ -58,7 +58,7 @@ void main() { ...@@ -58,7 +58,7 @@ void main() {
}); });
testUsingContext('Downgrade exits on no recorded version', () async { 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') fileSystem.currentDirectory.childFile('.flutter_tool_state')
.writeAsStringSync('{"last-active-master-version":"abcd"}'); .writeAsStringSync('{"last-active-master-version":"abcd"}');
final DowngradeCommand command = DowngradeCommand( final DowngradeCommand command = DowngradeCommand(
...@@ -86,7 +86,7 @@ void main() { ...@@ -86,7 +86,7 @@ void main() {
}); });
testUsingContext('Downgrade exits on unknown recorded version', () async { testUsingContext('Downgrade exits on unknown recorded version', () async {
final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'master'); final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion();
fileSystem.currentDirectory.childFile('.flutter_tool_state') fileSystem.currentDirectory.childFile('.flutter_tool_state')
.writeAsStringSync('{"last-active-master-version":"invalid"}'); .writeAsStringSync('{"last-active-master-version":"invalid"}');
final DowngradeCommand command = DowngradeCommand( final DowngradeCommand command = DowngradeCommand(
...@@ -110,7 +110,7 @@ void main() { ...@@ -110,7 +110,7 @@ void main() {
}); });
testUsingContext('Downgrade prompts for user input when terminal is attached - y', () async { 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; stdio.hasTerminal = true;
fileSystem.currentDirectory.childFile('.flutter_tool_state') fileSystem.currentDirectory.childFile('.flutter_tool_state')
.writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}'); .writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}');
...@@ -131,7 +131,7 @@ void main() { ...@@ -131,7 +131,7 @@ void main() {
}); });
testUsingContext('Downgrade prompts for user input when terminal is attached - n', () async { 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; stdio.hasTerminal = true;
fileSystem.currentDirectory.childFile('.flutter_tool_state') fileSystem.currentDirectory.childFile('.flutter_tool_state')
.writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}'); .writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}');
...@@ -152,7 +152,7 @@ void main() { ...@@ -152,7 +152,7 @@ void main() {
}); });
testUsingContext('Downgrade does not prompt when there is no terminal', () async { testUsingContext('Downgrade does not prompt when there is no terminal', () async {
final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'master'); final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion();
stdio.hasTerminal = false; stdio.hasTerminal = false;
fileSystem.currentDirectory.childFile('.flutter_tool_state') fileSystem.currentDirectory.childFile('.flutter_tool_state')
.writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}'); .writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}');
...@@ -174,7 +174,7 @@ void main() { ...@@ -174,7 +174,7 @@ void main() {
}); });
testUsingContext('Downgrade performs correct git commands', () async { testUsingContext('Downgrade performs correct git commands', () async {
final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion(channel: 'master'); final FakeFlutterVersion fakeFlutterVersion = FakeFlutterVersion();
stdio.hasTerminal = false; stdio.hasTerminal = false;
fileSystem.currentDirectory.childFile('.flutter_tool_state') fileSystem.currentDirectory.childFile('.flutter_tool_state')
.writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}'); .writeAsStringSync('{"last-active-master-version":"g6b00b5e88"}');
......
...@@ -114,7 +114,7 @@ void main() { ...@@ -114,7 +114,7 @@ void main() {
expect(logger.statusText, contains("Transitioning from 'dev' to 'beta'...")); expect(logger.statusText, contains("Transitioning from 'dev' to 'beta'..."));
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
FlutterVersion: () => FakeFlutterVersion(channel: 'dev'), FlutterVersion: () => FakeFlutterVersion(branch: 'dev'),
Logger: () => logger, Logger: () => logger,
ProcessManager: () => processManager, ProcessManager: () => processManager,
}); });
...@@ -197,7 +197,7 @@ void main() { ...@@ -197,7 +197,7 @@ void main() {
); );
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
FlutterVersion: () => FakeFlutterVersion(channel: 'master', frameworkVersion: startingTag, engineRevision: 'engine'), FlutterVersion: () => FakeFlutterVersion(frameworkVersion: startingTag, engineRevision: 'engine'),
Logger: () => logger, Logger: () => logger,
ProcessManager: () => processManager, ProcessManager: () => processManager,
}); });
...@@ -264,7 +264,7 @@ void main() { ...@@ -264,7 +264,7 @@ void main() {
); );
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
FlutterVersion: () => FakeFlutterVersion(channel: 'beta', frameworkVersion: startingTag, engineRevision: 'engine'), FlutterVersion: () => FakeFlutterVersion(branch: 'beta', frameworkVersion: startingTag, engineRevision: 'engine'),
Logger: () => logger, Logger: () => logger,
ProcessManager: () => processManager, ProcessManager: () => processManager,
}); });
......
...@@ -78,7 +78,7 @@ void main() { ...@@ -78,7 +78,7 @@ void main() {
projectDir = tempDir.childDirectory('flutter_project'); projectDir = tempDir.childDirectory('flutter_project');
fakeFlutterVersion = FakeFlutterVersion( fakeFlutterVersion = FakeFlutterVersion(
frameworkRevision: frameworkRevision, frameworkRevision: frameworkRevision,
channel: frameworkChannel, branch: frameworkChannel,
); );
fakeProcessManager = FakeProcessManager.empty(); fakeProcessManager = FakeProcessManager.empty();
mockStdio = FakeStdio(); mockStdio = FakeStdio();
...@@ -1269,8 +1269,8 @@ void main() { ...@@ -1269,8 +1269,8 @@ void main() {
expectExists(versionPath); expectExists(versionPath);
final String version = globals.fs.file(globals.fs.path.join(projectDir.path, versionPath)).readAsStringSync(); final String version = globals.fs.file(globals.fs.path.join(projectDir.path, versionPath)).readAsStringSync();
expect(version, contains('version:')); expect(version, contains('version:'));
expect(version, contains('revision: 12345678')); expect(version, contains('revision: "12345678"'));
expect(version, contains('channel: omega')); expect(version, contains('channel: "omega"'));
// IntelliJ metadata // IntelliJ metadata
final String intelliJSdkMetadataPath = globals.fs.path.join('.idea', 'libraries', 'Dart_SDK.xml'); final String intelliJSdkMetadataPath = globals.fs.path.join('.idea', 'libraries', 'Dart_SDK.xml');
...@@ -1349,8 +1349,8 @@ void main() { ...@@ -1349,8 +1349,8 @@ void main() {
expectExists(versionPath); expectExists(versionPath);
final String version = globals.fs.file(globals.fs.path.join(projectDir.path, versionPath)).readAsStringSync(); final String version = globals.fs.file(globals.fs.path.join(projectDir.path, versionPath)).readAsStringSync();
expect(version, contains('version:')); expect(version, contains('version:'));
expect(version, contains('revision: 12345678')); expect(version, contains('revision: "12345678"'));
expect(version, contains('channel: omega')); expect(version, contains('channel: "omega"'));
// IntelliJ metadata // IntelliJ metadata
final String intelliJSdkMetadataPath = globals.fs.path.join('.idea', 'libraries', 'Dart_SDK.xml'); final String intelliJSdkMetadataPath = globals.fs.path.join('.idea', 'libraries', 'Dart_SDK.xml');
......
...@@ -46,7 +46,7 @@ void main() { ...@@ -46,7 +46,7 @@ void main() {
}); });
testUsingContext('throws on unknown tag, official branch, noforce', () async { testUsingContext('throws on unknown tag, official branch, noforce', () async {
final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: 'beta'); final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: 'beta');
const String upstreamRevision = ''; const String upstreamRevision = '';
final FakeFlutterVersion latestVersion = FakeFlutterVersion(frameworkRevision: upstreamRevision); final FakeFlutterVersion latestVersion = FakeFlutterVersion(frameworkRevision: upstreamRevision);
fakeCommandRunner.remoteVersion = latestVersion; fakeCommandRunner.remoteVersion = latestVersion;
...@@ -66,7 +66,7 @@ void main() { ...@@ -66,7 +66,7 @@ void main() {
}); });
testUsingContext('throws tool exit with uncommitted changes', () async { testUsingContext('throws tool exit with uncommitted changes', () async {
final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: 'beta'); final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: 'beta');
const String upstreamRevision = ''; const String upstreamRevision = '';
final FakeFlutterVersion latestVersion = FakeFlutterVersion(frameworkRevision: upstreamRevision); final FakeFlutterVersion latestVersion = FakeFlutterVersion(frameworkRevision: upstreamRevision);
fakeCommandRunner.remoteVersion = latestVersion; fakeCommandRunner.remoteVersion = latestVersion;
...@@ -89,7 +89,7 @@ void main() { ...@@ -89,7 +89,7 @@ void main() {
testUsingContext("Doesn't continue on known tag, beta branch, no force, already up-to-date", () async { testUsingContext("Doesn't continue on known tag, beta branch, no force, already up-to-date", () async {
const String revision = 'abc123'; const String revision = 'abc123';
final FakeFlutterVersion latestVersion = FakeFlutterVersion(frameworkRevision: revision); 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.alreadyUpToDate = true;
fakeCommandRunner.remoteVersion = latestVersion; fakeCommandRunner.remoteVersion = latestVersion;
...@@ -116,7 +116,7 @@ void main() { ...@@ -116,7 +116,7 @@ void main() {
const String upstreamVersion = '4.5.6'; const String upstreamVersion = '4.5.6';
final FakeFlutterVersion flutterVersion = FakeFlutterVersion( final FakeFlutterVersion flutterVersion = FakeFlutterVersion(
channel: 'beta', branch: 'beta',
frameworkRevision: revision, frameworkRevision: revision,
frameworkRevisionShort: revision, frameworkRevisionShort: revision,
frameworkVersion: version, frameworkVersion: version,
...@@ -287,7 +287,7 @@ void main() { ...@@ -287,7 +287,7 @@ void main() {
const String upstreamVersion = '4.5.6'; const String upstreamVersion = '4.5.6';
final FakeFlutterVersion flutterVersion = FakeFlutterVersion( final FakeFlutterVersion flutterVersion = FakeFlutterVersion(
channel: 'beta', branch: 'beta',
frameworkRevision: revision, frameworkRevision: revision,
frameworkVersion: version, frameworkVersion: version,
); );
...@@ -348,7 +348,7 @@ void main() { ...@@ -348,7 +348,7 @@ void main() {
testUsingContext('does not throw on unknown tag, official branch, force', () async { testUsingContext('does not throw on unknown tag, official branch, force', () async {
fakeCommandRunner.remoteVersion = FakeFlutterVersion(frameworkRevision: '1234'); fakeCommandRunner.remoteVersion = FakeFlutterVersion(frameworkRevision: '1234');
final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: 'beta'); final FakeFlutterVersion flutterVersion = FakeFlutterVersion(branch: 'beta');
final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand( final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand(
force: true, force: true,
...@@ -366,7 +366,7 @@ void main() { ...@@ -366,7 +366,7 @@ void main() {
}); });
testUsingContext('does not throw tool exit with uncommitted changes and force', () async { 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.remoteVersion = FakeFlutterVersion(frameworkRevision: '1234');
fakeCommandRunner.willHaveUncommittedChanges = true; fakeCommandRunner.willHaveUncommittedChanges = true;
...@@ -386,7 +386,7 @@ void main() { ...@@ -386,7 +386,7 @@ void main() {
}); });
testUsingContext("Doesn't throw on known tag, beta branch, no force", () async { 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'); fakeCommandRunner.remoteVersion = FakeFlutterVersion(frameworkRevision: '1234');
final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand( final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand(
......
...@@ -13,6 +13,7 @@ import 'package:flutter_tools/src/version.dart'; ...@@ -13,6 +13,7 @@ import 'package:flutter_tools/src/version.dart';
import '../src/common.dart'; import '../src/common.dart';
import '../src/context.dart'; import '../src/context.dart';
import '../src/fake_process_manager.dart'; import '../src/fake_process_manager.dart';
import '../src/fakes.dart' show FakeFlutterVersion;
import '../src/test_flutter_command_runner.dart'; import '../src/test_flutter_command_runner.dart';
void main() { void main() {
...@@ -29,7 +30,16 @@ void main() { ...@@ -29,7 +30,16 @@ void main() {
Future<void> simpleChannelTest(List<String> args) async { Future<void> simpleChannelTest(List<String> args) async {
fakeProcessManager.addCommands(const <FakeCommand>[ fakeProcessManager.addCommands(const <FakeCommand>[
FakeCommand(command: <String>['git', 'branch', '-r'], stdout: ' branch-1\n branch-2'), FakeCommand(
command: <String>['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 ChannelCommand command = ChannelCommand();
final CommandRunner<void> runner = createTestCommandRunner(command); final CommandRunner<void> runner = createTestCommandRunner(command);
...@@ -75,11 +85,13 @@ void main() { ...@@ -75,11 +85,13 @@ void main() {
await runner.run(<String>['channel']); await runner.run(<String>['channel']);
expect(fakeProcessManager, hasNoRemainingExpectations); expect(fakeProcessManager, hasNoRemainingExpectations);
expect(testLogger.errorText, hasLength(0)); expect(testLogger.errorText, hasLength(0));
// format the status text for a simpler assertion. expect(testLogger.statusText,
final Iterable<String> rows = testLogger.statusText 'Flutter channels:\n'
.split('\n') '* master (latest development branch, for contributors)\n'
.map((String line) => line.substring(2)); // remove '* ' or ' ' from output ' main (latest development branch, follows master channel)\n'
expect(rows, containsAllInOrder(kOfficialChannels)); ' 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 // clear buffer for next process
testLogger.clear(); testLogger.clear();
...@@ -99,13 +111,14 @@ void main() { ...@@ -99,13 +111,14 @@ void main() {
await runner.run(<String>['channel']); await runner.run(<String>['channel']);
expect(fakeProcessManager, hasNoRemainingExpectations); expect(fakeProcessManager, hasNoRemainingExpectations);
expect(rows, containsAllInOrder(kOfficialChannels));
expect(testLogger.errorText, hasLength(0)); expect(testLogger.errorText, hasLength(0));
// format the status text for a simpler assertion. expect(testLogger.statusText,
final Iterable<String> rows2 = testLogger.statusText 'Flutter channels:\n'
.split('\n') '* master (latest development branch, for contributors)\n'
.map((String line) => line.substring(2)); // remove '* ' or ' ' from output ' main (latest development branch, follows master channel)\n'
expect(rows2, containsAllInOrder(kOfficialChannels)); ' 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 // clear buffer for next process
testLogger.clear(); testLogger.clear();
...@@ -114,10 +127,11 @@ void main() { ...@@ -114,10 +127,11 @@ void main() {
fakeProcessManager.addCommand( fakeProcessManager.addCommand(
const FakeCommand( const FakeCommand(
command: <String>['git', 'branch', '-r'], command: <String>['git', 'branch', '-r'],
stdout: 'origin/beta\n' stdout: 'origin/master\n'
'origin/dependabot/bundler\n' 'origin/dependabot/bundler\n'
'origin/v1.4.5-hotfixes\n' 'origin/v1.4.5-hotfixes\n'
'origin/stable\n', 'origin/stable\n'
'origin/beta\n',
), ),
); );
...@@ -158,18 +172,45 @@ void main() { ...@@ -158,18 +172,45 @@ void main() {
expect(fakeProcessManager, hasNoRemainingExpectations); expect(fakeProcessManager, hasNoRemainingExpectations);
expect(testLogger.errorText, hasLength(0)); 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: <Type, Generator>{
ProcessManager: () => fakeProcessManager,
FileSystem: () => MemoryFileSystem.test(),
FlutterVersion: () => FakeFlutterVersion(branch: 'beta'),
});
// format the status text for a simpler assertion. testUsingContext('handles custom branches', () async {
final Iterable<String> rows = testLogger.statusText fakeProcessManager.addCommand(
.split('\n') const FakeCommand(
.map((String line) => line.trim()) command: <String>['git', 'branch', '-r'],
.where((String line) => line.isNotEmpty) stdout: 'origin/beta\n'
.skip(1); // remove `Flutter channels:` line 'origin/stable\n'
'origin/foo',
),
);
final ChannelCommand command = ChannelCommand();
final CommandRunner<void> runner = createTestCommandRunner(command);
await runner.run(<String>['channel']);
expect(rows, <String>['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: <Type, Generator>{ }, overrides: <Type, Generator>{
ProcessManager: () => fakeProcessManager, ProcessManager: () => fakeProcessManager,
FileSystem: () => MemoryFileSystem.test(), FileSystem: () => MemoryFileSystem.test(),
FlutterVersion: () => FakeFlutterVersion(branch: 'foo'),
}); });
testUsingContext('removes duplicates', () async { testUsingContext('removes duplicates', () async {
...@@ -189,18 +230,15 @@ void main() { ...@@ -189,18 +230,15 @@ void main() {
expect(fakeProcessManager, hasNoRemainingExpectations); expect(fakeProcessManager, hasNoRemainingExpectations);
expect(testLogger.errorText, hasLength(0)); expect(testLogger.errorText, hasLength(0));
expect(testLogger.statusText,
// format the status text for a simpler assertion. 'Flutter channels:\n'
final Iterable<String> rows = testLogger.statusText '* beta (updated monthly, recommended for experienced users)\n'
.split('\n') ' stable (updated quarterly, for new users and for production app releases)\n'
.map((String line) => line.trim()) );
.where((String line) => line.isNotEmpty)
.skip(1); // remove `Flutter channels:` line
expect(rows, <String>['beta', 'stable', 'Currently not on an official channel.']);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
ProcessManager: () => fakeProcessManager, ProcessManager: () => fakeProcessManager,
FileSystem: () => MemoryFileSystem.test(), FileSystem: () => MemoryFileSystem.test(),
FlutterVersion: () => FakeFlutterVersion(branch: 'beta'),
}); });
testUsingContext('can switch channels', () async { testUsingContext('can switch channels', () async {
......
...@@ -33,7 +33,7 @@ void main() { ...@@ -33,7 +33,7 @@ void main() {
FeatureFlags createFlags(String channel) { FeatureFlags createFlags(String channel) {
return FlutterFeatureFlags( return FlutterFeatureFlags(
flutterVersion: FakeFlutterVersion(channel: channel), flutterVersion: FakeFlutterVersion(branch: channel),
config: testConfig, config: testConfig,
platform: platform, platform: platform,
); );
......
...@@ -34,7 +34,7 @@ void main() { ...@@ -34,7 +34,7 @@ void main() {
'downloaded and exits with code 1', () async { 'downloaded and exits with code 1', () async {
final FakeFlutterVersion flutterVersion = FakeFlutterVersion( final FakeFlutterVersion flutterVersion = FakeFlutterVersion(
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
channel: 'beta', branch: 'beta',
); );
final MemoryFileSystem fileSystem = MemoryFileSystem.test(); final MemoryFileSystem fileSystem = MemoryFileSystem.test();
final Artifacts artifacts = Artifacts.test(); final Artifacts artifacts = Artifacts.test();
...@@ -78,7 +78,7 @@ void main() { ...@@ -78,7 +78,7 @@ void main() {
testWithoutContext('FlutterValidator shows an error message if Rosetta is needed', () async { testWithoutContext('FlutterValidator shows an error message if Rosetta is needed', () async {
final FakeFlutterVersion flutterVersion = FakeFlutterVersion( final FakeFlutterVersion flutterVersion = FakeFlutterVersion(
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
channel: 'beta', branch: 'beta',
); );
final MemoryFileSystem fileSystem = MemoryFileSystem.test(); final MemoryFileSystem fileSystem = MemoryFileSystem.test();
final Artifacts artifacts = Artifacts.test(); final Artifacts artifacts = Artifacts.test();
...@@ -121,7 +121,7 @@ void main() { ...@@ -121,7 +121,7 @@ void main() {
testWithoutContext('FlutterValidator does not run gen_snapshot binary check if it is not already downloaded', () async { testWithoutContext('FlutterValidator does not run gen_snapshot binary check if it is not already downloaded', () async {
final FakeFlutterVersion flutterVersion = FakeFlutterVersion( final FakeFlutterVersion flutterVersion = FakeFlutterVersion(
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
channel: 'beta', branch: 'beta',
); );
final FlutterValidator flutterValidator = FlutterValidator( final FlutterValidator flutterValidator = FlutterValidator(
platform: FakePlatform( platform: FakePlatform(
...@@ -174,7 +174,7 @@ void main() { ...@@ -174,7 +174,7 @@ void main() {
testWithoutContext('FlutterValidator shows mirrors on pub and flutter cloud storage', () async { testWithoutContext('FlutterValidator shows mirrors on pub and flutter cloud storage', () async {
final FakeFlutterVersion flutterVersion = FakeFlutterVersion( final FakeFlutterVersion flutterVersion = FakeFlutterVersion(
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
channel: 'beta', branch: 'beta',
); );
final Platform platform = FakePlatform( final Platform platform = FakePlatform(
operatingSystem: 'windows', operatingSystem: 'windows',
...@@ -218,7 +218,7 @@ void main() { ...@@ -218,7 +218,7 @@ void main() {
), ),
flutterVersion: () => FakeFlutterVersion( flutterVersion: () => FakeFlutterVersion(
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
channel: 'beta' branch: 'beta'
), ),
devToolsVersion: () => '2.8.0', devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
...@@ -247,8 +247,8 @@ void main() { ...@@ -247,8 +247,8 @@ void main() {
final FlutterValidator flutterValidator = FlutterValidator( final FlutterValidator flutterValidator = FlutterValidator(
platform: FakePlatform(localeName: 'en_US.UTF-8'), platform: FakePlatform(localeName: 'en_US.UTF-8'),
flutterVersion: () => FakeFlutterVersion( flutterVersion: () => FakeFlutterVersion(
branch: 'unknown',
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
// channel is unknown by default
), ),
devToolsVersion: () => '2.8.0', devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
...@@ -261,10 +261,10 @@ void main() { ...@@ -261,10 +261,10 @@ void main() {
expect(await flutterValidator.validate(), _matchDoctorValidation( expect(await flutterValidator.validate(), _matchDoctorValidation(
validationType: ValidationType.partial, 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(<ValidationMessage>[ messages: containsAll(<ValidationMessage>[
const ValidationMessage.hint( 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' '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." "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() { ...@@ -281,7 +281,7 @@ void main() {
platform: FakePlatform(localeName: 'en_US.UTF-8'), platform: FakePlatform(localeName: 'en_US.UTF-8'),
flutterVersion: () => FakeFlutterVersion( flutterVersion: () => FakeFlutterVersion(
frameworkVersion: '0.0.0-unknown', frameworkVersion: '0.0.0-unknown',
channel: 'beta', branch: 'beta',
), ),
devToolsVersion: () => '2.8.0', devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
...@@ -315,7 +315,7 @@ void main() { ...@@ -315,7 +315,7 @@ void main() {
platform: FakePlatform(localeName: 'en_US.UTF-8'), platform: FakePlatform(localeName: 'en_US.UTF-8'),
flutterVersion: () => FakeFlutterVersion( flutterVersion: () => FakeFlutterVersion(
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
channel: 'beta' branch: 'beta'
), ),
devToolsVersion: () => '2.8.0', devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
...@@ -338,7 +338,7 @@ void main() { ...@@ -338,7 +338,7 @@ void main() {
platform: FakePlatform(localeName: 'en_US.UTF-8'), platform: FakePlatform(localeName: 'en_US.UTF-8'),
flutterVersion: () => FakeFlutterVersion( flutterVersion: () => FakeFlutterVersion(
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
channel: 'beta', branch: 'beta',
repositoryUrl: 'https://githubmirror.com/flutter.git' repositoryUrl: 'https://githubmirror.com/flutter.git'
), ),
devToolsVersion: () => '2.8.0', devToolsVersion: () => '2.8.0',
...@@ -372,7 +372,7 @@ void main() { ...@@ -372,7 +372,7 @@ void main() {
platform: FakePlatform(localeName: 'en_US.UTF-8'), platform: FakePlatform(localeName: 'en_US.UTF-8'),
flutterVersion: () => FakeFlutterVersion( flutterVersion: () => FakeFlutterVersion(
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
channel: 'beta', branch: 'beta',
repositoryUrl: null, repositoryUrl: null,
), ),
devToolsVersion: () => '2.8.0', devToolsVersion: () => '2.8.0',
...@@ -406,7 +406,7 @@ void main() { ...@@ -406,7 +406,7 @@ void main() {
platform: FakePlatform(localeName: 'en_US.UTF-8'), platform: FakePlatform(localeName: 'en_US.UTF-8'),
flutterVersion: () => FakeFlutterVersion( flutterVersion: () => FakeFlutterVersion(
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
channel: 'beta' branch: 'beta'
), ),
devToolsVersion: () => '2.8.0', devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
...@@ -435,7 +435,7 @@ void main() { ...@@ -435,7 +435,7 @@ void main() {
platform: FakePlatform(localeName: 'en_US.UTF-8'), platform: FakePlatform(localeName: 'en_US.UTF-8'),
flutterVersion: () => FakeFlutterVersion( flutterVersion: () => FakeFlutterVersion(
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
channel: 'beta' branch: 'beta'
), ),
devToolsVersion: () => '2.8.0', devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
...@@ -472,7 +472,7 @@ void main() { ...@@ -472,7 +472,7 @@ void main() {
platform: FakePlatform(operatingSystem: 'windows', localeName: 'en_US.UTF-8'), platform: FakePlatform(operatingSystem: 'windows', localeName: 'en_US.UTF-8'),
flutterVersion: () => FakeFlutterVersion( flutterVersion: () => FakeFlutterVersion(
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
channel: 'beta' branch: 'beta'
), ),
devToolsVersion: () => '2.8.0', devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
...@@ -513,7 +513,7 @@ void main() { ...@@ -513,7 +513,7 @@ void main() {
platform: FakePlatform(operatingSystem: 'windows', localeName: 'en_US.UTF-8'), platform: FakePlatform(operatingSystem: 'windows', localeName: 'en_US.UTF-8'),
flutterVersion: () => FakeFlutterVersion( flutterVersion: () => FakeFlutterVersion(
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
channel: 'beta' branch: 'beta'
), ),
devToolsVersion: () => '2.8.0', devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
...@@ -546,7 +546,7 @@ void main() { ...@@ -546,7 +546,7 @@ void main() {
platform: FakePlatform(localeName: 'en_US.UTF-8'), platform: FakePlatform(localeName: 'en_US.UTF-8'),
flutterVersion: () => FakeFlutterVersion( flutterVersion: () => FakeFlutterVersion(
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
channel: 'beta' branch: 'beta'
), ),
devToolsVersion: () => '2.8.0', devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
...@@ -580,7 +580,7 @@ void main() { ...@@ -580,7 +580,7 @@ void main() {
platform: FakePlatform(localeName: 'en_US.UTF-8'), platform: FakePlatform(localeName: 'en_US.UTF-8'),
flutterVersion: () => FakeFlutterVersion( flutterVersion: () => FakeFlutterVersion(
frameworkVersion: '1.0.0', frameworkVersion: '1.0.0',
channel: 'beta' branch: 'beta'
), ),
devToolsVersion: () => '2.8.0', devToolsVersion: () => '2.8.0',
userMessages: UserMessages(), userMessages: UserMessages(),
......
...@@ -194,6 +194,23 @@ void main() { ...@@ -194,6 +194,23 @@ void main() {
expect(logger.statusText, isEmpty); 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 { class FakeTemplateRenderer extends TemplateRenderer {
......
...@@ -16,6 +16,7 @@ import 'package:test/fake.dart'; ...@@ -16,6 +16,7 @@ import 'package:test/fake.dart';
import '../src/common.dart'; import '../src/common.dart';
import '../src/context.dart'; import '../src/context.dart';
import '../src/fake_process_manager.dart'; import '../src/fake_process_manager.dart';
import '../src/fakes.dart' show FakeFlutterVersion;
final SystemClock _testClock = SystemClock.fixed(DateTime(2015)); final SystemClock _testClock = SystemClock.fixed(DateTime(2015));
final DateTime _stampUpToDate = _testClock.ago(VersionFreshnessValidator.checkAgeConsideredUpToDate ~/ 2); final DateTime _stampUpToDate = _testClock.ago(VersionFreshnessValidator.checkAgeConsideredUpToDate ~/ 2);
...@@ -67,6 +68,10 @@ void main() { ...@@ -67,6 +68,10 @@ void main() {
command: <String>['git', 'describe', '--match', '*.*.*', '--long', '--tags', '1234abcd'], command: <String>['git', 'describe', '--match', '*.*.*', '--long', '--tags', '1234abcd'],
stdout: '0.1.2-3-1234abcd', stdout: '0.1.2-3-1234abcd',
), ),
FakeCommand(
command: const <String>['git', 'symbolic-ref', '--short', 'HEAD'],
stdout: channel,
),
FakeCommand( FakeCommand(
command: const <String>['git', 'rev-parse', '--abbrev-ref', '--symbolic', '@{upstream}'], command: const <String>['git', 'rev-parse', '--abbrev-ref', '--symbolic', '@{upstream}'],
stdout: 'origin/$channel', stdout: 'origin/$channel',
...@@ -94,10 +99,6 @@ void main() { ...@@ -94,10 +99,6 @@ void main() {
command: const <String>['git', '-c', 'log.showSignature=false', 'log', 'HEAD', '-n', '1', '--pretty=format:%ad', '--date=iso'], command: const <String>['git', '-c', 'log.showSignature=false', 'log', 'HEAD', '-n', '1', '--pretty=format:%ad', '--date=iso'],
stdout: getChannelUpToDateVersion().toString(), stdout: getChannelUpToDateVersion().toString(),
), ),
FakeCommand(
command: const <String>['git', 'rev-parse', '--abbrev-ref', 'HEAD'],
stdout: channel,
),
]); ]);
final FlutterVersion flutterVersion = globals.flutterVersion; final FlutterVersion flutterVersion = globals.flutterVersion;
...@@ -129,7 +130,7 @@ void main() { ...@@ -129,7 +130,7 @@ void main() {
}); });
testWithoutContext('prints nothing when Flutter installation looks out-of-date but is actually up-to-date', () async { 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 BufferLogger logger = BufferLogger.test();
final VersionCheckStamp stamp = VersionCheckStamp( final VersionCheckStamp stamp = VersionCheckStamp(
lastTimeVersionWasChecked: _stampOutOfDate, lastTimeVersionWasChecked: _stampOutOfDate,
...@@ -150,7 +151,7 @@ void main() { ...@@ -150,7 +151,7 @@ void main() {
}); });
testWithoutContext('does not ping server when version stamp is up-to-date', () async { 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 BufferLogger logger = BufferLogger.test();
final VersionCheckStamp stamp = VersionCheckStamp( final VersionCheckStamp stamp = VersionCheckStamp(
lastTimeVersionWasChecked: _stampUpToDate, lastTimeVersionWasChecked: _stampUpToDate,
...@@ -172,7 +173,7 @@ void main() { ...@@ -172,7 +173,7 @@ void main() {
}); });
testWithoutContext('does not print warning if printed recently', () async { 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 BufferLogger logger = BufferLogger.test();
final VersionCheckStamp stamp = VersionCheckStamp( final VersionCheckStamp stamp = VersionCheckStamp(
lastTimeVersionWasChecked: _stampUpToDate, lastTimeVersionWasChecked: _stampUpToDate,
...@@ -194,7 +195,7 @@ void main() { ...@@ -194,7 +195,7 @@ void main() {
}); });
testWithoutContext('pings server when version stamp is missing', () async { 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(); final BufferLogger logger = BufferLogger.test();
cache.versionStamp = '{}'; cache.versionStamp = '{}';
...@@ -212,7 +213,7 @@ void main() { ...@@ -212,7 +213,7 @@ void main() {
}); });
testWithoutContext('pings server when version stamp is out-of-date', () async { 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 BufferLogger logger = BufferLogger.test();
final VersionCheckStamp stamp = VersionCheckStamp( final VersionCheckStamp stamp = VersionCheckStamp(
lastTimeVersionWasChecked: _stampOutOfDate, lastTimeVersionWasChecked: _stampOutOfDate,
...@@ -233,7 +234,7 @@ void main() { ...@@ -233,7 +234,7 @@ void main() {
}); });
testWithoutContext('does not print warning when unable to connect to server if not out of date', () async { 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(); final BufferLogger logger = BufferLogger.test();
cache.versionStamp = '{}'; cache.versionStamp = '{}';
...@@ -250,7 +251,7 @@ void main() { ...@@ -250,7 +251,7 @@ void main() {
}); });
testWithoutContext('prints warning when unable to connect to server if really out of date', () async { 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 BufferLogger logger = BufferLogger.test();
final VersionCheckStamp stamp = VersionCheckStamp( final VersionCheckStamp stamp = VersionCheckStamp(
lastTimeVersionWasChecked: _stampOutOfDate, lastTimeVersionWasChecked: _stampOutOfDate,
...@@ -329,7 +330,7 @@ void main() { ...@@ -329,7 +330,7 @@ void main() {
if (flutterGitUrl != null) 'FLUTTER_GIT_URL': flutterGitUrl, if (flutterGitUrl != null) 'FLUTTER_GIT_URL': flutterGitUrl,
}); });
return VersionUpstreamValidator( return VersionUpstreamValidator(
version: FakeFlutterVersion(repositoryUrl: versionUpstreamUrl, channel: 'master'), version: FakeFlutterVersion(repositoryUrl: versionUpstreamUrl),
platform: testPlatform, platform: testPlatform,
).run(); ).run();
} }
...@@ -413,17 +414,13 @@ void main() { ...@@ -413,17 +414,13 @@ void main() {
stdout: '0.1.2-3-1234abcd', stdout: '0.1.2-3-1234abcd',
), ),
const FakeCommand( const FakeCommand(
command: <String>['git', 'rev-parse', '--abbrev-ref', '--symbolic', '@{upstream}'], command: <String>['git', 'symbolic-ref', '--short', 'HEAD'],
stdout: 'feature-branch',
),
const FakeCommand(
command: <String>['git', 'rev-parse', '--abbrev-ref', 'HEAD'],
stdout: 'feature-branch', stdout: 'feature-branch',
), ),
]); ]);
final FlutterVersion flutterVersion = globals.flutterVersion; final FlutterVersion flutterVersion = globals.flutterVersion;
expect(flutterVersion.channel, 'feature-branch'); expect(flutterVersion.channel, '[user-branch]');
expect(flutterVersion.getVersionString(), 'feature-branch/1234abcd'); expect(flutterVersion.getVersionString(), 'feature-branch/1234abcd');
expect(flutterVersion.getBranchName(), 'feature-branch'); expect(flutterVersion.getBranchName(), 'feature-branch');
expect(flutterVersion.getVersionString(redactUnknownBranches: true), '[user-branch]/1234abcd'); expect(flutterVersion.getVersionString(redactUnknownBranches: true), '[user-branch]/1234abcd');
...@@ -455,7 +452,7 @@ void main() { ...@@ -455,7 +452,7 @@ void main() {
expect(gitTagVersion.devVersion, null); expect(gitTagVersion.devVersion, null);
expect(gitTagVersion.devPatch, null); expect(gitTagVersion.devPatch, null);
// Dev channel // Beta channel
gitTagVersion = GitTagVersion.parse('1.2.3-4.5.pre'); gitTagVersion = GitTagVersion.parse('1.2.3-4.5.pre');
expect(gitTagVersion.frameworkVersionFor(hash), '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'); expect(gitTagVersion.gitTag, '1.2.3-4.5.pre');
...@@ -468,7 +465,7 @@ void main() { ...@@ -468,7 +465,7 @@ void main() {
expect(gitTagVersion.devVersion, null); expect(gitTagVersion.devVersion, null);
expect(gitTagVersion.devPatch, 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'); gitTagVersion = GitTagVersion.parse('1.2.3-4.5.pre-0-g$hash');
expect(gitTagVersion.frameworkVersionFor(hash), '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'); expect(gitTagVersion.gitTag, '1.2.3-4.5.pre');
...@@ -521,13 +518,13 @@ void main() { ...@@ -521,13 +518,13 @@ void main() {
expect(gitTagVersion.frameworkVersionFor('abcd1234'), stableTag); 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'; const String stableTag = '1.2.3';
final FakeProcessManager fakeProcessManager = FakeProcessManager.list( final FakeProcessManager fakeProcessManager = FakeProcessManager.list(
<FakeCommand>[ <FakeCommand>[
const FakeCommand( const FakeCommand(
command: <String>['git', 'tag', '--points-at', 'HEAD'], command: <String>['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', stdout: '1.2.3-6.0.pre\n$stableTag',
), ),
], ],
...@@ -589,11 +586,11 @@ void main() { ...@@ -589,11 +586,11 @@ void main() {
expect(fakeProcessManager, hasNoRemainingExpectations); 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(<FakeCommand>[ final FakeProcessManager fakeProcessManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand( const FakeCommand(
command: <String>['git', 'rev-parse', '--abbrev-ref', 'HEAD'], command: <String>['git', 'symbolic-ref', '--short', 'HEAD'],
stdout: 'dev', stdout: 'beta',
), ),
const FakeCommand( const FakeCommand(
command: <String>['git', 'tag', '--points-at', 'HEAD'], command: <String>['git', 'tag', '--points-at', 'HEAD'],
...@@ -616,7 +613,7 @@ void main() { ...@@ -616,7 +613,7 @@ void main() {
testUsingContext('determine calls fetch --tags on master', () { testUsingContext('determine calls fetch --tags on master', () {
final FakeProcessManager fakeProcessManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager fakeProcessManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand( const FakeCommand(
command: <String>['git', 'rev-parse', '--abbrev-ref', 'HEAD'], command: <String>['git', 'symbolic-ref', '--short', 'HEAD'],
stdout: 'master', stdout: 'master',
), ),
const FakeCommand( const FakeCommand(
...@@ -643,7 +640,7 @@ void main() { ...@@ -643,7 +640,7 @@ void main() {
testUsingContext('determine uses overridden git url', () { testUsingContext('determine uses overridden git url', () {
final FakeProcessManager fakeProcessManager = FakeProcessManager.list(<FakeCommand>[ final FakeProcessManager fakeProcessManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand( const FakeCommand(
command: <String>['git', 'rev-parse', '--abbrev-ref', 'HEAD'], command: <String>['git', 'symbolic-ref', '--short', 'HEAD'],
stdout: 'master', stdout: 'master',
), ),
const FakeCommand( const FakeCommand(
...@@ -701,13 +698,3 @@ class FakeCache extends Fake implements Cache { ...@@ -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;
}
...@@ -11,7 +11,7 @@ import 'package:flutter_tools/src/base/terminal.dart'; ...@@ -11,7 +11,7 @@ import 'package:flutter_tools/src/base/terminal.dart';
import '../src/common.dart'; import '../src/common.dart';
import 'test_utils.dart'; import 'test_utils.dart';
const String _kInitialVersion = 'v1.9.1'; const String _kInitialVersion = '3.0.0';
const String _kBranch = 'beta'; const String _kBranch = 'beta';
final Stdio stdio = Stdio(); final Stdio stdio = Stdio();
...@@ -80,6 +80,7 @@ void main() { ...@@ -80,6 +80,7 @@ void main() {
printOnFailure('Step 4 - upgrade to the newest $_kBranch'); printOnFailure('Step 4 - upgrade to the newest $_kBranch');
// This should update the persistent tool state with the sha for HEAD // 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(<String>[ exitCode = await processUtils.stream(<String>[
flutterBin, flutterBin,
'upgrade', 'upgrade',
...@@ -93,7 +94,7 @@ void main() { ...@@ -93,7 +94,7 @@ void main() {
'git', 'git',
'describe', 'describe',
'--match', '--match',
'v*.*.*', '*.*.*',
'--long', '--long',
'--tags', '--tags',
], workingDirectory: testDirectory.path); ], workingDirectory: testDirectory.path);
...@@ -114,7 +115,7 @@ void main() { ...@@ -114,7 +115,7 @@ void main() {
'git', 'git',
'describe', 'describe',
'--match', '--match',
'v*.*.*', '*.*.*',
'--long', '--long',
'--tags', '--tags',
], workingDirectory: testDirectory.path); ], workingDirectory: testDirectory.path);
......
...@@ -324,7 +324,7 @@ class FakeBotDetector implements BotDetector { ...@@ -324,7 +324,7 @@ class FakeBotDetector implements BotDetector {
class FakeFlutterVersion implements FlutterVersion { class FakeFlutterVersion implements FlutterVersion {
FakeFlutterVersion({ FakeFlutterVersion({
this.channel = 'unknown', this.branch = 'master',
this.dartSdkVersion = '12', this.dartSdkVersion = '12',
this.devToolsVersion = '2.8.0', this.devToolsVersion = '2.8.0',
this.engineRevision = 'abcdefghijklmnopqrstuvwxyz', this.engineRevision = 'abcdefghijklmnopqrstuvwxyz',
...@@ -338,6 +338,8 @@ class FakeFlutterVersion implements FlutterVersion { ...@@ -338,6 +338,8 @@ class FakeFlutterVersion implements FlutterVersion {
this.gitTagVersion = const GitTagVersion.unknown(), this.gitTagVersion = const GitTagVersion.unknown(),
}); });
final String branch;
bool get didFetchTagsAndUpdate => _didFetchTagsAndUpdate; bool get didFetchTagsAndUpdate => _didFetchTagsAndUpdate;
bool _didFetchTagsAndUpdate = false; bool _didFetchTagsAndUpdate = false;
...@@ -345,7 +347,12 @@ class FakeFlutterVersion implements FlutterVersion { ...@@ -345,7 +347,12 @@ class FakeFlutterVersion implements FlutterVersion {
bool _didCheckFlutterVersionFreshness = false; bool _didCheckFlutterVersionFreshness = false;
@override @override
final String channel; String get channel {
if (kOfficialChannels.contains(branch) || kObsoleteBranches.containsKey(branch)) {
return branch;
}
return kUserBranch;
}
@override @override
final String devToolsVersion; final String devToolsVersion;
...@@ -398,7 +405,10 @@ class FakeFlutterVersion implements FlutterVersion { ...@@ -398,7 +405,10 @@ class FakeFlutterVersion implements FlutterVersion {
@override @override
String getBranchName({bool redactUnknownBranches = false}) { String getBranchName({bool redactUnknownBranches = false}) {
return 'master'; if (!redactUnknownBranches || kOfficialChannels.contains(branch) || kObsoleteBranches.containsKey(branch)) {
return branch;
}
return kUserBranch;
} }
@override @override
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment