Flutter 1.17.0.dev.3.3 cherrypicks (#55871)
* [flutter_tools] fix type error in symbolize (#55212)
* [flutter_tools] check first for stable tag, then dev tag (#55342)
* [flutter_tools] enable `flutter upgrade` to support force pushed branches (#55594)
* [flutter_tools] catch ProcessException and throw ToolExit during upgrade (#55759)
* Update engine version to 376ad6a64b08aa26005e3f82aed26de2e290b572
Co-authored-by: Jonah Williams <campfish91@gmail.com>
Co-authored-by: Christopher Fujino <fujino@google.com>
Co-authored-by: Christopher Fujino <christopherfujino@gmail.com>
diff --git a/bin/internal/engine.version b/bin/internal/engine.version
index 7b9898d..0827024 100644
--- a/bin/internal/engine.version
+++ b/bin/internal/engine.version
@@ -1 +1 @@
-4c8c31f591882b3c668992d2e9da761118899f38
+376ad6a64b08aa26005e3f82aed26de2e290b572
diff --git a/packages/flutter_tools/lib/src/commands/symbolize.dart b/packages/flutter_tools/lib/src/commands/symbolize.dart
index c15a9ef..21cf3fa 100644
--- a/packages/flutter_tools/lib/src/commands/symbolize.dart
+++ b/packages/flutter_tools/lib/src/commands/symbolize.dart
@@ -113,9 +113,46 @@
}
}
+typedef SymbolsTransformer = StreamTransformer<String, String> Function(Uint8List);
+
+StreamTransformer<String, String> _defaultTransformer(Uint8List symbols) {
+ final Dwarf dwarf = Dwarf.fromBytes(symbols);
+ if (dwarf == null) {
+ throwToolExit('Failed to decode symbols file');
+ }
+ return DwarfStackTraceDecoder(dwarf, includeInternalFrames: true);
+}
+
+// A no-op transformer for `DwarfSymbolizationService.test`
+StreamTransformer<String, String> _testTransformer(Uint8List buffer) {
+ return StreamTransformer<String, String>.fromHandlers(
+ handleData: (String data, EventSink<String> sink) {
+ sink.add(data);
+ },
+ handleDone: (EventSink<String> sink) {
+ sink.close();
+ },
+ handleError: (dynamic error, StackTrace stackTrace, EventSink<String> sink) {
+ sink.addError(error, stackTrace);
+ }
+ );
+}
+
/// A service which decodes stack traces from Dart applications.
class DwarfSymbolizationService {
- const DwarfSymbolizationService();
+ const DwarfSymbolizationService({
+ SymbolsTransformer symbolsTransformer = _defaultTransformer,
+ }) : _transformer = symbolsTransformer;
+
+ /// Create a DwarfSymbolizationService with a no-op transformer for testing.
+ @visibleForTesting
+ factory DwarfSymbolizationService.test() {
+ return const DwarfSymbolizationService(
+ symbolsTransformer: _testTransformer
+ );
+ }
+
+ final SymbolsTransformer _transformer;
/// Decode a stack trace from [input] and place the results in [output].
///
@@ -129,17 +166,13 @@
@required IOSink output,
@required Uint8List symbols,
}) async {
- final Dwarf dwarf = Dwarf.fromBytes(symbols);
- if (dwarf == null) {
- throwToolExit('Failed to decode symbols file');
- }
-
final Completer<void> onDone = Completer<void>();
StreamSubscription<void> subscription;
subscription = input
+ .cast<List<int>>()
.transform(const Utf8Decoder())
.transform(const LineSplitter())
- .transform(DwarfStackTraceDecoder(dwarf, includeInternalFrames: true))
+ .transform(_transformer(symbols))
.listen((String line) {
try {
output.writeln(line);
diff --git a/packages/flutter_tools/lib/src/commands/upgrade.dart b/packages/flutter_tools/lib/src/commands/upgrade.dart
index 7b51c3b..21d1569 100644
--- a/packages/flutter_tools/lib/src/commands/upgrade.dart
+++ b/packages/flutter_tools/lib/src/commands/upgrade.dart
@@ -100,7 +100,12 @@
@required FlutterVersion flutterVersion,
@required bool testFlow,
}) async {
- await verifyUpstreamConfigured();
+ final String upstreamRevision = await fetchRemoteRevision();
+ if (flutterVersion.frameworkRevision == upstreamRevision) {
+ globals.printStatus('Flutter is already up to date on channel ${flutterVersion.channel}');
+ globals.printStatus('$flutterVersion');
+ return;
+ }
if (!force && gitTagVersion == const GitTagVersion.unknown()) {
// If the commit is a recognized branch and not master,
// explain that we are avoiding potential damage.
@@ -132,12 +137,8 @@
}
recordState(flutterVersion);
await upgradeChannel(flutterVersion);
- final bool alreadyUpToDate = await attemptFastForward(flutterVersion);
- if (alreadyUpToDate) {
- // If the upgrade was a no op, then do not continue with the second half.
- globals.printStatus('Flutter is already up to date on channel ${flutterVersion.channel}');
- globals.printStatus('$flutterVersion');
- } else if (!testFlow) {
+ await attemptReset(upstreamRevision);
+ if (!testFlow) {
await flutterUpgradeContinue();
}
}
@@ -199,16 +200,25 @@
return false;
}
- /// Check if there is an upstream repository configured.
+ /// Returns the remote HEAD revision.
///
/// Exits tool if there is no upstream.
- Future<void> verifyUpstreamConfigured() async {
+ Future<String> fetchRemoteRevision() async {
+ String revision;
try {
+ // Fetch upstream branch's commits and tags
await processUtils.run(
- <String>[ 'git', 'rev-parse', '@{u}'],
+ <String>['git', 'fetch', '--tags'],
throwOnError: true,
workingDirectory: workingDirectory,
);
+ // '@{u}' means upstream HEAD
+ final RunResult result = await processUtils.run(
+ <String>[ 'git', 'rev-parse', '--verify', '@{u}'],
+ throwOnError: true,
+ workingDirectory: workingDirectory,
+ );
+ revision = result.stdout.trim();
} on Exception {
throwToolExit(
'Unable to upgrade Flutter: no origin repository configured. '
@@ -216,6 +226,7 @@
"https://github.com/flutter/flutter' in $workingDirectory",
);
}
+ return revision;
}
/// Attempts to upgrade the channel.
@@ -227,33 +238,21 @@
await ChannelCommand.upgradeChannel();
}
- /// Attempts to rebase the upstream onto the local branch.
+ /// Attempts a hard reset to the given revision.
///
- /// If there haven't been any hot fixes or local changes, this is equivalent
- /// to a fast-forward.
- ///
- /// If the fast forward lands us on the same channel and revision, then
- /// returns true, otherwise returns false.
- Future<bool> attemptFastForward(FlutterVersion oldFlutterVersion) async {
- final int code = await processUtils.stream(
- <String>['git', 'pull', '--ff-only'],
- workingDirectory: workingDirectory,
- mapFunction: (String line) => matchesGitLine(line) ? null : line,
- );
- if (code != 0) {
- throwToolExit(null, exitCode: code);
- }
-
- // Check if the upgrade did anything.
- bool alreadyUpToDate = false;
+ /// This is a reset instead of fast forward because if we are on a release
+ /// branch with cherry picks, there may not be a direct fast-forward route
+ /// to the next release.
+ Future<void> attemptReset(String newRevision) async {
try {
- final FlutterVersion newFlutterVersion = FlutterVersion(const SystemClock(), workingDirectory);
- alreadyUpToDate = newFlutterVersion.channel == oldFlutterVersion.channel &&
- newFlutterVersion.frameworkRevision == oldFlutterVersion.frameworkRevision;
- } on Exception catch (e) {
- globals.printTrace('Failed to determine FlutterVersion after upgrade fast-forward: $e');
+ await processUtils.run(
+ <String>['git', 'reset', '--hard', newRevision],
+ throwOnError: true,
+ workingDirectory: workingDirectory,
+ );
+ } on ProcessException catch (e) {
+ throwToolExit(e.message, exitCode: e.errorCode);
}
- return alreadyUpToDate;
}
/// Update the engine repository and precache all artifacts.
@@ -300,18 +299,4 @@
allowReentrantFlutter: true,
);
}
-
- // dev/benchmarks/complex_layout/lib/main.dart | 24 +-
- static final RegExp _gitDiffRegex = RegExp(r' (\S+)\s+\|\s+\d+ [+-]+');
-
- // rename {packages/flutter/doc => dev/docs}/styles.html (92%)
- // delete mode 100644 doc/index.html
- // create mode 100644 dev/integration_tests/flutter_gallery/lib/gallery/demo.dart
- static final RegExp _gitChangedRegex = RegExp(r' (rename|delete mode|create mode) .+');
-
- static bool matchesGitLine(String line) {
- return _gitDiffRegex.hasMatch(line)
- || _gitChangedRegex.hasMatch(line)
- || line == 'Fast-forward';
- }
}
diff --git a/packages/flutter_tools/lib/src/version.dart b/packages/flutter_tools/lib/src/version.dart
index bbd6cef..75b186e 100644
--- a/packages/flutter_tools/lib/src/version.dart
+++ b/packages/flutter_tools/lib/src/version.dart
@@ -752,80 +752,83 @@
_runGit('git fetch $_flutterGit --tags', processUtils, workingDirectory);
}
}
- // `--match` glob must match old version tag `v1.2.3` and new `1.2.3-dev.4.5`
- return parse(_runGit('git describe --match *.*.* --first-parent --long --tags', processUtils, workingDirectory));
- }
+ final List<String> tags = _runGit(
+ 'git tag --contains HEAD', processUtils, workingDirectory).split('\n');
- // TODO(fujino): Deprecate this https://github.com/flutter/flutter/issues/53850
- /// Check for the release tag format of the form x.y.z-dev.m.n
- static GitTagVersion parseLegacyVersion(String version) {
- final RegExp versionPattern = RegExp(
- r'^([0-9]+)\.([0-9]+)\.([0-9]+)(-dev\.[0-9]+\.[0-9]+)?-([0-9]+)-g([a-f0-9]+)$');
- final List<String> parts = versionPattern.matchAsPrefix(version)?.groups(<int>[1, 2, 3, 4, 5, 6]);
- if (parts == null) {
- return const GitTagVersion.unknown();
+ // Check first for a stable tag
+ final RegExp stableTagPattern = RegExp(r'^\d+\.\d+\.\d+$');
+ for (final String tag in tags) {
+ final String trimmedTag = tag.trim();
+ if (stableTagPattern.hasMatch(trimmedTag)) {
+ return parse(trimmedTag);
+ }
}
- final List<int> parsedParts = parts.take(5).map<int>(
- (String source) => source == null ? null : int.tryParse(source)).toList();
- List<int> devParts = <int>[null, null];
- if (parts[3] != null) {
- devParts = RegExp(r'^-dev\.(\d+)\.(\d+)')
- .matchAsPrefix(parts[3])
- ?.groups(<int>[1, 2])
- ?.map<int>(
- (String source) => source == null ? null : int.tryParse(source)
- )?.toList() ?? <int>[null, null];
+ // Next check for a dev tag
+ final RegExp devTagPattern = RegExp(r'^\d+\.\d+\.\d+-\d+\.\d+\.pre$');
+ for (final String tag in tags) {
+ final String trimmedTag = tag.trim();
+ if (devTagPattern.hasMatch(trimmedTag)) {
+ return parse(trimmedTag);
+ }
}
- return GitTagVersion(
- x: parsedParts[0],
- y: parsedParts[1],
- z: parsedParts[2],
- devVersion: devParts[0],
- devPatch: devParts[1],
- commits: parsedParts[4],
- hash: parts[5],
- gitTag: '${parts[0]}.${parts[1]}.${parts[2]}${parts[3] ?? ''}', // x.y.z-dev.m.n
+
+ // If we're not currently on a tag, use git describe to find the most
+ // recent tag and number of commits past.
+ return parse(
+ _runGit(
+ 'git describe --match *.*.*-*.*.pre --first-parent --long --tags',
+ processUtils,
+ workingDirectory,
+ )
);
}
- /// Check for the release tag format of the form x.y.z-m.n.pre
+ /// Parse a version string.
+ ///
+ /// The version string can either be an exact release tag (e.g. '1.2.3' for
+ /// stable or 1.2.3-4.5.pre for a dev) or the output of `git describe` (e.g.
+ /// for commit abc123 that is 6 commits after tag 1.2.3-4.5.pre, git would
+ /// return '1.2.3-4.5.pre-6-gabc123').
static GitTagVersion parseVersion(String version) {
final RegExp versionPattern = RegExp(
- r'^(\d+)\.(\d+)\.(\d+)(-\d+\.\d+\.pre)?-(\d+)-g([a-f0-9]+)$');
- final List<String> parts = versionPattern.matchAsPrefix(version)?.groups(<int>[1, 2, 3, 4, 5, 6]);
- if (parts == null) {
+ r'^(\d+)\.(\d+)\.(\d+)(-\d+\.\d+\.pre)?(?:-(\d+)-g([a-f0-9]+))?$');
+ final Match match = versionPattern.firstMatch(version.trim());
+ if (match == null) {
return const GitTagVersion.unknown();
}
- final List<int> parsedParts = parts.take(5).map<int>(
- (String source) => source == null ? null : int.tryParse(source)).toList();
- List<int> devParts = <int>[null, null];
- if (parts[3] != null) {
- devParts = RegExp(r'^-(\d+)\.(\d+)\.pre')
- .matchAsPrefix(parts[3])
- ?.groups(<int>[1, 2])
- ?.map<int>(
- (String source) => source == null ? null : int.tryParse(source)
- )?.toList() ?? <int>[null, null];
+
+ final List<String> matchGroups = match.groups(<int>[1, 2, 3, 4, 5, 6]);
+ final int x = matchGroups[0] == null ? null : int.tryParse(matchGroups[0]);
+ final int y = matchGroups[1] == null ? null : int.tryParse(matchGroups[1]);
+ final int z = matchGroups[2] == null ? null : int.tryParse(matchGroups[2]);
+ final String devString = matchGroups[3];
+ int devVersion, devPatch;
+ if (devString != null) {
+ final Match devMatch = RegExp(r'^-(\d+)\.(\d+)\.pre$')
+ .firstMatch(devString);
+ final List<String> devGroups = devMatch.groups(<int>[1, 2]);
+ devVersion = devGroups[0] == null ? null : int.tryParse(devGroups[0]);
+ devPatch = devGroups[1] == null ? null : int.tryParse(devGroups[1]);
}
+ // count of commits past last tagged version
+ final int commits = matchGroups[4] == null ? 0 : int.tryParse(matchGroups[4]);
+ final String hash = matchGroups[5] ?? '';
+
return GitTagVersion(
- x: parsedParts[0],
- y: parsedParts[1],
- z: parsedParts[2],
- devVersion: devParts[0],
- devPatch: devParts[1],
- commits: parsedParts[4],
- hash: parts[5],
- gitTag: '${parts[0]}.${parts[1]}.${parts[2]}${parts[3] ?? ''}', // x.y.z-m.n.pre
+ x: x,
+ y: y,
+ z: z,
+ devVersion: devVersion,
+ devPatch: devPatch,
+ commits: commits,
+ hash: hash,
+ gitTag: '$x.$y.$z${devString ?? ''}', // e.g. 1.2.3-4.5.pre
);
}
static GitTagVersion parse(String version) {
GitTagVersion gitTagVersion;
- gitTagVersion = parseLegacyVersion(version);
- if (gitTagVersion != const GitTagVersion.unknown()) {
- return gitTagVersion;
- }
gitTagVersion = parseVersion(version);
if (gitTagVersion != const GitTagVersion.unknown()) {
return gitTagVersion;
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/symbolize_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/symbolize_test.dart
index 9211837..17c1026 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/symbolize_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/symbolize_test.dart
@@ -2,10 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import 'dart:async';
import 'dart:typed_data';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/common.dart';
+import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/symbolize.dart';
import 'package:flutter_tools/src/convert.dart';
@@ -38,6 +40,24 @@
applyMocksToCommand(command);
});
+ testUsingContext('Regression test for type error in codec', () async {
+ final DwarfSymbolizationService symbolizationService = DwarfSymbolizationService.test();
+ final StreamController<List<int>> output = StreamController<List<int>>();
+
+ unawaited(symbolizationService.decode(
+ input: Stream<Uint8List>.fromIterable(<Uint8List>[
+ utf8.encode('Hello, World\n') as Uint8List,
+ ]),
+ symbols: Uint8List(0),
+ output: IOSink(output.sink),
+ ));
+
+ await expectLater(
+ output.stream.transform(utf8.decoder),
+ emits('Hello, World'),
+ );
+ });
+
testUsingContext('symbolize exits when --debug-info argument is missing', () async {
final Future<void> result = createTestCommandRunner(command)
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart
index 0365e10..4ff197e 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart
@@ -259,7 +259,7 @@
return ProcessResult(0, 0, '000000000000000000000', '');
}
if (commandStr ==
- 'git describe --match *.*.* --first-parent --long --tags') {
+ 'git describe --match *.*.*-*.*.pre --first-parent --long --tags') {
if (version.isNotEmpty) {
return ProcessResult(0, 0, '$version-0-g00000000', '');
}
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 150dc26..633ff27 100644
--- a/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart
+++ b/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart
@@ -5,7 +5,6 @@
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
-import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/upgrade.dart';
import 'package:flutter_tools/src/convert.dart';
@@ -134,7 +133,10 @@
});
testUsingContext("Doesn't continue on known tag, dev branch, no force, already up-to-date", () async {
+ const String revision = 'abc123';
+ when(flutterVersion.frameworkRevision).thenReturn(revision);
fakeCommandRunner.alreadyUpToDate = true;
+ fakeCommandRunner.remoteRevision = revision;
final Future<FlutterCommandResult> result = fakeCommandRunner.runCommand(
force: false,
continueFlow: false,
@@ -159,16 +161,46 @@
Platform: () => fakePlatform,
});
- testUsingContext('verifyUpstreamConfigured', () async {
- when(globals.processManager.run(
- <String>['git', 'rev-parse', '@{u}'],
+ testUsingContext('fetchRemoteRevision', () async {
+ const String revision = 'abc123';
+ when(processManager.run(
+ <String>['git', 'fetch', '--tags'],
environment:anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory')),
).thenAnswer((Invocation invocation) async {
return FakeProcessResult()
..exitCode = 0;
});
- await realCommandRunner.verifyUpstreamConfigured();
+ when(processManager.run(
+ <String>['git', 'rev-parse', '--verify', '@{u}'],
+ environment:anyNamed('environment'),
+ workingDirectory: anyNamed('workingDirectory')),
+ ).thenAnswer((Invocation invocation) async {
+ return FakeProcessResult()
+ ..exitCode = 0
+ ..stdout = revision;
+ });
+ expect(await realCommandRunner.fetchRemoteRevision(), revision);
+ }, overrides: <Type, Generator>{
+ ProcessManager: () => processManager,
+ Platform: () => fakePlatform,
+ });
+
+ testUsingContext('git exception during attemptReset throwsToolExit', () async {
+ const String revision = 'abc123';
+ const String errorMessage = 'fatal: Could not parse object ´$revision´';
+ when(processManager.run(
+ <String>['git', 'reset', '--hard', revision]
+ )).thenThrow(const ProcessException(
+ 'git',
+ <String>['reset', '--hard', revision],
+ errorMessage,
+ ));
+
+ expect(
+ () async => await realCommandRunner.attemptReset(revision),
+ throwsToolExit(message: errorMessage),
+ );
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
Platform: () => fakePlatform,
@@ -238,7 +270,13 @@
fakeProcessManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(
command: <String>[
- 'git', 'describe', '--match', '*.*.*', '--first-parent', '--long', '--tags',
+ 'git', 'tag', '--contains', 'HEAD',
+ ],
+ stdout: '',
+ ),
+ const FakeCommand(
+ command: <String>[
+ 'git', 'describe', '--match', '*.*.*-*.*.pre', '--first-parent', '--long', '--tags',
],
stdout: 'v1.12.16-19-gb45b676af',
),
@@ -278,58 +316,6 @@
});
});
});
-
- group('matchesGitLine', () {
- setUpAll(() {
- Cache.disableLocking();
- });
-
- bool _match(String line) => UpgradeCommandRunner.matchesGitLine(line);
-
- test('regex match', () {
- expect(_match(' .../flutter_gallery/lib/demo/buttons_demo.dart | 10 +--'), true);
- expect(_match(' dev/benchmarks/complex_layout/lib/main.dart | 24 +-'), true);
-
- expect(_match(' rename {packages/flutter/doc => dev/docs}/styles.html (92%)'), true);
- expect(_match(' delete mode 100644 doc/index.html'), true);
- expect(_match(' create mode 100644 dev/integration_tests/flutter_gallery/lib/gallery/demo.dart'), true);
-
- expect(_match('Fast-forward'), true);
- });
-
- test("regex doesn't match", () {
- expect(_match('Updating 79cfe1e..5046107'), false);
- expect(_match('229 files changed, 6179 insertions(+), 3065 deletions(-)'), false);
- });
-
- group('findProjectRoot', () {
- Directory tempDir;
-
- setUp(() async {
- tempDir = globals.fs.systemTempDirectory.createTempSync('flutter_tools_upgrade_test.');
- });
-
- tearDown(() {
- tryToDelete(tempDir);
- });
-
- testUsingContext('in project', () async {
- final String projectPath = await createProject(tempDir);
- expect(findProjectRoot(projectPath), projectPath);
- expect(findProjectRoot(globals.fs.path.join(projectPath, 'lib')), projectPath);
-
- final String hello = globals.fs.path.join(Cache.flutterRoot, 'examples', 'hello_world');
- expect(findProjectRoot(hello), hello);
- expect(findProjectRoot(globals.fs.path.join(hello, 'lib')), hello);
- });
-
- testUsingContext('outside project', () async {
- final String projectPath = await createProject(tempDir);
- expect(findProjectRoot(globals.fs.directory(projectPath).parent.path), null);
- expect(findProjectRoot(Cache.flutterRoot), null);
- });
- });
- });
}
class FakeUpgradeCommandRunner extends UpgradeCommandRunner {
@@ -337,8 +323,10 @@
bool alreadyUpToDate = false;
+ String remoteRevision = '';
+
@override
- Future<void> verifyUpstreamConfigured() async {}
+ Future<String> fetchRemoteRevision() async => remoteRevision;
@override
Future<bool> hasUncomittedChanges() async => willHaveUncomittedChanges;
@@ -347,7 +335,7 @@
Future<void> upgradeChannel(FlutterVersion flutterVersion) async {}
@override
- Future<bool> attemptFastForward(FlutterVersion flutterVersion) async => alreadyUpToDate;
+ Future<void> attemptReset(String newRevision) async {}
@override
Future<void> precacheArtifacts() async {}
diff --git a/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart b/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart
index 3779ff8..cd51758 100644
--- a/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart
@@ -179,7 +179,9 @@
workingDirectory: Cache.flutterRoot)).thenReturn(result);
when(processManager.runSync('git fetch https://github.com/flutter/flutter.git --tags'.split(' '),
workingDirectory: Cache.flutterRoot)).thenReturn(result);
- when(processManager.runSync('git describe --match *.*.* --first-parent --long --tags'.split(' '),
+ when(processManager.runSync('git tag --contains HEAD'.split(' '),
+ workingDirectory: Cache.flutterRoot)).thenReturn(result);
+ when(processManager.runSync('git describe --match *.*.*-*.*.pre --first-parent --long --tags'.split(' '),
workingDirectory: Cache.flutterRoot)).thenReturn(result);
when(processManager.runSync(FlutterVersion.gitLog('-n 1 --pretty=format:%ad --date=iso'.split(' ')),
workingDirectory: Cache.flutterRoot)).thenReturn(result);
diff --git a/packages/flutter_tools/test/general.shard/version_test.dart b/packages/flutter_tools/test/general.shard/version_test.dart
index f47e5a2..6d7fa7f 100644
--- a/packages/flutter_tools/test/general.shard/version_test.dart
+++ b/packages/flutter_tools/test/general.shard/version_test.dart
@@ -394,16 +394,25 @@
const String hash = 'abcdef';
GitTagVersion gitTagVersion;
- // legacy tag format (x.y.z-dev.m.n), master channel
- gitTagVersion = GitTagVersion.parse('1.2.3-dev.4.5-4-g$hash');
- expect(gitTagVersion.frameworkVersionFor(hash), '1.2.3-5.0.pre.4');
- expect(gitTagVersion.gitTag, '1.2.3-dev.4.5');
+ // Master channel
+ gitTagVersion = GitTagVersion.parse('1.2.3-4.5.pre-13-g$hash');
+ expect(gitTagVersion.frameworkVersionFor(hash), '1.2.3-5.0.pre.13');
+ expect(gitTagVersion.gitTag, '1.2.3-4.5.pre');
expect(gitTagVersion.devVersion, 4);
expect(gitTagVersion.devPatch, 5);
- // new tag release format, master channel
- gitTagVersion = GitTagVersion.parse('1.2.3-4.5.pre-13-g$hash');
- expect(gitTagVersion.frameworkVersionFor(hash), '1.2.3-5.0.pre.13');
+ // Stable channel
+ gitTagVersion = GitTagVersion.parse('1.2.3');
+ expect(gitTagVersion.frameworkVersionFor(hash), '1.2.3');
+ expect(gitTagVersion.x, 1);
+ expect(gitTagVersion.y, 2);
+ expect(gitTagVersion.z, 3);
+ expect(gitTagVersion.devVersion, null);
+ expect(gitTagVersion.devPatch, null);
+
+ // Dev 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');
expect(gitTagVersion.devVersion, 4);
expect(gitTagVersion.devPatch, 5);
@@ -448,6 +457,29 @@
);
});
+ testUsingContext('determine favors stable tags over dev tags', () {
+ final MockProcessUtils mockProcessUtils = MockProcessUtils();
+ when(mockProcessUtils.runSync(
+ <String>['git', 'tag', '--contains', 'HEAD'],
+ workingDirectory: anyNamed('workingDirectory'),
+ environment: anyNamed('environment'),
+ )).thenReturn(RunResult(
+ ProcessResult(1, 0, '1.2.3-0.0.pre\n1.2.3\n1.2.3-0.1.pre', ''),
+ <String>['git', 'tag', '--contains', 'HEAD'],
+ ));
+ final GitTagVersion version = GitTagVersion.determine(mockProcessUtils, workingDirectory: '.');
+ expect(version.gitTag, '1.2.3');
+ expect(version.devPatch, null);
+ expect(version.devVersion, null);
+ // We shouldn't have to fallback to git describe, because we are exactly
+ // on a release tag.
+ verifyNever(mockProcessUtils.runSync(
+ <String>['git', 'describe', '--match', '*.*.*-*.*.pre', '--first-parent', '--long', '--tags'],
+ workingDirectory: anyNamed('workingDirectory'),
+ environment: anyNamed('environment'),
+ ));
+ });
+
testUsingContext('determine does not call fetch --tags', () {
final MockProcessUtils processUtils = MockProcessUtils();
when(processUtils.runSync(
@@ -456,10 +488,18 @@
environment: anyNamed('environment'),
)).thenReturn(RunResult(ProcessResult(105, 0, '', ''), <String>['git', 'fetch']));
when(processUtils.runSync(
- <String>['git', 'describe', '--match', '*.*.*', '--first-parent', '--long', '--tags'],
+ <String>['git', 'describe', '--match', '*.*.*-*.*.pre', '--first-parent', '--long', '--tags'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenReturn(RunResult(ProcessResult(106, 0, 'v0.1.2-3-1234abcd', ''), <String>['git', 'describe']));
+ when(processUtils.runSync(
+ <String>['git', 'tag', '--contains', 'HEAD'],
+ workingDirectory: anyNamed('workingDirectory'),
+ environment: anyNamed('environment'),
+ )).thenReturn(
+ RunResult(ProcessResult(110, 0, '', ''),
+ <String>['git', 'tag', '--contains', 'HEAD'],
+ ));
GitTagVersion.determine(processUtils, workingDirectory: '.');
@@ -474,7 +514,7 @@
environment: anyNamed('environment'),
));
verify(processUtils.runSync(
- <String>['git', 'describe', '--match', '*.*.*', '--first-parent', '--long', '--tags'],
+ <String>['git', 'describe', '--match', '*.*.*-*.*.pre', '--first-parent', '--long', '--tags'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).called(1);
@@ -493,10 +533,18 @@
environment: anyNamed('environment'),
)).thenReturn(RunResult(ProcessResult(106, 0, '', ''), <String>['git', 'fetch']));
when(processUtils.runSync(
- <String>['git', 'describe', '--match', '*.*.*', '--first-parent', '--long', '--tags'],
+ <String>['git', 'describe', '--match', '*.*.*-*.*.pre', '--first-parent', '--long', '--tags'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenReturn(RunResult(ProcessResult(107, 0, 'v0.1.2-3-1234abcd', ''), <String>['git', 'describe']));
+ when(processUtils.runSync(
+ <String>['git', 'tag', '--contains', 'HEAD'],
+ workingDirectory: anyNamed('workingDirectory'),
+ environment: anyNamed('environment'),
+ )).thenReturn(
+ RunResult(ProcessResult(108, 0, '', ''),
+ <String>['git', 'tag', '--contains', 'HEAD'],
+ ));
GitTagVersion.determine(processUtils, workingDirectory: '.', fetchTags: true);
@@ -511,7 +559,7 @@
environment: anyNamed('environment'),
));
verify(processUtils.runSync(
- <String>['git', 'describe', '--match', '*.*.*', '--first-parent', '--long', '--tags'],
+ <String>['git', 'describe', '--match', '*.*.*-*.*.pre', '--first-parent', '--long', '--tags'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).called(1);
@@ -530,10 +578,18 @@
environment: anyNamed('environment'),
)).thenReturn(RunResult(ProcessResult(109, 0, '', ''), <String>['git', 'fetch']));
when(processUtils.runSync(
- <String>['git', 'describe', '--match', '*.*.*', '--first-parent', '--long', '--tags'],
+ <String>['git', 'tag', '--contains', 'HEAD'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
- )).thenReturn(RunResult(ProcessResult(110, 0, 'v0.1.2-3-1234abcd', ''), <String>['git', 'describe']));
+ )).thenReturn(
+ RunResult(ProcessResult(110, 0, '', ''),
+ <String>['git', 'tag', '--contains', 'HEAD'],
+ ));
+ when(processUtils.runSync(
+ <String>['git', 'describe', '--match', '*.*.*-*.*.pre', '--first-parent', '--long', '--tags'],
+ workingDirectory: anyNamed('workingDirectory'),
+ environment: anyNamed('environment'),
+ )).thenReturn(RunResult(ProcessResult(111, 0, 'v0.1.2-3-1234abcd', ''), <String>['git', 'describe']));
GitTagVersion.determine(processUtils, workingDirectory: '.', fetchTags: true);
@@ -548,7 +604,7 @@
environment: anyNamed('environment'),
)).called(1);
verify(processUtils.runSync(
- <String>['git', 'describe', '--match', '*.*.*', '--first-parent', '--long', '--tags'],
+ <String>['git', 'describe', '--match', '*.*.*-*.*.pre', '--first-parent', '--long', '--tags'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).called(1);
@@ -669,10 +725,15 @@
environment: anyNamed('environment'),
)).thenReturn(ProcessResult(105, 0, '', ''));
when(pm.runSync(
- <String>['git', 'describe', '--match', '*.*.*', '--first-parent', '--long', '--tags'],
+ <String>['git', 'tag', '--contains', 'HEAD'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
- )).thenReturn(ProcessResult(106, 0, 'v0.1.2-3-1234abcd', ''));
+ )).thenReturn(ProcessResult(106, 0, '', ''));
+ when(pm.runSync(
+ <String>['git', 'describe', '--match', '*.*.*-*.*.pre', '--first-parent', '--long', '--tags'],
+ workingDirectory: anyNamed('workingDirectory'),
+ environment: anyNamed('environment'),
+ )).thenReturn(ProcessResult(107, 0, 'v0.1.2-3-1234abcd', ''));
}
class MockProcessManager extends Mock implements ProcessManager {}
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 438efc3..f6c5383 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
@@ -57,8 +57,7 @@
'git', 'config', '--system', 'core.longpaths', 'true',
]);
- print('Step 1');
- // Step 1. Clone the dev branch of flutter into the test directory.
+ print('Step 1 - clone the $_kBranch of flutter into the test directory');
exitCode = await processUtils.stream(<String>[
'git',
'clone',
@@ -66,8 +65,7 @@
], workingDirectory: parentDirectory.path, trace: true);
expect(exitCode, 0);
- print('Step 2');
- // Step 2. Switch to the dev branch.
+ print('Step 2 - switch to the $_kBranch');
exitCode = await processUtils.stream(<String>[
'git',
'checkout',
@@ -78,8 +76,7 @@
], workingDirectory: testDirectory.path, trace: true);
expect(exitCode, 0);
- print('Step 3');
- // Step 3. Revert to a prior version.
+ print('Step 3 - revert back to $_kInitialVersion');
exitCode = await processUtils.stream(<String>[
'git',
'reset',
@@ -88,9 +85,8 @@
], workingDirectory: testDirectory.path, trace: true);
expect(exitCode, 0);
- print('Step 4');
- // Step 4. Upgrade to the newest stable. This should update the persistent
- // tool state with the sha for v1.14.3
+ print('Step 4 - upgrade to the newest $_kBranch');
+ // This should update the persistent tool state with the sha for HEAD
exitCode = await processUtils.stream(<String>[
flutterBin,
'upgrade',
@@ -99,8 +95,7 @@
], workingDirectory: testDirectory.path, trace: true);
expect(exitCode, 0);
- print('Step 5');
- // Step 5. Verify that the version is different.
+ print('Step 5 - verify that the version is different');
final RunResult versionResult = await processUtils.run(<String>[
'git',
'describe',
@@ -111,8 +106,9 @@
'--tags',
], workingDirectory: testDirectory.path);
expect(versionResult.stdout, isNot(contains(_kInitialVersion)));
+ print('current version is ${versionResult.stdout.trim()}\ninitial was $_kInitialVersion');
- print('Step 6');
+ print('Step 6 - downgrade back to the initial version');
// Step 6. Downgrade back to initial version.
exitCode = await processUtils.stream(<String>[
flutterBin,
@@ -122,7 +118,7 @@
], workingDirectory: testDirectory.path, trace: true);
expect(exitCode, 0);
- print('Step 7');
+ print('Step 7 - verify downgraded version matches original version');
// Step 7. Verify downgraded version matches original version.
final RunResult oldVersionResult = await processUtils.run(<String>[
'git',
@@ -134,5 +130,6 @@
'--tags',
], workingDirectory: testDirectory.path);
expect(oldVersionResult.stdout, contains(_kInitialVersion));
+ print('current version is ${oldVersionResult.stdout.trim()}\ninitial was $_kInitialVersion');
});
}