Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
e38be671
Unverified
Commit
e38be671
authored
Mar 21, 2019
by
Jonah Williams
Committed by
GitHub
Mar 21, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update upgrade to rebase and stash local changes. (#29192)
parent
fc9f7dea
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
282 additions
and
19 deletions
+282
-19
upgrade.dart
packages/flutter_tools/lib/src/commands/upgrade.dart
+143
-17
upgrade_test.dart
packages/flutter_tools/test/commands/upgrade_test.dart
+139
-2
No files found.
packages/flutter_tools/lib/src/commands/upgrade.dart
View file @
e38be671
...
...
@@ -18,6 +18,15 @@ import '../version.dart';
import
'channel.dart'
;
class
UpgradeCommand
extends
FlutterCommand
{
UpgradeCommand
()
{
argParser
.
addFlag
(
'force'
,
abbr:
'f'
,
help:
'force upgrade the flutter branch, potentially discarding local changes.'
,
negatable:
false
,
);
}
@override
final
String
name
=
'upgrade'
;
...
...
@@ -29,64 +38,182 @@ class UpgradeCommand extends FlutterCommand {
@override
Future
<
FlutterCommandResult
>
runCommand
()
async
{
final
UpgradeCommandRunner
upgradeCommandRunner
=
UpgradeCommandRunner
();
await
upgradeCommandRunner
.
runCommand
(
argResults
[
'force'
],
GitTagVersion
.
determine
(),
FlutterVersion
.
instance
);
return
null
;
}
}
@visibleForTesting
class
UpgradeCommandRunner
{
Future
<
FlutterCommandResult
>
runCommand
(
bool
force
,
GitTagVersion
gitTagVersion
,
FlutterVersion
flutterVersion
)
async
{
await
verifyUpstreamConfigured
();
if
(!
force
&&
gitTagVersion
==
const
GitTagVersion
.
unknown
())
{
// If the commit is a recognized branch and not master,
// explain that we are avoiding potential damage.
if
(
flutterVersion
.
channel
!=
'master'
&&
FlutterVersion
.
officialChannels
.
contains
(
flutterVersion
.
channel
))
{
throwToolExit
(
'Unknown flutter tag. Abandoning upgrade to avoid destroying local '
'changes. It is recommended to use git directly if not working off of '
'an official channel.'
);
// Otherwise explain that local changes can be lost.
}
else
{
throwToolExit
(
'Unknown flutter tag. Abandoning upgrade to avoid destroying local '
'changes. If it is okay to remove local changes, then re-run this '
'command with --force.'
);
}
}
final
String
stashName
=
await
maybeStash
(
gitTagVersion
);
await
upgradeChannel
(
flutterVersion
);
await
attemptRebase
();
await
precacheArtifacts
();
await
updatePackages
(
flutterVersion
);
await
runDoctor
();
await
applyStash
(
stashName
);
return
null
;
}
/// Check if there is an upstream repository configured.
///
/// Exits tool if there is no upstream.
Future
<
void
>
verifyUpstreamConfigured
()
async
{
try
{
await
runCheckedAsync
(<
String
>[
'git'
,
'rev-parse'
,
'@{u}'
,
],
workingDirectory:
Cache
.
flutterRoot
);
}
catch
(
e
)
{
throwToolExit
(
'Unable to upgrade Flutter: no upstream repository configured.'
);
throwToolExit
(
'Unable to upgrade Flutter: no upstream repository configured. '
'Run
\'
git remote add upstream '
'https://github.com/flutter/flutter
\'
in
${Cache.flutterRoot}
'
,
);
}
}
final
FlutterVersion
flutterVersion
=
FlutterVersion
.
instance
;
/// Attempt to stash any local changes.
///
/// Returns the stash name if any changes were stashed. Exits tool if
/// `git stash` returns a non-zero exit code.
Future
<
String
>
maybeStash
(
GitTagVersion
gitTagVersion
)
async
{
final
String
stashName
=
'flutter-upgrade-from-v
${gitTagVersion.x}
.
${gitTagVersion.y}
.
${gitTagVersion.z}
'
;
try
{
final
RunResult
runResult
=
await
runCheckedAsync
(<
String
>[
'git'
,
'stash'
,
'push'
,
'-m'
,
stashName
]);
// output message will contain stash name if any changes were stashed..
if
(
runResult
.
stdout
.
contains
(
stashName
))
{
return
stashName
;
}
}
catch
(
e
)
{
throwToolExit
(
'Failed to stash local changes:
$e
'
);
}
return
null
;
}
/// Attempts to upgrade the channel.
///
/// If the user is on a deprecated channel, attempts to migrate them off of
/// it.
Future
<
void
>
upgradeChannel
(
FlutterVersion
flutterVersion
)
async
{
printStatus
(
'Upgrading Flutter from
${Cache.flutterRoot}
...'
);
await
ChannelCommand
.
upgradeChannel
();
}
int
code
=
await
runCommandAndStreamOutput
(
<
String
>[
'git'
,
'pull'
,
'--ff-only'
],
/// Attempts to rebase the upstream onto the local branch.
///
/// If there haven't been any hot fixes or local changes, this is equivalent
/// to a fast-forward.
Future
<
void
>
attemptRebase
()
async
{
final
int
code
=
await
runCommandAndStreamOutput
(
<
String
>[
'git'
,
'pull'
,
'--rebase'
],
workingDirectory:
Cache
.
flutterRoot
,
mapFunction:
(
String
line
)
=>
matchesGitLine
(
line
)
?
null
:
line
,
);
if
(
code
!=
0
)
if
(
code
!=
0
)
{
printError
(
'git rebase failed'
);
final
int
undoCode
=
await
runCommandAndStreamOutput
(
<
String
>[
'git'
,
'rebase'
,
'--abort'
],
workingDirectory:
Cache
.
flutterRoot
,
mapFunction:
(
String
line
)
=>
matchesGitLine
(
line
)
?
null
:
line
,
);
if
(
undoCode
!=
0
)
{
printError
(
'Failed to apply rebase: The flutter installation at'
'
${Cache.flutterRoot}
may be corrupted. A reinstallation of Flutter '
'is recommended'
);
}
throwToolExit
(
null
,
exitCode:
code
);
}
}
// Check for and download any engine and pkg/ updates.
// We run the 'flutter' shell script re-entrantly here
// so that it will download the updated Dart and so forth
// if necessary.
/// Update the engine repository and precache all artifacts.
///
/// Check for and download any engine and pkg/ updates. We run the 'flutter'
/// shell script re-entrantly here so that it will download the updated
/// Dart and so forth if necessary.
Future
<
void
>
precacheArtifacts
()
async
{
printStatus
(
''
);
printStatus
(
'Upgrading engine...'
);
code
=
await
runCommandAndStreamOutput
(
final
int
code
=
await
runCommandAndStreamOutput
(
<
String
>[
fs
.
path
.
join
(
'bin'
,
'flutter'
),
'--no-color'
,
'--no-version-check'
,
'precache'
,
],
workingDirectory:
Cache
.
flutterRoot
,
allowReentrantFlutter:
true
,
);
if
(
code
!=
0
)
{
throwToolExit
(
null
,
exitCode:
code
);
}
}
/// Update the user's packages.
Future
<
void
>
updatePackages
(
FlutterVersion
flutterVersion
)
async
{
printStatus
(
''
);
printStatus
(
flutterVersion
.
toString
());
final
String
projectRoot
=
findProjectRoot
();
if
(
projectRoot
!=
null
)
{
printStatus
(
''
);
await
pubGet
(
context:
PubContext
.
pubUpgrade
,
directory:
projectRoot
,
upgrade:
true
,
checkLastModified:
false
);
}
}
// Run a doctor check in case system requirements have changed.
/// Run flutter doctor in case requirements have changed.
Future
<
void
>
runDoctor
()
async
{
printStatus
(
''
);
printStatus
(
'Running flutter doctor...'
);
code
=
await
runCommandAndStreamOutput
(
await
runCommandAndStreamOutput
(
<
String
>[
fs
.
path
.
join
(
'bin'
,
'flutter'
),
'--no-version-check'
,
'doctor'
,
],
workingDirectory:
Cache
.
flutterRoot
,
allowReentrantFlutter:
true
,
);
}
return
null
;
/// Pop stash changes if [stashName] is non-null and contained in stash.
Future
<
void
>
applyStash
(
String
stashName
)
async
{
if
(
stashName
==
null
)
{
return
;
}
try
{
final
RunResult
result
=
await
runCheckedAsync
(<
String
>[
'git'
,
'stash'
,
'list'
]);
if
(!
result
.
stdout
.
contains
(
stashName
))
{
// print the same warning as if this threw.
throw
Exception
();
}
await
runCheckedAsync
(<
String
>[
'git'
,
'stash'
,
'pop'
,
]);
}
catch
(
e
)
{
printError
(
'Failed to re-apply local changes. State may have been lost.'
);
}
}
// dev/benchmarks/complex_layout/lib/main.dart | 24 +-
...
...
@@ -97,7 +224,6 @@ class UpgradeCommand extends FlutterCommand {
// create mode 100644 examples/flutter_gallery/lib/gallery/demo.dart
static
final
RegExp
_gitChangedRegex
=
RegExp
(
r' (rename|delete mode|create mode) .+'
);
@visibleForTesting
static
bool
matchesGitLine
(
String
line
)
{
return
_gitDiffRegex
.
hasMatch
(
line
)
||
_gitChangedRegex
.
hasMatch
(
line
)
...
...
packages/flutter_tools/test/commands/upgrade_test.dart
View file @
e38be671
...
...
@@ -2,21 +2,109 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter_tools/src/base/common.dart'
;
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/runner/flutter_command.dart'
;
import
'package:flutter_tools/src/version.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:process/process.dart'
;
import
'../src/common.dart'
;
import
'../src/context.dart'
;
void
main
(
)
{
group
(
'upgrade'
,
()
{
group
(
'UpgradeCommandRunner'
,
()
{
FakeUpgradeCommandRunner
fakeCommandRunner
;
UpgradeCommandRunner
realCommandRunner
;
MockProcessManager
processManager
;
final
MockFlutterVersion
flutterVersion
=
MockFlutterVersion
();
const
GitTagVersion
gitTagVersion
=
GitTagVersion
(
1
,
2
,
3
,
4
,
5
,
'asd'
);
when
(
flutterVersion
.
channel
).
thenReturn
(
'dev'
);
setUp
(()
{
fakeCommandRunner
=
FakeUpgradeCommandRunner
();
realCommandRunner
=
UpgradeCommandRunner
();
processManager
=
MockProcessManager
();
});
test
(
'throws on unknown tag, official branch, noforce'
,
()
async
{
final
Future
<
FlutterCommandResult
>
result
=
fakeCommandRunner
.
runCommand
(
false
,
const
GitTagVersion
.
unknown
(),
flutterVersion
,
);
expect
(
result
,
throwsA
(
isInstanceOf
<
ToolExit
>()));
});
test
(
'does not throw on unknown tag, official branch, force'
,
()
async
{
final
Future
<
FlutterCommandResult
>
result
=
fakeCommandRunner
.
runCommand
(
true
,
const
GitTagVersion
.
unknown
(),
flutterVersion
,
);
expect
(
await
result
,
null
);
});
test
(
'Doesn
\'
t throw on known tag, dev branch, no force'
,
()
async
{
final
Future
<
FlutterCommandResult
>
result
=
fakeCommandRunner
.
runCommand
(
false
,
gitTagVersion
,
flutterVersion
,
);
expect
(
await
result
,
null
);
});
test
(
'Only pops stash if it was pushed'
,
()
async
{
fakeCommandRunner
.
stashName
=
'test'
;
final
Future
<
FlutterCommandResult
>
result
=
fakeCommandRunner
.
runCommand
(
false
,
gitTagVersion
,
flutterVersion
,
);
expect
(
await
result
,
null
);
expect
(
fakeCommandRunner
.
appliedStashName
,
'test'
);
});
testUsingContext
(
'verifyUpstreamConfigured'
,
()
async
{
when
(
processManager
.
run
(
<
String
>[
'git'
,
'rev-parse'
,
'@{u}'
],
environment:
anyNamed
(
'environment'
),
workingDirectory:
anyNamed
(
'workingDirectory'
))
).
thenAnswer
((
Invocation
invocation
)
async
{
return
FakeProcessResult
()
..
exitCode
=
0
;
});
await
realCommandRunner
.
verifyUpstreamConfigured
();
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
processManager
,
});
testUsingContext
(
'maybeStash'
,
()
async
{
final
String
stashName
=
'flutter-upgrade-from-v
${gitTagVersion.x}
.
${gitTagVersion.y}
.
${gitTagVersion.z}
'
;
when
(
processManager
.
run
(
<
String
>[
'git'
,
'stash'
,
'push'
,
'-m'
,
stashName
],
environment:
anyNamed
(
'environment'
),
workingDirectory:
anyNamed
(
'workingDirectory'
))
).
thenAnswer
((
Invocation
invocation
)
async
{
return
FakeProcessResult
()
..
exitCode
=
0
;
});
await
realCommandRunner
.
maybeStash
(
gitTagVersion
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
processManager
,
});
});
group
(
'matchesGitLine'
,
()
{
setUpAll
(()
{
Cache
.
disableLocking
();
});
bool
_match
(
String
line
)
=>
UpgradeCommand
.
matchesGitLine
(
line
);
bool
_match
(
String
line
)
=>
UpgradeCommand
Runner
.
matchesGitLine
(
line
);
test
(
'regex match'
,
()
{
expect
(
_match
(
' .../flutter_gallery/lib/demo/buttons_demo.dart | 10 +--'
),
true
);
...
...
@@ -63,3 +151,52 @@ void main() {
});
});
}
class
FakeUpgradeCommandRunner
extends
UpgradeCommandRunner
{
String
stashName
;
String
appliedStashName
;
@override
Future
<
void
>
verifyUpstreamConfigured
()
async
{}
@override
Future
<
String
>
maybeStash
(
GitTagVersion
gitTagVersion
)
async
{
return
stashName
;
}
@override
Future
<
void
>
upgradeChannel
(
FlutterVersion
flutterVersion
)
async
{}
@override
Future
<
void
>
attemptRebase
()
async
{}
@override
Future
<
void
>
precacheArtifacts
()
async
{}
@override
Future
<
void
>
updatePackages
(
FlutterVersion
flutterVersion
)
async
{}
@override
Future
<
void
>
runDoctor
()
async
{}
@override
Future
<
void
>
applyStash
(
String
stashName
)
async
{
appliedStashName
=
stashName
;
}
}
class
MockFlutterVersion
extends
Mock
implements
FlutterVersion
{}
class
MockProcessManager
extends
Mock
implements
ProcessManager
{}
class
FakeProcessResult
implements
ProcessResult
{
@override
int
exitCode
;
@override
int
pid
=
0
;
@override
String
stderr
=
''
;
@override
String
stdout
=
''
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment