From 316d44989aa1c8d69ace74dff6ac42f1e3b36e43 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Wed, 10 Apr 2019 12:24:53 -0700 Subject: [PATCH] warn on uncomitted changes (#30235) --- .../lib/src/commands/upgrade.dart | 23 ++++++++++++++++ .../test/commands/upgrade_test.dart | 26 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/packages/flutter_tools/lib/src/commands/upgrade.dart b/packages/flutter_tools/lib/src/commands/upgrade.dart index 1b7cf7a8c48..896164d17e3 100644 --- a/packages/flutter_tools/lib/src/commands/upgrade.dart +++ b/packages/flutter_tools/lib/src/commands/upgrade.dart @@ -72,6 +72,17 @@ class UpgradeCommandRunner { ); } } + // If there are uncomitted changes we might be on the right commit but + // we should still warn. + if (!force && await hasUncomittedChanges()) { + throwToolExit( + 'Your flutter checkout has local changes that would be erased by ' + 'upgrading. If you want to keep these changes, it is recommended that ' + 'you stash them via "git stash" or else commit the changes to a local ' + 'branch. If it is okay to remove local changes, then re-run this ' + 'command with --force.' + ); + } await resetChanges(gitTagVersion); await upgradeChannel(flutterVersion); await attemptFastForward(); @@ -81,6 +92,18 @@ class UpgradeCommandRunner { return null; } + Future hasUncomittedChanges() async { + try { + final RunResult result = await runCheckedAsync([ + 'git', 'status', '-s' + ], workingDirectory: Cache.flutterRoot); + return result.stdout.trim().isNotEmpty; + } catch (e) { + throwToolExit('git status failed: $e'); + } + return false; + } + /// Check if there is an upstream repository configured. /// /// Exits tool if there is no upstream. diff --git a/packages/flutter_tools/test/commands/upgrade_test.dart b/packages/flutter_tools/test/commands/upgrade_test.dart index 2ee2b76d537..00e38a7f190 100644 --- a/packages/flutter_tools/test/commands/upgrade_test.dart +++ b/packages/flutter_tools/test/commands/upgrade_test.dart @@ -29,6 +29,7 @@ void main() { fakeCommandRunner = FakeUpgradeCommandRunner(); realCommandRunner = UpgradeCommandRunner(); processManager = MockProcessManager(); + fakeCommandRunner.willHaveUncomittedChanges = false; }); test('throws on unknown tag, official branch, noforce', () async { @@ -49,6 +50,26 @@ void main() { expect(await result, null); }); + test('throws tool exit with uncommited changes', () async { + fakeCommandRunner.willHaveUncomittedChanges = true; + final Future result = fakeCommandRunner.runCommand( + false, + gitTagVersion, + flutterVersion, + ); + expect(result, throwsA(isA())); + }); + + test('does not throw tool exit with uncommited changes and force', () async { + fakeCommandRunner.willHaveUncomittedChanges = true; + final Future result = fakeCommandRunner.runCommand( + true, + gitTagVersion, + flutterVersion, + ); + expect(await result, null); + }); + test('Doesn\'t throw on known tag, dev branch, no force', () async { final Future result = fakeCommandRunner.runCommand( false, @@ -127,9 +148,14 @@ void main() { } class FakeUpgradeCommandRunner extends UpgradeCommandRunner { + bool willHaveUncomittedChanges = false; + @override Future verifyUpstreamConfigured() async {} + @override + Future hasUncomittedChanges() async => willHaveUncomittedChanges; + @override Future resetChanges(GitTagVersion gitTagVersion) async {}