Unverified Commit 74f08c73 authored by Anurag Roy's avatar Anurag Roy Committed by GitHub

[flutter_tools] Skip version freshness check for non-standard remotes (#97202)

parent a2424602
...@@ -229,74 +229,6 @@ class UpgradeCommandRunner { ...@@ -229,74 +229,6 @@ 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
final String? repositoryUrl = localVersion.repositoryUrl;
if (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(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. /// Returns the remote HEAD flutter version.
/// ///
/// Exits tool if HEAD isn't pointing to a branch, or there is no upstream. /// Exits tool if HEAD isn't pointing to a branch, or there is no upstream.
...@@ -337,7 +269,17 @@ class UpgradeCommandRunner { ...@@ -337,7 +269,17 @@ class UpgradeCommandRunner {
throwToolExit(errorString); throwToolExit(errorString);
} }
} }
verifyStandardRemote(localVersion); // At this point the current checkout should be on HEAD of a branch having
// an upstream. Check whether this upstream is "standard".
final VersionCheckError? error = VersionUpstreamValidator(version: localVersion, platform: globals.platform).run();
if (error != null) {
throwToolExit(
'Unable to upgrade Flutter: '
'${error.message}\n'
'Reinstalling Flutter may fix this issue. Visit $_flutterInstallDocs '
'for instructions.'
);
}
return FlutterVersion(workingDirectory: workingDirectory, frameworkRevision: revision); return FlutterVersion(workingDirectory: workingDirectory, frameworkRevision: revision);
} }
......
...@@ -8,6 +8,7 @@ import 'base/common.dart'; ...@@ -8,6 +8,7 @@ import 'base/common.dart';
import 'base/file_system.dart'; import 'base/file_system.dart';
import 'base/io.dart'; import 'base/io.dart';
import 'base/logger.dart'; import 'base/logger.dart';
import 'base/platform.dart';
import 'base/process.dart'; import 'base/process.dart';
import 'base/time.dart'; import 'base/time.dart';
import 'cache.dart'; import 'cache.dart';
...@@ -239,11 +240,15 @@ class FlutterVersion { ...@@ -239,11 +240,15 @@ class FlutterVersion {
if (!kOfficialChannels.contains(channel)) { if (!kOfficialChannels.contains(channel)) {
return; return;
} }
// Don't perform the update check if the tracking remote is not standard.
if (VersionUpstreamValidator(version: this, platform: globals.platform).run() != null) {
return;
}
DateTime localFrameworkCommitDate; DateTime localFrameworkCommitDate;
try { try {
// Don't perform the update check if fetching the latest local commit failed.
localFrameworkCommitDate = DateTime.parse(_latestGitCommitDate()); localFrameworkCommitDate = DateTime.parse(_latestGitCommitDate());
} on VersionCheckError { } on VersionCheckError {
// Don't perform the update check if the version check failed.
return; return;
} }
final DateTime? latestFlutterCommitDate = await _getLatestAvailableFlutterDate(); final DateTime? latestFlutterCommitDate = await _getLatestAvailableFlutterDate();
...@@ -405,6 +410,91 @@ class FlutterVersion { ...@@ -405,6 +410,91 @@ class FlutterVersion {
} }
} }
/// Checks if the provided [version] is tracking a standard remote.
///
/// A "standard remote" is one having the same url as(in order of precedence):
/// * The value of `FLUTTER_GIT_URL` environment variable.
/// * The HTTPS or SSH url of the Flutter repository as provided by GitHub.
///
/// To initiate the validation check, call [run].
///
/// This prevents the tool to check for version freshness from the standard
/// remote but fetch updates from the upstream of current branch/channel, both
/// of which can be different.
///
/// This also prevents unnecessary freshness check from a forked repo unless the
/// user explicitly configures the environment to do so.
class VersionUpstreamValidator {
VersionUpstreamValidator({
required this.version,
required this.platform,
});
final Platform platform;
final FlutterVersion version;
/// Performs the validation against the tracking remote of the [version].
///
/// Returns [VersionCheckError] if the tracking remote is not standard.
VersionCheckError? run(){
final String? flutterGit = platform.environment['FLUTTER_GIT_URL'];
final String? repositoryUrl = version.repositoryUrl;
if (repositoryUrl == null) {
return VersionCheckError(
'The tool could not determine the remote upstream which is being '
'tracked by the SDK.'
);
}
// Strip `.git` suffix before comparing the remotes
final List<String> sanitizedStandardRemotes = <String>[
if (flutterGit != null) flutterGit,
'https://github.com/flutter/flutter.git',
'git@github.com:flutter/flutter.git',
].map((String remote) => stripDotGit(remote)).toList();
final String sanitizedRepositoryUrl = stripDotGit(repositoryUrl);
if (!sanitizedStandardRemotes.contains(sanitizedRepositoryUrl)) {
if (platform.environment.containsKey('FLUTTER_GIT_URL')) {
// If `FLUTTER_GIT_URL` is set, inform to either remove the
// `FLUTTER_GIT_URL` environment variable or set it to the current
// tracking remote.
return VersionCheckError(
'The Flutter SDK is tracking "$repositoryUrl" but "FLUTTER_GIT_URL" '
'is set to "$flutterGit".\n'
'Either remove "FLUTTER_GIT_URL" from the environment or set it to '
'"$repositoryUrl". '
'If this is intentional, it is recommended to use "git" directly to '
'manage the SDK.'
);
}
// If `FLUTTER_GIT_URL` is unset, inform to set the environment variable.
return VersionCheckError(
'The Flutter SDK is tracking a non-standard remote "$repositoryUrl".\n'
'Set the environment variable "FLUTTER_GIT_URL" to '
'"$repositoryUrl". '
'If this is intentional, it is recommended to use "git" directly to '
'manage the SDK.'
);
}
return null;
}
// 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.
static final RegExp _patternUrlDotGit = RegExp(r'(.*)(\.git)$');
static String stripDotGit(String url) {
final RegExpMatch? match = _patternUrlDotGit.firstMatch(url);
if (match == null) {
return url;
}
return match.group(1)!;
}
}
/// Contains data and load/save logic pertaining to Flutter version checks. /// Contains data and load/save logic pertaining to Flutter version checks.
@visibleForTesting @visibleForTesting
class VersionCheckStamp { class VersionCheckStamp {
......
...@@ -239,130 +239,6 @@ void main() { ...@@ -239,130 +239,6 @@ void main() {
Platform: () => fakePlatform, 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: 'beta',
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: 'beta',
);
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: 'beta',
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: 'beta',
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: 'beta',
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: 'beta',
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 { testUsingContext('git exception during attemptReset throwsToolExit', () async {
const String revision = 'abc123'; const String revision = 'abc123';
const String errorMessage = 'fatal: Could not parse object ´$revision´'; const String errorMessage = 'fatal: Could not parse object ´$revision´';
......
...@@ -56,51 +56,47 @@ void main() { ...@@ -56,51 +56,47 @@ void main() {
}); });
testUsingContext('prints nothing when Flutter installation looks fresh', () async { testUsingContext('prints nothing when Flutter installation looks fresh', () async {
processManager.addCommand(const FakeCommand( const String flutterUpstreamUrl = 'https://github.com/flutter/flutter.git';
command: <String>['git', '-c', 'log.showSignature=false', 'log', '-n', '1', '--pretty=format:%H'],
stdout: '1234abcd',
));
processManager.addCommand(const FakeCommand(
command: <String>['git', 'tag', '--points-at', '1234abcd'],
));
processManager.addCommand(const FakeCommand(
command: <String>['git', 'describe', '--match', '*.*.*', '--long', '--tags', '1234abcd'],
stdout: '0.1.2-3-1234abcd',
));
processManager.addCommand(FakeCommand(
command: const <String>['git', 'rev-parse', '--abbrev-ref', '--symbolic', '@{u}'],
stdout: channel,
));
processManager.addCommand(FakeCommand(
command: const <String>['git', '-c', 'log.showSignature=false', 'log', '-n', '1', '--pretty=format:%ad', '--date=iso'],
stdout: getChannelUpToDateVersion().toString(),
));
processManager.addCommand(const FakeCommand(
command: <String>['git', 'remote'],
));
processManager.addCommand(const FakeCommand(
command: <String>['git', 'remote', 'add', '__flutter_version_check__', 'https://github.com/flutter/flutter.git'],
));
processManager.addCommand(FakeCommand(
command: <String>['git', 'fetch', '__flutter_version_check__', channel],
));
processManager.addCommand(FakeCommand(
command: <String>['git', '-c', 'log.showSignature=false', 'log', '__flutter_version_check__/$channel', '-n', '1', '--pretty=format:%ad', '--date=iso'],
stdout: getChannelOutOfDateVersion().toString(),
));
processManager.addCommand(const FakeCommand(
command: <String>['git', 'remote'],
));
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
const FakeCommand(
command: <String>['git', '-c', 'log.showSignature=false', 'log', '-n', '1', '--pretty=format:%H'],
stdout: '1234abcd',
),
const FakeCommand(
command: <String>['git', 'tag', '--points-at', '1234abcd'],
),
const FakeCommand(
command: <String>['git', 'describe', '--match', '*.*.*', '--long', '--tags', '1234abcd'],
stdout: '0.1.2-3-1234abcd',
),
FakeCommand(
command: const <String>['git', 'rev-parse', '--abbrev-ref', '--symbolic', '@{u}'],
stdout: 'origin/$channel',
),
const FakeCommand(
command: <String>['git', 'ls-remote', '--get-url', 'origin'],
stdout: flutterUpstreamUrl,
),
FakeCommand(
command: const <String>['git', '-c', 'log.showSignature=false', 'log', '-n', '1', '--pretty=format:%ad', '--date=iso'],
stdout: getChannelUpToDateVersion().toString(),
),
const FakeCommand(
command: <String>['git', 'remote'],
),
const FakeCommand(
command: <String>['git', 'remote', 'add', '__flutter_version_check__', flutterUpstreamUrl],
),
FakeCommand(
command: <String>['git', 'fetch', '__flutter_version_check__', channel],
),
FakeCommand(
command: <String>['git', '-c', 'log.showSignature=false', 'log', '__flutter_version_check__/$channel', '-n', '1', '--pretty=format:%ad', '--date=iso'],
stdout: getChannelOutOfDateVersion().toString(),
),
const FakeCommand(
command: <String>['git', 'remote'],
),
const FakeCommand( const FakeCommand(
command: <String>['git', '-c', 'log.showSignature=false', 'log', '-n', '1', '--pretty=format:%ar'], command: <String>['git', '-c', 'log.showSignature=false', 'log', '-n', '1', '--pretty=format:%ar'],
stdout: '1 second ago', stdout: '1 second ago',
...@@ -123,7 +119,7 @@ void main() { ...@@ -123,7 +119,7 @@ void main() {
expect(flutterVersion.frameworkVersion, '0.0.0-unknown'); expect(flutterVersion.frameworkVersion, '0.0.0-unknown');
expect( expect(
flutterVersion.toString(), flutterVersion.toString(),
'Flutter • channel $channelunknown source\n' 'Flutter • channel $channel$flutterUpstreamUrl\n'
'Framework • revision 1234abcd (1 second ago) • ${getChannelUpToDateVersion()}\n' 'Framework • revision 1234abcd (1 second ago) • ${getChannelUpToDateVersion()}\n'
'Engine • revision abcdefg\n' 'Engine • revision abcdefg\n'
'Tools • Dart 2.12.0 • DevTools 2.8.0', 'Tools • Dart 2.12.0 • DevTools 2.8.0',
...@@ -143,7 +139,7 @@ void main() { ...@@ -143,7 +139,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); final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: channel);
final BufferLogger logger = BufferLogger.test(); final BufferLogger logger = BufferLogger.test();
final VersionCheckStamp stamp = VersionCheckStamp( final VersionCheckStamp stamp = VersionCheckStamp(
lastTimeVersionWasChecked: _stampOutOfDate, lastTimeVersionWasChecked: _stampOutOfDate,
...@@ -164,7 +160,7 @@ void main() { ...@@ -164,7 +160,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); final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: channel);
final BufferLogger logger = BufferLogger.test(); final BufferLogger logger = BufferLogger.test();
final VersionCheckStamp stamp = VersionCheckStamp( final VersionCheckStamp stamp = VersionCheckStamp(
lastTimeVersionWasChecked: _stampUpToDate, lastTimeVersionWasChecked: _stampUpToDate,
...@@ -186,7 +182,7 @@ void main() { ...@@ -186,7 +182,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); final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: channel);
final BufferLogger logger = BufferLogger.test(); final BufferLogger logger = BufferLogger.test();
final VersionCheckStamp stamp = VersionCheckStamp( final VersionCheckStamp stamp = VersionCheckStamp(
lastTimeVersionWasChecked: _stampUpToDate, lastTimeVersionWasChecked: _stampUpToDate,
...@@ -208,7 +204,7 @@ void main() { ...@@ -208,7 +204,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); final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: channel);
final BufferLogger logger = BufferLogger.test(); final BufferLogger logger = BufferLogger.test();
cache.versionStamp = '{}'; cache.versionStamp = '{}';
...@@ -226,7 +222,7 @@ void main() { ...@@ -226,7 +222,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); final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: channel);
final BufferLogger logger = BufferLogger.test(); final BufferLogger logger = BufferLogger.test();
final VersionCheckStamp stamp = VersionCheckStamp( final VersionCheckStamp stamp = VersionCheckStamp(
lastTimeVersionWasChecked: _stampOutOfDate, lastTimeVersionWasChecked: _stampOutOfDate,
...@@ -247,7 +243,7 @@ void main() { ...@@ -247,7 +243,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); final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: channel);
final BufferLogger logger = BufferLogger.test(); final BufferLogger logger = BufferLogger.test();
cache.versionStamp = '{}'; cache.versionStamp = '{}';
...@@ -264,7 +260,7 @@ void main() { ...@@ -264,7 +260,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); final FakeFlutterVersion flutterVersion = FakeFlutterVersion(channel: channel);
final BufferLogger logger = BufferLogger.test(); final BufferLogger logger = BufferLogger.test();
final VersionCheckStamp stamp = VersionCheckStamp( final VersionCheckStamp stamp = VersionCheckStamp(
lastTimeVersionWasChecked: _stampOutOfDate, lastTimeVersionWasChecked: _stampOutOfDate,
...@@ -330,6 +326,89 @@ void main() { ...@@ -330,6 +326,89 @@ void main() {
}); });
} }
group('VersionUpstreamValidator', () {
const String flutterStandardUrlDotGit = 'https://github.com/flutter/flutter.git';
const String flutterNonStandardUrlDotGit = 'https://githubmirror.com/flutter/flutter.git';
const String flutterStandardSshUrlDotGit = 'git@github.com:flutter/flutter.git';
VersionCheckError runUpstreamValidator({
String versionUpstreamUrl,
String flutterGitUrl,
}){
final Platform testPlatform = FakePlatform(environment: <String, String> {
if (flutterGitUrl != null) 'FLUTTER_GIT_URL': flutterGitUrl,
});
return VersionUpstreamValidator(
version: FakeFlutterVersion(repositoryUrl: versionUpstreamUrl),
platform: testPlatform,
).run();
}
testWithoutContext('returns error if repository url is null', () {
final VersionCheckError error = runUpstreamValidator(
// repositoryUrl is null by default
);
expect(error, isNotNull);
expect(
error.message,
contains('The tool could not determine the remote upstream which is being tracked by the SDK.'),
);
});
testWithoutContext('does not return error at standard remote url with FLUTTER_GIT_URL unset', () {
expect(runUpstreamValidator(versionUpstreamUrl: flutterStandardUrlDotGit), isNull);
});
testWithoutContext('returns error at non-standard remote url with FLUTTER_GIT_URL unset', () {
final VersionCheckError error = runUpstreamValidator(versionUpstreamUrl: flutterNonStandardUrlDotGit);
expect(error, isNotNull);
expect(
error.message,
contains(
'The Flutter SDK is tracking a non-standard remote "$flutterNonStandardUrlDotGit".\n'
'Set the environment variable "FLUTTER_GIT_URL" to "$flutterNonStandardUrlDotGit". '
'If this is intentional, it is recommended to use "git" directly to manage the SDK.'
),
);
});
testWithoutContext('does not return error at non-standard remote url with FLUTTER_GIT_URL set', () {
expect(runUpstreamValidator(
versionUpstreamUrl: flutterNonStandardUrlDotGit,
flutterGitUrl: flutterNonStandardUrlDotGit,
), isNull);
});
testWithoutContext('returns error at remote url and FLUTTER_GIT_URL set to different urls', () {
final VersionCheckError error = runUpstreamValidator(
versionUpstreamUrl: flutterNonStandardUrlDotGit,
flutterGitUrl: flutterStandardUrlDotGit,
);
expect(error, isNotNull);
expect(
error.message,
contains(
'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". '
'If this is intentional, it is recommended to use "git" directly to manage the SDK.'
),
);
});
testWithoutContext('does not return error at standard ssh url with FLUTTER_GIT_URL unset', () {
expect(runUpstreamValidator(versionUpstreamUrl: flutterStandardSshUrlDotGit), isNull);
});
testWithoutContext('stripDotGit removes ".git" suffix if any', () {
expect(VersionUpstreamValidator.stripDotGit('https://github.com/flutter/flutter.git'), 'https://github.com/flutter/flutter');
expect(VersionUpstreamValidator.stripDotGit('https://github.com/flutter/flutter'), 'https://github.com/flutter/flutter');
expect(VersionUpstreamValidator.stripDotGit('git@github.com:flutter/flutter.git'), 'git@github.com:flutter/flutter');
expect(VersionUpstreamValidator.stripDotGit('git@github.com:flutter/flutter'), 'git@github.com:flutter/flutter');
expect(VersionUpstreamValidator.stripDotGit('https://githubmirror.com/flutter/flutter.git.git'), 'https://githubmirror.com/flutter/flutter.git');
expect(VersionUpstreamValidator.stripDotGit('https://githubmirror.com/flutter/flutter.gitgit'), 'https://githubmirror.com/flutter/flutter.gitgit');
});
});
testUsingContext('version handles unknown branch', () async { testUsingContext('version handles unknown branch', () async {
processManager.addCommands(<FakeCommand>[ processManager.addCommands(<FakeCommand>[
const FakeCommand( const FakeCommand(
...@@ -627,8 +706,11 @@ class FakeCache extends Fake implements Cache { ...@@ -627,8 +706,11 @@ class FakeCache extends Fake implements Cache {
} }
class FakeFlutterVersion extends Fake implements FlutterVersion { class FakeFlutterVersion extends Fake implements FlutterVersion {
FakeFlutterVersion(this.channel); FakeFlutterVersion({this.channel, this.repositoryUrl});
@override @override
final String channel; final String channel;
@override
final String repositoryUrl;
} }
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