From 702523ccb214d497622a89f62f052af04a29ad8f Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 10 May 2023 20:29:14 -0400 Subject: [PATCH] [tool] Use new pub cache location for publish As of Dart 3.0 (Flutter 3.10), the location that the tool was using for the pub cache wasn't being read, breaking autopublish in CI. --- script/tool/lib/src/publish_command.dart | 58 +++++++++++--------- script/tool/test/publish_command_test.dart | 62 ++++++++++++++++++---- 2 files changed, 85 insertions(+), 35 deletions(-) diff --git a/script/tool/lib/src/publish_command.dart b/script/tool/lib/src/publish_command.dart index e7b3d110c5fa..717fb3b53733 100644 --- a/script/tool/lib/src/publish_command.dart +++ b/script/tool/lib/src/publish_command.dart @@ -99,6 +99,11 @@ class PublishCommand extends PackageLoopingCommand { // `flutter_plugin_tools-v0.0.24`. static const String _tagFormat = '%PACKAGE%-v%VERSION%'; + /// Returns the correct path where the pub credential is stored. + @visibleForTesting + late final String credentialsPath = + _getCredentialsPath(platform: platform, path: path); + @override final String name = 'publish'; @@ -397,13 +402,12 @@ Safe to ignore if the package is deleted in this commit. } void _ensureValidPubCredential() { - final String credentialsPath = _credentialsPath; final File credentialFile = packagesDir.fileSystem.file(credentialsPath); if (credentialFile.existsSync() && credentialFile.readAsStringSync().isNotEmpty) { return; } - final String? credential = io.Platform.environment[_pubCredentialName]; + final String? credential = platform.environment[_pubCredentialName]; if (credential == null) { printError(''' No pub credential available. Please check if `$credentialsPath` is valid. @@ -415,42 +419,46 @@ If running this command on CI, you can set the pub credential content in the $_p ..writeStringSync(credential) ..closeSync(); } - - /// Returns the correct path where the pub credential is stored. - @visibleForTesting - static String getCredentialPath() { - return _credentialsPath; - } } /// The path in which pub expects to find its credentials file. -final String _credentialsPath = () { - // This follows the same logic as pub: - // https://github.com/dart-lang/pub/blob/d99b0d58f4059d7bb4ac4616fd3d54ec00a2b5d4/lib/src/system_cache.dart#L34-L43 - String? cacheDir; - final String? pubCache = io.Platform.environment['PUB_CACHE']; - if (pubCache != null) { - cacheDir = pubCache; - } else if (io.Platform.isWindows) { - final String? appData = io.Platform.environment['APPDATA']; +String _getCredentialsPath( + {required Platform platform, required p.Context path}) { + // See https://github.com/dart-lang/pub/blob/master/doc/cache_layout.md#layout + String? configDir; + if (platform.isLinux) { + String? configHome = platform.environment['XDG_CONFIG_HOME']; + if (configHome == null) { + final String? home = platform.environment['HOME']; + if (home == null) { + printError('"HOME" environment variable is not set.'); + } else { + configHome = path.join(home, '.config'); + } + } + if (configHome != null) { + configDir = path.join(configHome, 'dart'); + } + } else if (platform.isWindows) { + final String? appData = platform.environment['APPDATA']; if (appData == null) { printError('"APPDATA" environment variable is not set.'); } else { - cacheDir = p.join(appData, 'Pub', 'Cache'); + configDir = path.join(appData, 'dart'); } - } else { - final String? home = io.Platform.environment['HOME']; + } else if (platform.isMacOS) { + final String? home = platform.environment['HOME']; if (home == null) { printError('"HOME" environment variable is not set.'); } else { - cacheDir = p.join(home, '.pub-cache'); + configDir = path.join(home, 'Library', 'Application Support', 'dart'); } } - if (cacheDir == null) { - printError('Unable to determine pub cache location'); + if (configDir == null) { + printError('Unable to determine pub con location'); throw ToolExit(1); } - return p.join(cacheDir, 'credentials.json'); -}(); + return path.join(configDir, 'pub-credentials.json'); +} diff --git a/script/tool/test/publish_command_test.dart b/script/tool/test/publish_command_test.dart index 94023032ecb6..bbee7f94a530 100644 --- a/script/tool/test/publish_command_test.dart +++ b/script/tool/test/publish_command_test.dart @@ -24,9 +24,11 @@ import 'util.dart'; void main() { final String flutterCommand = getFlutterCommand(const LocalPlatform()); + late MockPlatform platform; late Directory packagesDir; late MockGitDir gitDir; late TestProcessRunner processRunner; + late PublishCommand command; late CommandRunner commandRunner; late MockStdin mockStdin; late FileSystem fileSystem; @@ -34,13 +36,14 @@ void main() { late Map> mockHttpResponses; void createMockCredentialFile() { - final String credentialPath = PublishCommand.getCredentialPath(); - fileSystem.file(credentialPath) + fileSystem.file(command.credentialsPath) ..createSync(recursive: true) ..writeAsStringSync('some credential'); } setUp(() async { + platform = MockPlatform(isLinux: true); + platform.environment['HOME'] = '/home'; fileSystem = MemoryFileSystem(); packagesDir = createPackagesDirectory(fileSystem: fileSystem); processRunner = TestProcessRunner(); @@ -71,14 +74,15 @@ void main() { }); mockStdin = MockStdin(); - commandRunner = CommandRunner('tester', '') - ..addCommand(PublishCommand( - packagesDir, - processRunner: processRunner, - stdinput: mockStdin, - gitDir: gitDir, - httpClient: mockClient, - )); + command = PublishCommand( + packagesDir, + platform: platform, + processRunner: processRunner, + stdinput: mockStdin, + gitDir: gitDir, + httpClient: mockClient, + ); + commandRunner = CommandRunner('tester', '')..addCommand(command); }); group('Initial validation', () { @@ -880,6 +884,44 @@ void main() { isNot(contains('git-push'))); }); }); + + group('credential location', () { + test('Linux with XDG', () async { + platform = MockPlatform(isLinux: true); + platform.environment['XDG_CONFIG_HOME'] = '/xdghome/config'; + command = PublishCommand(packagesDir, platform: platform); + + expect( + command.credentialsPath, '/xdghome/config/dart/pub-credentials.json'); + }); + + test('Linux without XDG', () async { + platform = MockPlatform(isLinux: true); + platform.environment['HOME'] = '/home'; + command = PublishCommand(packagesDir, platform: platform); + + expect( + command.credentialsPath, '/home/.config/dart/pub-credentials.json'); + }); + + test('macOS', () async { + platform = MockPlatform(isMacOS: true); + platform.environment['HOME'] = '/Users/someuser'; + command = PublishCommand(packagesDir, platform: platform); + + expect(command.credentialsPath, + '/Users/someuser/Library/Application Support/dart/pub-credentials.json'); + }); + + test('Windows', () async { + platform = MockPlatform(isWindows: true); + platform.environment['APPDATA'] = r'C:\Users\SomeUser\AppData'; + command = PublishCommand(packagesDir, platform: platform); + + expect(command.credentialsPath, + r'C:\Users\SomeUser\AppData\dart\pub-credentials.json'); + }); + }); } /// An extension of [RecordingProcessRunner] that stores 'flutter pub publish'