mirror of
https://github.com/flutter/flutter
synced 2024-10-12 19:23:02 +00:00
[flutter_tools] Reland "Make upgrade only work with standard remotes" (#87731)
This commit is contained in:
parent
7bedd0f122
commit
758c28b813
|
@ -116,7 +116,7 @@ class UpgradeCommandRunner {
|
|||
@required bool testFlow,
|
||||
@required bool verifyOnly,
|
||||
}) async {
|
||||
final FlutterVersion upstreamVersion = await fetchLatestVersion();
|
||||
final FlutterVersion upstreamVersion = await fetchLatestVersion(localVersion: flutterVersion);
|
||||
if (flutterVersion.frameworkRevision == upstreamVersion.frameworkRevision) {
|
||||
globals.printStatus('Flutter is already up to date on channel ${flutterVersion.channel}');
|
||||
globals.printStatus('$flutterVersion');
|
||||
|
@ -225,10 +225,79 @@ class UpgradeCommandRunner {
|
|||
}
|
||||
}
|
||||
|
||||
/// Checks if the Flutter git repository is tracking a standard remote.
|
||||
///
|
||||
/// A "standard remote" is one having the same url as [globals.flutterGit].
|
||||
/// The upgrade process only supports standard remotes.
|
||||
///
|
||||
/// Exits tool if the tracking remote is not standard.
|
||||
void verifyStandardRemote(FlutterVersion localVersion) {
|
||||
// If repositoryUrl of the local version is null, exit
|
||||
if (localVersion.repositoryUrl == null) {
|
||||
throwToolExit(
|
||||
'Unable to upgrade Flutter: The tool could not determine the remote '
|
||||
'upstream which is being tracked by the SDK.\n'
|
||||
'Re-install Flutter by going to $_flutterInstallDocs.'
|
||||
);
|
||||
}
|
||||
|
||||
// Strip `.git` suffix before comparing the remotes
|
||||
final String trackingUrl = stripDotGit(localVersion.repositoryUrl);
|
||||
final String flutterGitUrl = stripDotGit(globals.flutterGit);
|
||||
|
||||
// Exempt the official flutter git SSH remote from this check
|
||||
if (trackingUrl == 'git@github.com:flutter/flutter') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (trackingUrl != flutterGitUrl) {
|
||||
if (globals.platform.environment.containsKey('FLUTTER_GIT_URL')) {
|
||||
// If `FLUTTER_GIT_URL` is set, inform the user to either remove the
|
||||
// `FLUTTER_GIT_URL` environment variable or set it to the current
|
||||
// tracking remote to continue.
|
||||
throwToolExit(
|
||||
'Unable to upgrade Flutter: The Flutter SDK is tracking '
|
||||
'"${localVersion.repositoryUrl}" but "FLUTTER_GIT_URL" is set to '
|
||||
'"${globals.flutterGit}".\n'
|
||||
'Either remove "FLUTTER_GIT_URL" from the environment or set it to '
|
||||
'"${localVersion.repositoryUrl}", and retry. '
|
||||
'Alternatively, re-install Flutter by going to $_flutterInstallDocs.\n'
|
||||
'If this is intentional, it is recommended to use "git" directly to '
|
||||
'keep Flutter SDK up-to date.'
|
||||
);
|
||||
}
|
||||
// If `FLUTTER_GIT_URL` is unset, inform that the user has to set the
|
||||
// environment variable to continue.
|
||||
throwToolExit(
|
||||
'Unable to upgrade Flutter: The Flutter SDK is tracking a non-standard '
|
||||
'remote "${localVersion.repositoryUrl}".\n'
|
||||
'Set the environment variable "FLUTTER_GIT_URL" to '
|
||||
'"${localVersion.repositoryUrl}", and retry. '
|
||||
'Alternatively, re-install Flutter by going to $_flutterInstallDocs.\n'
|
||||
'If this is intentional, it is recommended to use "git" directly to '
|
||||
'keep Flutter SDK up-to date.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Strips ".git" suffix from a given string, preferably an url.
|
||||
// For example, changes 'https://github.com/flutter/flutter.git' to 'https://github.com/flutter/flutter'.
|
||||
// URLs without ".git" suffix will remain unaffected.
|
||||
String stripDotGit(String url) {
|
||||
final RegExp pattern = RegExp(r'(.*)(\.git)$');
|
||||
final RegExpMatch match = pattern.firstMatch(url);
|
||||
if (match == null) {
|
||||
return url;
|
||||
}
|
||||
return match.group(1);
|
||||
}
|
||||
|
||||
/// Returns the remote HEAD flutter version.
|
||||
///
|
||||
/// Exits tool if HEAD isn't pointing to a branch, or there is no upstream.
|
||||
Future<FlutterVersion> fetchLatestVersion() async {
|
||||
Future<FlutterVersion> fetchLatestVersion({
|
||||
@required FlutterVersion localVersion,
|
||||
}) async {
|
||||
String revision;
|
||||
try {
|
||||
// Fetch upstream branch's commits and tags
|
||||
|
@ -263,6 +332,7 @@ class UpgradeCommandRunner {
|
|||
throwToolExit(errorString);
|
||||
}
|
||||
}
|
||||
verifyStandardRemote(localVersion);
|
||||
return FlutterVersion(workingDirectory: workingDirectory, frameworkRevision: revision);
|
||||
}
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ void main() {
|
|||
stdout: version),
|
||||
]);
|
||||
|
||||
final FlutterVersion updateVersion = await realCommandRunner.fetchLatestVersion();
|
||||
final FlutterVersion updateVersion = await realCommandRunner.fetchLatestVersion(localVersion: FakeFlutterVersion());
|
||||
|
||||
expect(updateVersion.frameworkVersion, version);
|
||||
expect(updateVersion.frameworkRevision, revision);
|
||||
|
@ -199,7 +199,7 @@ void main() {
|
|||
]);
|
||||
|
||||
await expectLater(
|
||||
() async => realCommandRunner.fetchLatestVersion(),
|
||||
() async => realCommandRunner.fetchLatestVersion(localVersion: FakeFlutterVersion()),
|
||||
throwsToolExit(message: 'Unable to upgrade Flutter: Your Flutter checkout '
|
||||
'is currently not on a release branch.\n'
|
||||
'Use "flutter channel" to switch to an official channel, and retry. '
|
||||
|
@ -228,7 +228,7 @@ void main() {
|
|||
]);
|
||||
|
||||
await expectLater(
|
||||
() async => realCommandRunner.fetchLatestVersion(),
|
||||
() async => realCommandRunner.fetchLatestVersion(localVersion: FakeFlutterVersion()),
|
||||
throwsToolExit(message: 'Unable to upgrade Flutter: The current Flutter '
|
||||
'branch/channel is not tracking any remote repository.\n'
|
||||
'Re-install Flutter by going to https://flutter.dev/docs/get-started/install.'
|
||||
|
@ -240,6 +240,131 @@ void main() {
|
|||
Platform: () => fakePlatform,
|
||||
});
|
||||
|
||||
group('verifyStandardRemote', () {
|
||||
const String flutterStandardUrlDotGit = 'https://github.com/flutter/flutter.git';
|
||||
const String flutterNonStandardUrlDotGit = 'https://githubmirror.com/flutter/flutter.git';
|
||||
const String flutterStandardSshUrl = 'git@github.com:flutter/flutter';
|
||||
|
||||
testUsingContext('throws toolExit if repository url is null', () async {
|
||||
final FakeFlutterVersion flutterVersion = FakeFlutterVersion(
|
||||
channel: 'dev',
|
||||
repositoryUrl: null,
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
() async => realCommandRunner.verifyStandardRemote(flutterVersion),
|
||||
throwsToolExit(message: 'Unable to upgrade Flutter: The tool could not '
|
||||
'determine the remote upstream which is being tracked by the SDK.\n'
|
||||
'Re-install Flutter by going to https://flutter.dev/docs/get-started/install.'
|
||||
),
|
||||
);
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
}, overrides: <Type, Generator> {
|
||||
ProcessManager: () => processManager,
|
||||
Platform: () => fakePlatform,
|
||||
});
|
||||
|
||||
testUsingContext('does not throw toolExit at standard remote url with FLUTTER_GIT_URL unset', () async {
|
||||
final FakeFlutterVersion flutterVersion = FakeFlutterVersion(
|
||||
channel: 'dev',
|
||||
repositoryUrl: flutterStandardUrlDotGit,
|
||||
);
|
||||
expect(() => realCommandRunner.verifyStandardRemote(flutterVersion), returnsNormally);
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
}, overrides: <Type, Generator> {
|
||||
ProcessManager: () => processManager,
|
||||
Platform: () => fakePlatform,
|
||||
});
|
||||
|
||||
testUsingContext('throws toolExit at non-standard remote url with FLUTTER_GIT_URL unset', () async {
|
||||
final FakeFlutterVersion flutterVersion = FakeFlutterVersion(
|
||||
channel: 'dev',
|
||||
repositoryUrl: flutterNonStandardUrlDotGit,
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
() async => realCommandRunner.verifyStandardRemote(flutterVersion),
|
||||
throwsToolExit(message: 'Unable to upgrade Flutter: The Flutter SDK '
|
||||
'is tracking a non-standard remote "$flutterNonStandardUrlDotGit".\n'
|
||||
'Set the environment variable "FLUTTER_GIT_URL" to '
|
||||
'"$flutterNonStandardUrlDotGit", and retry. '
|
||||
'Alternatively, re-install Flutter by going to '
|
||||
'https://flutter.dev/docs/get-started/install.\n'
|
||||
'If this is intentional, it is recommended to use "git" directly to '
|
||||
'keep Flutter SDK up-to date.'
|
||||
),
|
||||
);
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
}, overrides: <Type, Generator> {
|
||||
ProcessManager: () => processManager,
|
||||
Platform: () => fakePlatform,
|
||||
});
|
||||
|
||||
testUsingContext('does not throw toolExit at non-standard remote url with FLUTTER_GIT_URL set', () async {
|
||||
final FakeFlutterVersion flutterVersion = FakeFlutterVersion(
|
||||
channel: 'dev',
|
||||
repositoryUrl: flutterNonStandardUrlDotGit,
|
||||
);
|
||||
|
||||
expect(() => realCommandRunner.verifyStandardRemote(flutterVersion), returnsNormally);
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
}, overrides: <Type, Generator> {
|
||||
ProcessManager: () => processManager,
|
||||
Platform: () => fakePlatform..environment = Map<String, String>.unmodifiable(<String, String> {
|
||||
'FLUTTER_GIT_URL': flutterNonStandardUrlDotGit,
|
||||
}),
|
||||
});
|
||||
|
||||
testUsingContext('throws toolExit at remote url and FLUTTER_GIT_URL set to different urls', () async {
|
||||
final FakeFlutterVersion flutterVersion = FakeFlutterVersion(
|
||||
channel: 'dev',
|
||||
repositoryUrl: flutterNonStandardUrlDotGit,
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
() async => realCommandRunner.verifyStandardRemote(flutterVersion),
|
||||
throwsToolExit(message: 'Unable to upgrade Flutter: The Flutter SDK '
|
||||
'is tracking "$flutterNonStandardUrlDotGit" but "FLUTTER_GIT_URL" '
|
||||
'is set to "$flutterStandardUrlDotGit".\n'
|
||||
'Either remove "FLUTTER_GIT_URL" from the environment or set it to '
|
||||
'"$flutterNonStandardUrlDotGit", and retry. '
|
||||
'Alternatively, re-install Flutter by going to '
|
||||
'https://flutter.dev/docs/get-started/install.\n'
|
||||
'If this is intentional, it is recommended to use "git" directly to '
|
||||
'keep Flutter SDK up-to date.'
|
||||
),
|
||||
);
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
}, overrides: <Type, Generator> {
|
||||
ProcessManager: () => processManager,
|
||||
Platform: () => fakePlatform..environment = Map<String, String>.unmodifiable(<String, String> {
|
||||
'FLUTTER_GIT_URL': flutterStandardUrlDotGit,
|
||||
}),
|
||||
});
|
||||
|
||||
testUsingContext('exempts standard ssh url from check with FLUTTER_GIT_URL unset', () async {
|
||||
final FakeFlutterVersion flutterVersion = FakeFlutterVersion(
|
||||
channel: 'dev',
|
||||
repositoryUrl: flutterStandardSshUrl,
|
||||
);
|
||||
|
||||
expect(() => realCommandRunner.verifyStandardRemote(flutterVersion), returnsNormally);
|
||||
expect(processManager, hasNoRemainingExpectations);
|
||||
}, overrides: <Type, Generator> {
|
||||
ProcessManager: () => processManager,
|
||||
Platform: () => fakePlatform,
|
||||
});
|
||||
|
||||
testUsingContext('stripDotGit removes ".git" suffix if any', () async {
|
||||
expect(realCommandRunner.stripDotGit('https://github.com/flutter/flutter.git'), 'https://github.com/flutter/flutter');
|
||||
expect(realCommandRunner.stripDotGit('https://github.com/flutter/flutter'), 'https://github.com/flutter/flutter');
|
||||
expect(realCommandRunner.stripDotGit('git@github.com:flutter/flutter.git'), 'git@github.com:flutter/flutter');
|
||||
expect(realCommandRunner.stripDotGit('git@github.com:flutter/flutter'), 'git@github.com:flutter/flutter');
|
||||
expect(realCommandRunner.stripDotGit('https://githubmirror.com/flutter/flutter.git.git'), 'https://githubmirror.com/flutter/flutter.git');
|
||||
expect(realCommandRunner.stripDotGit('https://githubmirror.com/flutter/flutter.gitgit'), 'https://githubmirror.com/flutter/flutter.gitgit');
|
||||
});
|
||||
});
|
||||
|
||||
testUsingContext('git exception during attemptReset throwsToolExit', () async {
|
||||
const String revision = 'abc123';
|
||||
const String errorMessage = 'fatal: Could not parse object ´$revision´';
|
||||
|
@ -475,7 +600,7 @@ class FakeUpgradeCommandRunner extends UpgradeCommandRunner {
|
|||
FlutterVersion remoteVersion;
|
||||
|
||||
@override
|
||||
Future<FlutterVersion> fetchLatestVersion() async => remoteVersion;
|
||||
Future<FlutterVersion> fetchLatestVersion({FlutterVersion localVersion}) async => remoteVersion;
|
||||
|
||||
@override
|
||||
Future<bool> hasUncommittedChanges() async => willHaveUncommittedChanges;
|
||||
|
|
Loading…
Reference in a new issue