diff --git a/packages/flutter_tools/lib/src/dart/pub.dart b/packages/flutter_tools/lib/src/dart/pub.dart index f817f8d7fe..b4c3e682d4 100644 --- a/packages/flutter_tools/lib/src/dart/pub.dart +++ b/packages/flutter_tools/lib/src/dart/pub.dart @@ -27,6 +27,10 @@ const String _kPubEnvironmentKey = 'PUB_ENVIRONMENT'; /// The console environment key used by the pub tool to find the cache directory. const String _kPubCacheEnvironmentKey = 'PUB_CACHE'; +/// The UNAVAILABLE exit code returned by the pub tool. +/// (see https://github.com/dart-lang/pub/blob/master/lib/src/exit_codes.dart) +const int _kPubExitCodeUnavailable = 69; + typedef MessageFilter = String Function(String message); /// Represents Flutter-specific data that is added to the `PUB_ENVIRONMENT` @@ -250,7 +254,7 @@ class _DefaultPub implements Pub { context: context, directory: directory, failureMessage: 'pub $command failed', - retry: true, + retry: !offline, flutterRootOverride: flutterRootOverride, ); status.stop(); @@ -303,7 +307,7 @@ class _DefaultPub implements Pub { int attempts = 0; int duration = 1; int code; - loop: while (true) { + while (true) { attempts += 1; code = await _processUtils.stream( _pubCommand(arguments), @@ -311,15 +315,15 @@ class _DefaultPub implements Pub { mapFunction: filterWrapper, // may set versionSolvingFailed, lastPubMessage environment: await _createPubEnvironment(context, flutterRootOverride), ); - String message; - switch (code) { - case 69: // UNAVAILABLE in https://github.com/dart-lang/pub/blob/master/lib/src/exit_codes.dart + String? message; + if (retry) { + if (code == _kPubExitCodeUnavailable) { message = 'server unavailable'; - break; - default: - break loop; + } + } + if (message == null) { + break; } - assert(message != null); versionSolvingFailed = false; _logger.printStatus( '$failureMessage ($message) -- attempting retry $attempts in $duration ' diff --git a/packages/flutter_tools/test/general.shard/dart/pub_get_test.dart b/packages/flutter_tools/test/general.shard/dart/pub_get_test.dart index 7395b9451e..73aa9b499d 100644 --- a/packages/flutter_tools/test/general.shard/dart/pub_get_test.dart +++ b/packages/flutter_tools/test/general.shard/dart/pub_get_test.dart @@ -594,6 +594,54 @@ void main() { expect(processManager, hasNoRemainingExpectations); }); + testWithoutContext('pub get offline does not retry', () async { + String? error; + + const FakeCommand pubGetCommand = FakeCommand( + command: [ + 'bin/cache/dart-sdk/bin/dart', + '__deprecated_pub', + '--verbosity=warning', + 'get', + '--no-precompile', + '--offline', + ], + exitCode: 69, + environment: {'FLUTTER_ROOT': '', 'PUB_ENVIRONMENT': 'flutter_cli:flutter_tests'}, + ); + final FakeProcessManager processManager = FakeProcessManager.list([ + pubGetCommand, + ]); + final BufferLogger logger = BufferLogger.test(); + final FileSystem fileSystem = MemoryFileSystem.test(); + final Pub pub = Pub( + fileSystem: fileSystem, + logger: logger, + processManager: processManager, + usage: TestUsage(), + platform: FakePlatform( + environment: const {}, + ), + botDetector: const BotDetectorAlwaysNo(), + ); + + FakeAsync().run((FakeAsync time) { + expect(logger.statusText, ''); + pub.get(context: PubContext.flutterTests, offline: true).then((void value) { + error = 'test completed unexpectedly'; + }, onError: (dynamic thrownError) { + error = 'test failed unexpectedly: $thrownError'; + }); + time.elapse(const Duration(milliseconds: 500)); + expect(logger.statusText, + 'Running "flutter pub get" in /...\n' + ); + }); + expect(logger.errorText, isEmpty); + expect(error, 'test failed unexpectedly: Exception: pub get failed (69; no message)'); + expect(processManager, hasNoRemainingExpectations); + }); + testWithoutContext('pub get 66 shows message from pub', () async { final BufferLogger logger = BufferLogger.test(); final FileSystem fileSystem = MemoryFileSystem.test();