Merge mainline into pub_dependency_services (#3301)
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 9cefb58..6177eba 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,4 +1,4 @@
-include: package:pedantic/analysis_options.yaml
+include: package:lints/recommended.yaml
analyzer:
errors:
@@ -12,53 +12,27 @@
linter:
rules:
- avoid_catching_errors
- - avoid_function_literals_in_foreach_calls
- avoid_private_typedef_functions
- avoid_redundant_argument_values
- - avoid_renaming_method_parameters
- avoid_returning_null_for_future
- - avoid_returning_null_for_void
- avoid_unused_constructor_parameters
- avoid_void_async
- - await_only_futures
- - camel_case_types
- cancel_subscriptions
- - control_flow_in_finally
- directives_ordering
- - empty_statements
- - file_names
- - implementation_imports
- - iterable_contains_unrelated_type
- - list_remove_unrelated_type
- - literal_only_boolean_expressions
- missing_whitespace_between_adjacent_strings
- no_adjacent_strings_in_list
- no_runtimeType_toString
- - non_constant_identifier_names
- only_throw_errors
- - overridden_fields
- package_api_docs
- - package_names
- - package_prefixed_library_names
- prefer_asserts_in_initializer_lists
- prefer_const_declarations
- - prefer_function_declarations_over_variables
- - prefer_initializing_formals
- - prefer_inlined_adds
- - prefer_is_not_operator
- - prefer_null_aware_operators
- prefer_relative_imports
- - prefer_typing_uninitialized_variables
- - prefer_void_to_null
+ - prefer_single_quotes
- sort_pub_dependencies
- test_types_in_equals
- throw_in_finally
- - unnecessary_brace_in_string_interps
- - unnecessary_getters_setters
+ - unawaited_futures
- unnecessary_lambdas
- unnecessary_null_aware_assignments
- - unnecessary_overrides
- unnecessary_parenthesis
- unnecessary_statements
- - unnecessary_string_interpolations
- - void_checks
diff --git a/bin/dependency_services.dart b/bin/dependency_services.dart
new file mode 100644
index 0000000..1e7b4c1
--- /dev/null
+++ b/bin/dependency_services.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Support for automated upgrades.
+///
+/// For now this is not a finalized interface. Don't rely on this.
+import 'dart:async';
+
+import 'package:args/args.dart';
+import 'package:args/command_runner.dart';
+import 'package:pub/src/command.dart';
+import 'package:pub/src/command/dependency_services.dart';
+import 'package:pub/src/exit_codes.dart' as exit_codes;
+import 'package:pub/src/io.dart';
+import 'package:pub/src/log.dart' as log;
+
+class DependencyServicesCommandRunner extends CommandRunner<int>
+ implements PubTopLevel {
+ @override
+ String? get directory => argResults['directory'];
+
+ @override
+ bool get captureStackChains {
+ return argResults['trace'] ||
+ argResults['verbose'] ||
+ argResults['verbosity'] == 'all';
+ }
+
+ @override
+ bool get trace => argResults['trace'];
+
+ ArgResults? _argResults;
+
+ /// The top-level options parsed by the command runner.
+ @override
+ ArgResults get argResults {
+ final a = _argResults;
+ if (a == null) {
+ throw StateError(
+ 'argResults cannot be used before Command.run is called.');
+ }
+ return a;
+ }
+
+ DependencyServicesCommandRunner()
+ : super('dependency_services', 'Support for automatic upgrades',
+ usageLineLength: lineLength) {
+ argParser.addFlag('version', negatable: false, help: 'Print pub version.');
+ argParser.addFlag('trace',
+ help: 'Print debugging information when an error occurs.');
+ argParser
+ .addOption('verbosity', help: 'Control output verbosity.', allowed: [
+ 'error',
+ 'warning',
+ 'normal',
+ 'io',
+ 'solver',
+ 'all'
+ ], allowedHelp: {
+ 'error': 'Show only errors.',
+ 'warning': 'Show only errors and warnings.',
+ 'normal': 'Show errors, warnings, and user messages.',
+ 'io': 'Also show IO operations.',
+ 'solver': 'Show steps during version resolution.',
+ 'all': 'Show all output including internal tracing messages.'
+ });
+ argParser.addFlag('verbose',
+ abbr: 'v', negatable: false, help: 'Shortcut for "--verbosity=all".');
+ argParser.addOption(
+ 'directory',
+ abbr: 'C',
+ help: 'Run the subcommand in the directory<dir>.',
+ defaultsTo: '.',
+ valueHelp: 'dir',
+ );
+
+ addCommand(DependencyServicesListCommand());
+ addCommand(DependencyServicesReportCommand());
+ addCommand(DependencyServicesApplyCommand());
+ }
+
+ @override
+ Future<int> run(Iterable<String> args) async {
+ try {
+ _argResults = parse(args);
+ return await runCommand(argResults) ?? exit_codes.SUCCESS;
+ } on UsageException catch (error) {
+ log.exception(error);
+ return exit_codes.USAGE;
+ }
+ }
+
+ @override
+ void printUsage() {
+ log.message(usage);
+ }
+
+ @override
+ log.Verbosity get verbosity => log.Verbosity.normal;
+}
+
+Future<void> main(List<String> arguments) async {
+ await flushThenExit(await DependencyServicesCommandRunner().run(arguments));
+}
diff --git a/bin/pub.dart b/bin/pub.dart
index 926db85..f133a0f 100644
--- a/bin/pub.dart
+++ b/bin/pub.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/command_runner.dart';
import 'package:pub/src/io.dart';
diff --git a/doc/repository-spec-v2.md b/doc/repository-spec-v2.md
index 6db7763..6ddfd0f 100644
--- a/doc/repository-spec-v2.md
+++ b/doc/repository-spec-v2.md
@@ -227,7 +227,7 @@
"replacedBy": "<package>", /* optional field, if isDiscontinued == true */
"latest": {
"version": "<version>",
- "isRetracted": true || false, /* optional field, false if omitted */
+ "retracted": true || false, /* optional field, false if omitted */
"archive_url": "https://.../archive.tar.gz",
"pubspec": {
/* pubspec contents as JSON object */
@@ -236,7 +236,7 @@
"versions": [
{
"version": "<package>",
- "isRetracted": true || false, /* optional field, false if omitted */
+ "retracted": true || false, /* optional field, false if omitted */
"archive_url": "https://.../archive.tar.gz",
"pubspec": {
/* pubspec contents as JSON object */
@@ -371,7 +371,9 @@
archive size, or enforce any other repository specific constraints.
This upload flow allows for archives to be uploaded directly to a signed POST
-URL for S3, GCS or similar blob storage service. Both the
+URL for [S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/HTTPPOSTExamples.html),
+[GCS](https://cloud.google.com/storage/docs/xml-api/post-object-forms) or
+similar blob storage service. Both the
`<multipart-upload-url>` and `<finalize-upload-url>` is allowed to contain
query-string parameters, and both of these URLs need only be temporary.
diff --git a/lib/pub.dart b/lib/pub.dart
index b78cbca..71de9d6 100644
--- a/lib/pub.dart
+++ b/lib/pub.dart
@@ -2,17 +2,28 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:args/command_runner.dart';
import 'src/command_runner.dart';
import 'src/pub_embeddable_command.dart';
export 'src/executable.dart'
- show getExecutableForCommand, CommandResolutionFailedException;
+ show
+ getExecutableForCommand,
+ CommandResolutionFailedException,
+ CommandResolutionIssue,
+ DartExecutableWithPackageConfig;
+export 'src/pub_embeddable_command.dart' show PubAnalytics;
/// Returns a [Command] for pub functionality that can be used by an embedding
/// CommandRunner.
-Command<int> pubCommand() => PubEmbeddableCommand();
+///
+/// If [analytics] is given, pub will use that analytics instance to send
+/// statistics about resolutions.
+///
+/// [isVerbose] should return `true` (after argument resolution) if the
+/// embedding top-level is in verbose mode.
+Command<int> pubCommand(
+ {PubAnalytics? analytics, required bool Function() isVerbose}) =>
+ PubEmbeddableCommand(analytics, isVerbose);
/// Support for the `pub` toplevel command.
@Deprecated('Use [pubCommand] instead.')
diff --git a/lib/src/authentication/client.dart b/lib/src/authentication/client.dart
index 3de5b2e..a6001ec 100644
--- a/lib/src/authentication/client.dart
+++ b/lib/src/authentication/client.dart
@@ -2,15 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.11
-
import 'dart:io';
import 'package:collection/collection.dart';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';
-import '../exceptions.dart';
import '../http.dart';
import '../log.dart' as log;
import '../system_cache.dart';
@@ -24,14 +21,17 @@
/// Constructs Http client wrapper that injects `authorization` header to
/// requests and handles authentication errors.
///
- /// [credential] might be `null`. In that case `authorization` header will not
+ /// [_credential] might be `null`. In that case `authorization` header will not
/// be injected to requests.
- _AuthenticatedClient(this._inner, this.credential);
+ _AuthenticatedClient(this._inner, this._credential);
final http.BaseClient _inner;
/// Authentication scheme that could be used for authenticating requests.
- final Credential credential;
+ final Credential? _credential;
+
+ /// Detected that [_credential] are invalid, happens when server responds 401.
+ bool _detectInvalidCredentials = false;
@override
Future<http.StreamedResponse> send(http.BaseRequest request) async {
@@ -42,20 +42,21 @@
// to given serverBaseUrl. Otherwise credential leaks might ocurr when
// archive_url hosted on 3rd party server that should not receive
// credentials of the first party.
- if (credential != null &&
- credential.canAuthenticate(request.url.toString())) {
+ if (_credential != null &&
+ _credential!.canAuthenticate(request.url.toString())) {
request.headers[HttpHeaders.authorizationHeader] =
- await credential.getAuthorizationHeaderValue();
+ await _credential!.getAuthorizationHeaderValue();
}
try {
final response = await _inner.send(request);
if (response.statusCode == 401) {
+ _detectInvalidCredentials = true;
_throwAuthException(response);
}
return response;
} on PubHttpException catch (e) {
- if (e.response?.statusCode == 403) {
+ if (e.response.statusCode == 403) {
_throwAuthException(e.response);
}
rethrow;
@@ -68,16 +69,18 @@
///
/// [RFC]: https://datatracker.ietf.org/doc/html/rfc7235#section-4.1
void _throwAuthException(http.BaseResponse response) {
- String serverMessage;
+ String? serverMessage;
if (response.headers.containsKey(HttpHeaders.wwwAuthenticateHeader)) {
try {
- final header = response.headers[HttpHeaders.wwwAuthenticateHeader];
+ final header = response.headers[HttpHeaders.wwwAuthenticateHeader]!;
final challenge = AuthenticationChallenge.parseHeader(header)
.firstWhereOrNull((challenge) =>
challenge.scheme == 'bearer' &&
challenge.parameters['realm'] == 'pub' &&
challenge.parameters['message'] != null);
- serverMessage = challenge?.parameters['message'];
+ if (challenge != null) {
+ serverMessage = challenge.parameters['message'];
+ }
} on FormatException {
// Ignore errors might be caused when parsing invalid header values
}
@@ -101,7 +104,7 @@
const AuthenticationException(this.statusCode, this.serverMessage);
final int statusCode;
- final String serverMessage;
+ final String? serverMessage;
@override
String toString() {
@@ -124,31 +127,17 @@
Future<T> Function(http.Client) fn,
) async {
final credential = systemCache.tokenStore.findCredential(hostedUrl);
- final http.Client client = _AuthenticatedClient(httpClient, credential);
+ final client = _AuthenticatedClient(httpClient, credential);
try {
return await fn(client);
- } on AuthenticationException catch (error) {
- String message;
-
- if (error.statusCode == 401) {
- if (systemCache.tokenStore.removeCredential(hostedUrl)) {
+ } finally {
+ if (client._detectInvalidCredentials) {
+ // try to remove the credential, if we detected that it is invalid!
+ final removed = systemCache.tokenStore.removeCredential(hostedUrl);
+ if (removed) {
log.warning('Invalid token for $hostedUrl deleted.');
}
- message = '$hostedUrl package repository requested authentication! '
- 'You can provide credential using:\n'
- ' pub token add $hostedUrl';
}
- if (error.statusCode == 403) {
- message = 'Insufficient permissions to the resource in $hostedUrl '
- 'package repository. You can modify credential using:\n'
- ' pub token add $hostedUrl';
- }
-
- if (error.serverMessage?.isNotEmpty == true) {
- message += '\n${error.serverMessage}';
- }
-
- throw DataException(message);
}
}
diff --git a/lib/src/authentication/credential.dart b/lib/src/authentication/credential.dart
index a44cc91..e1dfc79 100644
--- a/lib/src/authentication/credential.dart
+++ b/lib/src/authentication/credential.dart
@@ -2,12 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.11
-
import 'dart:io';
-import 'package:meta/meta.dart';
-
import '../exceptions.dart';
import '../source/hosted.dart';
@@ -27,10 +23,10 @@
class Credential {
/// Internal constructor that's only used by [fromJson].
Credential._internal({
- @required this.url,
- @required this.unknownFields,
- @required this.token,
- @required this.env,
+ required this.url,
+ required this.unknownFields,
+ required this.token,
+ required this.env,
});
/// Create credential that stores clear text token.
@@ -62,7 +58,7 @@
/// doesn't contains [key].
///
/// Throws [FormatException] if value type is not [String].
- String _string(String key) {
+ String? _string(String key) {
if (json.containsKey(key)) {
if (json[key] is! String) {
throw FormatException('Provided $key value should be string');
@@ -84,10 +80,10 @@
final Uri url;
/// Authentication token value
- final String token;
+ final String? token;
/// Environment variable name that stores token value
- final String env;
+ final String? env;
/// Unknown fields found in pub-tokens.json. The fields might be created by the
/// future version of pub tool. We don't want to override them when using the
@@ -114,13 +110,14 @@
Future<String> getAuthorizationHeaderValue() {
if (!isValid()) {
throw DataException(
- 'Saved credential for $url pub repository is not supported by current '
- 'version of Dart SDK.',
+ 'Saved credential for "$url" pub repository is not supported by '
+ 'current version of Dart SDK.',
);
}
- if (env != null) {
- final value = Platform.environment[env];
+ final environment = env;
+ if (environment != null) {
+ final value = Platform.environment[environment];
if (value == null) {
throw DataException(
'Saved credential for "$url" pub repository requires environment '
diff --git a/lib/src/authentication/token_store.dart b/lib/src/authentication/token_store.dart
index 24f70fc..3ef948d 100644
--- a/lib/src/authentication/token_store.dart
+++ b/lib/src/authentication/token_store.dart
@@ -2,12 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.11
-
import 'dart:convert';
+import 'dart:io';
import 'package:path/path.dart' as path;
+import '../exceptions.dart';
import '../io.dart';
import '../log.dart' as log;
import 'credential.dart';
@@ -17,7 +17,7 @@
TokenStore(this.configDir);
/// Cache directory.
- final String configDir;
+ final String? configDir;
/// List of saved authentication tokens.
///
@@ -28,9 +28,9 @@
/// Reads "pub-tokens.json" and parses / deserializes it into list of
/// [Credential].
List<Credential> _loadCredentials() {
- final result = List<Credential>.empty(growable: true);
+ final result = <Credential>[];
final path = _tokensFile;
- if (!fileExists(path)) {
+ if (path == null || !fileExists(path)) {
return result;
}
@@ -90,11 +90,20 @@
return result;
}
+ Never missingConfigDir() {
+ final variable = Platform.isWindows ? '%APPDATA%' : r'$HOME';
+ throw DataException('No config dir found. Check that $variable is set');
+ }
+
/// Writes [credentials] into "pub-tokens.json".
void _saveCredentials(List<Credential> credentials) {
- ensureDir(path.dirname(_tokensFile));
+ final tokensFile = _tokensFile;
+ if (tokensFile == null) {
+ missingConfigDir();
+ }
+ ensureDir(path.dirname(tokensFile));
writeTextFile(
- _tokensFile,
+ tokensFile,
jsonEncode(<String, dynamic>{
'version': 1,
'hosted': credentials.map((it) => it.toJson()).toList(),
@@ -134,8 +143,8 @@
/// Returns [Credential] for authenticating given [hostedUrl] or `null` if no
/// matching credential is found.
- Credential findCredential(Uri hostedUrl) {
- Credential matchedCredential;
+ Credential? findCredential(Uri hostedUrl) {
+ Credential? matchedCredential;
for (final credential in credentials) {
if (credential.url == hostedUrl && credential.isValid()) {
if (matchedCredential == null) {
@@ -161,10 +170,22 @@
/// Deletes pub-tokens.json file from the disk.
void deleteTokensFile() {
- deleteEntry(_tokensFile);
- log.message('pub-tokens.json is deleted.');
+ final tokensFile = _tokensFile;
+ if (tokensFile == null) {
+ missingConfigDir();
+ } else if (!fileExists(tokensFile)) {
+ log.message('No credentials file found at "$tokensFile"');
+ } else {
+ deleteEntry(tokensFile);
+ log.message('pub-tokens.json is deleted.');
+ }
}
/// Full path to the "pub-tokens.json" file.
- String get _tokensFile => path.join(configDir, 'pub-tokens.json');
+ ///
+ /// `null` if no config directory could be found.
+ String? get _tokensFile {
+ var dir = configDir;
+ return dir == null ? null : path.join(dir, 'pub-tokens.json');
+ }
}
diff --git a/lib/src/command.dart b/lib/src/command.dart
index cd4a524..4d02c8a 100644
--- a/lib/src/command.dart
+++ b/lib/src/command.dart
@@ -2,15 +2,15 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:io';
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
+import 'package:collection/collection.dart' show IterableExtension;
import 'package:http/http.dart' as http;
import 'package:meta/meta.dart';
+import 'package:path/path.dart' as p;
import 'authentication/token_store.dart';
import 'command_runner.dart';
@@ -46,15 +46,27 @@
/// of subcommands. Only leaf commands are ever actually invoked. If a command
/// has subcommands, then one of those must always be chosen.
abstract class PubCommand extends Command<int> {
- String get directory => argResults['directory'] ?? _pubTopLevel.directory;
+ @override
+ ArgResults get argResults {
+ final a = super.argResults;
+ if (a == null) {
+ throw StateError(
+ 'argResults cannot be used before Command.run is called.');
+ }
+ return a;
+ }
- SystemCache get cache => _cache ??= SystemCache(isOffline: isOffline);
+ String get directory =>
+ (argResults.options.contains('directory')
+ ? argResults['directory']
+ : null) ??
+ _pubTopLevel.directory;
- SystemCache _cache;
+ late final SystemCache cache = SystemCache(isOffline: isOffline);
GlobalPackages get globals => _globals ??= GlobalPackages(cache);
- GlobalPackages _globals;
+ GlobalPackages? _globals;
TokenStore get tokenStore => cache.tokenStore;
@@ -62,12 +74,10 @@
///
/// This will load the pubspec and fail with an error if the current directory
/// is not a package.
- Entrypoint get entrypoint => _entrypoint ??= Entrypoint(directory, cache);
-
- Entrypoint _entrypoint;
+ late final Entrypoint entrypoint = Entrypoint(directory, cache);
/// The URL for web documentation for this command.
- String get docUrl => null;
+ String? get docUrl => null;
/// Override this and return `false` to disallow trailing options from being
/// parsed after a non-option argument is parsed.
@@ -76,11 +86,9 @@
// Lazily initialize the parser because the superclass constructor requires
// it but we want to initialize it based on [allowTrailingOptions].
@override
- ArgParser get argParser => _argParser ??= ArgParser(
+ late final ArgParser argParser = ArgParser(
allowTrailingOptions: allowTrailingOptions, usageLineLength: lineLength);
- ArgParser _argParser;
-
/// Override this to use offline-only sources instead of hitting the network.
///
/// This will only be called before the [SystemCache] is created. After that,
@@ -88,7 +96,7 @@
bool get isOffline => false;
@override
- String get usageFooter {
+ String? get usageFooter {
if (docUrl == null) return null;
return 'See $docUrl for detailed documentation.';
}
@@ -98,35 +106,41 @@
/// The first command in the command chain.
Command get _topCommand {
- var command = this;
- while (command.parent != null) {
+ Command current = this;
+ while (true) {
+ var parent = current.parent;
+ if (parent == null) return current;
+ current = parent;
+ }
+ }
+
+ PubEmbeddableCommand? get _pubEmbeddableCommand {
+ Command? command = this;
+ while (command is! PubEmbeddableCommand) {
+ if (command == null) {
+ return null;
+ }
command = command.parent;
}
+
return command;
}
- PubEmbeddableCommand get _pubEmbeddableCommand {
- var command = this;
- while (command != null && command is! PubEmbeddableCommand) {
- command = command.parent;
- }
- return command;
- }
+ PubTopLevel get _pubTopLevel =>
+ _pubEmbeddableCommand ?? runner as PubTopLevel;
- PubTopLevel get _pubTopLevel {
- return _pubEmbeddableCommand ?? (runner as PubCommandRunner);
- }
+ PubAnalytics? get analytics => _pubEmbeddableCommand?.analytics;
@override
String get invocation {
- var command = this;
+ PubCommand? command = this;
var names = [];
do {
- names.add(command.name);
- command = command.parent;
+ names.add(command?.name);
+ command = command?.parent as PubCommand?;
} while (command != null);
return [
- runner.executableName,
+ runner!.executableName,
...names.reversed,
argumentsDescription,
].join(' ');
@@ -143,7 +157,7 @@
/// when exiting successfully.
///
/// This should only be modified by [overrideExitCode].
- int _exitCodeOverride;
+ int? _exitCodeOverride;
/// Override the exit code that would normally be used when exiting
/// successfully. Intended to be used by subcommands like `run` that wishes
@@ -161,25 +175,40 @@
@nonVirtual
FutureOr<int> run() async {
computeCommand(_pubTopLevel.argResults);
- if (_pubTopLevel.trace) {
- log.recordTranscript();
- }
+
log.verbosity = _pubTopLevel.verbosity;
log.fine('Pub ${sdk.version}');
+ var crashed = false;
try {
- await captureErrors(runProtected,
+ await captureErrors<void>(() async => runProtected(),
captureStackChains: _pubTopLevel.captureStackChains);
if (_exitCodeOverride != null) {
- return _exitCodeOverride;
+ return _exitCodeOverride!;
}
return exit_codes.SUCCESS;
} catch (error, chain) {
log.exception(error, chain);
if (_pubTopLevel.trace) {
- log.dumpTranscript();
+ log.dumpTranscriptToStdErr();
} else if (!isUserFacingException(error)) {
+ log.error('''
+This is an unexpected error. The full log and other details are collected in:
+
+ $transcriptPath
+
+Consider creating an issue on https://github.com/dart-lang/pub/issues/new
+and attaching the relevant parts of that log file.
+''');
+ crashed = true;
+ }
+ return _chooseExitCode(error);
+ } finally {
+ final verbose = _pubTopLevel.verbosity == log.Verbosity.all;
+
+ // Write the whole log transcript to file.
+ if (verbose || crashed) {
// Escape the argument for users to copy-paste in bash.
// Wrap with single quotation, and use '\'' to insert single quote, as
// long as we have no spaces this doesn't create a new argument.
@@ -187,29 +216,36 @@
RegExp(r'^[a-zA-Z0-9-_]+$').stringMatch(x) == null
? "'${x.replaceAll("'", r"'\''")}'"
: x;
- log.error("""
-This is an unexpected error. Please run
- dart pub --trace ${_topCommand.name} ${_topCommand.argResults.arguments.map(protectArgument).join(' ')}
+ late final Entrypoint? e;
+ try {
+ e = entrypoint;
+ } on ApplicationException {
+ e = null;
+ }
+ log.dumpTranscriptToFile(
+ transcriptPath,
+ 'dart pub ${_topCommand.argResults!.arguments.map(protectArgument).join(' ')}',
+ e,
+ );
-and include the logs in an issue on https://github.com/dart-lang/pub/issues/new
-""");
+ if (!crashed) {
+ log.message('Logs written to $transcriptPath.');
+ }
}
- return _chooseExitCode(error);
- } finally {
httpClient.close();
}
}
/// Returns the appropriate exit code for [exception], falling back on 1 if no
/// appropriate exit code could be found.
- int _chooseExitCode(exception) {
+ int _chooseExitCode(Object exception) {
if (exception is SolveFailure) {
var packageNotFound = exception.packageNotFound;
if (packageNotFound != null) exception = packageNotFound;
}
while (exception is WrappedException && exception.innerError is Exception) {
- exception = exception.innerError;
+ exception = exception.innerError!;
}
if (exception is HttpException ||
@@ -244,7 +280,7 @@
log.message(usage);
}
- static String _command;
+ static String? _command;
/// Returns the nested name of the command that's currently being run.
/// Examples:
@@ -258,10 +294,10 @@
///
/// For top-level commands, if an alias is used, the primary command name is
/// returned. For instance `install` becomes `get`.
- static String get command => _command;
+ static late final String command = _command ?? '';
static void computeCommand(ArgResults argResults) {
- var list = <String>[];
+ var list = <String?>[];
for (var command = argResults.command;
command != null;
command = command.command) {
@@ -269,9 +305,8 @@
if (list.isEmpty) {
// this is a top-level command
- final rootCommand = pubCommandAliases.entries.singleWhere(
- (element) => element.value.contains(command.name),
- orElse: () => null);
+ final rootCommand = pubCommandAliases.entries.singleWhereOrNull(
+ (element) => element.value.contains(command!.name));
if (rootCommand != null) {
commandName = rootCommand.key;
}
@@ -280,13 +315,17 @@
}
_command = list.join(' ');
}
+
+ String get transcriptPath {
+ return p.join(cache.rootDir, 'log', 'pub_log.txt');
+ }
}
abstract class PubTopLevel {
bool get captureStackChains;
log.Verbosity get verbosity;
bool get trace;
- String get directory;
+ String? get directory;
/// The argResults from the level of parsing of the 'pub' command.
ArgResults get argResults;
diff --git a/lib/src/command/add.dart b/lib/src/command/add.dart
index 728f8ea..3557104 100644
--- a/lib/src/command/add.dart
+++ b/lib/src/command/add.dart
@@ -2,8 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
+import 'package:collection/collection.dart' show IterableExtension;
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';
@@ -14,6 +13,7 @@
import '../exceptions.dart';
import '../git.dart';
import '../io.dart';
+import '../language_version.dart';
import '../log.dart' as log;
import '../package.dart';
import '../package_name.dart';
@@ -34,9 +34,10 @@
@override
String get name => 'add';
@override
- String get description => 'Add a dependency to pubspec.yaml.';
+ String get description => 'Add dependencies to pubspec.yaml.';
@override
- String get argumentsDescription => '<package>[:<constraint>] [options]';
+ String get argumentsDescription =>
+ '<package>[:<constraint>] [<package2>[:<constraint2>]...] [options]';
@override
String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-add';
@override
@@ -44,29 +45,34 @@
bool get isDev => argResults['dev'];
bool get isDryRun => argResults['dry-run'];
- String get gitUrl => argResults['git-url'];
- String get gitPath => argResults['git-path'];
- String get gitRef => argResults['git-ref'];
- String get hostUrl => argResults['hosted-url'];
- String get path => argResults['path'];
- String get sdk => argResults['sdk'];
+ String? get gitUrl => argResults['git-url'];
+ String? get gitPath => argResults['git-path'];
+ String? get gitRef => argResults['git-ref'];
+ String? get hostUrl => argResults['hosted-url'];
+ String? get path => argResults['path'];
+ String? get sdk => argResults['sdk'];
bool get hasGitOptions => gitUrl != null || gitRef != null || gitPath != null;
bool get hasHostOptions => hostUrl != null;
+ bool get isHosted => !hasGitOptions && path == null && path == null;
+
AddCommand() {
argParser.addFlag('dev',
abbr: 'd',
negatable: false,
- help: 'Adds package to the development dependencies instead.');
+ help: 'Adds to the development dependencies instead.');
argParser.addOption('git-url', help: 'Git URL of the package');
argParser.addOption('git-ref',
help: 'Git branch or commit to be retrieved');
argParser.addOption('git-path', help: 'Path of git package in repository');
argParser.addOption('hosted-url', help: 'URL of package host server');
- argParser.addOption('path', help: 'Local path');
- argParser.addOption('sdk', help: 'SDK source for package');
+ argParser.addOption('path', help: 'Add package from local path');
+ argParser.addOption('sdk',
+ help: 'add package from SDK source',
+ allowed: ['flutter'],
+ valueHelp: '[flutter]');
argParser.addFlag(
'example',
help:
@@ -85,25 +91,32 @@
argParser.addFlag('precompile',
help: 'Build executables in immediate dependencies.');
argParser.addOption('directory',
- abbr: 'C', help: 'Run this in the directory<dir>.', valueHelp: 'dir');
+ abbr: 'C', help: 'Run this in the directory <dir>.', valueHelp: 'dir');
+ argParser.addFlag('legacy-packages-file',
+ help: 'Generate the legacy ".packages" file', negatable: false);
}
@override
Future<void> runProtected() async {
if (argResults.rest.isEmpty) {
- usageException('Must specify a package to be added.');
- } else if (argResults.rest.length > 1) {
- usageException('Takes only a single argument.');
+ usageException('Must specify at least one package to be added.');
+ } else if (argResults.rest.length > 1 && gitUrl != null) {
+ usageException('Can only add a single git package at a time.');
+ } else if (argResults.rest.length > 1 && path != null) {
+ usageException('Can only add a single local package at a time.');
+ }
+ final languageVersion = entrypoint.root.pubspec.languageVersion;
+ final updates =
+ argResults.rest.map((p) => _parsePackage(p, languageVersion)).toList();
+
+ var updatedPubSpec = entrypoint.root.pubspec;
+ for (final update in updates) {
+ /// Perform version resolution in-memory.
+ updatedPubSpec =
+ await _addPackageToPubspec(updatedPubSpec, update.packageRange);
}
- final packageInformation = _parsePackage(argResults.rest.first);
- final package = packageInformation.first;
-
- /// Perform version resolution in-memory.
- final updatedPubSpec =
- await _addPackageToPubspec(entrypoint.root.pubspec, package);
-
- SolveResult solveResult;
+ late SolveResult solveResult;
try {
/// Use [SolveType.UPGRADE] to solve for the highest version of [package]
@@ -112,9 +125,11 @@
/// that a resolution exists before we update pubspec.yaml.
// TODO(sigurdm): We should really use a spinner here.
solveResult = await resolveVersions(
- SolveType.UPGRADE, cache, Package.inMemory(updatedPubSpec));
+ SolveType.upgrade, cache, Package.inMemory(updatedPubSpec));
} on GitException {
- dataError('Unable to resolve package "${package.name}" with the given '
+ final packageRange = updates.first.packageRange;
+ dataError(
+ 'Unable to resolve package "${packageRange.name}" with the given '
'git parameters.');
} on SolveFailure catch (e) {
dataError(e.message);
@@ -123,56 +138,63 @@
dataError(e.message);
}
- final resultPackage = solveResult.packages
- .firstWhere((packageId) => packageId.name == package.name);
+ /// Verify the results for each package.
+ for (final update in updates) {
+ final packageRange = update.packageRange;
+ final name = packageRange.name;
+ final resultPackage = solveResult.packages
+ .firstWhere((packageId) => packageId.name == name);
- /// Assert that [resultPackage] is within the original user's expectations.
- if (package.constraint != null &&
- !package.constraint.allows(resultPackage.version)) {
- if (updatedPubSpec.dependencyOverrides != null &&
- updatedPubSpec.dependencyOverrides.isNotEmpty) {
- dataError(
- '"${package.name}" resolved to "${resultPackage.version}" which '
- 'does not satisfy constraint "${package.constraint}". This could be '
- 'caused by "dependency_overrides".');
+ /// Assert that [resultPackage] is within the original user's expectations.
+ var constraint = packageRange.constraint;
+ if (!constraint.allows(resultPackage.version)) {
+ var dependencyOverrides = updatedPubSpec.dependencyOverrides;
+ if (dependencyOverrides.isNotEmpty) {
+ dataError('"$name" resolved to "${resultPackage.version}" which '
+ 'does not satisfy constraint "$constraint". This could be '
+ 'caused by "dependency_overrides".');
+ }
+ dataError('"$name" resolved to "${resultPackage.version}" which '
+ 'does not satisfy constraint "$constraint".');
}
- dataError(
- '"${package.name}" resolved to "${resultPackage.version}" which '
- 'does not satisfy constraint "${package.constraint}".');
}
-
if (isDryRun) {
/// Even if it is a dry run, run `acquireDependencies` so that the user
/// gets a report on the other packages that might change version due
/// to this new dependency.
final newRoot = Package.inMemory(updatedPubSpec);
- // TODO(jonasfj): Stop abusing Entrypoint.global for dry-run output
- await Entrypoint.global(newRoot, entrypoint.lockFile, cache,
- solveResult: solveResult)
- .acquireDependencies(
- SolveType.GET,
- dryRun: true,
- precompile: argResults['precompile'],
- );
+ await Entrypoint.inMemory(newRoot, cache,
+ solveResult: solveResult, lockFile: entrypoint.lockFile)
+ .acquireDependencies(SolveType.get,
+ dryRun: true,
+ precompile: argResults['precompile'],
+ analytics: analytics,
+ generateDotPackages: false);
} else {
/// Update the `pubspec.yaml` before calling [acquireDependencies] to
/// ensure that the modification timestamp on `pubspec.lock` and
/// `.dart_tool/package_config.json` is newer than `pubspec.yaml`,
/// ensuring that [entrypoint.assertUptoDate] will pass.
- _updatePubspec(resultPackage, packageInformation, isDev);
+ _updatePubspec(solveResult.packages, updates, isDev);
/// Create a new [Entrypoint] since we have to reprocess the updated
/// pubspec file.
final updatedEntrypoint = Entrypoint(directory, cache);
- await updatedEntrypoint.acquireDependencies(SolveType.GET,
- precompile: argResults['precompile']);
+ await updatedEntrypoint.acquireDependencies(
+ SolveType.get,
+ precompile: argResults['precompile'],
+ analytics: analytics,
+ generateDotPackages: argResults['legacy-packages-file'],
+ );
if (argResults['example'] && entrypoint.example != null) {
- await entrypoint.example.acquireDependencies(
- SolveType.GET,
+ await entrypoint.example!.acquireDependencies(
+ SolveType.get,
precompile: argResults['precompile'],
onlyReportSuccessOrFailure: true,
+ analytics: analytics,
+ generateDotPackages: argResults['legacy-packages-file'],
);
}
}
@@ -272,9 +294,7 @@
///
/// If any of the other git options are defined when `--git-url` is not
/// defined, an error will be thrown.
- Pair<PackageRange, dynamic> _parsePackage(String package) {
- ArgumentError.checkNotNull(package, 'package');
-
+ _ParseResult _parsePackage(String package, LanguageVersion languageVersion) {
final _conflictingFlagSets = [
['git-url', 'git-ref', 'git-path'],
['hosted-url'],
@@ -287,7 +307,7 @@
final conflictingFlag = _conflictingFlagSets
.where((s) => !s.contains(flag))
.expand((s) => s)
- .firstWhere(argResults.wasParsed, orElse: () => null);
+ .firstWhereOrNull(argResults.wasParsed);
if (conflictingFlag != null) {
usageException(
'Packages can only have one source, "pub add" flags "--$flag" and '
@@ -314,7 +334,7 @@
/// We want to allow for [constraint] to take on a `null` value here to
/// preserve the fact that the user did not specify a constraint.
- VersionConstraint constraint;
+ VersionConstraint? constraint;
try {
constraint = splitPackage.length == 2
@@ -326,6 +346,7 @@
/// Determine the relevant [packageRange] and [pubspecInformation] depending
/// on the type of package.
+ var path = this.path;
if (hasGitOptions) {
dynamic git;
@@ -334,7 +355,7 @@
}
Uri parsed;
try {
- parsed = Uri.parse(gitUrl);
+ parsed = Uri.parse(gitUrl!);
} on FormatException catch (e) {
usageException('The --git-url must be a valid url: ${e.message}.');
}
@@ -357,7 +378,7 @@
git.removeWhere((key, value) => value == null);
}
- packageRange = cache.sources['git']
+ packageRange = cache.sources.git
.parseRef(packageName, git, containingPath: entrypoint.pubspecPath)
.withConstraint(constraint ?? VersionConstraint.any);
pubspecInformation = {'git': git};
@@ -366,28 +387,38 @@
? PathSource.relativePathWithPosixSeparators(
p.relative(path, from: entrypoint.root.dir))
: path;
- packageRange = cache.sources['path']
+ packageRange = cache.sources.path
.parseRef(packageName, relativeToEntryPoint,
containingPath: entrypoint.pubspecPath)
.withConstraint(constraint ?? VersionConstraint.any);
pubspecInformation = {'path': relativeToEntryPoint};
} else if (sdk != null) {
- packageRange = cache.sources['sdk']
+ packageRange = cache.sources.sdk
.parseRef(packageName, sdk)
.withConstraint(constraint ?? VersionConstraint.any);
pubspecInformation = {'sdk': sdk};
} else {
- final hostInfo =
- hasHostOptions ? {'url': hostUrl, 'name': packageName} : null;
-
- if (hostInfo == null) {
- pubspecInformation = constraint?.toString();
+ // Hosted
+ final Object? hostInfo;
+ if (hasHostOptions) {
+ hostInfo = languageVersion.supportsShorterHostedSyntax
+ ? hostUrl
+ : {'url': hostUrl, 'name': packageName};
+ pubspecInformation = {
+ 'hosted': hostInfo,
+ };
} else {
- pubspecInformation = {'hosted': hostInfo};
+ hostInfo = null;
+ pubspecInformation = constraint?.toString();
}
- packageRange = PackageRange(packageName, cache.sources['hosted'],
- constraint ?? VersionConstraint.any, hostInfo ?? packageName);
+ packageRange = cache.hosted.source
+ .parseRef(
+ packageName,
+ hostInfo,
+ languageVersion: entrypoint.root.pubspec.languageVersion,
+ )
+ .withConstraint(constraint ?? VersionConstraint.any);
}
if (pubspecInformation is Map && constraint != null) {
@@ -400,65 +431,64 @@
};
}
- return Pair(packageRange, pubspecInformation);
+ return _ParseResult(packageRange, pubspecInformation);
}
/// Writes the changes to the pubspec file.
- void _updatePubspec(PackageId resultPackage,
- Pair<PackageRange, dynamic> packageInformation, bool isDevelopment) {
- ArgumentError.checkNotNull(resultPackage, 'resultPackage');
- ArgumentError.checkNotNull(packageInformation, 'pubspecInformation');
-
- final package = packageInformation.first;
- var pubspecInformation = packageInformation.last;
-
- if ((sdk != null || hasHostOptions) &&
- pubspecInformation is Map &&
- pubspecInformation['version'] == null) {
- /// We cannot simply assign the value of version since it is likely that
- /// [pubspecInformation] takes on the type
- /// [Map<String, Map<String, String>>]
- pubspecInformation = {
- ...pubspecInformation,
- 'version': '^${resultPackage.version}'
- };
- }
-
- final dependencyKey = isDevelopment ? 'dev_dependencies' : 'dependencies';
- final packagePath = [dependencyKey, package.name];
-
+ void _updatePubspec(List<PackageId> resultPackages,
+ List<_ParseResult> updates, bool isDevelopment) {
final yamlEditor = YamlEditor(readTextFile(entrypoint.pubspecPath));
log.io('Reading ${entrypoint.pubspecPath}.');
log.fine('Contents:\n$yamlEditor');
- /// Handle situations where the user might not have the dependencies or
- /// dev_dependencies map.
- if (yamlEditor.parseAt([dependencyKey], orElse: () => null)?.value ==
- null) {
- yamlEditor.update([dependencyKey],
- {package.name: pubspecInformation ?? '^${resultPackage.version}'});
- } else {
- yamlEditor.update(
- packagePath, pubspecInformation ?? '^${resultPackage.version}');
- }
+ for (final update in updates) {
+ final packageRange = update.packageRange;
+ final name = packageRange.name;
+ final resultId = resultPackages.firstWhere((id) => id.name == name);
+ var description = update.description;
- log.fine('Added ${package.name} to "$dependencyKey".');
-
- /// Remove the package from dev_dependencies if we are adding it to
- /// dependencies. Refer to [_addPackageToPubspec] for additional discussion.
- if (!isDevelopment) {
- final devDependenciesNode =
- yamlEditor.parseAt(['dev_dependencies'], orElse: () => null);
-
- if (devDependenciesNode is YamlMap &&
- devDependenciesNode.containsKey(package.name)) {
- if (devDependenciesNode.length == 1) {
- yamlEditor.remove(['dev_dependencies']);
- } else {
- yamlEditor.remove(['dev_dependencies', package.name]);
+ if (isHosted) {
+ final inferredConstraint =
+ VersionConstraint.compatibleWith(resultId.version).toString();
+ if (description == null) {
+ description = inferredConstraint;
+ } else if (description is Map && description['version'] == null) {
+ /// We cannot simply assign the value of version since it is likely that
+ /// [description] takes on the type
+ /// [Map<String, Map<String, String>>]
+ description = {...description, 'version': '^${resultId.version}'};
}
+ }
- log.fine('Removed ${package.name} from "dev_dependencies".');
+ final dependencyKey = isDevelopment ? 'dev_dependencies' : 'dependencies';
+ final packagePath = [dependencyKey, name];
+
+ /// Ensure we have a [dependencyKey] map in the `pubspec.yaml`.
+ if (yamlEditor.parseAt([dependencyKey],
+ orElse: () => YamlScalar.wrap(null)).value ==
+ null) {
+ yamlEditor.update([dependencyKey], {});
+ }
+ yamlEditor.update(packagePath, description);
+
+ log.fine('Added ${packageRange.name} to "$dependencyKey".');
+
+ /// Remove the package from dev_dependencies if we are adding it to
+ /// dependencies. Refer to [_addPackageToPubspec] for additional discussion.
+ if (!isDevelopment) {
+ final devDependenciesNode = yamlEditor
+ .parseAt(['dev_dependencies'], orElse: () => YamlScalar.wrap(null));
+
+ if (devDependenciesNode is YamlMap &&
+ devDependenciesNode.containsKey(name)) {
+ if (devDependenciesNode.length == 1) {
+ yamlEditor.remove(['dev_dependencies']);
+ } else {
+ yamlEditor.remove(['dev_dependencies', name]);
+ }
+
+ log.fine('Removed $name from "dev_dependencies".');
+ }
}
}
@@ -466,3 +496,9 @@
writeTextFile(entrypoint.pubspecPath, yamlEditor.toString());
}
}
+
+class _ParseResult {
+ PackageRange packageRange;
+ Object? description;
+ _ParseResult(this.packageRange, this.description);
+}
diff --git a/lib/src/command/barback.dart b/lib/src/command/barback.dart
index f059827..d058015 100644
--- a/lib/src/command/barback.dart
+++ b/lib/src/command/barback.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import '../command.dart';
import '../log.dart' as log;
import '../utils.dart';
diff --git a/lib/src/command/build.dart b/lib/src/command/build.dart
index 6673722..8c199d6 100644
--- a/lib/src/command/build.dart
+++ b/lib/src/command/build.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'barback.dart';
/// Handles the `build` pub command.
diff --git a/lib/src/command/cache.dart b/lib/src/command/cache.dart
index baa7403..12c4fbf 100644
--- a/lib/src/command/cache.dart
+++ b/lib/src/command/cache.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import '../command.dart';
import 'cache_add.dart';
import 'cache_clean.dart';
diff --git a/lib/src/command/cache_add.dart b/lib/src/command/cache_add.dart
index 8dc76b7..e3e64e4 100644
--- a/lib/src/command/cache_add.dart
+++ b/lib/src/command/cache_add.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:pub_semver/pub_semver.dart';
diff --git a/lib/src/command/cache_clean.dart b/lib/src/command/cache_clean.dart
index e5ae0df..42b0f1f 100644
--- a/lib/src/command/cache_clean.dart
+++ b/lib/src/command/cache_clean.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import '../command.dart';
import '../command_runner.dart';
import '../io.dart';
diff --git a/lib/src/command/cache_list.dart b/lib/src/command/cache_list.dart
index 9316172..f5ec62e 100644
--- a/lib/src/command/cache_list.dart
+++ b/lib/src/command/cache_list.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import '../command.dart';
diff --git a/lib/src/command/cache_repair.dart b/lib/src/command/cache_repair.dart
index 3658531..74968be 100644
--- a/lib/src/command/cache_repair.dart
+++ b/lib/src/command/cache_repair.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import '../command.dart';
@@ -25,6 +23,8 @@
@override
Future<void> runProtected() async {
+ // Delete any eventual temp-files left in the cache.
+ cache.deleteTempDir();
// Repair every cached source.
final repairResults = (await Future.wait(
cache.sources.all.map(cache.source).map((source) async {
diff --git a/lib/src/command/dependency_services.dart b/lib/src/command/dependency_services.dart
index 9926731..8731fe3 100644
--- a/lib/src/command/dependency_services.dart
+++ b/lib/src/command/dependency_services.dart
@@ -2,14 +2,13 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
/// This implements support for dependency-bot style automated upgrades.
/// It is still work in progress - do not rely on the current output.
import 'dart:convert';
import 'dart:io';
import 'package:async/async.dart' show collectBytes;
+import 'package:collection/collection.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';
import 'package:yaml_edit/yaml_edit.dart';
@@ -24,6 +23,7 @@
import '../pubspec_utils.dart';
import '../solver.dart';
import '../system_cache.dart';
+import '../utils.dart';
class DependencyServicesCommand extends PubCommand {
@override
@@ -64,16 +64,15 @@
final breakingPubspec = stripVersionUpperBounds(compatiblePubspec);
- final compatiblePackagesResult =
- await _tryResolve(compatiblePubspec, cache);
+ final compatiblePackagesResult = await _resolve(compatiblePubspec, cache);
- final breakingPackagesResult = await _tryResolve(breakingPubspec, cache);
+ final breakingPackagesResult = await _resolve(breakingPubspec, cache);
// This list will be empty if there is no lock file.
final currentPackages = fileExists(entrypoint.lockFilePath)
? Map<String, PackageId>.from(entrypoint.lockFile.packages)
: Map<String, PackageId>.fromIterable(
- await _tryResolve(entrypoint.root.pubspec, cache),
+ await _resolve(entrypoint.root.pubspec, cache),
key: (e) => e.name);
currentPackages.remove(entrypoint.root.name);
@@ -82,7 +81,7 @@
Future<List<Object>> _computeUpgradeSet(
Pubspec rootPubspec, PackageId package,
- {UpgradeType upgradeType}) async {
+ {required UpgradeType upgradeType}) async {
final lockFile = entrypoint.lockFile;
final pubspec = upgradeType == UpgradeType.multiBreaking
? stripVersionUpperBounds(rootPubspec)
@@ -100,12 +99,14 @@
}
final resolution = await tryResolveVersions(
- SolveType.GET,
+ SolveType.get,
cache,
Package.inMemory(pubspec),
lockFile: lockFile,
);
+ if (resolution == null) return [];
+
return [
...resolution.packages.where((r) {
if (r.name == rootPubspec.name) return false;
@@ -132,12 +133,10 @@
}
for (final package in currentPackages.values) {
- final compatibleVersion = compatiblePackagesResult.firstWhere(
- (element) => element.name == package.name,
- orElse: () => null);
- final multiBreakingVersion = breakingPackagesResult.firstWhere(
- (element) => element.name == package.name,
- orElse: () => null);
+ final compatibleVersion = compatiblePackagesResult
+ .firstWhereOrNull((element) => element.name == package.name);
+ final multiBreakingVersion = breakingPackagesResult
+ .firstWhereOrNull((element) => element.name == package.name);
final singleBreakingPubspec = Pubspec(
compatiblePubspec.name,
version: compatiblePubspec.version,
@@ -149,24 +148,24 @@
.toRange()
.withConstraint(stripUpperBound(package.toRange().constraint));
final singleBreakingPackagesResult =
- await _tryResolve(singleBreakingPubspec, cache);
- final singleBreakingVersion = singleBreakingPackagesResult.firstWhere(
- (element) => element.name == package.name,
- orElse: () => null);
+ await _resolve(singleBreakingPubspec, cache);
+ final singleBreakingVersion = singleBreakingPackagesResult
+ .firstWhereOrNull((element) => element.name == package.name);
dependencies.add({
'name': package.name,
'version': package.version.toString(),
'kind': _kindString(compatiblePubspec, package.name),
- 'latest': (await cache.getLatest(package)).version.toString(),
+ 'latest': (await cache.getLatest(package))?.version.toString(),
'constraint': _constraintOf(compatiblePubspec, package.name).toString(),
if (compatibleVersion != null)
'compatible': await _computeUpgradeSet(
compatiblePubspec, compatibleVersion,
upgradeType: UpgradeType.compatible),
- 'single-breaking': await _computeUpgradeSet(
- singleBreakingPubspec, singleBreakingVersion,
- upgradeType: UpgradeType.singleBreaking),
+ if (singleBreakingVersion != null)
+ 'single-breaking': await _computeUpgradeSet(
+ singleBreakingPubspec, singleBreakingVersion,
+ upgradeType: UpgradeType.singleBreaking),
if (multiBreakingVersion != null)
'multi-breaking': await _computeUpgradeSet(
breakingPubspec, multiBreakingVersion,
@@ -177,11 +176,9 @@
}
}
-VersionConstraint _constraintOf(Pubspec pubspec, String packageName) {
- return (pubspec.dependencies[packageName] ??
- pubspec.devDependencies[packageName])
- ?.constraint;
-}
+VersionConstraint? _constraintOf(Pubspec pubspec, String packageName) =>
+ (pubspec.dependencies[packageName] ?? pubspec.devDependencies[packageName])
+ ?.constraint;
String _kindString(Pubspec pubspec, String packageName) {
return pubspec.dependencies.containsKey(packageName)
@@ -193,15 +190,13 @@
/// Try to solve [pubspec] return [PackageId]s in the resolution or `null` if no
/// resolution was found.
-Future<List<PackageId>> _tryResolve(Pubspec pubspec, SystemCache cache) async {
- final solveResult = await tryResolveVersions(
- SolveType.UPGRADE,
- cache,
- Package.inMemory(pubspec),
- );
-
- return solveResult?.packages;
-}
+Future<List<PackageId>> _resolve(Pubspec pubspec, SystemCache cache) async =>
+ (await resolveVersions(
+ SolveType.upgrade,
+ cache,
+ Package.inMemory(pubspec),
+ ))
+ .packages;
class DependencyServicesListCommand extends PubCommand {
@override
@@ -227,7 +222,7 @@
final currentPackages = fileExists(entrypoint.lockFilePath)
? Map<String, PackageId>.from(entrypoint.lockFile.packages)
: Map<String, PackageId>.fromIterable(
- await _tryResolve(entrypoint.root.pubspec, cache),
+ await _resolve(entrypoint.root.pubspec, cache),
key: (e) => e.name);
currentPackages.remove(entrypoint.root.name);
@@ -273,11 +268,25 @@
YamlEditor(readTextFile(entrypoint.pubspecPath));
final toApply = <_PackageVersion>[];
final input = json.decode(utf8.decode(await collectBytes(stdin)));
- for (final change in input['dependencyChanges']) {
- toApply.add(_PackageVersion(
- change['name'],
- change['version'] != null ? Version.parse(change['version']) : null,
- ));
+ final changes = input['dependencyChanges'];
+ if (changes is! List) {
+ dataError('The dependencyChanges field must be a list');
+ }
+ for (final change in changes) {
+ final name = change['name'];
+ if (name is! String) {
+ dataError('The "name" field must be a string');
+ }
+ final version = change['version'];
+ if (version is! String?) {
+ dataError('The "version" field must be a string');
+ }
+ toApply.add(
+ _PackageVersion(
+ name,
+ version != null ? Version.parse(version) : null,
+ ),
+ );
}
final pubspec = entrypoint.root.pubspec;
@@ -301,7 +310,7 @@
VersionConstraint.compatibleWith(targetVersion).toString());
}
- if (lockFile != null) {
+ if (lockFileEditor != null) {
if (lockFileYaml['packages'].containsKey(targetPackage)) {
lockFileEditor.update(['packages', targetPackage, 'version'],
targetVersion.toString());
@@ -312,14 +321,18 @@
if (pubspecEditor.edits.isNotEmpty) {
writeTextFile(entrypoint.pubspecPath, pubspecEditor.toString());
}
- if (lockFile != null && lockFileEditor.edits.isNotEmpty) {
+ if (lockFileEditor != null && lockFileEditor.edits.isNotEmpty) {
writeTextFile(entrypoint.lockFilePath, lockFileEditor.toString());
}
await log.warningsOnlyUnlessTerminal(
() => () async {
// This will fail if the new configuration does not resolve.
- await Entrypoint(directory, cache)
- .acquireDependencies(SolveType.GET, dryRun: true);
+ await Entrypoint(directory, cache).acquireDependencies(
+ SolveType.get,
+ dryRun: true,
+ analytics: null,
+ generateDotPackages: false,
+ );
},
);
// Dummy message.
@@ -329,6 +342,6 @@
class _PackageVersion {
String name;
- Version version;
+ Version? version;
_PackageVersion(this.name, this.version);
}
diff --git a/lib/src/command/deps.dart b/lib/src/command/deps.dart
index 1742701..79463fc 100644
--- a/lib/src/command/deps.dart
+++ b/lib/src/command/deps.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:collection';
import 'dart:convert';
@@ -37,7 +35,8 @@
AnalysisContextManager();
/// The [StringBuffer] used to accumulate the output.
- StringBuffer _buffer;
+ // TODO(sigurdm): use a local variable for this.
+ final _buffer = StringBuffer();
/// Whether to include dev dependencies.
bool get _includeDev => argResults['dev'];
@@ -67,8 +66,7 @@
Future<void> runProtected() async {
// Explicitly Run this in the directorycase we don't access `entrypoint.packageGraph`.
entrypoint.assertUpToDate();
-
- _buffer = StringBuffer();
+ _buffer.clear();
if (argResults['json']) {
if (argResults.wasParsed('dev')) {
@@ -89,7 +87,7 @@
final current = toVisit.removeLast();
if (visited.contains(current)) continue;
visited.add(current);
- final currentPackage = entrypoint.packageGraph.packages[current];
+ final currentPackage = entrypoint.packageGraph.packages[current]!;
final next = (current == entrypoint.root.name
? entrypoint.root.immediateDependencies
: currentPackage.dependencies)
@@ -121,7 +119,7 @@
...entrypoint.root.immediateDependencies.keys
.map((name) => entrypoint.packageGraph.packages[name])
])
- ...package.executableNames.map((name) => package == entrypoint.root
+ ...package!.executableNames.map((name) => package == entrypoint.root
? ':$name'
: (package.name == name ? name : '${package.name}:$name'))
];
@@ -331,7 +329,6 @@
if (package != null) return package;
dataError('The pubspec.yaml file has changed since the pubspec.lock file '
'was generated, please run "$topLevelProgram pub get" again.');
- return null;
}
/// Outputs all executables reachable from [entrypoint].
@@ -342,7 +339,7 @@
? entrypoint.root.immediateDependencies
: entrypoint.root.dependencies)
.keys
- .map((name) => entrypoint.packageGraph.packages[name])
+ .map((name) => entrypoint.packageGraph.packages[name]!)
];
for (var package in packages) {
diff --git a/lib/src/command/downgrade.dart b/lib/src/command/downgrade.dart
index 2d0840a..fce5ef3 100644
--- a/lib/src/command/downgrade.dart
+++ b/lib/src/command/downgrade.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import '../command.dart';
@@ -44,6 +42,8 @@
argParser.addOption('directory',
abbr: 'C', help: 'Run this in the directory<dir>.', valueHelp: 'dir');
+ argParser.addFlag('legacy-packages-file',
+ help: 'Generate the legacy ".packages" file', negatable: false);
}
@override
@@ -53,16 +53,24 @@
'The --packages-dir flag is no longer used and does nothing.'));
}
var dryRun = argResults['dry-run'];
+
await entrypoint.acquireDependencies(
- SolveType.DOWNGRADE,
+ SolveType.downgrade,
unlock: argResults.rest,
dryRun: dryRun,
+ analytics: analytics,
+ generateDotPackages: argResults['legacy-packages-file'],
);
- if (argResults['example'] && entrypoint.example != null) {
- await entrypoint.example.acquireDependencies(SolveType.GET,
- unlock: argResults.rest,
- dryRun: dryRun,
- onlyReportSuccessOrFailure: true);
+ var example = entrypoint.example;
+ if (argResults['example'] && example != null) {
+ await example.acquireDependencies(
+ SolveType.get,
+ unlock: argResults.rest,
+ dryRun: dryRun,
+ onlyReportSuccessOrFailure: true,
+ analytics: analytics,
+ generateDotPackages: argResults['legacy-packages-file'],
+ );
}
if (isOffline) {
diff --git a/lib/src/command/get.dart b/lib/src/command/get.dart
index 2709238..7b8906c 100644
--- a/lib/src/command/get.dart
+++ b/lib/src/command/get.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import '../command.dart';
@@ -35,6 +33,9 @@
argParser.addFlag('packages-dir', hide: true);
+ argParser.addFlag('legacy-packages-file',
+ help: 'Generate the legacy ".packages" file', negatable: false);
+
argParser.addFlag(
'example',
help: 'Also run in `example/` (if it exists).',
@@ -51,14 +52,24 @@
log.warning(log.yellow(
'The --packages-dir flag is no longer used and does nothing.'));
}
- await entrypoint.acquireDependencies(SolveType.GET,
- dryRun: argResults['dry-run'], precompile: argResults['precompile']);
+ await entrypoint.acquireDependencies(
+ SolveType.get,
+ dryRun: argResults['dry-run'],
+ precompile: argResults['precompile'],
+ generateDotPackages: argResults['legacy-packages-file'],
+ analytics: analytics,
+ );
- if (argResults['example'] && entrypoint.example != null) {
- await entrypoint.example.acquireDependencies(SolveType.GET,
- dryRun: argResults['dry-run'],
- precompile: argResults['precompile'],
- onlyReportSuccessOrFailure: true);
+ var example = entrypoint.example;
+ if (argResults['example'] && example != null) {
+ await example.acquireDependencies(
+ SolveType.get,
+ dryRun: argResults['dry-run'],
+ precompile: argResults['precompile'],
+ generateDotPackages: argResults['legacy-packages-file'],
+ analytics: analytics,
+ onlyReportSuccessOrFailure: true,
+ );
}
}
}
diff --git a/lib/src/command/global.dart b/lib/src/command/global.dart
index b7f7b01..a7e8898 100644
--- a/lib/src/command/global.dart
+++ b/lib/src/command/global.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import '../command.dart';
import 'global_activate.dart';
import 'global_deactivate.dart';
diff --git a/lib/src/command/global_activate.dart b/lib/src/command/global_activate.dart
index 2959e6e..a21386a 100644
--- a/lib/src/command/global_activate.dart
+++ b/lib/src/command/global_activate.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:pub_semver/pub_semver.dart';
@@ -54,13 +52,13 @@
@override
Future<void> runProtected() async {
// Default to `null`, which means all executables.
- List<String> executables;
+ List<String>? executables;
if (argResults.wasParsed('executable')) {
if (argResults.wasParsed('no-executables')) {
usageException('Cannot pass both --no-executables and --executable.');
}
- executables = argResults['executable'] as List<String>;
+ executables = argResults['executable'];
} else if (argResults['no-executables']) {
// An empty list means no executables.
executables = [];
@@ -78,8 +76,8 @@
features[feature] = FeatureDependency.unused;
}
- var overwrite = argResults['overwrite'];
- Uri hostedUrl;
+ final overwrite = argResults['overwrite'] as bool;
+ Uri? hostedUrl;
if (argResults.wasParsed('hosted-url')) {
try {
hostedUrl = validateAndNormalizeHostedUrl(argResults['hosted-url']);
@@ -90,7 +88,7 @@
Iterable<String> args = argResults.rest;
- dynamic readArg([String error]) {
+ String readArg([String error = '']) {
if (args.isEmpty) usageException(error);
var arg = args.first;
args = args.skip(1);
@@ -139,8 +137,12 @@
var path = readArg('No package to activate given.');
validateNoExtraArgs();
- return globals.activatePath(path, executables,
- overwriteBinStubs: overwrite);
+ return globals.activatePath(
+ path,
+ executables,
+ overwriteBinStubs: overwrite,
+ analytics: analytics,
+ );
}
throw StateError('unreachable');
diff --git a/lib/src/command/global_deactivate.dart b/lib/src/command/global_deactivate.dart
index e06bb5e..7e99e19 100644
--- a/lib/src/command/global_deactivate.dart
+++ b/lib/src/command/global_deactivate.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import '../command.dart';
import '../log.dart' as log;
import '../utils.dart';
diff --git a/lib/src/command/global_list.dart b/lib/src/command/global_list.dart
index cd72791..5e22042 100644
--- a/lib/src/command/global_list.dart
+++ b/lib/src/command/global_list.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import '../command.dart';
/// Handles the `global list` pub command.
diff --git a/lib/src/command/global_run.dart b/lib/src/command/global_run.dart
index 28d5ca6..71e0a9d 100644
--- a/lib/src/command/global_run.dart
+++ b/lib/src/command/global_run.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:path/path.dart' as p;
@@ -19,8 +17,7 @@
String get name => 'run';
@override
String get description =>
- 'Run an executable from a globally activated package.\n'
- "NOTE: We are currently optimizing this command's startup time.";
+ 'Run an executable from a globally activated package.';
@override
String get argumentsDescription => '<package>:<executable> [args...]';
@override
diff --git a/lib/src/command/lish.dart b/lib/src/command/lish.dart
index 151ee79..c927e07 100644
--- a/lib/src/command/lish.dart
+++ b/lib/src/command/lish.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:io';
@@ -36,15 +34,13 @@
bool get takesArguments => false;
/// The URL of the server to which to upload the package.
- Uri get server {
- if (_server != null) {
- return _server;
- }
+ late final Uri server = _createServer();
+ Uri _createServer() {
// An explicit argument takes precedence.
if (argResults.wasParsed('server')) {
try {
- return _server = validateAndNormalizeHostedUrl(argResults['server']);
+ return validateAndNormalizeHostedUrl(argResults['server']);
} on FormatException catch (e) {
usageException('Invalid server: $e');
}
@@ -54,19 +50,16 @@
final publishTo = entrypoint.root.pubspec.publishTo;
if (publishTo != null) {
try {
- return _server = validateAndNormalizeHostedUrl(publishTo);
+ return validateAndNormalizeHostedUrl(publishTo);
} on FormatException catch (e) {
throw DataException('Invalid publish_to: $e');
}
}
// Use the default server if nothing else is specified
- return _server = cache.sources.hosted.defaultUrl;
+ return cache.sources.hosted.defaultUrl;
}
- /// Cache value for [server].
- Uri _server;
-
/// Whether the publish is just a preview.
bool get dryRun => argResults['dry-run'];
@@ -92,13 +85,13 @@
Future<void> _publishUsingClient(
List<int> packageBytes,
- http.BaseClient client,
+ http.Client client,
) async {
- Uri cloudStorageUrl;
+ Uri? cloudStorageUrl;
try {
await log.progress('Uploading', () async {
- var newUri = server.resolve('/api/packages/versions/new');
+ var newUri = server.resolve('api/packages/versions/new');
var response = await client.get(newUri, headers: pubApiHeaders);
var parameters = parseJsonResponse(response);
@@ -107,7 +100,7 @@
cloudStorageUrl = Uri.parse(url);
// TODO(nweiz): Cloud Storage can provide an XML-formatted error. We
// should report that error and exit.
- var request = http.MultipartRequest('POST', cloudStorageUrl);
+ var request = http.MultipartRequest('POST', cloudStorageUrl!);
var fields = _expectField(parameters, 'fields', response);
if (fields is! Map) invalidServerResponse(response);
@@ -127,8 +120,24 @@
handleJsonSuccess(
await client.get(Uri.parse(location), headers: pubApiHeaders));
});
+ } on AuthenticationException catch (error) {
+ var msg = '';
+ if (error.statusCode == 401) {
+ msg += '$server package repository requested authentication!\n'
+ 'You can provide credentials using:\n'
+ ' pub token add $server\n';
+ }
+ if (error.statusCode == 403) {
+ msg += 'Insufficient permissions to the resource at the $server '
+ 'package repository.\nYou can modify credentials using:\n'
+ ' pub token add $server\n';
+ }
+ if (error.serverMessage != null) {
+ msg += '\n' + error.serverMessage! + '\n';
+ }
+ dataError(msg + log.red('Authentication failed!'));
} on PubHttpException catch (error) {
- var url = error.response.request.url;
+ var url = error.response.request!.url;
if (url == cloudStorageUrl) {
// TODO(nweiz): the response may have XML-formatted information about
// the error. Try to parse that out once we have an easily-accessible
@@ -156,7 +165,8 @@
// explicitly have to define mock servers as official server to test
// publish command with oauth2 credentials.
if (runningFromTest &&
- Platform.environment.containsKey('PUB_HOSTED_URL'))
+ Platform.environment.containsKey('PUB_HOSTED_URL') &&
+ Platform.environment['_PUB_TEST_AUTH_METHOD'] == 'oauth2')
Platform.environment['PUB_HOSTED_URL'],
};
@@ -172,7 +182,7 @@
});
}
} on PubHttpException catch (error) {
- var url = error.response.request.url;
+ var url = error.response.request!.url;
if (Uri.parse(url.origin) == Uri.parse(server.origin)) {
handleJsonError(error.response);
} else {
diff --git a/lib/src/command/list_package_dirs.dart b/lib/src/command/list_package_dirs.dart
index 96c0735..09d248e 100644
--- a/lib/src/command/list_package_dirs.dart
+++ b/lib/src/command/list_package_dirs.dart
@@ -2,15 +2,13 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import '../command.dart';
import '../command_runner.dart';
-import '../exit_codes.dart' as exit_codes;
import '../io.dart';
import '../log.dart' as log;
+import '../package_name.dart';
import '../utils.dart';
/// Handles the `list-package-dirs` pub command.
@@ -45,7 +43,8 @@
var output = {};
// Include the local paths to all locked packages.
- var packages = mapMap(entrypoint.lockFile.packages, value: (name, package) {
+ var packages = mapMap(entrypoint.lockFile.packages,
+ value: (String name, PackageId package) {
var source = entrypoint.cache.source(package.source);
var packageDir = source.getDirectory(package);
// Normalize paths and make them absolute for backwards compatibility
@@ -67,6 +66,5 @@
];
log.json.message(output);
- return exit_codes.SUCCESS;
}
}
diff --git a/lib/src/command/login.dart b/lib/src/command/login.dart
index 747bb55..8c31e69 100644
--- a/lib/src/command/login.dart
+++ b/lib/src/command/login.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:convert';
@@ -40,7 +38,7 @@
}
}
- Future<_UserInfo> _retrieveUserInfo() async {
+ Future<_UserInfo?> _retrieveUserInfo() async {
return await oauth2.withClient(cache, (client) async {
final discovery = await httpClient.get(Uri.https(
'accounts.google.com', '/.well-known/openid-configuration'));
@@ -62,5 +60,5 @@
final String email;
_UserInfo(this.name, this.email);
@override
- String toString() => ['<$email>', if (name != null) name].join(' ');
+ String toString() => ['<$email>', name].join(' ');
}
diff --git a/lib/src/command/logout.dart b/lib/src/command/logout.dart
index 071e8c0..04ffe12 100644
--- a/lib/src/command/logout.dart
+++ b/lib/src/command/logout.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import '../command.dart';
diff --git a/lib/src/command/outdated.dart b/lib/src/command/outdated.dart
index 444bd03..2941952 100644
--- a/lib/src/command/outdated.dart
+++ b/lib/src/command/outdated.dart
@@ -2,14 +2,13 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';
-import 'package:meta/meta.dart';
+import 'package:collection/collection.dart'
+ show IterableExtension, IterableNullableExtension;
import 'package:path/path.dart' as path;
import '../command.dart';
@@ -119,7 +118,7 @@
'outdated': _OutdatedMode(),
'null-safety': _NullSafetyMode(cache, entrypoint,
shouldShowSpinner: _shouldShowSpinner),
- }[argResults['mode']];
+ }[argResults['mode']]!;
final includeDevDependencies = argResults['dev-dependencies'];
final includeDependencyOverrides = argResults['dependency-overrides'];
@@ -138,10 +137,10 @@
final resolvablePubspec = await mode.resolvablePubspec(upgradablePubspec);
- List<PackageId> upgradablePackages;
- List<PackageId> resolvablePackages;
- bool hasUpgradableResolution;
- bool hasResolvableResolution;
+ late List<PackageId> upgradablePackages;
+ late List<PackageId> resolvablePackages;
+ late bool hasUpgradableResolution;
+ late bool hasResolvableResolution;
await log.spinner('Resolving', () async {
final upgradablePackagesResult =
@@ -169,16 +168,16 @@
Future<_PackageDetails> analyzeDependency(PackageRef packageRef) async {
final name = packageRef.name;
- final current = (entrypoint.lockFile?.packages ?? {})[name];
+ final current = entrypoint.lockFile.packages[name];
- final upgradable = upgradablePackages.firstWhere((id) => id.name == name,
- orElse: () => null);
- final resolvable = resolvablePackages.firstWhere((id) => id.name == name,
- orElse: () => null);
+ final upgradable =
+ upgradablePackages.firstWhereOrNull((id) => id.name == name);
+ final resolvable =
+ resolvablePackages.firstWhereOrNull((id) => id.name == name);
// Find the latest version, and if it's overridden.
var latestIsOverridden = false;
- PackageId latest;
+ PackageId? latest;
// If not overridden in current resolution we can use this
if (!entrypoint.root.pubspec.dependencyOverrides.containsKey(name)) {
latest ??=
@@ -296,27 +295,25 @@
return argResults['mode'] != 'null-safety';
}
- bool _prereleases;
-
- bool get prereleases => _prereleases ??= () {
- // First check if 'prereleases' was passed as an argument.
- // If that was not the case, check for use of the legacy spelling
- // 'pre-releases'.
- // Otherwise fall back to the default implied by the mode.
- if (argResults.wasParsed('prereleases')) {
- return argResults['prereleases'];
- }
- if (argResults.wasParsed('pre-releases')) {
- return argResults['pre-releases'];
- }
- return argResults['mode'] == 'null-safety';
- }();
+ late final bool prereleases = () {
+ // First check if 'prereleases' was passed as an argument.
+ // If that was not the case, check for use of the legacy spelling
+ // 'pre-releases'.
+ // Otherwise fall back to the default implied by the mode.
+ if (argResults.wasParsed('prereleases')) {
+ return argResults['prereleases'];
+ }
+ if (argResults.wasParsed('pre-releases')) {
+ return argResults['pre-releases'];
+ }
+ return argResults['mode'] == 'null-safety';
+ }();
/// Retrieves the pubspec of package [name] in [version] from [source].
///
/// Returns `null`, if given `null` as a convinience.
- Future<_VersionDetails> _describeVersion(
- PackageId id,
+ Future<_VersionDetails?> _describeVersion(
+ PackageId? id,
bool isOverridden,
) async {
if (id == null) {
@@ -367,9 +364,9 @@
/// Try to solve [pubspec] return [PackageId]s in the resolution or `null` if no
/// resolution was found.
-Future<List<PackageId>> _tryResolve(Pubspec pubspec, SystemCache cache) async {
+Future<List<PackageId>?> _tryResolve(Pubspec pubspec, SystemCache cache) async {
final solveResult = await tryResolveVersions(
- SolveType.UPGRADE,
+ SolveType.upgrade,
cache,
Package.inMemory(pubspec),
);
@@ -380,13 +377,13 @@
Future<void> _outputJson(
List<_PackageDetails> rows,
Mode mode, {
- @required bool showAll,
- @required bool includeDevDependencies,
+ required bool showAll,
+ required bool includeDevDependencies,
}) async {
final markedRows =
Map.fromIterables(rows, await mode.markVersionDetails(rows));
if (!showAll) {
- rows.removeWhere((row) => markedRows[row][0].asDesired);
+ rows.removeWhere((row) => markedRows[row]![0].asDesired);
}
if (!includeDevDependencies) {
rows.removeWhere(
@@ -402,10 +399,10 @@
...(rows..sort((a, b) => a.name.compareTo(b.name)))
.map((packageDetails) => {
'package': packageDetails.name,
- 'current': markedRows[packageDetails][0]?.toJson(),
- 'upgradable': markedRows[packageDetails][1]?.toJson(),
- 'resolvable': markedRows[packageDetails][2]?.toJson(),
- 'latest': markedRows[packageDetails][3]?.toJson(),
+ 'current': markedRows[packageDetails]![0].toJson(),
+ 'upgradable': markedRows[packageDetails]![1].toJson(),
+ 'resolvable': markedRows[packageDetails]![2].toJson(),
+ 'latest': markedRows[packageDetails]![3].toJson(),
})
]
},
@@ -416,16 +413,16 @@
Future<void> _outputHuman(
List<_PackageDetails> rows,
Mode mode, {
- @required bool showAll,
- @required bool useColors,
- @required bool includeDevDependencies,
- @required bool lockFileExists,
- @required bool hasDirectDependencies,
- @required bool hasDevDependencies,
- @required bool showTransitiveDependencies,
- @required bool hasUpgradableResolution,
- @required bool hasResolvableResolution,
- @required String directory,
+ required bool showAll,
+ required bool useColors,
+ required bool includeDevDependencies,
+ required bool lockFileExists,
+ required bool hasDirectDependencies,
+ required bool hasDevDependencies,
+ required bool showTransitiveDependencies,
+ required bool hasUpgradableResolution,
+ required bool hasResolvableResolution,
+ required String directory,
}) async {
final directoryDesc = directory == '.' ? '' : ' in $directory';
log.message(mode.explanation(directoryDesc) + '\n');
@@ -434,11 +431,11 @@
List<_FormattedString> formatted(_PackageDetails package) => [
_FormattedString(package.name),
- ...markedRows[package].map((m) => m.toHuman()),
+ ...markedRows[package]!.map((m) => m.toHuman()),
];
if (!showAll) {
- rows.removeWhere((row) => markedRows[row][0].asDesired);
+ rows.removeWhere((row) => markedRows[row]![0].asDesired);
}
if (rows.isEmpty) {
log.message(mode.foundNoBadText);
@@ -506,7 +503,8 @@
for (var j = 0; j < row.length; j++) {
b.write(row[j].formatted(useColors: useColors));
b.write(' ' *
- ((columnWidths[j] + 2) - row[j].computeLength(useColors: useColors)));
+ ((columnWidths[j]! + 2) -
+ row[j].computeLength(useColors: useColors)));
}
log.message(b.toString());
}
@@ -624,15 +622,15 @@
final rows = <List<_MarkedVersionDetails>>[];
for (final packageDetails in packages) {
final cols = <_MarkedVersionDetails>[];
- _VersionDetails previous;
+ _VersionDetails? previous;
for (final versionDetails in [
packageDetails.current,
packageDetails.upgradable,
packageDetails.resolvable,
packageDetails.latest
]) {
- String Function(String) color;
- String prefix;
+ String Function(String)? color;
+ String? prefix;
var asDesired = false;
if (versionDetails != null) {
final isLatest = versionDetails == packageDetails.latest;
@@ -660,8 +658,8 @@
}
@override
- Future<Pubspec> resolvablePubspec(Pubspec pubspec) async {
- return stripVersionUpperBounds(pubspec);
+ Future<Pubspec> resolvablePubspec(Pubspec? pubspec) async {
+ return stripVersionUpperBounds(pubspec!);
}
}
@@ -674,7 +672,7 @@
final _notCompliantEmoji = emoji('✗', 'x');
_NullSafetyMode(this.cache, this.entrypoint,
- {@required this.shouldShowSpinner});
+ {required this.shouldShowSpinner});
@override
String explanation(String directoryDescription) => '''
@@ -714,14 +712,14 @@
packageDetails.resolvable?._id,
packageDetails.latest?._id,
]
- }.where((id) => id != null);
+ }.whereNotNull();
return Map.fromEntries(
await Future.wait(
ids.map(
(id) async => MapEntry(
id,
- (await id.source.bind(cache).describe(id))
+ (await id.source!.bind(cache).describe(id))
.languageVersion
.supportsNullSafety),
),
@@ -737,20 +735,20 @@
packageDetails.latest
].map(
(versionDetails) {
- String Function(String) color;
- String prefix;
- bool nullSafetyJson;
+ String Function(String)? color;
+ String? prefix;
+ MapEntry<String, Object>? jsonExplanation;
var asDesired = false;
if (versionDetails != null) {
- if (nullSafetyMap[versionDetails._id]) {
+ if (nullSafetyMap[versionDetails._id]!) {
color = log.green;
prefix = _compliantEmoji;
- nullSafetyJson = true;
+ jsonExplanation = MapEntry('nullSafety', true);
asDesired = true;
} else {
color = log.red;
prefix = _notCompliantEmoji;
- nullSafetyJson = false;
+ jsonExplanation = MapEntry('nullSafety', false);
}
}
return _MarkedVersionDetails(
@@ -758,7 +756,7 @@
asDesired: asDesired,
format: color,
prefix: prefix,
- jsonExplanation: MapEntry('nullSafety', nullSafetyJson),
+ jsonExplanation: jsonExplanation,
);
},
).toList()
@@ -809,14 +807,17 @@
_overridden == other._overridden &&
_id.source == other._id.source &&
_pubspec.version == other._pubspec.version;
+
+ @override
+ int get hashCode => Object.hash(_pubspec.version, _id.source, _overridden);
}
class _PackageDetails implements Comparable<_PackageDetails> {
final String name;
- final _VersionDetails current;
- final _VersionDetails upgradable;
- final _VersionDetails resolvable;
- final _VersionDetails latest;
+ final _VersionDetails? current;
+ final _VersionDetails? upgradable;
+ final _VersionDetails? resolvable;
+ final _VersionDetails? latest;
final _DependencyKind kind;
_PackageDetails(this.name, this.current, this.upgradable, this.resolvable,
@@ -830,7 +831,7 @@
return name.compareTo(other.name);
}
- Map<String, Object> toJson() {
+ Map<String, Object?> toJson() {
return {
'package': name,
'current': current?.toJson(),
@@ -870,15 +871,16 @@
devTransitive,
}
-_FormattedString _format(String value, Function(String) format, {prefix = ''}) {
+_FormattedString _format(String value, String Function(String) format,
+ {prefix = ''}) {
return _FormattedString(value, format: format, prefix: prefix);
}
class _MarkedVersionDetails {
- final MapEntry<String, Object> _jsonExplanation;
- final _VersionDetails _versionDetails;
- final String Function(String) _format;
- final String _prefix;
+ final MapEntry<String, Object>? _jsonExplanation;
+ final _VersionDetails? _versionDetails;
+ final String Function(String)? _format;
+ final String? _prefix;
/// This should be true if the mode creating this consideres the version as
/// "good".
@@ -889,7 +891,7 @@
_MarkedVersionDetails(
this._versionDetails, {
- @required this.asDesired,
+ required this.asDesired,
format,
prefix = '',
jsonExplanation,
@@ -903,12 +905,13 @@
prefix: _prefix,
);
- Object toJson() {
+ Object? toJson() {
if (_versionDetails == null) return null;
- return _jsonExplanation == null
- ? _versionDetails.toJson()
- : (_versionDetails.toJson()..addEntries([_jsonExplanation]));
+ var jsonExplanation = _jsonExplanation;
+ return jsonExplanation == null
+ ? _versionDetails!.toJson()
+ : (_versionDetails!.toJson()..addEntries([jsonExplanation]));
}
}
@@ -921,15 +924,15 @@
/// A prefix for marking this string if colors are not used.
final String _prefix;
- _FormattedString(this.value, {String Function(String) format, prefix})
+ _FormattedString(this.value, {String Function(String)? format, prefix})
: _format = format ?? _noFormat,
_prefix = prefix ?? '';
- String formatted({@required bool useColors}) {
+ String formatted({required bool useColors}) {
return useColors ? _format(_prefix + value) : _prefix + value;
}
- int computeLength({@required bool useColors}) {
+ int computeLength({required bool? useColors}) {
return _prefix.length + value.length;
}
diff --git a/lib/src/command/remove.dart b/lib/src/command/remove.dart
index f505785..82a9547 100644
--- a/lib/src/command/remove.dart
+++ b/lib/src/command/remove.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:yaml/yaml.dart';
import 'package:yaml_edit/yaml_edit.dart';
@@ -52,6 +50,9 @@
argParser.addOption('directory',
abbr: 'C', help: 'Run this in the directory<dir>.', valueHelp: 'dir');
+
+ argParser.addFlag('legacy-packages-file',
+ help: 'Generate the legacy ".packages" file', negatable: false);
}
@override
@@ -67,12 +68,12 @@
final newPubspec = _removePackagesFromPubspec(rootPubspec, packages);
final newRoot = Package.inMemory(newPubspec);
- await Entrypoint.global(newRoot, entrypoint.lockFile, cache)
- .acquireDependencies(
- SolveType.GET,
- precompile: argResults['precompile'],
- dryRun: true,
- );
+ await Entrypoint.inMemory(newRoot, cache, lockFile: entrypoint.lockFile)
+ .acquireDependencies(SolveType.get,
+ precompile: argResults['precompile'],
+ dryRun: true,
+ analytics: null,
+ generateDotPackages: false);
} else {
/// Update the pubspec.
_writeRemovalToPubspec(packages);
@@ -80,13 +81,22 @@
/// Create a new [Entrypoint] since we have to reprocess the updated
/// pubspec file.
final updatedEntrypoint = Entrypoint(directory, cache);
- await updatedEntrypoint.acquireDependencies(SolveType.GET,
- precompile: argResults['precompile']);
+ await updatedEntrypoint.acquireDependencies(
+ SolveType.get,
+ precompile: argResults['precompile'],
+ analytics: analytics,
+ generateDotPackages: argResults['legacy-packages-file'],
+ );
- if (argResults['example'] && entrypoint.example != null) {
- await entrypoint.example.acquireDependencies(SolveType.GET,
- precompile: argResults['precompile'],
- onlyReportSuccessOrFailure: true);
+ var example = entrypoint.example;
+ if (argResults['example'] && example != null) {
+ await example.acquireDependencies(
+ SolveType.get,
+ precompile: argResults['precompile'],
+ onlyReportSuccessOrFailure: true,
+ analytics: analytics,
+ generateDotPackages: argResults['legacy-packages-file'],
+ );
}
}
}
@@ -122,8 +132,8 @@
/// There may be packages where the dependency is declared both in
/// dependencies and dev_dependencies.
for (final dependencyKey in ['dependencies', 'dev_dependencies']) {
- final dependenciesNode =
- yamlEditor.parseAt([dependencyKey], orElse: () => null);
+ final dependenciesNode = yamlEditor
+ .parseAt([dependencyKey], orElse: () => YamlScalar.wrap(null));
if (dependenciesNode is YamlMap &&
dependenciesNode.containsKey(package)) {
diff --git a/lib/src/command/run.dart b/lib/src/command/run.dart
index c706c72..e223c5a 100644
--- a/lib/src/command/run.dart
+++ b/lib/src/command/run.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:path/path.dart' as p;
@@ -45,8 +43,6 @@
argParser.addFlag('sound-null-safety',
help: 'Override the default null safety execution mode.');
argParser.addOption('mode', help: 'Deprecated option', hide: true);
- // mode exposed for `dartdev run` to use as subprocess.
- argParser.addFlag('dart-dev-run', hide: true);
argParser.addOption('directory',
abbr: 'C', help: 'Run this in the directory<dir>.', valueHelp: 'dir');
}
@@ -58,9 +54,6 @@
log.message('Deprecated. Use `dart run` instead.');
});
}
- if (argResults['dart-dev-run']) {
- return await _runFromDartDev();
- }
if (argResults.rest.isEmpty) {
usageException('Must specify an executable to run.');
}
@@ -104,54 +97,4 @@
);
overrideExitCode(exitCode);
}
-
- /// Implement a mode for use in `dartdev run`.
- ///
- /// Usage: `dartdev run [package[:command]]`
- ///
- /// If `package` is not given, defaults to current root package.
- /// If `command` is not given, defaults to name of `package`.
- ///
- /// Runs `bin/<command>.dart` from package `<package>`. If `<package>` is not
- /// mutable (local root package or path-dependency) a source snapshot will be
- /// cached in
- /// `.dart_tool/pub/bin/<package>/<command>.dart-<sdkVersion>.snapshot`.
- Future<void> _runFromDartDev() async {
- var package = entrypoint.root.name;
- var command = package;
- var args = <String>[];
-
- if (argResults.rest.isNotEmpty) {
- if (argResults.rest[0].contains(RegExp(r'[/\\]'))) {
- usageException('[<package>[:command]] cannot contain "/" or "\\"');
- }
-
- package = argResults.rest[0];
- if (package.contains(':')) {
- final parts = package.split(':');
- if (parts.length > 2) {
- usageException('[<package>[:command]] cannot contain multiple ":"');
- }
- package = parts[0];
- command = parts[1];
- } else {
- command = package;
- }
- args = argResults.rest.skip(1).toList();
- }
-
- final vmArgs = vmArgsFromArgResults(argResults);
-
- overrideExitCode(
- await runExecutable(
- entrypoint,
- Executable(package, 'bin/$command.dart'),
- args,
- vmArgs: vmArgs,
- enableAsserts: argResults['enable-asserts'] || argResults['checked'],
- recompile: entrypoint.precompileExecutable,
- alwaysUseSubprocess: alwaysUseSubprocess,
- ),
- );
- }
}
diff --git a/lib/src/command/serve.dart b/lib/src/command/serve.dart
index 76c0002..4c560e7 100644
--- a/lib/src/command/serve.dart
+++ b/lib/src/command/serve.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'barback.dart';
/// Handles the `serve` pub command.
diff --git a/lib/src/command/token.dart b/lib/src/command/token.dart
index dafa88f..9886dcf 100644
--- a/lib/src/command/token.dart
+++ b/lib/src/command/token.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.11
-
import '../command.dart';
import 'token_add.dart';
import 'token_list.dart';
diff --git a/lib/src/command/token_add.dart b/lib/src/command/token_add.dart
index f7cd6b9..caf3b8b 100644
--- a/lib/src/command/token_add.dart
+++ b/lib/src/command/token_add.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.11
-
import 'dart:async';
import 'dart:io';
@@ -26,7 +24,7 @@
@override
String get argumentsDescription => '[hosted-url]';
- String get envVar => argResults['env-var'];
+ String? get envVar => argResults['env-var'];
TokenAddCommand() {
argParser.addOption('env-var',
@@ -42,32 +40,28 @@
} else if (argResults.rest.length > 1) {
usageException('Takes only a single argument.');
}
+ final rawHostedUrl = argResults.rest.first;
try {
- var hostedUrl = validateAndNormalizeHostedUrl(argResults.rest.first);
- if (hostedUrl.isScheme('HTTP')) {
- throw DataException('Insecure package repository could not be added.');
+ var hostedUrl = validateAndNormalizeHostedUrl(rawHostedUrl);
+ if (!hostedUrl.isScheme('HTTPS')) {
+ throw FormatException('url must be https://, '
+ 'insecure repositories cannot use authentication.');
}
if (envVar == null) {
await _addTokenFromStdin(hostedUrl);
} else {
- await _addEnvVarToken(hostedUrl);
+ await _addEnvVarToken(hostedUrl, envVar!);
}
} on FormatException catch (e) {
- usageException('Invalid [hosted-url]: "${argResults.rest.first}"\n'
+ usageException('Invalid [hosted-url]: "$rawHostedUrl"\n'
'${e.message}');
- } on TimeoutException catch (_) {
- // Timeout is added to readLine call to make sure automated jobs doesn't
- // get stuck on noop state if user forget to pipe token to the 'token add'
- // command. This behavior might be removed.
- throw ApplicationException('Token is not provided within 15 minutes.');
}
}
Future<void> _addTokenFromStdin(Uri hostedUrl) async {
- final token = await stdinPrompt('Enter secret token:', echoMode: false)
- .timeout(const Duration(minutes: 15));
+ final token = await stdinPrompt('Enter secret token:', echoMode: false);
if (token.isEmpty) {
usageException('Token is not provided.');
}
@@ -79,22 +73,45 @@
);
}
- Future<void> _addEnvVarToken(Uri hostedUrl) async {
+ Future<void> _addEnvVarToken(Uri hostedUrl, String envVar) async {
if (envVar.isEmpty) {
- throw DataException('Cannot use the empty string as --env-var');
+ usageException('Cannot use the empty string as --env-var');
+ }
+
+ // Environment variable names on Windows [1] and UNIX [2] cannot contain
+ // equal signs.
+ // [1] https://docs.microsoft.com/en-us/windows/win32/procthread/environment-variables
+ // [2] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
+ if (envVar.contains('=')) {
+ throw DataException(
+ 'Environment variable name --env-var="$envVar" cannot contain "=", the '
+ 'equals sign is not allowed in environment variable names.',
+ );
+ }
+
+ // Help the user if they typed something that is unlikely to be correct.
+ // This could happen if you include $, whitespace, quotes or accidentally
+ // dereference the environment variable instead.
+ if (!RegExp(r'^[A-Z_][A-Z0-9_]*$').hasMatch(envVar)) {
+ log.warning(
+ 'The environment variable name --env-var="$envVar" does not use '
+ 'uppercase characters A-Z, 0-9 and underscore. This is unusual for '
+ 'environment variable names.\n'
+ 'Check that you meant to use the environment variable name: "$envVar".',
+ );
}
tokenStore.addCredential(Credential.env(hostedUrl, envVar));
log.message(
'Requests to "$hostedUrl" will now be authenticated using the secret '
- 'token stored in the environment variable `$envVar`.',
+ 'token stored in the environment variable "$envVar".',
);
if (!Platform.environment.containsKey(envVar)) {
// If environment variable doesn't exist when
// pub token add <hosted-url> --env-var <ENV_VAR> is called, we should
// print a warning.
- log.warning('Environment variable `$envVar` is not defined.');
+ log.warning('Environment variable "$envVar" is not defined.');
}
}
}
diff --git a/lib/src/command/token_list.dart b/lib/src/command/token_list.dart
index 828f004..3cf73ee 100644
--- a/lib/src/command/token_list.dart
+++ b/lib/src/command/token_list.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.11
-
import '../command.dart';
import '../log.dart' as log;
diff --git a/lib/src/command/token_remove.dart b/lib/src/command/token_remove.dart
index 7c49a0d..1b08127 100644
--- a/lib/src/command/token_remove.dart
+++ b/lib/src/command/token_remove.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.11
-
import '../command.dart';
import '../exceptions.dart';
import '../log.dart' as log;
diff --git a/lib/src/command/upgrade.dart b/lib/src/command/upgrade.dart
index 39a42c7..0dc5fb7 100644
--- a/lib/src/command/upgrade.dart
+++ b/lib/src/command/upgrade.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:io';
@@ -58,6 +56,9 @@
argParser.addFlag('packages-dir', hide: true);
+ argParser.addFlag('legacy-packages-file',
+ help: 'Generate the legacy ".packages" file', negatable: false);
+
argParser.addFlag(
'major-versions',
help: 'Upgrades packages to their latest resolvable versions, '
@@ -82,6 +83,8 @@
bool get _precompile => argResults['precompile'];
+ bool get _packagesFile => argResults['legacy-packages-file'];
+
bool get _upgradeNullSafety =>
argResults['nullsafety'] || argResults['null-safety'];
@@ -116,18 +119,21 @@
if (argResults['example'] && entrypoint.example != null) {
// Reload the entrypoint to ensure we pick up potential changes that has
// been made.
- final exampleEntrypoint = Entrypoint(directory, cache).example;
+ final exampleEntrypoint = Entrypoint(directory, cache).example!;
await _runUpgrade(exampleEntrypoint, onlySummary: true);
}
}
Future<void> _runUpgrade(Entrypoint e, {bool onlySummary = false}) async {
- await e.acquireDependencies(SolveType.UPGRADE,
- unlock: argResults.rest,
- dryRun: _dryRun,
- precompile: _precompile,
- onlyReportSuccessOrFailure: onlySummary);
-
+ await e.acquireDependencies(
+ SolveType.upgrade,
+ unlock: argResults.rest,
+ dryRun: _dryRun,
+ precompile: _precompile,
+ onlyReportSuccessOrFailure: onlySummary,
+ generateDotPackages: _packagesFile,
+ analytics: analytics,
+ );
_showOfflineWarning();
}
@@ -179,12 +185,12 @@
final resolvedPackages = <String, PackageId>{};
final solveResult = await log.spinner('Resolving dependencies', () async {
return await resolveVersions(
- SolveType.UPGRADE,
+ SolveType.upgrade,
cache,
Package.inMemory(resolvablePubspec),
);
}, condition: _shouldShowSpinner);
- for (final resolvedPackage in solveResult?.packages ?? []) {
+ for (final resolvedPackage in solveResult.packages) {
resolvedPackages[resolvedPackage.name] = resolvedPackage;
}
@@ -196,9 +202,8 @@
...entrypoint.root.pubspec.devDependencies.values,
].where((dep) => dep.source is HostedSource);
for (final dep in declaredHostedDependencies) {
- final resolvedPackage = resolvedPackages[dep.name];
- assert(resolvedPackage != null);
- if (resolvedPackage == null || !toUpgrade.contains(dep.name)) {
+ final resolvedPackage = resolvedPackages[dep.name]!;
+ if (!toUpgrade.contains(dep.name)) {
// If we're not to upgrade this package, or it wasn't in the
// resolution somehow, then we ignore it.
continue;
@@ -219,30 +224,37 @@
resolvedPackage.version,
));
}
+ final newPubspecText = _updatePubspec(changes);
if (_dryRun) {
// Even if it is a dry run, run `acquireDependencies` so that the user
// gets a report on changes.
- // TODO(jonasfj): Stop abusing Entrypoint.global for dry-run output
- await Entrypoint.global(
- Package.inMemory(resolvablePubspec),
- entrypoint.lockFile,
+ await Entrypoint.inMemory(
+ Package.inMemory(
+ Pubspec.parse(newPubspecText, cache.sources),
+ ),
cache,
+ lockFile: entrypoint.lockFile,
solveResult: solveResult,
).acquireDependencies(
- SolveType.UPGRADE,
+ SolveType.get,
dryRun: true,
precompile: _precompile,
+ analytics: null, // No analytics for dry-run
+ generateDotPackages: false,
);
} else {
- await _updatePubspec(changes);
-
+ if (changes.isNotEmpty) {
+ writeTextFile(entrypoint.pubspecPath, newPubspecText);
+ }
// TODO: Allow Entrypoint to be created with in-memory pubspec, so that
// we can show the changes when not in --dry-run mode. For now we only show
// the changes made to pubspec.yaml in dry-run mode.
await Entrypoint(directory, cache).acquireDependencies(
- SolveType.UPGRADE,
+ SolveType.get,
precompile: _precompile,
+ analytics: analytics,
+ generateDotPackages: argResults['legacy-packages-file'],
);
}
@@ -275,12 +287,12 @@
final resolvedPackages = <String, PackageId>{};
final solveResult = await log.spinner('Resolving dependencies', () async {
return await resolveVersions(
- SolveType.UPGRADE,
+ SolveType.upgrade,
cache,
Package.inMemory(nullsafetyPubspec),
);
}, condition: _shouldShowSpinner);
- for (final resolvedPackage in solveResult?.packages ?? []) {
+ for (final resolvedPackage in solveResult.packages) {
resolvedPackages[resolvedPackage.name] = resolvedPackage;
}
@@ -292,9 +304,8 @@
...entrypoint.root.pubspec.devDependencies.values,
].where((dep) => dep.source is HostedSource);
for (final dep in declaredHostedDependencies) {
- final resolvedPackage = resolvedPackages[dep.name];
- assert(resolvedPackage != null);
- if (resolvedPackage == null || !toUpgrade.contains(dep.name)) {
+ final resolvedPackage = resolvedPackages[dep.name]!;
+ if (!toUpgrade.contains(dep.name)) {
// If we're not to upgrade this package, or it wasn't in the
// resolution somehow, then we ignore it.
continue;
@@ -313,29 +324,35 @@
changes[dep] = dep.withConstraint(constraint);
}
+ final newPubspecText = _updatePubspec(changes);
if (_dryRun) {
// Even if it is a dry run, run `acquireDependencies` so that the user
// gets a report on changes.
// TODO(jonasfj): Stop abusing Entrypoint.global for dry-run output
- await Entrypoint.global(
- Package.inMemory(nullsafetyPubspec),
- entrypoint.lockFile,
+ await Entrypoint.inMemory(
+ Package.inMemory(Pubspec.parse(newPubspecText, cache.sources)),
cache,
+ lockFile: entrypoint.lockFile,
solveResult: solveResult,
).acquireDependencies(
- SolveType.UPGRADE,
+ SolveType.upgrade,
dryRun: true,
precompile: _precompile,
+ analytics: null,
+ generateDotPackages: false,
);
} else {
- await _updatePubspec(changes);
-
+ if (changes.isNotEmpty) {
+ writeTextFile(entrypoint.pubspecPath, newPubspecText);
+ }
// TODO: Allow Entrypoint to be created with in-memory pubspec, so that
// we can show the changes in --dry-run mode. For now we only show
// the changes made to pubspec.yaml in dry-run mode.
await Entrypoint(directory, cache).acquireDependencies(
- SolveType.UPGRADE,
+ SolveType.upgrade,
precompile: _precompile,
+ analytics: analytics,
+ generateDotPackages: argResults['legacy-packages-file'],
);
}
@@ -353,10 +370,9 @@
...entrypoint.root.pubspec.devDependencies.keys
];
await Future.wait(directDeps.map((name) async {
- final resolvedPackage = resolvedPackages[name];
- assert(resolvedPackage != null);
+ final resolvedPackage = resolvedPackages[name]!;
- final boundSource = resolvedPackage.source.bind(cache);
+ final boundSource = resolvedPackage.source!.bind(cache);
final pubspec = await boundSource.describe(resolvedPackage);
if (!pubspec.languageVersion.supportsNullSafety) {
nonMigratedDirectDeps.add(name);
@@ -380,13 +396,11 @@
}
/// Updates `pubspec.yaml` with given [changes].
- Future<void> _updatePubspec(
+ String _updatePubspec(
Map<PackageRange, PackageRange> changes,
- ) async {
+ ) {
ArgumentError.checkNotNull(changes, 'changes');
- if (changes.isEmpty) return;
-
final yamlEditor = YamlEditor(readTextFile(entrypoint.pubspecPath));
final deps = entrypoint.root.pubspec.dependencies.keys;
final devDeps = entrypoint.root.pubspec.devDependencies.keys;
@@ -406,9 +420,7 @@
);
}
}
-
- /// Windows line endings are already handled by [yamlEditor]
- writeTextFile(entrypoint.pubspecPath, yamlEditor.toString());
+ return yamlEditor.toString();
}
/// Outputs a summary of changes made to `pubspec.yaml`.
@@ -468,7 +480,7 @@
return dep;
}
- final boundSource = dep.source.bind(cache);
+ final boundSource = dep.source!.bind(cache);
final packages = await boundSource.getVersions(dep.toRef());
packages.sort((a, b) => a.version.compareTo(b.version));
@@ -483,7 +495,9 @@
}
hasNoNullSafetyVersions.add(dep.name);
- return null;
+ // This value is never used. We will throw an exception because
+ //`hasNonNullSafetyVersions` is not empty.
+ return dep.withConstraint(VersionConstraint.empty);
}));
final deps = _removeUpperConstraints(original.dependencies.values);
diff --git a/lib/src/command/uploader.dart b/lib/src/command/uploader.dart
index 2498eea..99a6a57 100644
--- a/lib/src/command/uploader.dart
+++ b/lib/src/command/uploader.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:io';
diff --git a/lib/src/command/version.dart b/lib/src/command/version.dart
index 51eeb8f..2ac96e7 100644
--- a/lib/src/command/version.dart
+++ b/lib/src/command/version.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import '../command.dart';
import '../log.dart' as log;
import '../sdk.dart';
diff --git a/lib/src/command_runner.dart b/lib/src/command_runner.dart
index 8bfa25b..7c8b041 100644
--- a/lib/src/command_runner.dart
+++ b/lib/src/command_runner.dart
@@ -2,20 +2,18 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:io';
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:path/path.dart' as p;
-import 'package:pub/src/command/dependency_services.dart';
import 'command.dart' show PubTopLevel, lineLength;
import 'command/add.dart';
import 'command/build.dart';
import 'command/cache.dart';
+import 'command/dependency_services.dart';
import 'command/deps.dart';
import 'command/downgrade.dart';
import 'command/get.dart';
@@ -48,45 +46,53 @@
class PubCommandRunner extends CommandRunner<int> implements PubTopLevel {
@override
- String get directory => _argResults['directory'];
+ String? get directory => argResults['directory'];
@override
bool get captureStackChains {
- return _argResults['trace'] ||
- _argResults['verbose'] ||
- _argResults['verbosity'] == 'all';
+ return argResults['trace'] ||
+ argResults['verbose'] ||
+ argResults['verbosity'] == 'all';
}
@override
Verbosity get verbosity {
- switch (_argResults['verbosity']) {
+ switch (argResults['verbosity']) {
case 'error':
- return log.Verbosity.ERROR;
+ return log.Verbosity.error;
case 'warning':
- return log.Verbosity.WARNING;
+ return log.Verbosity.warning;
case 'normal':
- return log.Verbosity.NORMAL;
+ return log.Verbosity.normal;
case 'io':
- return log.Verbosity.IO;
+ return log.Verbosity.io;
case 'solver':
- return log.Verbosity.SOLVER;
+ return log.Verbosity.solver;
case 'all':
- return log.Verbosity.ALL;
+ return log.Verbosity.all;
default:
// No specific verbosity given, so check for the shortcut.
- if (_argResults['verbose']) return log.Verbosity.ALL;
- return log.Verbosity.NORMAL;
+ if (argResults['verbose']) return log.Verbosity.all;
+ if (runningFromTest) return log.Verbosity.testing;
+ return log.Verbosity.normal;
}
}
@override
- bool get trace => _argResults['trace'];
+ bool get trace => argResults['trace'];
- ArgResults _argResults;
+ ArgResults? _argResults;
/// The top-level options parsed by the command runner.
@override
- ArgResults get argResults => _argResults;
+ ArgResults get argResults {
+ final a = _argResults;
+ if (a == null) {
+ throw StateError(
+ 'argResults cannot be used before Command.run is called.');
+ }
+ return a;
+ }
@override
String get usageFooter =>
@@ -152,7 +158,7 @@
Future<int> run(Iterable<String> args) async {
try {
_argResults = parse(args);
- return await runCommand(_argResults) ?? exit_codes.SUCCESS;
+ return await runCommand(argResults) ?? exit_codes.SUCCESS;
} on UsageException catch (error) {
log.exception(error);
return exit_codes.USAGE;
@@ -160,7 +166,7 @@
}
@override
- Future<int> runCommand(ArgResults topLevelResults) async {
+ Future<int?> runCommand(ArgResults topLevelResults) async {
_checkDepsSynced();
if (topLevelResults['version']) {
diff --git a/lib/src/dart.dart b/lib/src/dart.dart
index e498058..f4f8686 100644
--- a/lib/src/dart.dart
+++ b/lib/src/dart.dart
@@ -7,8 +7,7 @@
import 'dart:io';
import 'package:analyzer/dart/analysis/analysis_context.dart';
-import 'package:analyzer/dart/analysis/context_builder.dart';
-import 'package:analyzer/dart/analysis/context_locator.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
@@ -67,21 +66,22 @@
modificationStamp: 0,
);
+ var contextCollection = AnalysisContextCollection(
+ includedPaths: [path],
+ resourceProvider: resourceProvider,
+ sdkPath: getSdkPath(),
+ );
+
// Add new contexts for the given path.
- var contextLocator = ContextLocator(resourceProvider: resourceProvider);
- var roots = contextLocator.locateRoots(includedPaths: [path]);
- for (var root in roots) {
- var contextRootPath = root.root.path;
+ for (var analysisContext in contextCollection.contexts) {
+ var contextRootPath = analysisContext.contextRoot.root.path;
// If there is already a context for this context root path, keep it.
if (_contexts.containsKey(contextRootPath)) {
continue;
}
- var contextBuilder = ContextBuilder();
- var context = contextBuilder.createContext(
- contextRoot: root, sdkPath: getSdkPath());
- _contexts[contextRootPath] = context;
+ _contexts[contextRootPath] = analysisContext;
}
}
@@ -94,7 +94,7 @@
/// Throws [AnalyzerErrorGroup] is the file has parsing errors.
CompilationUnit parse(String path) {
path = p.normalize(p.absolute(path));
- var parseResult = _getExistingSession(path).getParsedUnit2(path);
+ var parseResult = _getExistingSession(path).getParsedUnit(path);
if (parseResult is ParsedUnitResult) {
if (parseResult.errors.isNotEmpty) {
throw AnalyzerErrorGroup(parseResult.errors);
@@ -146,11 +146,14 @@
String toString() => errors.join('\n');
}
-/// Precompiles the Dart executable at [executablePath] to a kernel file at
-/// [outputPath].
+/// Precompiles the Dart executable at [executablePath].
///
-/// This file is also cached at [incrementalDillOutputPath] which is used to
-/// initialize the compiler on future runs.
+/// If the compilation succeeds it is saved to a kernel file at [outputPath].
+///
+/// If compilation fails, the output is cached at [incrementalDillOutputPath].
+///
+/// Whichever of [incrementalDillOutputPath] and [outputPath] already exists is
+/// used to initialize the compiler run.
///
/// The [packageConfigPath] should point at the package config file to be used
/// for `package:` uri resolution.
@@ -158,39 +161,65 @@
/// The [name] is used to describe the executable in logs and error messages.
Future<void> precompile({
required String executablePath,
- required String incrementalDillOutputPath,
+ required String incrementalDillPath,
required String name,
required String outputPath,
required String packageConfigPath,
}) async {
ensureDir(p.dirname(outputPath));
- ensureDir(p.dirname(incrementalDillOutputPath));
+ ensureDir(p.dirname(incrementalDillPath));
+
const platformDill = 'lib/_internal/vm_platform_strong.dill';
final sdkRoot = p.relative(p.dirname(p.dirname(Platform.resolvedExecutable)));
- var client = await FrontendServerClient.start(
- executablePath,
- incrementalDillOutputPath,
- platformDill,
- sdkRoot: sdkRoot,
- packagesJson: packageConfigPath,
- printIncrementalDependencies: false,
- );
+ String? tempDir;
+ FrontendServerClient? client;
try {
- var result = await client.compile();
+ tempDir = createTempDir(p.dirname(incrementalDillPath), 'tmp');
+ // To avoid potential races we copy the incremental data to a temporary file
+ // for just this compilation.
+ final temporaryIncrementalDill =
+ p.join(tempDir, '${p.basename(incrementalDillPath)}.incremental.dill');
+ try {
+ if (fileExists(incrementalDillPath)) {
+ copyFile(incrementalDillPath, temporaryIncrementalDill);
+ } else if (fileExists(outputPath)) {
+ copyFile(outputPath, temporaryIncrementalDill);
+ }
+ } on FileSystemException {
+ // Not able to copy existing file, compilation will start from scratch.
+ }
+
+ client = await FrontendServerClient.start(
+ executablePath,
+ temporaryIncrementalDill,
+ platformDill,
+ sdkRoot: sdkRoot,
+ packagesJson: packageConfigPath,
+ printIncrementalDependencies: false,
+ );
+ final result = await client.compile();
final highlightedName = log.bold(name);
if (result?.errorCount == 0) {
log.message('Built $highlightedName.');
- await File(incrementalDillOutputPath).copy(outputPath);
+ // By using rename we ensure atomicity. An external observer will either
+ // see the old or the new snapshot.
+ renameFile(temporaryIncrementalDill, outputPath);
} else {
- // Don't leave partial results.
- deleteEntry(outputPath);
+ // By using rename we ensure atomicity. An external observer will either
+ // see the old or the new snapshot.
+ renameFile(temporaryIncrementalDill, incrementalDillPath);
+ // If compilation failed we don't want to leave an incorrect snapshot.
+ tryDeleteEntry(outputPath);
throw ApplicationException(
log.yellow('Failed to build $highlightedName:\n') +
(result?.compilerOutputLines.join('\n') ?? ''));
}
} finally {
- client.kill();
+ client?.kill();
+ if (tempDir != null) {
+ tryDeleteEntry(tempDir);
+ }
}
}
diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index 8820c33..202580c 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:convert';
import 'dart:io';
@@ -12,12 +10,12 @@
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
+import 'package:yaml/yaml.dart';
import 'command_runner.dart';
import 'dart.dart' as dart;
import 'exceptions.dart';
import 'executable.dart';
-import 'http.dart' as http;
import 'io.dart';
import 'language_version.dart';
import 'lock_file.dart';
@@ -28,6 +26,7 @@
import 'package_graph.dart';
import 'package_name.dart';
import 'packages_file.dart' as packages_file;
+import 'pub_embeddable_command.dart';
import 'pubspec.dart';
import 'sdk.dart';
import 'solver.dart';
@@ -73,78 +72,81 @@
/// but may be the entrypoint when you're running its tests.
class Entrypoint {
/// The root package this entrypoint is associated with.
+ ///
+ /// For a global package, this is the activated package.
final Package root;
+ /// For a global package, this is the directory that the package is installed
+ /// in. Non-global packages have null.
+ final String? globalDir;
+
/// The system-wide cache which caches packages that need to be fetched over
/// the network.
final SystemCache cache;
/// Whether this entrypoint exists within the package cache.
- bool get isCached => root.dir != null && p.isWithin(cache.rootDir, root.dir);
+ bool get isCached => !root.isInMemory && p.isWithin(cache.rootDir, root.dir);
/// Whether this is an entrypoint for a globally-activated package.
- final bool isGlobal;
+ // final bool isGlobal;
+ bool get isGlobal => globalDir != null;
/// The lockfile for the entrypoint.
///
/// If not provided to the entrypoint, it will be loaded lazily from disk.
- LockFile get lockFile {
- if (_lockFile != null) return _lockFile;
+ LockFile get lockFile => _lockFile ??= _loadLockFile();
+ LockFile _loadLockFile() {
if (!fileExists(lockFilePath)) {
- _lockFile = LockFile.empty();
+ return _lockFile = LockFile.empty();
} else {
- _lockFile = LockFile.load(lockFilePath, cache.sources);
+ return _lockFile = LockFile.load(lockFilePath, cache.sources);
}
-
- return _lockFile;
}
- LockFile _lockFile;
+ LockFile? _lockFile;
/// The package graph for the application and all of its transitive
/// dependencies.
///
/// Throws a [DataError] if the `.dart_tool/package_config.json` file isn't
/// up-to-date relative to the pubspec and the lockfile.
- PackageGraph get packageGraph {
- if (_packageGraph != null) return _packageGraph;
+ PackageGraph get packageGraph => _packageGraph ??= _createPackageGraph();
+ PackageGraph _createPackageGraph() {
assertUpToDate();
var packages = {
for (var id in lockFile.packages.values) id.name: cache.load(id)
};
packages[root.name] = root;
- _packageGraph = PackageGraph(this, lockFile, packages);
- return _packageGraph;
+ return PackageGraph(this, lockFile, packages);
}
- PackageGraph _packageGraph;
+ PackageGraph? _packageGraph;
/// Where the lock file and package configurations are to be found.
///
/// Global packages (except those from path source)
/// store these in the global cache.
- String get _configRoot =>
- isCached ? p.join(cache.rootDir, 'global_packages', root.name) : root.dir;
+ String? get _configRoot => isCached ? globalDir : root.dir;
/// The path to the entrypoint's ".packages" file.
///
/// This file is being slowly deprecated in favor of
/// `.dart_tool/package_config.json`. Pub will still create it, but will
/// not require it or make use of it within pub.
- String get packagesFile => p.normalize(p.join(_configRoot, '.packages'));
+ String get packagesFile => p.normalize(p.join(_configRoot!, '.packages'));
/// The path to the entrypoint's ".dart_tool/package_config.json" file.
String get packageConfigFile =>
- p.normalize(p.join(_configRoot, '.dart_tool', 'package_config.json'));
+ p.normalize(p.join(_configRoot!, '.dart_tool', 'package_config.json'));
/// The path to the entrypoint package's pubspec.
String get pubspecPath => p.normalize(root.path('pubspec.yaml'));
/// The path to the entrypoint package's lockfile.
- String get lockFilePath => p.normalize(p.join(_configRoot, 'pubspec.lock'));
+ String get lockFilePath => p.normalize(p.join(_configRoot!, 'pubspec.lock'));
/// The path to the entrypoint package's `.dart_tool/pub` cache directory.
///
@@ -156,11 +158,7 @@
/// but the configuration is stored at the package itself.
String get cachePath {
if (isGlobal) {
- return p.join(
- cache.rootDir,
- 'global_packages',
- root.name,
- );
+ return globalDir!;
} else {
var newPath = root.path('.dart_tool/pub');
var oldPath = root.path('.pub');
@@ -177,15 +175,25 @@
String get _incrementalDillsPath => p.join(cachePath, 'incremental');
/// Loads the entrypoint from a package at [rootDir].
- Entrypoint(String rootDir, this.cache)
- : root = Package.load(null, rootDir, cache.sources),
- isGlobal = false;
+ Entrypoint(
+ String rootDir,
+ this.cache,
+ ) : root = Package.load(null, rootDir, cache.sources),
+ globalDir = null;
+
+ Entrypoint.inMemory(this.root, this.cache,
+ {required LockFile? lockFile, SolveResult? solveResult})
+ : _lockFile = lockFile,
+ globalDir = null {
+ if (solveResult != null) {
+ _packageGraph = PackageGraph.fromSolveResult(this, solveResult);
+ }
+ }
/// Creates an entrypoint given package and lockfile objects.
- /// If a SolveResult is already created it can be passes as an optimization.
- Entrypoint.global(this.root, this._lockFile, this.cache,
- {SolveResult solveResult})
- : isGlobal = true {
+ /// If a SolveResult is already created it can be passed as an optimization.
+ Entrypoint.global(this.globalDir, this.root, this._lockFile, this.cache,
+ {SolveResult? solveResult}) {
if (solveResult != null) {
_packageGraph = PackageGraph.fromSolveResult(this, solveResult);
}
@@ -194,7 +202,7 @@
/// Gets the [Entrypoint] package for the current working directory.
///
/// This will be null if the example folder doesn't have a `pubspec.yaml`.
- Entrypoint get example {
+ Entrypoint? get example {
if (_example != null) return _example;
if (!fileExists(root.path('example', 'pubspec.yaml'))) {
return null;
@@ -202,22 +210,28 @@
return _example = Entrypoint(root.path('example'), cache);
}
- Entrypoint _example;
+ Entrypoint? _example;
/// Writes .packages and .dart_tool/package_config.json
- Future<void> writePackagesFiles() async {
- writeTextFile(
- packagesFile,
- lockFile.packagesFile(cache,
- entrypoint: root.name, relativeFrom: root.dir));
+ Future<void> writePackagesFiles({bool generateDotPackages = false}) async {
+ final entrypointName = isGlobal ? null : root.name;
+ if (generateDotPackages) {
+ writeTextFile(
+ packagesFile,
+ lockFile.packagesFile(cache,
+ entrypoint: entrypointName,
+ relativeFrom: isGlobal ? null : root.dir));
+ } else {
+ tryDeleteEntry(packagesFile);
+ }
ensureDir(p.dirname(packageConfigFile));
writeTextFile(
packageConfigFile,
await lockFile.packageConfigFile(cache,
- entrypoint: root.name,
+ entrypoint: entrypointName,
entrypointSdkConstraint:
root.pubspec.sdkConstraints[sdk.identifier],
- relativeFrom: root.dir));
+ relativeFrom: isGlobal ? null : root.dir));
}
/// Gets all dependencies of the [root] package.
@@ -244,28 +258,29 @@
/// Updates [lockFile] and [packageRoot] accordingly.
Future<void> acquireDependencies(
SolveType type, {
- Iterable<String> unlock,
+ Iterable<String>? unlock,
bool dryRun = false,
bool precompile = false,
+ required bool generateDotPackages,
+ required PubAnalytics? analytics,
bool onlyReportSuccessOrFailure = false,
}) async {
- final suffix = root.dir == null || root.dir == '.' ? '' : ' in ${root.dir}';
+ final suffix = root.isInMemory || root.dir == '.' ? '' : ' in ${root.dir}';
SolveResult result;
try {
result = await log.progress('Resolving dependencies$suffix', () async {
- // We require an SDK constraint lower-bound as of Dart 2.12.0
- _checkSdkConstraintIsDefined(root.pubspec);
+ _checkSdkConstraint(root.pubspec);
return resolveVersions(
type,
cache,
root,
lockFile: lockFile,
- unlock: unlock,
+ unlock: unlock ?? [],
);
});
} catch (e) {
if (onlyReportSuccessOrFailure && (e is ApplicationException)) {
- final directoryOption = root.dir == null || root.dir == '.'
+ final directoryOption = root.isInMemory || root.dir == '.'
? ''
: ' --directory ${root.dir}';
throw ApplicationException(
@@ -276,7 +291,7 @@
}
// Log once about all overridden packages.
- if (warnAboutPreReleaseSdkOverrides && result.pubspecs != null) {
+ if (warnAboutPreReleaseSdkOverrides) {
var overriddenPackages = (result.pubspecs.values
.where((pubspec) => pubspec.dartSdkWasOverridden)
.map((pubspec) => pubspec.name)
@@ -297,7 +312,7 @@
await result.showReport(type, cache);
}
if (!dryRun) {
- await Future.wait(result.packages.map(_get));
+ await result.downloadCachedPackages(cache);
_saveLockFile(result);
}
if (onlyReportSuccessOrFailure) {
@@ -307,15 +322,19 @@
}
if (!dryRun) {
+ if (analytics != null) {
+ result.sendAnalytics(analytics);
+ }
+
/// Build a package graph from the version solver results so we don't
/// have to reload and reparse all the pubspecs.
_packageGraph = PackageGraph.fromSolveResult(this, result);
- await writePackagesFiles();
+ await writePackagesFiles(generateDotPackages: generateDotPackages);
try {
if (precompile) {
- await precompileExecutables(changed: result.changedPackages);
+ await precompileExecutables();
} else {
_deleteExecutableSnapshots(changed: result.changedPackages);
}
@@ -345,7 +364,7 @@
}
}
final r = root.immediateDependencies.keys.expand((packageName) {
- final package = packageGraph.packages[packageName];
+ final package = packageGraph.packages[packageName]!;
return package.executablePaths
.map((path) => Executable(packageName, path));
}).toList();
@@ -353,7 +372,7 @@
}
/// Precompiles all [_builtExecutables].
- Future<void> precompileExecutables({Iterable<String> changed}) async {
+ Future<void> precompileExecutables() async {
migrateCache();
final executables = _builtExecutables;
@@ -378,7 +397,7 @@
/// Precompiles executable .dart file at [path] to a snapshot.
Future<void> precompileExecutable(Executable executable) async {
- return await log.progress('Building package executable', () async {
+ await log.progress('Building package executable', () async {
ensureDir(p.dirname(pathOfExecutable(executable)));
return waitAndPrintErrors([_precompileExecutable(executable)]);
});
@@ -386,10 +405,11 @@
Future<void> _precompileExecutable(Executable executable) async {
final package = executable.package;
+
await dart.precompile(
executablePath: resolveExecutable(executable),
outputPath: pathOfExecutable(executable),
- incrementalDillOutputPath: incrementalDillPathOfExecutable(executable),
+ incrementalDillPath: incrementalDillPathOfExecutable(executable),
packageConfigPath: packageConfigFile,
name:
'$package:${p.basenameWithoutExtension(executable.relativePath)}');
@@ -424,7 +444,7 @@
/// The absolute path of [executable] resolved relative to [this].
String resolveExecutable(Executable executable) {
return p.join(
- packageGraph.packages[executable.package].dir,
+ packageGraph.packages[executable.package]!.dir,
executable.relativePath,
);
}
@@ -433,7 +453,7 @@
///
/// If [changed] is passed, only dependencies whose contents might be changed
/// if one of the given packages changes will have their executables deleted.
- void _deleteExecutableSnapshots({Iterable<String> changed}) {
+ void _deleteExecutableSnapshots({Iterable<String>? changed}) {
if (!dirExists(_snapshotPath)) return;
// If we don't know what changed, we can't safely re-use any snapshots.
@@ -441,7 +461,8 @@
deleteEntry(_snapshotPath);
return;
}
- changed = changed.toSet();
+ var changedDeps = changed;
+ changedDeps = changedDeps.toSet();
// If the existing executable was compiled with a different SDK, we need to
// recompile regardless of what changed.
@@ -462,27 +483,12 @@
packageGraph.isPackageMutable(package) ||
packageGraph
.transitiveDependencies(package)
- .any((dep) => changed.contains(dep.name))) {
+ .any((dep) => changedDeps.contains(dep.name))) {
deleteEntry(entry);
}
}
}
- /// Makes sure the package at [id] is locally available.
- ///
- /// This automatically downloads the package to the system-wide cache as well
- /// if it requires network access to retrieve (specifically, if the package's
- /// source is a [CachedSource]).
- Future<void> _get(PackageId id) async {
- return await http.withDependencyType(root.dependencyType(id.name),
- () async {
- if (id.isRoot) return;
-
- var source = cache.source(id.source);
- if (source is CachedSource) await source.downloadToSystemCache(id);
- });
- }
-
/// Throws a [DataError] if the `.dart_tool/package_config.json` file doesn't
/// exist or if it's out-of-date relative to the lockfile or the pubspec.
///
@@ -555,8 +561,8 @@
}
for (var match in _sdkConstraint.allMatches(lockFileText)) {
- var identifier = match[1] == 'sdk' ? 'dart' : match[1].trim();
- var sdk = sdks[identifier];
+ var identifier = match[1] == 'sdk' ? 'dart' : match[1]!.trim();
+ var sdk = sdks[identifier]!;
// Don't complain if there's an SDK constraint for an unavailable SDK. For
// example, the Flutter SDK being unavailable just means that we aren't
@@ -564,8 +570,8 @@
// able to `pub run` non-Flutter tools even in a Flutter app.
if (!sdk.isAvailable) continue;
- var parsedConstraint = VersionConstraint.parse(match[2]);
- if (!parsedConstraint.allows(sdk.version)) {
+ var parsedConstraint = VersionConstraint.parse(match[2]!);
+ if (!parsedConstraint.allows(sdk.version!)) {
dataError('${sdk.name} ${sdk.version} is incompatible with your '
"dependencies' SDK constraints. Please run \"$topLevelProgram pub get\" again.");
}
@@ -709,7 +715,7 @@
final packagePathsMapping = <String, String>{};
for (final package in packages.keys) {
- final packageUri = packages[package];
+ final packageUri = packages[package]!;
// Pub only generates "file:" and relative URIs.
if (packageUri.scheme != 'file' && packageUri.scheme.isNotEmpty) {
@@ -747,7 +753,7 @@
'"pub" version, please run "$topLevelProgram pub get".');
}
- String packageConfigRaw;
+ late String packageConfigRaw;
try {
packageConfigRaw = readTextFile(packageConfigFile);
} on FileException {
@@ -755,7 +761,7 @@
'The "$packageConfigFile" file does not exist, please run "$topLevelProgram pub get".');
}
- PackageConfig cfg;
+ late PackageConfig cfg;
try {
cfg = PackageConfig.fromJson(json.decode(packageConfigRaw));
} on FormatException {
@@ -844,7 +850,7 @@
final windowsLineEndings = fileExists(lockFilePath) &&
detectWindowsLineEndings(readTextFile(lockFilePath));
- final serialized = _lockFile.serialize(root.dir);
+ final serialized = lockFile.serialize(root.dir);
writeTextFile(lockFilePath,
windowsLineEndings ? serialized.replaceAll('\n', '\r\n') : serialized);
}
@@ -855,7 +861,7 @@
// Cached packages don't have these.
if (isCached) return;
- var oldPath = p.join(_configRoot, '.pub');
+ var oldPath = p.join(_configRoot!, '.pub');
if (!dirExists(oldPath)) return;
var newPath = root.path('.dart_tool/pub');
@@ -870,10 +876,11 @@
}
/// We require an SDK constraint lower-bound as of Dart 2.12.0
- void _checkSdkConstraintIsDefined(Pubspec pubspec) {
+ ///
+ /// We don't allow unknown sdks.
+ void _checkSdkConstraint(Pubspec pubspec) {
final dartSdkConstraint = pubspec.sdkConstraints['dart'];
- if (dartSdkConstraint is! VersionRange ||
- (dartSdkConstraint is VersionRange && dartSdkConstraint.min == null)) {
+ if (dartSdkConstraint is! VersionRange || dartSdkConstraint.min == null) {
// Suggest version range '>=2.10.0 <3.0.0', we avoid using:
// [CompatibleWithVersionRange] because some pub versions don't support
// caret syntax (e.g. '^2.10.0')
@@ -901,6 +908,24 @@
See https://dart.dev/go/sdk-constraint
''');
}
+ for (final sdk in pubspec.sdkConstraints.keys) {
+ if (!sdks.containsKey(sdk)) {
+ final environment = pubspec.fields.nodes['environment'] as YamlMap;
+ final keyNode = environment.nodes.entries
+ .firstWhere((e) => (e.key as YamlNode).value == sdk)
+ .key as YamlNode;
+ throw PubspecException('''
+$pubspecPath refers to an unknown sdk '$sdk'.
+
+Did you mean to add it as a dependency?
+
+Either remove the constraint, or upgrade to a version of pub that supports the
+given sdk.
+
+See https://dart.dev/go/sdk-constraint
+''', keyNode.span);
+ }
+ }
}
}
diff --git a/lib/src/exceptions.dart b/lib/src/exceptions.dart
index 82a5dac..fcde747 100644
--- a/lib/src/exceptions.dart
+++ b/lib/src/exceptions.dart
@@ -11,7 +11,6 @@
import 'package:yaml/yaml.dart';
import 'dart.dart';
-import 'sdk.dart';
/// An exception class for exceptions that are intended to be seen by the user.
///
@@ -89,18 +88,20 @@
/// that other code in pub can use this to show a more detailed explanation of
/// why the package was being requested.
class PackageNotFoundException extends WrappedException {
- /// If this failure was caused by an SDK being unavailable, this is that SDK.
- final Sdk? missingSdk;
+ /// A hint indicating an action the user could take to resolve this problem.
+ ///
+ /// This will be printed after the package resolution conflict.
+ final String? hint;
PackageNotFoundException(
String message, {
Object? innerError,
StackTrace? innerTrace,
- this.missingSdk,
+ this.hint,
}) : super(message, innerError, innerTrace);
@override
- String toString() => "Package doesn't exist ($message).";
+ String toString() => 'Package not available ($message).';
}
/// Returns whether [error] is a user-facing error object.
diff --git a/lib/src/executable.dart b/lib/src/executable.dart
index 08722e5..3f8f6a9 100644
--- a/lib/src/executable.dart
+++ b/lib/src/executable.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:io';
import 'dart:isolate';
@@ -19,12 +17,12 @@
import 'isolate.dart' as isolate;
import 'log.dart' as log;
import 'log.dart';
+import 'pub_embeddable_command.dart';
import 'solver/type.dart';
import 'system_cache.dart';
import 'utils.dart';
-/// Code shared between `run` `global run` and `run --dartdev` for extracting
-/// vm arguments from arguments.
+/// Extracting vm arguments from arguments.
List<String> vmArgsFromArgResults(ArgResults argResults) {
final experiments = argResults['enable-experiment'] as List;
return [
@@ -50,11 +48,11 @@
///
/// Returns the exit code of the spawned app.
Future<int> runExecutable(
- Entrypoint entrypoint, Executable executable, Iterable<String> args,
+ Entrypoint entrypoint, Executable executable, List<String> args,
{bool enableAsserts = false,
- Future<void> Function(Executable) recompile,
+ required Future<void> Function(Executable) recompile,
List<String> vmArgs = const [],
- @required bool alwaysUseSubprocess}) async {
+ required bool alwaysUseSubprocess}) async {
final package = executable.package;
// Make sure the package is an immediate dependency of the entrypoint or the
@@ -103,18 +101,7 @@
await recompile(executable);
}
executablePath = snapshotPath;
- } else {
- if (executablePath == null) {
- var message =
- 'Could not find ${log.bold(p.normalize(executable.relativePath))}';
- if (entrypoint.isGlobal || package != entrypoint.root.name) {
- message += ' in package ${log.bold(package)}';
- }
- log.error('$message.');
- return exit_codes.NO_INPUT;
- }
}
-
// We use an absolute path here not because the VM insists but because it's
// helpful for the subprocess to be able to spawn Dart with
// Platform.executableArguments and have that work regardless of the working
@@ -124,7 +111,7 @@
try {
return await _runDartProgram(
executablePath,
- args,
+ args.toList(),
packageConfigAbsolute,
enableAsserts: enableAsserts,
vmArgs: vmArgs,
@@ -140,7 +127,7 @@
await recompile(executable);
return await _runDartProgram(
executablePath,
- args,
+ args.toList(),
packageConfigAbsolute,
enableAsserts: enableAsserts,
vmArgs: vmArgs,
@@ -165,9 +152,9 @@
/// a new process will always be started.
Future<int> _runDartProgram(
String path, List<String> args, String packageConfig,
- {bool enableAsserts,
- List<String> vmArgs,
- @required bool alwaysUseSubprocess}) async {
+ {bool enableAsserts = false,
+ List<String> vmArgs = const <String>[],
+ required bool alwaysUseSubprocess}) async {
path = p.absolute(path);
packageConfig = p.absolute(packageConfig);
@@ -175,10 +162,8 @@
// That provides better signal handling, and possibly faster startup.
if ((!alwaysUseSubprocess) && vmArgs.isEmpty) {
var argList = args.toList();
- return await isolate.runUri(p.toUri(path), argList, null,
- enableAsserts: enableAsserts,
- automaticPackageResolution: packageConfig == null,
- packageConfig: p.toUri(packageConfig));
+ return await isolate.runUri(p.toUri(path), argList, '',
+ enableAsserts: enableAsserts, packageConfig: p.toUri(packageConfig));
} else {
// By ignoring sigint, only the child process will get it when
// they are sent to the current process group. That is what happens when
@@ -218,7 +203,23 @@
}
}
-/// Returns the path to dart program/snapshot to invoke for running [descriptor]
+/// The result of a `getExecutableForCommand` command resolution.
+@sealed
+class DartExecutableWithPackageConfig {
+ /// Can be a .dart file or a incremental snapshot.
+ final String executable;
+
+ /// The package_config.json to run [executable] with. Or <null> if the VM
+ /// should find it according to the standard rules.
+ final String? packageConfig;
+
+ DartExecutableWithPackageConfig({
+ required this.executable,
+ required this.packageConfig,
+ });
+}
+
+/// Returns the dart program/snapshot to invoke for running [descriptor]
/// resolved according to the package configuration of the package at [root]
/// (defaulting to the current working directory). Using the pub-cache at
/// [pubCacheDir] (defaulting to the default pub cache).
@@ -236,7 +237,9 @@
/// [CommandResolutionFailedException].
///
/// * Otherwise if the current package resolution is outdated do an implicit
-/// `pub get`, if that fails, throw a [CommandResolutionFailedException].
+/// `pub get`, if that fails, throw a [CommandResolutionFailedException].
+///
+/// This pub get will send analytics events to [analytics] if provided.
///
/// * Otherwise let `<current>` be the name of the package at [root], and
/// interpret [descriptor] as `[<package>][:<command>]`.
@@ -251,7 +254,7 @@
/// * `` and `:` both resolves to `<current>:bin/<current>.dart` or
/// `bin/<current>:main.dart`.
///
-/// If that doesn't resolve as an existing file throw an exception.
+/// If that doesn't resolve as an existing file, throw an exception.
///
/// ## Snapshotting
///
@@ -264,11 +267,12 @@
///
/// Throws an [CommandResolutionFailedException] if the command is not found or
/// if the entrypoint is not up to date (requires `pub get`) and a `pub get`.
-Future<String> getExecutableForCommand(
+Future<DartExecutableWithPackageConfig> getExecutableForCommand(
String descriptor, {
bool allowSnapshot = true,
- String root,
- String pubCacheDir,
+ String? root,
+ String? pubCacheDir,
+ PubAnalytics? analytics,
}) async {
root ??= p.current;
var asPath = descriptor;
@@ -283,67 +287,128 @@
}
final asDirectFile = p.join(root, asPath);
- if (fileExists(asDirectFile)) return p.relative(asDirectFile, from: root);
- if (!fileExists(p.join(root, 'pubspec.yaml'))) {
- throw CommandResolutionFailedException('Could not find file `$descriptor`');
+ if (fileExists(asDirectFile)) {
+ return DartExecutableWithPackageConfig(
+ executable: p.relative(asDirectFile, from: root),
+ packageConfig: null,
+ );
}
+ if (!fileExists(p.join(root, 'pubspec.yaml'))) {
+ throw CommandResolutionFailedException._(
+ 'Could not find file `$descriptor`',
+ CommandResolutionIssue.fileNotFound);
+ }
+ final entrypoint = Entrypoint(root, SystemCache(rootDir: pubCacheDir));
try {
- final entrypoint = Entrypoint(root, SystemCache(rootDir: pubCacheDir));
+ // TODO(sigurdm): it would be nicer with a 'isUpToDate' function.
+ entrypoint.assertUpToDate();
+ } on DataException {
try {
- // TODO(sigurdm): it would be nicer with a 'isUpToDate' function.
- entrypoint.assertUpToDate();
- } on DataException {
await warningsOnlyUnlessTerminal(
- () => entrypoint.acquireDependencies(SolveType.GET));
+ () => entrypoint.acquireDependencies(
+ SolveType.get,
+ analytics: analytics,
+ generateDotPackages: false,
+ ),
+ );
+ } on ApplicationException catch (e) {
+ throw CommandResolutionFailedException._(
+ e.toString(), CommandResolutionIssue.pubGetFailed);
}
+ }
- String command;
- String package;
- if (descriptor.contains(':')) {
- final parts = descriptor.split(':');
- if (parts.length > 2) {
- throw CommandResolutionFailedException(
- '[<package>[:command]] cannot contain multiple ":"');
- }
- package = parts[0];
- if (package.isEmpty) package = entrypoint.root.name;
- command = parts[1];
- } else {
- package = descriptor;
- if (package.isEmpty) package = entrypoint.root.name;
- command = package;
+ late final String command;
+ String package;
+ if (descriptor.contains(':')) {
+ final parts = descriptor.split(':');
+ if (parts.length > 2) {
+ throw CommandResolutionFailedException._(
+ '[<package>[:command]] cannot contain multiple ":"',
+ CommandResolutionIssue.parseError,
+ );
}
+ package = parts[0];
+ if (package.isEmpty) package = entrypoint.root.name;
+ command = parts[1];
+ } else {
+ package = descriptor;
+ if (package.isEmpty) package = entrypoint.root.name;
+ command = package;
+ }
- final executable = Executable(package, p.join('bin', '$command.dart'));
- if (!entrypoint.packageGraph.packages.containsKey(package)) {
- throw CommandResolutionFailedException(
- 'Could not find package `$package` or file `$descriptor`');
- }
- final path = entrypoint.resolveExecutable(executable);
- if (!fileExists(path)) {
- throw CommandResolutionFailedException(
- 'Could not find `bin${p.separator}$command.dart` in package `$package`.');
- }
- if (!allowSnapshot) {
- return p.relative(path, from: root);
- } else {
- final snapshotPath = entrypoint.pathOfExecutable(executable);
- if (!fileExists(snapshotPath) ||
- entrypoint.packageGraph.isPackageMutable(package)) {
+ if (!entrypoint.packageGraph.packages.containsKey(package)) {
+ throw CommandResolutionFailedException._(
+ 'Could not find package `$package` or file `$descriptor`',
+ CommandResolutionIssue.packageNotFound,
+ );
+ }
+ final executable = Executable(package, p.join('bin', '$command.dart'));
+ final packageConfig = p.join('.dart_tool', 'package_config.json');
+
+ final path = entrypoint.resolveExecutable(executable);
+ if (!fileExists(path)) {
+ throw CommandResolutionFailedException._(
+ 'Could not find `bin${p.separator}$command.dart` in package `$package`.',
+ CommandResolutionIssue.noBinaryFound,
+ );
+ }
+ if (!allowSnapshot) {
+ return DartExecutableWithPackageConfig(
+ executable: p.relative(path, from: root),
+ packageConfig: packageConfig,
+ );
+ } else {
+ final snapshotPath = entrypoint.pathOfExecutable(executable);
+ if (!fileExists(snapshotPath) ||
+ entrypoint.packageGraph.isPackageMutable(package)) {
+ try {
await warningsOnlyUnlessTerminal(
() => entrypoint.precompileExecutable(executable),
);
+ } on ApplicationException catch (e) {
+ throw CommandResolutionFailedException._(
+ e.toString(),
+ CommandResolutionIssue.compilationFailed,
+ );
}
- return p.relative(snapshotPath, from: root);
}
- } on ApplicationException catch (e) {
- throw CommandResolutionFailedException(e.toString());
+ return DartExecutableWithPackageConfig(
+ executable: p.relative(snapshotPath, from: root),
+ packageConfig: packageConfig,
+ );
}
}
+/// Information on why no executable is returned.
+enum CommandResolutionIssue {
+ /// The command string looked like a file (contained '.' '/' or '\\'), but no
+ /// such file exists.
+ fileNotFound,
+
+ /// The command-string was '<package>:<binary>' or '<package>', and <package>
+ /// was not in dependencies.
+ packageNotFound,
+
+ /// The command string was '<package>:<binary>' or ':<binary>' and <binary>
+ /// was not found.
+ noBinaryFound,
+
+ /// Failed retrieving dependencies (pub get).
+ pubGetFailed,
+
+ /// Pre-compilation of the binary failed.
+ compilationFailed,
+
+ /// The command string did not have a valid form (eg. more than one ':').
+ parseError,
+}
+
+/// Indicates that a command string did not resolve to an executable.
+@sealed
class CommandResolutionFailedException implements Exception {
final String message;
- CommandResolutionFailedException(this.message);
+ final CommandResolutionIssue issue;
+ CommandResolutionFailedException._(this.message, this.issue);
@override
String toString() {
diff --git a/lib/src/exit_codes.dart b/lib/src/exit_codes.dart
index e072ef2..c6acaf7 100644
--- a/lib/src/exit_codes.dart
+++ b/lib/src/exit_codes.dart
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+// ignore_for_file: constant_identifier_names
+
/// Exit code constants.
///
/// From [the BSD sysexits manpage][manpage]. Not every constant here is used,
diff --git a/lib/src/feature.dart b/lib/src/feature.dart
index ca98bc1..94134ab 100644
--- a/lib/src/feature.dart
+++ b/lib/src/feature.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:collection/collection.dart';
import 'package:pub_semver/pub_semver.dart';
@@ -41,7 +39,7 @@
void enableFeature(Feature feature) {
if (!enabledFeatures.add(feature)) return;
for (var require in feature.requires) {
- enableFeature(features[require]);
+ enableFeature(features[require]!);
}
}
@@ -57,8 +55,8 @@
}
Feature(this.name, Iterable<PackageRange> dependencies,
- {Iterable<String> requires,
- Map<String, VersionConstraint> sdkConstraints,
+ {Iterable<String>? requires,
+ Map<String, VersionConstraint>? sdkConstraints,
this.onByDefault = true})
: dependencies = UnmodifiableListView(dependencies.toList()),
requires = requires == null
diff --git a/lib/src/git.dart b/lib/src/git.dart
index 8c86390..5fa7536 100644
--- a/lib/src/git.dart
+++ b/lib/src/git.dart
@@ -2,11 +2,11 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
/// Helper functionality for invoking Git.
import 'dart:async';
+import 'package:path/path.dart' as p;
+
import 'exceptions.dart';
import 'io.dart';
import 'log.dart' as log;
@@ -47,7 +47,7 @@
/// Returns the stdout as a list of strings if it succeeded. Completes to an
/// exception if it failed.
Future<List<String>> run(List<String> args,
- {String workingDir, Map<String, String> environment}) async {
+ {String? workingDir, Map<String, String>? environment}) async {
if (!isInstalled) {
fail('Cannot find a Git executable.\n'
'Please ensure Git is correctly installed.');
@@ -55,7 +55,7 @@
log.muteProgress();
try {
- var result = await runProcess(command, args,
+ final result = await runProcess(command!, args,
workingDir: workingDir,
environment: {...?environment, 'LANG': 'en_GB'});
if (!result.success) {
@@ -70,13 +70,13 @@
/// Like [run], but synchronous.
List<String> runSync(List<String> args,
- {String workingDir, Map<String, String> environment}) {
+ {String? workingDir, Map<String, String>? environment}) {
if (!isInstalled) {
fail('Cannot find a Git executable.\n'
'Please ensure Git is correctly installed.');
}
- var result = runProcessSync(command, args,
+ final result = runProcessSync(command!, args,
workingDir: workingDir, environment: environment);
if (!result.success) {
throw GitException(args, result.stdout.join('\n'), result.stderr.join('\n'),
@@ -88,7 +88,7 @@
/// Returns the name of the git command-line app, or `null` if Git could not be
/// found on the user's PATH.
-String get command {
+String? get command {
if (_commandCache != null) return _commandCache;
if (_tryGitCommand('git')) {
@@ -103,7 +103,23 @@
return _commandCache;
}
-String _commandCache;
+String? _commandCache;
+
+/// Returns the root of the git repo [dir] belongs to. Returns `null` if not
+/// in a git repo or git is not installed.
+String? repoRoot(String dir) {
+ if (isInstalled) {
+ try {
+ return p.normalize(
+ runSync(['rev-parse', '--show-toplevel'], workingDir: dir).first,
+ );
+ } on GitException {
+ // Not in a git folder.
+ return null;
+ }
+ }
+ return null;
+}
/// Checks whether [command] is the Git command for this computer.
bool _tryGitCommand(String command) {
diff --git a/lib/src/global_packages.dart b/lib/src/global_packages.dart
index 49d681f..07e2513 100644
--- a/lib/src/global_packages.dart
+++ b/lib/src/global_packages.dart
@@ -2,12 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:io';
-import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
@@ -15,14 +12,15 @@
import 'entrypoint.dart';
import 'exceptions.dart';
import 'executable.dart' as exec;
-import 'http.dart' as http;
import 'io.dart';
import 'lock_file.dart';
import 'log.dart' as log;
import 'package.dart';
import 'package_name.dart';
+import 'pub_embeddable_command.dart';
import 'pubspec.dart';
import 'sdk.dart';
+import 'sdk/dart.dart';
import 'solver.dart';
import 'solver/incompatibility_cause.dart';
import 'source/cached.dart';
@@ -63,6 +61,8 @@
/// The directory where the lockfiles for activated packages are stored.
String get _directory => p.join(cache.rootDir, 'global_packages');
+ String _packageDir(String packageName) => p.join(_directory, packageName);
+
/// The directory where binstubs for global package executables are stored.
String get _binStubDir => p.join(cache.rootDir, 'bin');
@@ -85,8 +85,9 @@
/// If [overwriteBinStubs] is `true`, any binstubs that collide with
/// existing binstubs in other packages will be overwritten by this one's.
/// Otherwise, the previous ones will be preserved.
- Future<void> activateGit(String repo, List<String> executables,
- {Map<String, FeatureDependency> features, bool overwriteBinStubs}) async {
+ Future<void> activateGit(String repo, List<String>? executables,
+ {Map<String, FeatureDependency>? features,
+ required bool overwriteBinStubs}) async {
var name = await cache.git.getPackageNameFromRepo(repo);
// TODO(nweiz): Add some special handling for git repos that contain path
@@ -121,10 +122,10 @@
/// [url] is an optional custom pub server URL. If not null, the package to be
/// activated will be fetched from this URL instead of the default pub URL.
Future<void> activateHosted(
- String name, VersionConstraint constraint, List<String> executables,
- {Map<String, FeatureDependency> features,
- bool overwriteBinStubs,
- Uri url}) async {
+ String name, VersionConstraint constraint, List<String>? executables,
+ {Map<String, FeatureDependency>? features,
+ required bool overwriteBinStubs,
+ Uri? url}) async {
await _installInCache(
cache.hosted.source
.refFor(name, url: url)
@@ -143,33 +144,31 @@
/// if [overwriteBinStubs] is `true`, any binstubs that collide with
/// existing binstubs in other packages will be overwritten by this one's.
/// Otherwise, the previous ones will be preserved.
- Future<void> activatePath(String path, List<String> executables,
- {bool overwriteBinStubs}) async {
+ Future<void> activatePath(String path, List<String>? executables,
+ {required bool overwriteBinStubs,
+ required PubAnalytics? analytics}) async {
var entrypoint = Entrypoint(path, cache);
// Get the package's dependencies.
- await entrypoint.acquireDependencies(SolveType.GET);
+ await entrypoint.acquireDependencies(
+ SolveType.get,
+ analytics: analytics,
+ generateDotPackages: false,
+ );
var name = entrypoint.root.name;
-
- try {
- var originalLockFile =
- LockFile.load(_getLockFilePath(name), cache.sources);
- // Call this just to log what the current active package is, if any.
- _describeActive(originalLockFile, name);
- } on IOException {
- // Couldn't read the lock file. It probably doesn't exist.
- }
+ _describeActive(name, cache);
// Write a lockfile that points to the local package.
var fullPath = canonicalize(entrypoint.root.dir);
var id = cache.path.source.idFor(name, entrypoint.root.version, fullPath);
+ final tempDir = cache.createTempDir();
// TODO(rnystrom): Look in "bin" and display list of binaries that
// user can run.
- _writeLockFile(name, LockFile([id]));
+ _writeLockFile(tempDir, LockFile([id]));
- var binDir = p.join(_directory, name, 'bin');
- if (dirExists(binDir)) deleteEntry(binDir);
+ tryDeleteEntry(_packageDir(name));
+ tryRenameDir(tempDir, _packageDir(name));
_updateBinStubs(entrypoint, entrypoint.root, executables,
overwriteBinStubs: overwriteBinStubs);
@@ -177,17 +176,12 @@
}
/// Installs the package [dep] and its dependencies into the system cache.
- Future<void> _installInCache(PackageRange dep, List<String> executables,
- {bool overwriteBinStubs}) async {
- LockFile originalLockFile;
- try {
- originalLockFile =
- LockFile.load(_getLockFilePath(dep.name), cache.sources);
- // Call this just to log what the current active package is, if any.
- _describeActive(originalLockFile, dep.name);
- } on IOException {
- // Couldn't read the lock file. It probably doesn't exist.
- }
+ ///
+ /// If [silent] less logging will be printed.
+ Future<void> _installInCache(PackageRange dep, List<String>? executables,
+ {required bool overwriteBinStubs, bool silent = false}) async {
+ final name = dep.name;
+ LockFile? originalLockFile = _describeActive(name, cache);
// Create a dummy package with just [dep] so we can do resolution on it.
var root = Package.inMemory(Pubspec('pub global activate',
@@ -199,104 +193,90 @@
// being available, report that as a [dataError].
SolveResult result;
try {
- result = await log.progress('Resolving dependencies',
- () => resolveVersions(SolveType.GET, cache, root));
+ result = await log.spinner(
+ 'Resolving dependencies',
+ () => resolveVersions(SolveType.get, cache, root),
+ condition: !silent,
+ );
} on SolveFailure catch (error) {
for (var incompatibility
in error.incompatibility.externalIncompatibilities) {
if (incompatibility.cause != IncompatibilityCause.noVersions) continue;
- if (incompatibility.terms.single.package.name != dep.name) continue;
+ if (incompatibility.terms.single.package.name != name) continue;
dataError(error.toString());
}
rethrow;
}
+ // We want the entrypoint to be rooted at 'dep' not the dummy-package.
+ result.packages.removeWhere((id) => id.name == 'pub global activate');
final sameVersions = originalLockFile != null &&
originalLockFile.samePackageIds(result.lockFile);
+ final PackageId id = result.lockFile.packages[name]!;
if (sameVersions) {
log.message('''
-The package ${dep.name} is already activated at newest available version.
-To recompile executables, first run `global deactivate ${dep.name}`.
+The package $name is already activated at newest available version.
+To recompile executables, first run `$topLevelProgram pub global deactivate $name`.
''');
} else {
- await result.showReport(SolveType.GET, cache);
+ // Only precompile binaries if we have a new resolution.
+ if (!silent) await result.showReport(SolveType.get, cache);
+
+ await result.downloadCachedPackages(cache);
+
+ final lockFile = result.lockFile;
+ final tempDir = cache.createTempDir();
+ _writeLockFile(tempDir, lockFile);
+
+ // Load the package graph from [result] so we don't need to re-parse all
+ // the pubspecs.
+ final entrypoint = Entrypoint.global(
+ tempDir,
+ cache.loadCached(id),
+ lockFile,
+ cache,
+ solveResult: result,
+ );
+
+ await entrypoint.writePackagesFiles();
+
+ await entrypoint.precompileExecutables();
+
+ tryDeleteEntry(_packageDir(name));
+ tryRenameDir(tempDir, _packageDir(name));
}
-
- // Make sure all of the dependencies are locally installed.
- await Future.wait(result.packages.map((id) {
- return http.withDependencyType(root.dependencyType(id.name), () async {
- if (id.isRoot) return;
-
- var source = cache.source(id.source);
- if (source is CachedSource) await source.downloadToSystemCache(id);
- });
- }));
-
- var lockFile = result.lockFile;
- _writeLockFile(dep.name, lockFile);
- await _writePackageConfigFiles(dep.name, lockFile);
-
- // We want the entrypoint to be rooted at 'dep' not the dummy-package.
- result.packages.removeWhere((id) => id.name == 'pub global activate');
-
- var id = lockFile.packages[dep.name];
- // Load the package graph from [result] so we don't need to re-parse all
- // the pubspecs.
final entrypoint = Entrypoint.global(
- Package(
- result.pubspecs[dep.name],
- (cache.source(dep.source) as CachedSource).getDirectoryInCache(id),
- ),
- lockFile,
+ _packageDir(id.name),
+ cache.loadCached(id),
+ result.lockFile,
cache,
solveResult: result,
);
- if (!sameVersions) {
- // Only precompile binaries if we have a new resolution.
- await entrypoint.precompileExecutables();
- }
-
_updateBinStubs(
entrypoint,
- cache.load(entrypoint.lockFile.packages[dep.name]),
+ cache.load(entrypoint.lockFile.packages[dep.name]!),
executables,
overwriteBinStubs: overwriteBinStubs,
);
-
- log.message('Activated ${_formatPackage(id)}.');
- }
-
- Future<void> _writePackageConfigFiles(
- String package, LockFile lockFile) async {
- // TODO(sigurdm): Use [Entrypoint.writePackagesFiles] instead.
- final packagesFilePath = _getPackagesFilePath(package);
- final packageConfigFilePath = _getPackageConfigFilePath(package);
- final dir = p.dirname(packagesFilePath);
- writeTextFile(
- packagesFilePath, lockFile.packagesFile(cache, relativeFrom: dir));
- ensureDir(p.dirname(packageConfigFilePath));
- writeTextFile(packageConfigFilePath,
- await lockFile.packageConfigFile(cache, relativeFrom: dir));
+ if (!silent) log.message('Activated ${_formatPackage(id)}.');
}
/// Finishes activating package [package] by saving [lockFile] in the cache.
- void _writeLockFile(String package, LockFile lockFile) {
- ensureDir(p.join(_directory, package));
-
- // TODO(nweiz): This cleans up Dart 1.6's old lockfile location. Remove it
- // when Dart 1.6 is old enough that we don't think anyone will have these
- // lockfiles anymore (issue 20703).
- var oldPath = p.join(_directory, '$package.lock');
- if (fileExists(oldPath)) deleteEntry(oldPath);
-
- writeTextFile(_getLockFilePath(package),
- lockFile.serialize(p.join(_directory, package)));
+ void _writeLockFile(String dir, LockFile lockFile) {
+ writeTextFile(p.join(dir, 'pubspec.lock'), lockFile.serialize(null));
}
/// Shows the user the currently active package with [name], if any.
- void _describeActive(LockFile lockFile, String name) {
- var id = lockFile.packages[name];
+ LockFile? _describeActive(String name, SystemCache cache) {
+ late final LockFile lockFile;
+ try {
+ lockFile = LockFile.load(_getLockFilePath(name), cache.sources);
+ } on IOException {
+ // Couldn't read the lock file. It probably doesn't exist.
+ return null;
+ }
+ var id = lockFile.packages[name]!;
var source = id.source;
if (source is GitSource) {
@@ -311,6 +291,7 @@
log.message('Package ${log.bold(name)} is currently active at version '
'${log.bold(id.version)}.');
}
+ return lockFile;
}
/// Deactivates a previously-activated package named [name].
@@ -323,7 +304,7 @@
_deleteBinStubs(name);
var lockFile = LockFile.load(_getLockFilePath(name), cache.sources);
- var id = lockFile.packages[name];
+ var id = lockFile.packages[name]!;
log.message('Deactivated package ${_formatPackage(id)}.');
deleteEntry(dir);
@@ -336,32 +317,18 @@
/// Returns an [Entrypoint] loaded with the active package if found.
Future<Entrypoint> find(String name) async {
var lockFilePath = _getLockFilePath(name);
- LockFile lockFile;
+ late LockFile lockFile;
try {
lockFile = LockFile.load(lockFilePath, cache.sources);
} on IOException {
- var oldLockFilePath = p.join(_directory, '$name.lock');
- try {
- // TODO(nweiz): This looks for Dart 1.6's old lockfile location.
- // Remove it when Dart 1.6 is old enough that we don't think anyone
- // will have these lockfiles anymore (issue 20703).
- lockFile = LockFile.load(oldLockFilePath, cache.sources);
- } on IOException {
- // If we couldn't read the lock file, it's not activated.
- dataError('No active package ${log.bold(name)}.');
- }
-
- // Move the old lockfile to its new location.
- ensureDir(p.dirname(lockFilePath));
- File(oldLockFilePath).renameSync(lockFilePath);
- // Just make sure these files are created as well.
- await _writePackageConfigFiles(name, lockFile);
+ // If we couldn't read the lock file, it's not activated.
+ dataError('No active package ${log.bold(name)}.');
}
// Remove the package itself from the lockfile. We put it in there so we
// could find and load the [Package] object, but normally an entrypoint
// doesn't expect to be in its own lockfile.
- var id = lockFile.packages[name];
+ var id = lockFile.packages[name]!;
lockFile = lockFile.removePackage(name);
var source = cache.source(id.source);
@@ -369,7 +336,8 @@
if (source is CachedSource) {
// For cached sources, the package itself is in the cache and the
// lockfile is the one we just loaded.
- entrypoint = Entrypoint.global(cache.loadCached(id), lockFile, cache);
+ entrypoint = Entrypoint.global(
+ _packageDir(id.name), cache.loadCached(id), lockFile, cache);
} else {
// For uncached sources (i.e. path), the ID just points to the real
// directory for the package.
@@ -383,7 +351,7 @@
dataError('${log.bold(name)} ${entrypoint.root.version} requires '
'unknown SDK "$name".');
} else if (sdkName == 'dart') {
- if (constraint.allows(sdk.version)) return;
+ if (constraint.allows((sdk as DartSdk).version)) return;
dataError("${log.bold(name)} ${entrypoint.root.version} doesn't "
'support Dart ${sdk.version}.');
} else {
@@ -399,7 +367,7 @@
dataError('${log.bold(name)} as globally activated requires '
'unknown SDK "$name".');
} else if (sdkName == 'dart') {
- if (constraint.allows(sdk.version)) return;
+ if (constraint.allows((sdk as DartSdk).version)) return;
dataError("${log.bold(name)} as globally activated doesn't "
'support Dart ${sdk.version}, try: $topLevelProgram pub global activate $name');
} else {
@@ -421,11 +389,11 @@
///
/// Returns the exit code from the executable.
Future<int> runExecutable(
- Entrypoint entrypoint, exec.Executable executable, Iterable<String> args,
+ Entrypoint entrypoint, exec.Executable executable, List<String> args,
{bool enableAsserts = false,
- Future<void> Function(exec.Executable) recompile,
+ required Future<void> Function(exec.Executable) recompile,
List<String> vmArgs = const [],
- @required bool alwaysUseSubprocess}) async {
+ required bool alwaysUseSubprocess}) async {
return await exec.runExecutable(
entrypoint,
executable,
@@ -445,16 +413,6 @@
String _getLockFilePath(String name) =>
p.join(_directory, name, 'pubspec.lock');
- /// Gets the path to the .packages file for an activated cached package with
- /// [name].
- String _getPackagesFilePath(String name) =>
- p.join(_directory, name, '.packages');
-
- /// Gets the path to the `package_config.json` file for an
- /// activated cached package with [name].
- String _getPackageConfigFilePath(String name) =>
- p.join(_directory, name, '.dart_tool', 'package_config.json');
-
/// Shows the user a formatted list of globally activated packages.
void listActivePackages() {
if (!dirExists(_directory)) return;
@@ -535,23 +493,30 @@
var failures = <String>[];
if (dirExists(_directory)) {
for (var entry in listDir(_directory)) {
- PackageId id;
+ PackageId? id;
try {
id = _loadPackageId(entry);
log.message('Reactivating ${log.bold(id.name)} ${id.version}...');
var entrypoint = await find(id.name);
+ final packageExecutables = executables.remove(id.name) ?? [];
- await _writePackageConfigFiles(id.name, entrypoint.lockFile);
- await entrypoint.precompileExecutables();
- var packageExecutables = executables.remove(id.name) ?? [];
- _updateBinStubs(
- entrypoint,
- cache.load(id),
- packageExecutables,
- overwriteBinStubs: true,
- suggestIfNotOnPath: false,
- );
+ if (entrypoint.isCached) {
+ deleteEntry(entrypoint.globalDir!);
+ await _installInCache(
+ id.toRange(),
+ packageExecutables,
+ overwriteBinStubs: true,
+ silent: true,
+ );
+ } else {
+ await activatePath(
+ entrypoint.root.dir,
+ packageExecutables,
+ overwriteBinStubs: true,
+ analytics: null,
+ );
+ }
successes.add(id.name);
} catch (error, stackTrace) {
var message = 'Failed to reactivate '
@@ -631,8 +596,8 @@
/// If [suggestIfNotOnPath] is `true` (the default), this will warn the user if
/// the bin directory isn't on their path.
void _updateBinStubs(
- Entrypoint entrypoint, Package package, List<String> executables,
- {bool overwriteBinStubs, bool suggestIfNotOnPath = true}) {
+ Entrypoint entrypoint, Package package, List<String>? executables,
+ {required bool overwriteBinStubs, bool suggestIfNotOnPath = true}) {
// Remove any previously activated binstubs for this package, in case the
// list of executables has changed.
_deleteBinStubs(package.name);
@@ -650,7 +615,7 @@
for (var executable in allExecutables) {
if (executables != null && !executables.contains(executable)) continue;
- var script = package.pubspec.executables[executable];
+ var script = package.pubspec.executables[executable]!;
var previousPackage = _createBinStub(
package,
@@ -705,10 +670,7 @@
// Show errors for any missing scripts.
// TODO(rnystrom): This can print false positives since a script may be
// produced by a transformer. Do something better.
- var binFiles = package
- .listFiles(beneath: 'bin', recursive: false)
- .map(package.relative)
- .toList();
+ var binFiles = package.executablePaths;
for (var executable in installed) {
var script = package.pubspec.executables[executable];
var scriptPath = p.join('bin', '$script.dart');
@@ -734,19 +696,19 @@
///
/// If a collision occurs, returns the name of the package that owns the
/// existing binstub. Otherwise returns `null`.
- String _createBinStub(
+ String? _createBinStub(
Package package,
String executable,
String script, {
- @required bool overwrite,
- @required String snapshot,
+ required bool overwrite,
+ required String snapshot,
}) {
var binStubPath = p.join(_binStubDir, executable);
if (Platform.isWindows) binStubPath += '.bat';
// See if the binstub already exists. If so, it's for another package
// since we already deleted all of this package's binstubs.
- String previousPackage;
+ String? previousPackage;
if (fileExists(binStubPath)) {
var contents = readTextFile(binStubPath);
previousPackage = _binStubProperty(contents, 'Package');
@@ -760,8 +722,9 @@
// If the script was built to a snapshot, just try to invoke that
// directly and skip pub global run entirely.
String invocation;
+ late String binstub;
if (Platform.isWindows) {
- if (snapshot != null && fileExists(snapshot)) {
+ if (fileExists(snapshot)) {
// We expect absolute paths from the precompiler since relative ones
// won't be relative to the right directory when the user runs this.
assert(p.isAbsolute(snapshot));
@@ -785,7 +748,7 @@
} else {
invocation = 'dart pub global run ${package.name}:$script %*';
}
- var batch = '''
+ binstub = '''
@echo off
rem This file was created by pub v${sdk.version}.
rem Package: ${package.name}
@@ -794,9 +757,8 @@
rem Script: $script
$invocation
''';
- writeTextFile(binStubPath, batch);
} else {
- if (snapshot != null && fileExists(snapshot)) {
+ if (fileExists(snapshot)) {
// We expect absolute paths from the precompiler since relative ones
// won't be relative to the right directory when the user runs this.
assert(p.isAbsolute(snapshot));
@@ -817,7 +779,7 @@
} else {
invocation = 'dart pub global run ${package.name}:$script "\$@"';
}
- var bash = '''
+ binstub = '''
#!/usr/bin/env sh
# This file was created by pub v${sdk.version}.
# Package: ${package.name}
@@ -826,25 +788,31 @@
# Script: $script
$invocation
''';
+ }
- // Write this as the system encoding since the system is going to execute
- // it and it might contain non-ASCII characters in the pathnames.
- writeTextFile(binStubPath, bash, encoding: const SystemEncoding());
+ // Write the binstub to a temporary location, make it executable and move
+ // it into place afterwards to avoid races.
+ final tempDir = cache.createTempDir();
+ try {
+ final tmpPath = p.join(tempDir, binStubPath);
- // Make it executable.
- var result = Process.runSync('chmod', ['+x', binStubPath]);
- if (result.exitCode != 0) {
- // Couldn't make it executable so don't leave it laying around.
- try {
- deleteEntry(binStubPath);
- } on IOException catch (err) {
- // Do nothing. We're going to fail below anyway.
- log.fine('Could not delete binstub:\n$err');
+ // Write this as the system encoding since the system is going to
+ // execute it and it might contain non-ASCII characters in the
+ // pathnames.
+ writeTextFile(tmpPath, binstub, encoding: const SystemEncoding());
+
+ if (Platform.isLinux || Platform.isMacOS) {
+ // Make it executable.
+ var result = Process.runSync('chmod', ['+x', tmpPath]);
+ if (result.exitCode != 0) {
+ // Couldn't make it executable so don't leave it laying around.
+ fail('Could not make "$tmpPath" executable (exit code '
+ '${result.exitCode}):\n${result.stderr}');
}
-
- fail('Could not make "$binStubPath" executable (exit code '
- '${result.exitCode}):\n${result.stderr}');
}
+ File(tmpPath).renameSync(binStubPath);
+ } finally {
+ deleteEntry(tempDir);
}
return previousPackage;
@@ -896,7 +864,7 @@
if (result.exitCode == 0) return;
var binDir = _binStubDir;
- if (binDir.startsWith(Platform.environment['HOME'])) {
+ if (binDir.startsWith(Platform.environment['HOME']!)) {
binDir = p.join(
r'$HOME', p.relative(binDir, from: Platform.environment['HOME']));
}
@@ -913,7 +881,7 @@
/// Returns the value of the property named [name] in the bin stub script
/// [source].
- String _binStubProperty(String source, String name) {
+ String? _binStubProperty(String source, String name) {
var pattern = RegExp(RegExp.escape(name) + r': ([a-zA-Z0-9_-]+)');
var match = pattern.firstMatch(source);
return match == null ? null : match[1];
diff --git a/lib/src/http.dart b/lib/src/http.dart
index 541931f..724962b 100644
--- a/lib/src/http.dart
+++ b/lib/src/http.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
/// Helpers for dealing with HTTP.
import 'dart:async';
import 'dart:convert';
@@ -12,7 +10,6 @@
import 'package:http/http.dart' as http;
import 'package:http/retry.dart';
-import 'package:pedantic/pedantic.dart';
import 'package:pool/pool.dart';
import 'package:stack_trace/stack_trace.dart';
@@ -44,7 +41,7 @@
http.Client _inner;
- _PubHttpClient([http.Client inner]) : _inner = inner ?? http.Client();
+ _PubHttpClient([http.Client? inner]) : _inner = inner ?? http.Client();
@override
Future<http.StreamedResponse> send(http.BaseRequest request) async {
@@ -132,8 +129,8 @@
// careful not to log OAuth2 private data, though.
var responseLog = StringBuffer();
- var request = response.request;
- var stopwatch = _requestStopwatches.remove(request)..stop();
+ var request = response.request!;
+ var stopwatch = _requestStopwatches.remove(request)!..stop();
responseLog.writeln('HTTP response ${response.statusCode} '
'${response.reasonPhrase} for ${request.method} ${request.url}');
responseLog.writeln('took ${stopwatch.elapsed}');
@@ -173,12 +170,12 @@
@override
Future<http.StreamedResponse> send(http.BaseRequest request) async {
- http.StreamedResponse streamedResponse;
+ late http.StreamedResponse streamedResponse;
try {
streamedResponse = await _inner.send(request);
} on SocketException catch (error, stackTraceOrNull) {
// Work around issue 23008.
- var stackTrace = stackTraceOrNull ?? Chain.current();
+ var stackTrace = stackTraceOrNull;
if (error.osError == null) rethrow;
@@ -191,14 +188,14 @@
// with a retry. Failing to retry intermittent issues is likely to cause
// customers to wrap pub in a retry loop which will not improve the
// end-user experience.
- if (error.osError.errorCode == 8 ||
- error.osError.errorCode == -2 ||
- error.osError.errorCode == -5 ||
- error.osError.errorCode == 11001 ||
- error.osError.errorCode == 11004) {
+ if (error.osError!.errorCode == 8 ||
+ error.osError!.errorCode == -2 ||
+ error.osError!.errorCode == -5 ||
+ error.osError!.errorCode == 11001 ||
+ error.osError!.errorCode == 11004) {
fail('Could not resolve URL "${request.url.origin}".', error,
stackTrace);
- } else if (error.osError.errorCode == -12276) {
+ } else if (error.osError!.errorCode == -12276) {
fail(
'Unable to validate SSL certificate for '
'"${request.url.origin}".',
@@ -213,7 +210,7 @@
// 401 responses should be handled by the OAuth2 client. It's very
// unlikely that they'll be returned by non-OAuth2 requests. We also want
// to pass along 400 responses from the token endpoint.
- var tokenRequest = streamedResponse.request.url == oauth2.tokenEndpoint;
+ var tokenRequest = streamedResponse.request!.url == oauth2.tokenEndpoint;
if (status < 400 || status == 401 || (status == 400 && tokenRequest)) {
return streamedResponse;
}
@@ -342,7 +339,7 @@
}
/// Throws an error describing an invalid response from the server.
-void invalidServerResponse(http.Response response) =>
+Never invalidServerResponse(http.Response response) =>
fail(log.red('Invalid server response:\n${response.body}'));
/// Exception thrown when an HTTP operation fails.
diff --git a/lib/src/ignore.dart b/lib/src/ignore.dart
index ade58d0..ff22dff 100644
--- a/lib/src/ignore.dart
+++ b/lib/src/ignore.dart
@@ -94,7 +94,7 @@
/// [1]: https://git-scm.com/docs/gitignore
/// [2]: https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreignoreCase
Ignore(
- Iterable<String> patterns, {
+ List<String> patterns, {
bool ignoreCase = false,
void Function(String pattern, FormatException exception)? onInvalidPattern,
}) : _rules = _parseIgnorePatterns(
@@ -464,6 +464,9 @@
} else {
expr += '.*';
}
+ } else if (peekChar() == '/' || peekChar() == null) {
+ // /a/* should not match '/a/'
+ expr += '[^/]+';
} else {
// Handle a single '*'
expr += '[^/]*';
@@ -520,7 +523,6 @@
expr = '$expr/\$';
} else {
expr = '$expr/?\$';
- // expr = '$expr\$';
}
try {
return _IgnoreParseResult(
diff --git a/lib/src/io.dart b/lib/src/io.dart
index 9622eaa..280dcbd 100644
--- a/lib/src/io.dart
+++ b/lib/src/io.dart
@@ -8,11 +8,12 @@
import 'dart:convert';
import 'dart:io';
+import 'package:cli_util/cli_util.dart'
+ show EnvironmentNotFoundException, applicationConfigHome;
import 'package:http/http.dart' show ByteStream;
import 'package:http_multi_server/http_multi_server.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
-import 'package:pedantic/pedantic.dart';
import 'package:pool/pool.dart';
import 'package:stack_trace/stack_trace.dart';
@@ -158,7 +159,9 @@
String readTextFile(String file) => File(file).readAsStringSync();
/// Reads the contents of the text file [file].
-Future<String> readTextFileAsync(String file) => File(file).readAsString();
+Future<String> readTextFileAsync(String file) {
+ return _descriptorPool.withResource(() => File(file).readAsString());
+}
/// Reads the contents of the binary file [file].
List<int> readBinaryFile(String file) {
@@ -358,52 +361,54 @@
/// when we try to delete or move something while it's being scanned. To
/// mitigate that, on Windows, this will retry the operation a few times if it
/// fails.
-void _attempt(String description, void Function() operation) {
+///
+/// For some operations it makes sense to handle ERROR_DIR_NOT_EMPTY
+/// differently. They can pass [ignoreEmptyDir] = `true`.
+void _attempt(String description, void Function() operation,
+ {bool ignoreEmptyDir = false}) {
if (!Platform.isWindows) {
operation();
return;
}
String? getErrorReason(FileSystemException error) {
+ // ERROR_ACCESS_DENIED
if (error.osError?.errorCode == 5) {
return 'access was denied';
}
+ // ERROR_SHARING_VIOLATION
if (error.osError?.errorCode == 32) {
return 'it was in use by another process';
}
- if (error.osError?.errorCode == 145) {
+ // ERROR_DIR_NOT_EMPTY
+ if (!ignoreEmptyDir && _isDirectoryNotEmptyException(error)) {
return 'of dart-lang/sdk#25353';
}
return null;
}
- for (var i = 0; i < 2; i++) {
+ for (var i = 0; i < 3; i++) {
try {
operation();
- return;
+ break;
} on FileSystemException catch (error) {
var reason = getErrorReason(error);
if (reason == null) rethrow;
- log.io('Pub failed to $description because $reason. '
- 'Retrying in 50ms.');
- sleep(Duration(milliseconds: 50));
+ if (i < 2) {
+ log.io('Pub failed to $description because $reason. '
+ 'Retrying in 50ms.');
+ sleep(Duration(milliseconds: 50));
+ } else {
+ fail('Pub failed to $description because $reason.\n'
+ 'This may be caused by a virus scanner or having a file\n'
+ 'in the directory open in another application.');
+ }
}
}
-
- try {
- operation();
- } on FileSystemException catch (error) {
- var reason = getErrorReason(error);
- if (reason == null) rethrow;
-
- fail('Pub failed to $description because $reason.\n'
- 'This may be caused by a virus scanner or having a file\n'
- 'in the directory open in another application.');
- }
}
/// Deletes whatever's at [path], whether it's a file, directory, or symlink.
@@ -448,14 +453,53 @@
void renameDir(String from, String to) {
_attempt('rename directory', () {
log.io('Renaming directory $from to $to.');
- try {
- Directory(from).renameSync(to);
- } on IOException {
- // Ensure that [to] isn't left in an inconsistent state. See issue 12436.
- if (entryExists(to)) deleteEntry(to);
+ Directory(from).renameSync(to);
+ }, ignoreEmptyDir: true);
+}
+
+/// Renames directory [from] to [to].
+/// If it fails with "destination not empty" we log and continue, assuming
+/// another process got there before us.
+void tryRenameDir(String from, String to) {
+ ensureDir(path.dirname(to));
+ try {
+ renameDir(from, to);
+ } on FileSystemException catch (e) {
+ tryDeleteEntry(from);
+ if (!_isDirectoryNotEmptyException(e)) {
rethrow;
}
- });
+ log.fine('''
+Destination directory $to already existed.
+Assuming a concurrent pub invocation installed it.''');
+ }
+}
+
+void copyFile(String from, String to) {
+ log.io('Copying "$from" to "$to".');
+ File(from).copySync(to);
+}
+
+void renameFile(String from, String to) {
+ log.io('Renaming "$from" to "$to".');
+ File(from).renameSync(to);
+}
+
+bool _isDirectoryNotEmptyException(FileSystemException e) {
+ final errorCode = e.osError?.errorCode;
+ return
+ // On Linux rename will fail with ENOTEMPTY if directory exists:
+ // https://man7.org/linux/man-pages/man2/rename.2.html
+ // #define ENOTEMPTY 39 /* Directory not empty */
+ // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/errno.h#n20
+ (Platform.isLinux && errorCode == 39) ||
+ // On Windows this may fail with ERROR_DIR_NOT_EMPTY
+ // https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
+ (Platform.isWindows && errorCode == 145) ||
+ // On MacOS rename will fail with ENOTEMPTY if directory exists.
+ // #define ENOTEMPTY 66 /* Directory not empty */
+ // https://github.com/apple-oss-distributions/xnu/blob/bb611c8fecc755a0d8e56e2fa51513527c5b7a0e/bsd/sys/errno.h#L190
+ (Platform.isMacOS && errorCode == 66);
}
/// Creates a new symlink at path [symlink] that points to [target].
@@ -557,10 +601,6 @@
return path.fromUri(url);
})();
-/// A line-by-line stream of standard input.
-final Stream<String> _stdinLines =
- ByteStream(stdin).toStringStream().transform(const LineSplitter());
-
/// Displays a message and reads a yes/no confirmation from the user.
///
/// Returns a [Future] that completes to `true` if the user confirms or `false`
@@ -576,7 +616,7 @@
}
/// Writes [prompt] and reads a line from stdin.
-Future<String> stdinPrompt(String prompt, {bool? echoMode}) {
+Future<String> stdinPrompt(String prompt, {bool? echoMode}) async {
if (runningFromTest) {
log.message(prompt);
} else {
@@ -584,12 +624,16 @@
}
if (echoMode != null && stdin.hasTerminal) {
final previousEchoMode = stdin.echoMode;
- stdin.echoMode = echoMode;
- return _stdinLines.first.whenComplete(() {
+ try {
+ stdin.echoMode = echoMode;
+ final result = stdin.readLineSync() ?? '';
+ stdout.write('\n');
+ return result;
+ } finally {
stdin.echoMode = previousEchoMode;
- });
+ }
} else {
- return _stdinLines.first;
+ return stdin.readLineSync() ?? '';
}
}
@@ -963,10 +1007,10 @@
log.fine(buffer.toString());
ArgumentError.checkNotNull(baseDir, 'baseDir');
- baseDir = path.absolute(baseDir);
+ baseDir = path.normalize(path.absolute(baseDir));
final tarContents = Stream.fromIterable(contents.map((entry) {
- entry = path.absolute(entry);
+ entry = path.normalize(path.absolute(entry));
if (!path.isWithin(baseDir, entry)) {
throw ArgumentError('Entry $entry is not inside $baseDir.');
}
@@ -1023,22 +1067,16 @@
}
/// The location for dart-specific configuration.
-final String dartConfigDir = () {
- // TODO: Migrate to new value from cli_util
- if (runningFromTest) {
+///
+/// `null` if no config dir could be found.
+final String? dartConfigDir = () {
+ if (runningFromTest &&
+ Platform.environment.containsKey('_PUB_TEST_CONFIG_DIR')) {
return Platform.environment['_PUB_TEST_CONFIG_DIR'];
}
- String configDir;
- if (Platform.isLinux) {
- configDir = Platform.environment['XDG_CONFIG_HOME'] ??
- path.join(Platform.environment['HOME']!, '.config');
- } else if (Platform.isWindows) {
- configDir = Platform.environment['APPDATA']!;
- } else if (Platform.isMacOS) {
- configDir = path.join(
- Platform.environment['HOME']!, 'Library', 'Application Support');
- } else {
- configDir = path.join(Platform.environment['HOME']!, '.config');
+ try {
+ return applicationConfigHome('dart');
+ } on EnvironmentNotFoundException {
+ return null;
}
- return path.join(configDir, 'dart');
-}()!;
+}();
diff --git a/lib/src/language_version.dart b/lib/src/language_version.dart
index e294014..ad331b2 100644
--- a/lib/src/language_version.dart
+++ b/lib/src/language_version.dart
@@ -69,6 +69,21 @@
bool get supportsNullSafety => this >= firstVersionWithNullSafety;
+ /// Minimum language version at which short hosted syntax is supported.
+ ///
+ /// This allows `hosted` dependencies to be expressed as:
+ /// ```yaml
+ /// dependencies:
+ /// foo:
+ /// hosted: https://some-pub.com/path
+ /// version: ^1.0.0
+ /// ```
+ ///
+ /// At older versions, `hosted` dependencies had to be a map with a `url` and
+ /// a `name` key.
+ bool get supportsShorterHostedSyntax =>
+ this >= firstVersionWithShorterHostedSyntax;
+
@override
int compareTo(LanguageVersion other) {
if (major != other.major) return major.compareTo(other.major);
@@ -89,6 +104,7 @@
static const defaultLanguageVersion = LanguageVersion(2, 7);
static const firstVersionWithNullSafety = LanguageVersion(2, 12);
+ static const firstVersionWithShorterHostedSyntax = LanguageVersion(2, 15);
/// Transform language version to string that can be parsed with
/// [LanguageVersion.parse].
diff --git a/lib/src/lock_file.dart b/lib/src/lock_file.dart
index b2139fe..8f563ab 100644
--- a/lib/src/lock_file.dart
+++ b/lib/src/lock_file.dart
@@ -2,12 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:collection/collection.dart' hide mapMap;
-import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
import 'package:source_span/source_span.dart';
@@ -52,10 +49,10 @@
/// `dependency_overrides` sections, respectively. These are consumed by the
/// analysis server to provide better auto-completion.
LockFile(Iterable<PackageId> ids,
- {Map<String, VersionConstraint> sdkConstraints,
- Set<String> mainDependencies,
- Set<String> devDependencies,
- Set<String> overriddenDependencies})
+ {Map<String, VersionConstraint>? sdkConstraints,
+ Set<String>? mainDependencies,
+ Set<String>? devDependencies,
+ Set<String>? overriddenDependencies})
: this._(
Map.fromIterable(ids.where((id) => !id.isRoot),
key: (id) => id.name),
@@ -94,10 +91,10 @@
/// [filePath] is the system-native path to the lockfile on disc. It may be
/// `null`.
static LockFile _parse(
- String filePath, String contents, SourceRegistry sources) {
+ String? filePath, String contents, SourceRegistry sources) {
if (contents.trim() == '') return LockFile.empty();
- Uri sourceUrl;
+ Uri? sourceUrl;
if (filePath != null) sourceUrl = p.toUri(filePath);
var parsed = loadYamlNode(contents, sourceUrl: sourceUrl);
@@ -145,7 +142,7 @@
var description = spec['description'];
// Let the source parse the description.
- var source = sources[sourceName];
+ var source = sources[sourceName]!;
PackageId id;
try {
id = source.parseId(name, version, description,
@@ -173,8 +170,6 @@
/// Asserts that [node] is a version constraint, and parses it.
static VersionConstraint _parseVersionConstraint(YamlNode node) {
- if (node == null) return null;
-
_validate(node.value is String,
'Invalid version constraint: must be a string.', node);
@@ -199,9 +194,9 @@
}
/// If [condition] is `false` throws a format error with [message] for [node].
- static void _validate(bool condition, String message, YamlNode node) {
+ static void _validate(bool condition, String message, YamlNode? node) {
if (condition) return;
- throw SourceSpanFormatException(message, node.span);
+ throw SourceSpanFormatException(message, node!.span);
}
/// Returns a copy of this LockFile with a package named [name] removed.
@@ -222,8 +217,8 @@
/// directory.
String packagesFile(
SystemCache cache, {
- String entrypoint,
- @required String relativeFrom,
+ String? entrypoint,
+ String? relativeFrom,
}) {
var header = '''
This file is deprecated. Tools should instead consume
@@ -233,9 +228,9 @@
Generated by pub on ${DateTime.now()}.''';
- var map =
- Map<String, Uri>.fromIterable(ordered(packages.keys), value: (name) {
- var id = packages[name];
+ var map = Map<String, Uri>.fromIterable(ordered<String>(packages.keys),
+ value: (name) {
+ var id = packages[name]!;
var source = cache.source(id.source);
return p.toUri(
p.join(source.getDirectory(id, relativeFrom: relativeFrom), 'lib'));
@@ -259,13 +254,13 @@
/// current package has no SDK constraint.
Future<String> packageConfigFile(
SystemCache cache, {
- String entrypoint,
- VersionConstraint entrypointSdkConstraint,
- @required String relativeFrom,
+ String? entrypoint,
+ VersionConstraint? entrypointSdkConstraint,
+ String? relativeFrom,
}) async {
final entries = <PackageConfigEntry>[];
for (final name in ordered(packages.keys)) {
- final id = packages[name];
+ final id = packages[name]!;
final source = cache.source(id.source);
final rootPath = source.getDirectory(id, relativeFrom: relativeFrom);
Uri rootUri;
@@ -311,17 +306,18 @@
/// Returns the serialized YAML text of the lock file.
///
/// [packageDir] is the containing directory of the root package, used to
- /// properly serialize package descriptions.
- String serialize(String packageDir) {
+ /// serialize relative path package descriptions. If it is null, they will be
+ /// serialized as absolute.
+ String serialize(String? packageDir) {
// Convert the dependencies to a simple object.
var packageMap = {};
packages.forEach((name, package) {
var description =
- package.source.serializeDescription(packageDir, package.description);
+ package.source!.serializeDescription(packageDir, package.description);
packageMap[name] = {
'version': package.version.toString(),
- 'source': package.source.name,
+ 'source': package.source!.name,
'description': description,
'dependency': _dependencyType(package.name)
};
diff --git a/lib/src/log.dart b/lib/src/log.dart
index ff7fe29..db24d7a 100644
--- a/lib/src/log.dart
+++ b/lib/src/log.dart
@@ -12,9 +12,11 @@
import 'package:source_span/source_span.dart';
import 'package:stack_trace/stack_trace.dart';
+import 'entrypoint.dart';
import 'exceptions.dart';
import 'io.dart';
import 'progress.dart';
+import 'sdk.dart';
import 'transcript.dart';
import 'utils.dart';
@@ -24,7 +26,7 @@
final json = _JsonLogger();
/// The current logging verbosity.
-Verbosity verbosity = Verbosity.NORMAL;
+Verbosity verbosity = Verbosity.normal;
/// In cases where there's a ton of log spew, make sure we don't eat infinite
/// memory.
@@ -32,11 +34,11 @@
/// This can occur when the backtracking solver stumbles into a pathological
/// dependency graph. It generally will find a solution, but it may log
/// thousands and thousands of entries to get there.
-const _MAX_TRANSCRIPT = 10000;
+const _maxTranscript = 10000;
/// The list of recorded log messages. Will only be recorded if
/// [recordTranscript()] is called.
-Transcript<_Entry>? _transcript;
+final Transcript<_Entry> _transcript = Transcript(_maxTranscript);
/// The currently-animated progress indicator, if any.
///
@@ -58,34 +60,34 @@
/// An enum type for defining the different logging levels a given message can
/// be associated with.
///
-/// By default, [ERROR] and [WARNING] messages are printed to sterr. [MESSAGE]
+/// By default, [error] and [warning] messages are printed to sterr. [message]
/// messages are printed to stdout, and others are ignored.
class Level {
/// An error occurred and an operation could not be completed.
///
/// Usually shown to the user on stderr.
- static const ERROR = Level._('ERR ');
+ static const error = Level._('ERR ');
/// Something unexpected happened, but the program was able to continue,
/// though possibly in a degraded fashion.
- static const WARNING = Level._('WARN');
+ static const warning = Level._('WARN');
/// A message intended specifically to be shown to the user.
- static const MESSAGE = Level._('MSG ');
+ static const message = Level._('MSG ');
/// Some interaction with the external world occurred, such as a network
/// operation, process spawning, or file IO.
- static const IO = Level._('IO ');
+ static const io = Level._('IO ');
/// Incremental output during pub's version constraint solver.
- static const SOLVER = Level._('SLVR');
+ static const solver = Level._('SLVR');
/// Fine-grained and verbose additional information.
///
/// Used to provide program state context for other logs (such as what pub
/// was doing when an IO operation occurred) or just more detail for an
/// operation.
- static const FINE = Level._('FINE');
+ static const fine = Level._('FINE');
const Level._(this.name);
@@ -99,73 +101,83 @@
/// displayed.
class Verbosity {
/// Silence all logging.
- static const NONE = Verbosity._('none', {
- Level.ERROR: null,
- Level.WARNING: null,
- Level.MESSAGE: null,
- Level.IO: null,
- Level.SOLVER: null,
- Level.FINE: null
+ static const none = Verbosity._('none', {
+ Level.error: null,
+ Level.warning: null,
+ Level.message: null,
+ Level.io: null,
+ Level.solver: null,
+ Level.fine: null
});
/// Shows only errors.
- static const ERROR = Verbosity._('error', {
- Level.ERROR: _logToStderr,
- Level.WARNING: null,
- Level.MESSAGE: null,
- Level.IO: null,
- Level.SOLVER: null,
- Level.FINE: null
+ static const error = Verbosity._('error', {
+ Level.error: _logToStderr,
+ Level.warning: null,
+ Level.message: null,
+ Level.io: null,
+ Level.solver: null,
+ Level.fine: null
});
/// Shows only errors and warnings.
- static const WARNING = Verbosity._('warning', {
- Level.ERROR: _logToStderr,
- Level.WARNING: _logToStderr,
- Level.MESSAGE: null,
- Level.IO: null,
- Level.SOLVER: null,
- Level.FINE: null
+ static const warning = Verbosity._('warning', {
+ Level.error: _logToStderr,
+ Level.warning: _logToStderr,
+ Level.message: null,
+ Level.io: null,
+ Level.solver: null,
+ Level.fine: null
});
/// The default verbosity which shows errors, warnings, and messages.
- static const NORMAL = Verbosity._('normal', {
- Level.ERROR: _logToStderr,
- Level.WARNING: _logToStderr,
- Level.MESSAGE: _logToStdout,
- Level.IO: null,
- Level.SOLVER: null,
- Level.FINE: null
+ static const normal = Verbosity._('normal', {
+ Level.error: _logToStderr,
+ Level.warning: _logToStderr,
+ Level.message: _logToStdout,
+ Level.io: null,
+ Level.solver: null,
+ Level.fine: null
});
/// Shows errors, warnings, messages, and IO event logs.
- static const IO = Verbosity._('io', {
- Level.ERROR: _logToStderrWithLabel,
- Level.WARNING: _logToStderrWithLabel,
- Level.MESSAGE: _logToStdoutWithLabel,
- Level.IO: _logToStderrWithLabel,
- Level.SOLVER: null,
- Level.FINE: null
+ static const io = Verbosity._('io', {
+ Level.error: _logToStderrWithLabel,
+ Level.warning: _logToStderrWithLabel,
+ Level.message: _logToStdoutWithLabel,
+ Level.io: _logToStderrWithLabel,
+ Level.solver: null,
+ Level.fine: null
});
/// Shows errors, warnings, messages, and version solver logs.
- static const SOLVER = Verbosity._('solver', {
- Level.ERROR: _logToStderr,
- Level.WARNING: _logToStderr,
- Level.MESSAGE: _logToStdout,
- Level.IO: null,
- Level.SOLVER: _logToStdout,
- Level.FINE: null
+ static const solver = Verbosity._('solver', {
+ Level.error: _logToStderr,
+ Level.warning: _logToStderr,
+ Level.message: _logToStdout,
+ Level.io: null,
+ Level.solver: _logToStdout,
+ Level.fine: null
});
/// Shows all logs.
- static const ALL = Verbosity._('all', {
- Level.ERROR: _logToStderrWithLabel,
- Level.WARNING: _logToStderrWithLabel,
- Level.MESSAGE: _logToStdoutWithLabel,
- Level.IO: _logToStderrWithLabel,
- Level.SOLVER: _logToStderrWithLabel,
- Level.FINE: _logToStderrWithLabel
+ static const all = Verbosity._('all', {
+ Level.error: _logToStderrWithLabel,
+ Level.warning: _logToStderrWithLabel,
+ Level.message: _logToStdoutWithLabel,
+ Level.io: _logToStderrWithLabel,
+ Level.solver: _logToStderrWithLabel,
+ Level.fine: _logToStderrWithLabel
+ });
+
+ /// Shows all logs.
+ static const testing = Verbosity._('testing', {
+ Level.error: _logToStderrWithLabel,
+ Level.warning: _logToStderrWithLabel,
+ Level.message: _logToStdoutWithLabel,
+ Level.io: _logToStderrWithLabel,
+ Level.solver: _logToStderrWithLabel,
+ Level.fine: _logToStderrWithLabel
});
const Verbosity._(this.name, this._loggers);
@@ -188,7 +200,7 @@
_Entry(this.level, this.lines);
}
-/// Logs [message] at [Level.ERROR].
+/// Logs [message] at [Level.error].
///
/// If [error] is passed, it's appended to [message]. If [trace] is passed, it's
/// printed at log level fine.
@@ -198,24 +210,24 @@
message = message.isEmpty ? '$error' : '$message: $error';
if (error is Error && trace == null) trace = error.stackTrace;
}
- write(Level.ERROR, message);
- if (trace != null) write(Level.FINE, Chain.forTrace(trace));
+ write(Level.error, message);
+ if (trace != null) write(Level.fine, Chain.forTrace(trace));
}
-/// Logs [message] at [Level.WARNING].
-void warning(message) => write(Level.WARNING, message);
+/// Logs [message] at [Level.warning].
+void warning(message) => write(Level.warning, message);
-/// Logs [message] at [Level.MESSAGE].
-void message(message) => write(Level.MESSAGE, message);
+/// Logs [message] at [Level.message].
+void message(message) => write(Level.message, message);
-/// Logs [message] at [Level.IO].
-void io(message) => write(Level.IO, message);
+/// Logs [message] at [Level.io].
+void io(message) => write(Level.io, message);
-/// Logs [message] at [Level.SOLVER].
-void solver(message) => write(Level.SOLVER, message);
+/// Logs [message] at [Level.solver].
+void solver(message) => write(Level.solver, message);
-/// Logs [message] at [Level.FINE].
-void fine(message) => write(Level.FINE, message);
+/// Logs [message] at [Level.fine].
+void fine(message) => write(Level.fine, message);
/// Logs [message] at [level].
void write(Level level, message) {
@@ -233,10 +245,10 @@
var logFn = verbosity._loggers[level];
if (logFn != null) logFn(entry);
- if (_transcript != null) _transcript!.add(entry);
+ _transcript.add(entry);
}
-/// Logs the spawning of an [executable] process with [arguments] at [IO]
+/// Logs the spawning of an [executable] process with [arguments] at [io]
/// level.
void process(
String executable, List<String> arguments, String workingDirectory) {
@@ -313,18 +325,10 @@
}
}
-/// Enables recording of log entries.
-void recordTranscript() {
- _transcript = Transcript<_Entry>(_MAX_TRANSCRIPT);
-}
-
-/// If [recordTranscript()] was called, then prints the previously recorded log
-/// transcript to stderr.
-void dumpTranscript() {
- if (_transcript == null) return;
-
+/// Prints the recorded log transcript to stderr.
+void dumpTranscriptToStdErr() {
stderr.writeln('---- Log transcript ----');
- _transcript!.forEach((entry) {
+ _transcript.forEach((entry) {
_printToStream(stderr, entry, showLabel: true);
}, (discarded) {
stderr.writeln('---- ($discarded discarded) ----');
@@ -332,6 +336,68 @@
stderr.writeln('---- End log transcript ----');
}
+String _limit(String input, int limit) {
+ const snip = '[...]';
+ if (input.length < limit - snip.length) return input;
+ return '${input.substring(0, limit ~/ 2 - snip.length)}'
+ '$snip'
+ '${input.substring(limit)}';
+}
+
+/// Prints relevant system information and the log transcript to [path].
+void dumpTranscriptToFile(String path, String command, Entrypoint? entrypoint) {
+ final buffer = StringBuffer();
+ buffer.writeln('''
+Information about the latest pub run.
+
+If you believe something is not working right, you can go to
+https://github.com/dart-lang/pub/issues/new to post a new issue and attach this file.
+
+Before making this file public, make sure to remove any sensitive information!
+
+Pub version: ${sdk.version}
+Created: ${DateTime.now().toIso8601String()}
+FLUTTER_ROOT: ${Platform.environment['FLUTTER_ROOT'] ?? '<not set>'}
+PUB_HOSTED_URL: ${Platform.environment['PUB_HOSTED_URL'] ?? '<not set>'}
+PUB_CACHE: "${Platform.environment['PUB_CACHE'] ?? '<not set>'}"
+Command: $command
+Platform: ${Platform.operatingSystem}
+''');
+
+ if (entrypoint != null) {
+ buffer.writeln('---- ${p.absolute(entrypoint.pubspecPath)} ----');
+ if (fileExists(entrypoint.pubspecPath)) {
+ buffer.writeln(_limit(readTextFile(entrypoint.pubspecPath), 5000));
+ } else {
+ buffer.writeln('<No pubspec.yaml>');
+ }
+ buffer.writeln('---- End pubspec.yaml ----');
+ buffer.writeln('---- ${p.absolute(entrypoint.lockFilePath)} ----');
+ if (fileExists(entrypoint.lockFilePath)) {
+ buffer.writeln(_limit(readTextFile(entrypoint.lockFilePath), 5000));
+ } else {
+ buffer.writeln('<No pubspec.lock>');
+ }
+ buffer.writeln('---- End pubspec.lock ----');
+ }
+
+ buffer.writeln('---- Log transcript ----');
+
+ _transcript.forEach((entry) {
+ _printToStream(buffer, entry, showLabel: true);
+ }, (discarded) {
+ buffer.writeln('---- ($discarded entries discarded) ----');
+ });
+ buffer.writeln('---- End log transcript ----');
+ ensureDir(p.dirname(path));
+ try {
+ writeTextFile(path, buffer.toString(), dontLogContents: true);
+ } on IOException catch (e) {
+ stderr.writeln('Failed writing log to `$path` ($e), writing it to stderr:');
+ dumpTranscriptToStdErr();
+ }
+}
+
/// Filter out normal pub output when not attached to a terminal
///
/// Unless the user has overriden the verbosity,
@@ -339,8 +405,8 @@
/// This is useful to not pollute stdout when the output is piped somewhere.
Future<T> warningsOnlyUnlessTerminal<T>(FutureOr<T> Function() callback) async {
final oldVerbosity = verbosity;
- if (verbosity == Verbosity.NORMAL && !stdout.hasTerminal) {
- verbosity = Verbosity.WARNING;
+ if (verbosity == Verbosity.normal && !stdout.hasTerminal) {
+ verbosity = Verbosity.warning;
}
final result = await callback();
verbosity = oldVerbosity;
@@ -353,7 +419,7 @@
/// If anything else is logged during this (including another call to
/// [progress]) that cancels the progress animation, although the total time
/// will still be printed once it finishes. If [fine] is passed, the progress
-/// information will only be visible at [Level.FINE].
+/// information will only be visible at [Level.fine].
Future<T> progress<T>(String message, Future<T> Function() callback) {
_stopProgress();
@@ -492,7 +558,7 @@
_printToStream(sink, entry, showLabel: showLabel);
}
-void _printToStream(IOSink sink, _Entry entry, {required bool showLabel}) {
+void _printToStream(StringSink sink, _Entry entry, {required bool showLabel}) {
_stopProgress();
var firstLine = true;
diff --git a/lib/src/null_safety_analysis.dart b/lib/src/null_safety_analysis.dart
index fb1c8ad..5b882a8 100644
--- a/lib/src/null_safety_analysis.dart
+++ b/lib/src/null_safety_analysis.dart
@@ -2,13 +2,11 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
-import 'package:analyzer/dart/analysis/context_builder.dart';
-import 'package:analyzer/dart/analysis/context_locator.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:cli_util/cli_util.dart';
import 'package:path/path.dart' as path;
import 'package:source_span/source_span.dart';
@@ -74,16 +72,17 @@
/// If [packageId] is a relative path dependency [containingPath] must be
/// provided with an absolute path to resolve it against.
Future<NullSafetyAnalysisResult> nullSafetyCompliance(PackageId packageId,
- {String containingPath}) async {
+ {String? containingPath}) async {
// A space in the name prevents clashes with other package names.
final fakeRootName = '${packageId.name} importer';
final fakeRoot = Package.inMemory(Pubspec(fakeRootName,
fields: {
'dependencies': {
packageId.name: {
- packageId.source.name: packageId.source is PathSource
+ packageId.source!.name: packageId.source is PathSource
? (packageId.description['relative']
- ? path.join(containingPath, packageId.description['path'])
+ ? path.join(
+ containingPath!, packageId.description['path'])
: packageId.description['path'])
: packageId.description,
'version': packageId.version.toString(),
@@ -93,7 +92,7 @@
sources: _systemCache.sources));
final rootPubspec =
- await packageId.source.bind(_systemCache).describe(packageId);
+ await packageId.source!.bind(_systemCache).describe(packageId);
final rootLanguageVersion = rootPubspec.languageVersion;
if (!rootLanguageVersion.supportsNullSafety) {
final span =
@@ -110,7 +109,7 @@
SolveResult result;
try {
result = await resolveVersions(
- SolveType.GET,
+ SolveType.get,
_systemCache,
fakeRoot,
);
@@ -119,10 +118,10 @@
'Could not resolve constraints: $e');
}
return nullSafetyComplianceOfPackages(
- result.packages.where((id) => id.name != fakeRootName),
- Package(rootPubspec,
- packageId.source.bind(_systemCache).getDirectory(packageId)),
- containingPath);
+ result.packages.where((id) => id.name != fakeRootName),
+ Package(rootPubspec,
+ packageId.source!.bind(_systemCache).getDirectory(packageId)),
+ );
}
/// Decides if all dependendencies (transitively) have a language version
@@ -139,14 +138,13 @@
Future<NullSafetyAnalysisResult> nullSafetyComplianceOfPackages(
Iterable<PackageId> packages,
Package rootPackage,
- String containingPath,
) async {
- NullSafetyAnalysisResult firstBadPackage;
+ NullSafetyAnalysisResult? firstBadPackage;
for (final dependencyId in packages) {
final packageInternalAnalysis =
await _packageInternallyGoodCache.putIfAbsent(dependencyId, () async {
Pubspec pubspec;
- BoundSource boundSource;
+ BoundSource? boundSource;
String packageDir;
if (dependencyId.source == null) {
pubspec = rootPackage.pubspec;
@@ -177,14 +175,13 @@
final libDir =
path.absolute(path.normalize(path.join(packageDir, 'lib')));
if (dirExists(libDir)) {
- final analysisSession = ContextBuilder()
- .createContext(
- sdkPath: getSdkPath(),
- contextRoot: ContextLocator().locateRoots(
- includedPaths: [path.normalize(packageDir)],
- ).first,
- )
- .currentSession;
+ var contextCollection = AnalysisContextCollection(
+ includedPaths: [path.normalize(packageDir)],
+ resourceProvider: PhysicalResourceProvider.INSTANCE,
+ sdkPath: getSdkPath(),
+ );
+ var analysisContext = contextCollection.contexts.first;
+ var analysisSession = analysisContext.currentSession;
for (final file in listDir(libDir,
recursive: true, includeDirs: false, includeHidden: true)) {
@@ -192,7 +189,7 @@
final fileUrl =
'package:${dependencyId.name}/${path.relative(file, from: libDir)}';
final someUnitResult =
- analysisSession.getParsedUnit2(path.normalize(file));
+ analysisSession.getParsedUnit(path.normalize(file));
ParsedUnitResult unitResult;
if (someUnitResult is ParsedUnitResult) {
unitResult = someUnitResult;
@@ -225,7 +222,6 @@
}
return NullSafetyAnalysisResult(NullSafetyCompliance.compliant, null);
});
- assert(packageInternalAnalysis != null);
if (packageInternalAnalysis.compliance ==
NullSafetyCompliance.analysisFailed) {
return packageInternalAnalysis;
@@ -251,12 +247,12 @@
final NullSafetyCompliance compliance;
/// `null` if compliance == [NullSafetyCompliance.compliant].
- final String reason;
+ final String? reason;
NullSafetyAnalysisResult(this.compliance, this.reason);
}
-SourceSpan _tryGetSpanFromYamlMap(Object map, String key) {
+SourceSpan? _tryGetSpanFromYamlMap(Object? map, String key) {
if (map is YamlMap) {
return map.nodes[key]?.span;
}
diff --git a/lib/src/oauth2.dart b/lib/src/oauth2.dart
index c1284e9..7229bb1 100644
--- a/lib/src/oauth2.dart
+++ b/lib/src/oauth2.dart
@@ -2,11 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:io';
+import 'package:collection/collection.dart' show IterableExtension;
import 'package:oauth2/oauth2.dart';
import 'package:path/path.dart' as path;
import 'package:shelf/shelf.dart' as shelf;
@@ -64,19 +63,21 @@
///
/// This should always be the same as the credentials file stored in the system
/// cache.
-Credentials _credentials;
+Credentials? _credentials;
/// Delete the cached credentials, if they exist.
void _clearCredentials(SystemCache cache) {
_credentials = null;
var credentialsFile = _credentialsFile(cache);
- if (entryExists(credentialsFile)) deleteEntry(credentialsFile);
+ if (credentialsFile != null && entryExists(credentialsFile)) {
+ deleteEntry(credentialsFile);
+ }
}
/// Try to delete the cached credentials.
void logout(SystemCache cache) {
var credentialsFile = _credentialsFile(cache);
- if (entryExists(_credentialsFile(cache))) {
+ if (credentialsFile != null && entryExists(credentialsFile)) {
log.message('Logging out of pub.dartlang.org.');
log.message('Deleting $credentialsFile');
_clearCredentials(cache);
@@ -151,14 +152,14 @@
///
/// If the credentials can't be loaded for any reason, the returned [Future]
/// completes to `null`.
-Credentials loadCredentials(SystemCache cache) {
+Credentials? loadCredentials(SystemCache cache) {
log.fine('Loading OAuth2 credentials.');
try {
if (_credentials != null) return _credentials;
var path = _credentialsFile(cache);
- if (!fileExists(path)) return null;
+ if (path == null || !fileExists(path)) return null;
var credentials = Credentials.fromJson(readTextFile(path));
if (credentials.isExpired && !credentials.canRefresh) {
@@ -181,8 +182,10 @@
log.fine('Saving OAuth2 credentials.');
_credentials = credentials;
var credentialsPath = _credentialsFile(cache);
- ensureDir(path.dirname(credentialsPath));
- writeTextFile(credentialsPath, credentials.toJson(), dontLogContents: true);
+ if (credentialsPath != null) {
+ ensureDir(path.dirname(credentialsPath));
+ writeTextFile(credentialsPath, credentials.toJson(), dontLogContents: true);
+ }
}
/// The path to the file in which the user's OAuth2 credentials are stored.
@@ -191,10 +194,18 @@
/// best place for storing secrets, as it might be shared.
///
/// To provide backwards compatibility we use the legacy file if only it exists.
-String _credentialsFile(SystemCache cache) {
- final newCredentialsFile = path.join(dartConfigDir, 'pub-credentials.json');
- return [newCredentialsFile, _legacyCredentialsFile(cache)]
- .firstWhere(fileExists, orElse: () => newCredentialsFile);
+///
+/// Returns `null` if there is no good place for the file.
+String? _credentialsFile(SystemCache cache) {
+ final configDir = dartConfigDir;
+
+ final newCredentialsFile =
+ configDir == null ? null : path.join(configDir, 'pub-credentials.json');
+ var file = [
+ if (newCredentialsFile != null) newCredentialsFile,
+ _legacyCredentialsFile(cache)
+ ].firstWhereOrNull(fileExists);
+ return file ?? newCredentialsFile;
}
String _legacyCredentialsFile(SystemCache cache) {
@@ -223,7 +234,7 @@
}
log.message('Authorization received, processing...');
- var queryString = request.url.query ?? '';
+ var queryString = request.url.query;
// Closing the server here is safe, since it will wait until the response
// is sent to actually shut down.
server.close();
diff --git a/lib/src/package.dart b/lib/src/package.dart
index 6a3b0ff..d100157 100644
--- a/lib/src/package.dart
+++ b/lib/src/package.dart
@@ -2,10 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
+import 'package:collection/collection.dart' show IterableExtension;
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
@@ -36,19 +35,26 @@
return a.version.compareTo(b.version);
}
+ final String? _dir;
+
/// The path to the directory containing the package.
- final String dir;
+ ///
+ /// It is an error to access this on an in-memory package.
+ String get dir {
+ if (isInMemory) {
+ throw UnsupportedError(
+ 'Package directory cannot be used for an in-memory package');
+ }
+
+ return _dir!;
+ }
/// An in-memory package can be created for doing a resolution without having
/// a package on disk. Paths should not be resolved for these.
- bool get _isInMemory => dir == null;
+ bool get isInMemory => _dir == null;
/// The name of the package.
- String get name {
- if (pubspec.name != null) return pubspec.name;
- if (dir != null) return p.basename(dir);
- return null;
- }
+ String get name => pubspec.name;
/// The package's version.
Version get version => pubspec.version;
@@ -77,10 +83,12 @@
..addAll(dependencyOverrides);
}
- /// Returns a list of asset ids for all Dart executables in this package's bin
+ /// Returns a list of paths to all Dart executables in this package's bin
/// directory.
List<String> get executablePaths {
- return ordered(listFiles(beneath: 'bin', recursive: false))
+ final binDir = p.join(dir, 'bin');
+ if (!dirExists(binDir)) return <String>[];
+ return ordered(listDir(p.join(dir, 'bin'), includeDirs: false))
.where((executable) => p.extension(executable) == '.dart')
.map((executable) => p.relative(executable, from: dir))
.toList();
@@ -95,7 +103,7 @@
/// If multiple READMEs are found, this uses the same conventions as
/// pub.dartlang.org for choosing the primary one: the README with the fewest
/// extensions that is lexically ordered first is chosen.
- String get readmePath {
+ String? get readmePath {
var readmes = listFiles(recursive: false)
.map(p.basename)
.where((entry) => entry.contains(_readmeRegexp));
@@ -112,61 +120,57 @@
/// Returns the path to the CHANGELOG file at the root of the entrypoint, or
/// null if no CHANGELOG file is found.
- String get changelogPath {
- return listFiles(recursive: false).firstWhere(
- (entry) => p.basename(entry).contains(_changelogRegexp),
- orElse: () => null);
+ String? get changelogPath {
+ return listFiles(recursive: false).firstWhereOrNull(
+ (entry) => p.basename(entry).contains(_changelogRegexp));
}
/// Returns whether or not this package is in a Git repo.
- bool get inGitRepo {
- if (_inGitRepoCache != null) return _inGitRepoCache;
+ late final bool inGitRepo = computeInGitRepoCache();
- if (dir == null || !git.isInstalled) {
- _inGitRepoCache = false;
+ bool computeInGitRepoCache() {
+ if (isInMemory || !git.isInstalled) {
+ return false;
} else {
// If the entire package directory is ignored, don't consider it part of a
// git repo. `git check-ignore` will return a status code of 0 for
// ignored, 1 for not ignored, and 128 for not a Git repo.
- var result = runProcessSync(git.command, ['check-ignore', '--quiet', '.'],
+ var result = runProcessSync(
+ git.command!, ['check-ignore', '--quiet', '.'],
workingDir: dir);
- _inGitRepoCache = result.exitCode == 1;
+ return result.exitCode == 1;
}
-
- return _inGitRepoCache;
}
- bool _inGitRepoCache;
-
/// Loads the package whose root directory is [packageDir].
///
/// [name] is the expected name of that package (e.g. the name given in the
/// dependency), or `null` if the package being loaded is the entrypoint
/// package.
- Package.load(String name, this.dir, SourceRegistry sources)
- : pubspec = Pubspec.load(dir, sources, expectedName: name);
+ Package.load(String? name, String this._dir, SourceRegistry sources)
+ : pubspec = Pubspec.load(_dir, sources, expectedName: name);
/// Constructs a package with the given pubspec.
///
/// The package will have no directory associated with it.
- Package.inMemory(this.pubspec) : dir = null;
+ Package.inMemory(this.pubspec) : _dir = null;
/// Creates a package with [pubspec] located at [dir].
- Package(this.pubspec, this.dir);
+ Package(this.pubspec, String this._dir);
/// Given a relative path within this package, returns its absolute path.
///
/// This is similar to `p.join(dir, part1, ...)`, except that subclasses may
/// override it to report that certain paths exist elsewhere than within
/// [dir].
- String path(String part1,
- [String part2,
- String part3,
- String part4,
- String part5,
- String part6,
- String part7]) {
- if (_isInMemory) {
+ String path(String? part1,
+ [String? part2,
+ String? part3,
+ String? part4,
+ String? part5,
+ String? part6,
+ String? part7]) {
+ if (isInMemory) {
throw StateError("Package $name is in-memory and doesn't have paths "
'on disk.');
}
@@ -176,7 +180,7 @@
/// Given an absolute path within this package (such as that returned by
/// [path] or [listFiles]), returns it relative to the package root.
String relative(String path) {
- if (dir == null) {
+ if (isInMemory) {
throw StateError("Package $name is in-memory and doesn't have paths "
'on disk.');
}
@@ -184,7 +188,7 @@
}
/// Returns the type of dependency from this package onto [name].
- DependencyType dependencyType(String name) {
+ DependencyType dependencyType(String? name) {
if (pubspec.fields['dependencies']?.containsKey(name) ?? false) {
return DependencyType.direct;
} else if (pubspec.fields['dev_dependencies']?.containsKey(name) ?? false) {
@@ -220,22 +224,15 @@
///
/// Note that the returned paths won't always be beneath [dir]. To safely
/// convert them to paths relative to the package root, use [relative].
- List<String> listFiles({String beneath, bool recursive = true}) {
+ List<String> listFiles({String? beneath, bool recursive = true}) {
// An in-memory package has no files.
- if (dir == null) return [];
+ if (isInMemory) return [];
- var root = dir;
- if (git.isInstalled) {
- try {
- root = p.normalize(
- git.runSync(['rev-parse', '--show-toplevel'], workingDir: dir).first,
- );
- } on git.GitException {
- // Not in a git folder.
- }
- }
+ var packageDir = dir;
+ var root = git.repoRoot(packageDir) ?? packageDir;
beneath = p
- .toUri(p.normalize(p.relative(p.join(dir, beneath ?? '.'), from: root)))
+ .toUri(p.normalize(
+ p.relative(p.join(packageDir, beneath ?? '.'), from: root)))
.path;
if (beneath == './') beneath = '.';
String resolve(String path) {
@@ -279,7 +276,7 @@
: (fileExists(gitIgnore) ? gitIgnore : null);
final rules = [
- if (dir == '.') ..._basicIgnoreRules,
+ if (dir == beneath) ..._basicIgnoreRules,
if (ignoreFile != null) readTextFile(ignoreFile),
];
return rules.isEmpty
diff --git a/lib/src/package_config.dart b/lib/src/package_config.dart
index fad20f7..d64808b 100644
--- a/lib/src/package_config.dart
+++ b/lib/src/package_config.dart
@@ -2,9 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
-import 'package:meta/meta.dart';
+import 'dart:convert';
import 'package:pub_semver/pub_semver.dart';
@@ -22,38 +20,36 @@
/// Date-time the `.dart_tool/package_config.json` file was generated.
///
- /// This property is **optional** and may be `null` if not given.
- DateTime generated;
+ /// `null` if not given.
+ DateTime? generated;
/// Tool that generated the `.dart_tool/package_config.json` file.
///
/// For `pub` this is always `'pub'`.
///
- /// This property is **optional** and may be `null` if not given.
- String generator;
+ /// `null` if not given.
+ String? generator;
/// Version of the tool that generated the `.dart_tool/package_config.json`
/// file.
///
/// For `pub` this is the Dart SDK version from which `pub get` was called.
///
- /// This property is **optional** and may be `null` if not given.
- Version generatorVersion;
+ /// `null` if not given.
+ Version? generatorVersion;
/// Additional properties not in the specification for the
/// `.dart_tool/package_config.json` file.
Map<String, dynamic> additionalProperties;
PackageConfig({
- @required this.configVersion,
- @required this.packages,
+ required this.configVersion,
+ required this.packages,
this.generated,
this.generator,
this.generatorVersion,
- this.additionalProperties,
- }) {
- additionalProperties ??= {};
- }
+ Map<String, dynamic>? additionalProperties,
+ }) : additionalProperties = additionalProperties ?? {};
/// Create [PackageConfig] from JSON [data].
///
@@ -63,7 +59,7 @@
if (data is! Map<String, dynamic>) {
throw FormatException('package_config.json must be a JSON object');
}
- final root = data as Map<String, dynamic>;
+ final root = data;
void _throw(String property, String mustBe) => throw FormatException(
'"$property" in .dart_tool/package_config.json $mustBe');
@@ -87,7 +83,7 @@
}
// Read the 'generated' property
- DateTime generated;
+ DateTime? generated;
final generatedRaw = root['generated'];
if (generatedRaw != null) {
if (generatedRaw is! String) {
@@ -104,7 +100,7 @@
}
// Read the 'generatorVersion' property
- Version generatorVersion;
+ Version? generatorVersion;
final generatorVersionRaw = root['generatorVersion'];
if (generatorVersionRaw != null) {
if (generatorVersionRaw is! String) {
@@ -134,13 +130,13 @@
}
/// Convert to JSON structure.
- Map<String, Object> toJson() => {
+ Map<String, Object?> toJson() => {
'configVersion': configVersion,
'packages': packages.map((p) => p.toJson()).toList(),
- 'generated': generated?.toUtc()?.toIso8601String(),
+ 'generated': generated?.toUtc().toIso8601String(),
'generator': generator,
'generatorVersion': generatorVersion?.toString(),
- }..addAll(additionalProperties ?? {});
+ }..addAll(additionalProperties);
}
class PackageConfigEntry {
@@ -158,31 +154,27 @@
/// Import statements in Dart programs are resolved relative to this folder.
/// This must be in the sub-tree under [rootUri].
///
- /// This property is **optional** and may be `null` if not given.
- Uri packageUri;
+ /// `null` if not given.
+ Uri? packageUri;
/// Language version used by package.
///
/// Given as `<major>.<minor>` version, similar to the `// @dart = X.Y`
/// comment. This is derived from the lower-bound on the Dart SDK requirement
/// in the `pubspec.yaml` for the given package.
- ///
- /// This property is **optional** and may be `null` if not given.
- LanguageVersion languageVersion;
+ LanguageVersion? languageVersion;
/// Additional properties not in the specification for the
/// `.dart_tool/package_config.json` file.
- Map<String, dynamic> additionalProperties;
+ Map<String, dynamic>? additionalProperties;
PackageConfigEntry({
- @required this.name,
- @required this.rootUri,
+ required this.name,
+ required this.rootUri,
this.packageUri,
this.languageVersion,
- this.additionalProperties,
- }) {
- additionalProperties ??= {};
- }
+ this.additionalProperties = const {},
+ });
/// Create [PackageConfigEntry] from JSON [data].
///
@@ -193,9 +185,9 @@
throw FormatException(
'packages[] entries in package_config.json must be JSON objects');
}
- final root = data as Map<String, dynamic>;
+ final root = data;
- void _throw(String property, String mustBe) => throw FormatException(
+ Never _throw(String property, String mustBe) => throw FormatException(
'"packages[].$property" in .dart_tool/package_config.json $mustBe');
final name = root['name'];
@@ -203,7 +195,7 @@
_throw('name', 'must be a string');
}
- Uri rootUri;
+ final Uri rootUri;
final rootUriRaw = root['rootUri'];
if (rootUriRaw is! String) {
_throw('rootUri', 'must be a string');
@@ -214,7 +206,7 @@
_throw('rootUri', 'must be a URI');
}
- Uri packageUri;
+ Uri? packageUri;
var packageUriRaw = root['packageUri'];
if (packageUriRaw != null) {
if (packageUriRaw is! String) {
@@ -230,7 +222,7 @@
}
}
- LanguageVersion languageVersion;
+ LanguageVersion? languageVersion;
final languageVersionRaw = root['languageVersion'];
if (languageVersionRaw != null) {
if (languageVersionRaw is! String) {
@@ -252,10 +244,16 @@
}
/// Convert to JSON structure.
- Map<String, Object> toJson() => {
+ Map<String, Object?> toJson() => {
'name': name,
'rootUri': rootUri.toString(),
- if (packageUri != null) 'packageUri': packageUri?.toString(),
+ if (packageUri != null) 'packageUri': packageUri.toString(),
if (languageVersion != null) 'languageVersion': '$languageVersion',
}..addAll(additionalProperties ?? {});
+
+ @override
+ String toString() {
+ // TODO: implement toString
+ return JsonEncoder.withIndent(' ').convert(toJson());
+ }
}
diff --git a/lib/src/package_graph.dart b/lib/src/package_graph.dart
index ed1f30f..45351d7 100644
--- a/lib/src/package_graph.dart
+++ b/lib/src/package_graph.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:collection/collection.dart' hide mapMap;
import 'entrypoint.dart';
@@ -32,7 +30,7 @@
final Map<String, Package> packages;
/// A map of transitive dependencies for each package.
- Map<String, Set<Package>> _transitiveDependencies;
+ Map<String, Set<Package>>? _transitiveDependencies;
PackageGraph(this.entrypoint, this.lockFile, this.packages);
@@ -47,7 +45,7 @@
value: (id) {
if (id.name == entrypoint.root.name) return entrypoint.root;
- return Package(result.pubspecs[id.name],
+ return Package(result.pubspecs[id.name]!,
entrypoint.cache.source(id.source).getDirectory(id));
});
@@ -69,13 +67,12 @@
_transitiveDependencies =
mapMap<String, Set<String>, String, Set<Package>>(closure,
value: (depender, names) {
- var set = names.map((name) => packages[name]).toSet();
- set.add(packages[depender]);
+ var set = names.map((name) => packages[name]!).toSet();
+ set.add(packages[depender]!);
return set;
});
}
-
- return _transitiveDependencies[package];
+ return _transitiveDependencies![package]!;
}
bool _isPackageCached(String package) {
@@ -86,7 +83,7 @@
if (package == entrypoint.root.name) {
return entrypoint.isCached;
} else {
- var id = lockFile.packages[package];
+ var id = lockFile.packages[package]!;
return entrypoint.cache.source(id.source) is CachedSource;
}
}
diff --git a/lib/src/package_name.dart b/lib/src/package_name.dart
index a301338..d83f466 100644
--- a/lib/src/package_name.dart
+++ b/lib/src/package_name.dart
@@ -2,16 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:collection/collection.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package.dart';
import 'source.dart';
-import 'source/git.dart';
import 'source/hosted.dart';
-import 'source/path.dart';
import 'utils.dart';
/// The equality to use when comparing the feature sets of two package names.
@@ -25,7 +21,7 @@
/// The [Source] used to look up this package.
///
/// If this is a root package, this will be `null`.
- final Source source;
+ final Source? source;
/// The metadata used by the package's [source] to identify and locate it.
///
@@ -53,25 +49,31 @@
/// `this.toRef() == other.toRef()`.
bool samePackage(PackageName other) {
if (other.name != name) return false;
- if (source == null) return other.source == null;
+ var thisSource = source;
+ if (thisSource == null) return other.source == null;
- return other.source == source &&
- source.descriptionsEqual(description, other.description);
+ return other.source == thisSource &&
+ thisSource.descriptionsEqual(description, other.description);
}
@override
+ bool operator ==(Object other) =>
+ throw UnimplementedError('Subclass should implement ==');
+
+ @override
int get hashCode {
- if (source == null) return name.hashCode;
+ var thisSource = source;
+ if (thisSource == null) return name.hashCode;
return name.hashCode ^
- source.hashCode ^
- source.hashDescription(description);
+ thisSource.hashCode ^
+ thisSource.hashDescription(description);
}
/// Returns a string representation of this package name.
///
/// If [detail] is passed, it controls exactly which details are included.
@override
- String toString([PackageDetail detail]);
+ String toString([PackageDetail? detail]);
}
/// A reference to a [Package], but not any particular version(s) of it.
@@ -82,14 +84,14 @@
/// Since an ID's description is an implementation detail of its source, this
/// should generally not be called outside of [Source] subclasses. A reference
/// can be obtained from a user-supplied description using [Source.parseRef].
- PackageRef(String name, Source source, description)
+ PackageRef(String name, Source? source, description)
: super._(name, source, description);
/// Creates a reference to the given root package.
PackageRef.root(Package package) : super._(package.name, null, package.name);
@override
- String toString([PackageDetail detail]) {
+ String toString([PackageDetail? detail]) {
detail ??= PackageDetail.defaults;
if (isRoot) return name;
@@ -97,7 +99,7 @@
if (detail.showSource ?? source is! HostedSource) {
buffer.write(' from $source');
if (detail.showDescription) {
- buffer.write(' ${source.formatDescription(description)}');
+ buffer.write(' ${source!.formatDescription(description)}');
}
}
@@ -106,6 +108,9 @@
@override
bool operator ==(other) => other is PackageRef && samePackage(other);
+
+ @override
+ int get hashCode => super.hashCode ^ 'PackageRef'.hashCode;
}
/// A reference to a specific version of a package.
@@ -130,7 +135,7 @@
///
/// Since an ID's description is an implementation detail of its source, this
/// should generally not be called outside of [Source] subclasses.
- PackageId(String name, Source source, this.version, description)
+ PackageId(String name, Source? source, this.version, description)
: super._(name, source, description);
/// Creates an ID for the given root package.
@@ -149,7 +154,7 @@
PackageRange toRange() => withConstraint(version);
@override
- String toString([PackageDetail detail]) {
+ String toString([PackageDetail? detail]) {
detail ??= PackageDetail.defaults;
var buffer = StringBuffer(name);
@@ -158,7 +163,7 @@
if (!isRoot && (detail.showSource ?? source is! HostedSource)) {
buffer.write(' from $source');
if (detail.showDescription) {
- buffer.write(' ${source.formatDescription(description)}');
+ buffer.write(' ${source!.formatDescription(description)}');
}
}
@@ -179,8 +184,8 @@
///
/// Since an ID's description is an implementation detail of its source, this
/// should generally not be called outside of [Source] subclasses.
- PackageRange(String name, Source source, this.constraint, description,
- {Map<String, FeatureDependency> features})
+ PackageRange(String name, Source? source, this.constraint, description,
+ {Map<String, FeatureDependency>? features})
: features = features == null
? const {}
: UnmodifiableMapView(Map.from(features)),
@@ -220,7 +225,7 @@
}
@override
- String toString([PackageDetail detail]) {
+ String toString([PackageDetail? detail]) {
detail ??= PackageDetail.defaults;
var buffer = StringBuffer(name);
@@ -231,7 +236,7 @@
if (!isRoot && (detail.showSource ?? source is! HostedSource)) {
buffer.write(' from $source');
if (detail.showDescription) {
- buffer.write(' ${source.formatDescription(description)}');
+ buffer.write(' ${source!.formatDescription(description)}');
}
}
@@ -246,9 +251,7 @@
bool get _showVersionConstraint {
if (isRoot) return false;
if (!constraint.isAny) return true;
- if (source is PathSource) return false;
- if (source is GitSource) return false;
- return true;
+ return source!.hasMultipleVersions;
}
/// Returns a new [PackageRange] with [features] merged with [this.features].
@@ -267,9 +270,10 @@
var range = constraint as VersionRange;
if (!range.includeMin) return this;
if (range.includeMax) return this;
- if (range.min == null) return this;
- if (range.max == range.min.nextBreaking.firstPreRelease) {
- return withConstraint(VersionConstraint.compatibleWith(range.min));
+ var min = range.min;
+ if (min == null) return this;
+ if (range.max == min.nextBreaking.firstPreRelease) {
+ return withConstraint(VersionConstraint.compatibleWith(min));
} else {
return this;
}
@@ -328,13 +332,13 @@
/// If this is `null`, the version is shown for all packages other than root
/// [PackageId]s or [PackageRange]s with `git` or `path` sources and `any`
/// constraints.
- final bool showVersion;
+ final bool? showVersion;
/// Whether to show the package source.
///
/// If this is `null`, the source is shown for all non-hosted, non-root
/// packages. It's always `true` if [showDescription] is `true`.
- final bool showSource;
+ final bool? showSource;
/// Whether to show the package description.
///
@@ -348,9 +352,9 @@
const PackageDetail(
{this.showVersion,
- bool showSource,
- bool showDescription,
- bool showFeatures})
+ bool? showSource,
+ bool? showDescription,
+ bool? showFeatures})
: showSource = showDescription == true ? true : showSource,
showDescription = showDescription ?? false,
showFeatures = showFeatures ?? true;
@@ -358,8 +362,8 @@
/// Returns a [PackageDetail] with the maximum amount of detail between [this]
/// and [other].
PackageDetail max(PackageDetail other) => PackageDetail(
- showVersion: showVersion || other.showVersion,
- showSource: showSource || other.showSource,
+ showVersion: showVersion! || other.showVersion!,
+ showSource: showSource! || other.showSource!,
showDescription: showDescription || other.showDescription,
showFeatures: showFeatures || other.showFeatures);
}
diff --git a/lib/src/progress.dart b/lib/src/progress.dart
index 06ad9e9..b9c6931 100644
--- a/lib/src/progress.dart
+++ b/lib/src/progress.dart
@@ -34,7 +34,7 @@
Progress(this._message, {bool fine = false}) {
_stopwatch.start();
- var level = fine ? log.Level.FINE : log.Level.MESSAGE;
+ var level = fine ? log.Level.fine : log.Level.message;
// The animation is only shown when it would be meaningful to a human.
// That means we're writing a visible message to a TTY at normal log levels
@@ -43,7 +43,7 @@
!log.verbosity.isLevelVisible(level) ||
log.json.enabled ||
fine ||
- log.verbosity.isLevelVisible(log.Level.FINE)) {
+ log.verbosity.isLevelVisible(log.Level.fine)) {
// Not animating, so just log the start and wait until the task is
// completed.
log.write(level, '$_message...');
diff --git a/lib/src/pub_embeddable_command.dart b/lib/src/pub_embeddable_command.dart
index 4240ad1..b9e59c6 100644
--- a/lib/src/pub_embeddable_command.dart
+++ b/lib/src/pub_embeddable_command.dart
@@ -2,8 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
+import 'package:meta/meta.dart';
+import 'package:usage/usage.dart';
+import 'command.dart' show PubCommand, PubTopLevel;
import 'command.dart';
import 'command/add.dart';
import 'command/build.dart';
@@ -24,6 +26,22 @@
import 'log.dart' as log;
import 'log.dart';
+/// The information needed for the embedded pub command to send analytics.
+@sealed
+class PubAnalytics {
+ /// Name of the custom dimension of the dependency kind.
+ final String dependencyKindCustomDimensionName;
+
+ final Analytics? Function() _analyticsGetter;
+
+ Analytics? get analytics => _analyticsGetter();
+
+ PubAnalytics(
+ this._analyticsGetter, {
+ required this.dependencyKindCustomDimensionName,
+ });
+}
+
/// Exposes the `pub` commands as a command to be embedded in another command
/// runner such as `dart pub`.
class PubEmbeddableCommand extends PubCommand implements PubTopLevel {
@@ -37,11 +55,16 @@
@override
String get directory => argResults['directory'];
- PubEmbeddableCommand() : super() {
+ @override
+ final PubAnalytics? analytics;
+
+ final bool Function() isVerbose;
+
+ PubEmbeddableCommand(this.analytics, this.isVerbose) : super() {
argParser.addFlag('trace',
help: 'Print debugging information when an error occurs.');
argParser.addFlag('verbose',
- abbr: 'v', negatable: false, help: 'Shortcut for "--verbosity=all".');
+ abbr: 'v', negatable: false, help: 'Print detailed logging.');
argParser.addOption(
'directory',
abbr: 'C',
@@ -80,12 +103,15 @@
}
@override
- bool get captureStackChains => argResults['verbose'];
+ bool get captureStackChains => _isVerbose;
@override
- Verbosity get verbosity =>
- argResults['verbose'] ? Verbosity.ALL : Verbosity.NORMAL;
+ Verbosity get verbosity => _isVerbose ? Verbosity.all : Verbosity.normal;
@override
- bool get trace => argResults['verbose'];
+ bool get trace => _isVerbose;
+
+ bool get _isVerbose {
+ return argResults['verbose'] || isVerbose();
+ }
}
diff --git a/lib/src/pubspec.dart b/lib/src/pubspec.dart
index 5a3d3c0..cc75b2d 100644
--- a/lib/src/pubspec.dart
+++ b/lib/src/pubspec.dart
@@ -2,12 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
import 'package:collection/collection.dart' hide mapMap;
-import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:pub_semver/pub_semver.dart';
import 'package:source_span/source_span.dart';
@@ -19,23 +16,18 @@
import 'language_version.dart';
import 'log.dart';
import 'package_name.dart';
+import 'pubspec_parse.dart';
import 'sdk.dart';
import 'source_registry.dart';
import 'utils.dart';
-/// A regular expression matching allowed package names.
-///
-/// This allows dot-separated valid Dart identifiers. The dots are there for
-/// compatibility with Google's internal Dart packages, but they may not be used
-/// when publishing a package to pub.dartlang.org.
-final _packageName =
- RegExp('^${identifierRegExp.pattern}(\\.${identifierRegExp.pattern})*\$');
+export 'pubspec_parse.dart' hide PubspecBase;
/// The default SDK upper bound constraint for packages that don't declare one.
///
/// This provides a sane default for packages that don't have an upper bound.
final VersionRange _defaultUpperBoundSdkConstraint =
- VersionConstraint.parse('<2.0.0');
+ VersionConstraint.parse('<2.0.0') as VersionRange;
/// Whether or not to allow the pre-release SDK for packages that have an
/// upper bound Dart SDK constraint of <2.0.0.
@@ -72,7 +64,7 @@
/// accessed. This allows a partially-invalid pubspec to be used if only the
/// valid portions are relevant. To get a list of all errors in the pubspec, use
/// [allErrors].
-class Pubspec {
+class Pubspec extends PubspecBase {
// If a new lazily-initialized field is added to this class and the
// initialization can throw a [PubspecException], that error should also be
// exposed through [allErrors].
@@ -82,145 +74,64 @@
///
/// This will be null if this was created using [new Pubspec] or [new
/// Pubspec.empty].
- final SourceRegistry _sources;
+ final SourceRegistry? _sources;
/// The location from which the pubspec was loaded.
///
/// This can be null if the pubspec was created in-memory or if its location
/// is unknown.
- Uri get _location => fields.span.sourceUrl;
-
- /// All pubspec fields.
- ///
- /// This includes the fields from which other properties are derived.
- final YamlMap fields;
-
- /// Whether or not to apply the [_defaultUpperBoundsSdkConstraint] to this
- /// pubspec.
- final bool _includeDefaultSdkConstraint;
-
- /// Whether or not the SDK version was overridden from <2.0.0 to
- /// <2.0.0-dev.infinity.
- bool get dartSdkWasOverridden => _dartSdkWasOverridden;
- bool _dartSdkWasOverridden = false;
-
- /// The package's name.
- String get name {
- if (_name != null) return _name;
-
- var name = fields['name'];
- if (name == null) {
- throw PubspecException('Missing the required "name" field.', fields.span);
- } else if (name is! String) {
- throw PubspecException(
- '"name" field must be a string.', fields.nodes['name'].span);
- } else if (!_packageName.hasMatch(name)) {
- throw PubspecException('"name" field must be a valid Dart identifier.',
- fields.nodes['name'].span);
- } else if (reservedWords.contains(name)) {
- throw PubspecException('"name" field may not be a Dart reserved word.',
- fields.nodes['name'].span);
- }
-
- _name = name;
- return _name;
- }
-
- String _name;
-
- /// The package's version.
- Version get version {
- if (_version != null) return _version;
-
- var version = fields['version'];
- if (version == null) {
- _version = Version.none;
- return _version;
- }
-
- var span = fields.nodes['version'].span;
- if (version is num) {
- var fixed = '$version.0';
- if (version is int) {
- fixed = '$fixed.0';
- }
- _error(
- '"version" field must have three numeric components: major, '
- 'minor, and patch. Instead of "$version", consider "$fixed".',
- span);
- }
- if (version is! String) {
- _error('"version" field must be a string.', span);
- }
-
- _version = _wrapFormatException(
- 'version number', span, () => Version.parse(version));
- return _version;
- }
-
- Version _version;
+ Uri? get _location => fields.span.sourceUrl;
/// The additional packages this package depends on.
- Map<String, PackageRange> get dependencies {
- if (_dependencies != null) return _dependencies;
- _dependencies =
- _parseDependencies('dependencies', fields.nodes['dependencies']);
- return _dependencies;
- }
+ Map<String, PackageRange> get dependencies => _dependencies ??=
+ _parseDependencies('dependencies', fields.nodes['dependencies']);
- Map<String, PackageRange> _dependencies;
+ Map<String, PackageRange>? _dependencies;
/// The packages this package depends on when it is the root package.
- Map<String, PackageRange> get devDependencies {
- if (_devDependencies != null) return _devDependencies;
- _devDependencies = _parseDependencies(
- 'dev_dependencies', fields.nodes['dev_dependencies']);
- return _devDependencies;
- }
+ Map<String, PackageRange> get devDependencies => _devDependencies ??=
+ _parseDependencies('dev_dependencies', fields.nodes['dev_dependencies']);
- Map<String, PackageRange> _devDependencies;
+ Map<String, PackageRange>? _devDependencies;
/// The dependency constraints that this package overrides when it is the
/// root package.
///
/// Dependencies here will replace any dependency on a package with the same
/// name anywhere in the dependency graph.
- Map<String, PackageRange> get dependencyOverrides {
- if (_dependencyOverrides != null) return _dependencyOverrides;
- _dependencyOverrides = _parseDependencies(
- 'dependency_overrides', fields.nodes['dependency_overrides']);
- return _dependencyOverrides;
- }
+ Map<String, PackageRange> get dependencyOverrides =>
+ _dependencyOverrides ??= _parseDependencies(
+ 'dependency_overrides', fields.nodes['dependency_overrides']);
- Map<String, PackageRange> _dependencyOverrides;
+ Map<String, PackageRange>? _dependencyOverrides;
- Map<String, Feature> get features {
- if (_features != null) return _features;
- var features = fields['features'];
+ late final Map<String, Feature> features = _computeFeatures();
+
+ Map<String, Feature> _computeFeatures() {
+ final features = fields['features'];
if (features == null) {
- _features = const {};
- return _features;
+ return const {};
}
- if (features is! Map) {
- _error('"features" field must be a map.', fields.nodes['features'].span);
+ if (features is! YamlMap) {
+ _error('"features" field must be a map.', fields.nodes['features']!.span);
}
- _features = mapMap(features.nodes,
- key: (nameNode, _) => _validateFeatureName(nameNode),
- value: (nameNode, specNode) {
+ return mapMap(features.nodes,
+ key: (dynamic nameNode, dynamic _) => _validateFeatureName(nameNode),
+ value: (dynamic nameNode, dynamic specNode) {
if (specNode.value == null) {
return Feature(nameNode.value, const []);
}
- if (specNode is! Map) {
+ if (specNode is! YamlMap) {
_error('A feature specification must be a map.', specNode.span);
}
var onByDefault = specNode['default'] ?? true;
if (onByDefault is! bool) {
_error('Default must be true or false.',
- specNode.nodes['default'].span);
+ specNode.nodes['default']!.span);
}
var requires = _parseStringList(specNode.nodes['requires'],
@@ -238,18 +149,24 @@
sdkConstraints: sdkConstraints,
onByDefault: onByDefault);
});
- return _features;
}
- Map<String, Feature> _features;
-
/// A map from SDK identifiers to constraints on those SDK versions.
Map<String, VersionConstraint> get sdkConstraints {
_ensureEnvironment();
- return _sdkConstraints;
+ return _sdkConstraints!;
}
- Map<String, VersionConstraint> _sdkConstraints;
+ Map<String, VersionConstraint>? _sdkConstraints;
+
+ /// Whether or not to apply the [_defaultUpperBoundsSdkConstraint] to this
+ /// pubspec.
+ final bool _includeDefaultSdkConstraint;
+
+ /// Whether or not the SDK version was overridden from <2.0.0 to
+ /// <2.0.0-dev.infinity.
+ bool get dartSdkWasOverridden => _dartSdkWasOverridden;
+ bool _dartSdkWasOverridden = false;
/// The original Dart SDK constraint as written in the pubspec.
///
@@ -257,10 +174,10 @@
/// `sdkConstraints["dart"]`.
VersionConstraint get originalDartSdkConstraint {
_ensureEnvironment();
- return _originalDartSdkConstraint ?? sdkConstraints['dart'];
+ return _originalDartSdkConstraint ?? sdkConstraints['dart']!;
}
- VersionConstraint _originalDartSdkConstraint;
+ VersionConstraint? _originalDartSdkConstraint;
/// Ensures that the top-level "environment" field has been parsed and
/// [_sdkConstraints] is set accordingly.
@@ -300,17 +217,19 @@
if (!_allowPreReleaseSdk) return false;
if (!sdk.version.isPreRelease) return false;
if (sdkConstraint.includeMax) return false;
- if (sdkConstraint.min != null &&
- sdkConstraint.min.isPreRelease &&
- equalsIgnoringPreRelease(sdkConstraint.min, sdk.version)) {
+ var minSdkConstraint = sdkConstraint.min;
+ if (minSdkConstraint != null &&
+ minSdkConstraint.isPreRelease &&
+ equalsIgnoringPreRelease(sdkConstraint.min!, sdk.version)) {
return false;
}
- if (sdkConstraint.max == null) return false;
- if (sdkConstraint.max.isPreRelease &&
- !sdkConstraint.max.isFirstPreRelease) {
+ var maxSdkConstraint = sdkConstraint.max;
+ if (maxSdkConstraint == null) return false;
+ if (maxSdkConstraint.max.isPreRelease &&
+ !maxSdkConstraint.isFirstPreRelease) {
return false;
}
- return equalsIgnoringPreRelease(sdkConstraint.max, sdk.version);
+ return equalsIgnoringPreRelease(maxSdkConstraint, sdk.version);
}
/// Parses the "environment" field in [parent] and returns a map from SDK
@@ -325,9 +244,9 @@
};
}
- if (yaml is! Map) {
+ if (yaml is! YamlMap) {
_error('"environment" field must be a map.',
- parent.nodes['environment'].span);
+ parent.nodes['environment']!.span);
}
var constraints = {
@@ -353,141 +272,6 @@
return constraints;
}
- /// The URL of the server that the package should default to being published
- /// to, "none" if the package should not be published, or `null` if it should
- /// be published to the default server.
- ///
- /// If this does return a URL string, it will be a valid parseable URL.
- String get publishTo {
- if (_parsedPublishTo) return _publishTo;
-
- var publishTo = fields['publish_to'];
- if (publishTo != null) {
- var span = fields.nodes['publish_to'].span;
-
- if (publishTo is! String) {
- _error('"publish_to" field must be a string.', span);
- }
-
- // It must be "none" or a valid URL.
- if (publishTo != 'none') {
- _wrapFormatException('"publish_to" field', span, () {
- var url = Uri.parse(publishTo);
- if (url.scheme.isEmpty) {
- throw FormatException('must be an absolute URL.');
- }
- });
- }
- }
-
- _parsedPublishTo = true;
- _publishTo = publishTo;
- return _publishTo;
- }
-
- bool _parsedPublishTo = false;
- String _publishTo;
-
- /// The list of patterns covering _false-positive secrets_ in the package.
- ///
- /// This is a list of git-ignore style patterns for files that should be
- /// ignored when trying to detect possible leaks of secrets during
- /// package publication.
- List<String> get falseSecrets {
- if (_falseSecrets == null) {
- final falseSecrets = <String>[];
-
- // Throws a [PubspecException]
- void _falseSecretsError(SourceSpan span) => _error(
- '"false_secrets" field must be a list of git-ignore style patterns',
- span,
- );
-
- final falseSecretsNode = fields.nodes['false_secrets'];
- if (falseSecretsNode != null) {
- if (falseSecretsNode is YamlList) {
- for (final node in falseSecretsNode.nodes) {
- final value = node.value;
- if (value is! String) {
- _falseSecretsError(node.span);
- }
- falseSecrets.add(value);
- }
- } else {
- _falseSecretsError(falseSecretsNode.span);
- }
- }
-
- _falseSecrets = List.unmodifiable(falseSecrets);
- }
- return _falseSecrets;
- }
-
- List<String> _falseSecrets;
-
- /// The executables that should be placed on the user's PATH when this
- /// package is globally activated.
- ///
- /// It is a map of strings to string. Each key is the name of the command
- /// that will be placed on the user's PATH. The value is the name of the
- /// .dart script (without extension) in the package's `bin` directory that
- /// should be run for that command. Both key and value must be "simple"
- /// strings: alphanumerics, underscores and hypens only. If a value is
- /// omitted, it is inferred to use the same name as the key.
- Map<String, String> get executables {
- if (_executables != null) return _executables;
-
- _executables = {};
- var yaml = fields['executables'];
- if (yaml == null) return _executables;
-
- if (yaml is! Map) {
- _error('"executables" field must be a map.',
- fields.nodes['executables'].span);
- }
-
- yaml.nodes.forEach((key, value) {
- if (key.value is! String) {
- _error('"executables" keys must be strings.', key.span);
- }
-
- final keyPattern = RegExp(r'^[a-zA-Z0-9_-]+$');
- if (!keyPattern.hasMatch(key.value)) {
- _error(
- '"executables" keys may only contain letters, '
- 'numbers, hyphens and underscores.',
- key.span);
- }
-
- if (value.value == null) {
- value = key;
- } else if (value.value is! String) {
- _error('"executables" values must be strings or null.', value.span);
- }
-
- final valuePattern = RegExp(r'[/\\]');
- if (valuePattern.hasMatch(value.value)) {
- _error('"executables" values may not contain path separators.',
- value.span);
- }
-
- _executables[key.value] = value.value;
- });
-
- return _executables;
- }
-
- Map<String, String> _executables;
-
- /// Whether the package is private and cannot be published.
- ///
- /// This is specified in the pubspec by setting "publish_to" to "none".
- bool get isPrivate => publishTo == 'none';
-
- /// Whether or not the pubspec has no contents.
- bool get isEmpty =>
- name == null && version == Version.none && dependencies.isEmpty;
-
/// The language version implied by the sdk constraint.
LanguageVersion get languageVersion =>
LanguageVersion.fromSdkConstraint(originalDartSdkConstraint);
@@ -497,7 +281,7 @@
/// If [expectedName] is passed and the pubspec doesn't have a matching name
/// field, this will throw a [PubspecException].
factory Pubspec.load(String packageDir, SourceRegistry sources,
- {String expectedName}) {
+ {String? expectedName}) {
var pubspecPath = path.join(packageDir, 'pubspec.yaml');
var pubspecUri = path.toUri(pubspecPath);
if (!fileExists(pubspecPath)) {
@@ -513,16 +297,15 @@
expectedName: expectedName, location: pubspecUri);
}
- Pubspec(this._name,
- {Version version,
- Iterable<PackageRange> dependencies,
- Iterable<PackageRange> devDependencies,
- Iterable<PackageRange> dependencyOverrides,
- Map fields,
- SourceRegistry sources,
- Map<String, VersionConstraint> sdkConstraints})
- : _version = version,
- _dependencies = dependencies == null
+ Pubspec(String name,
+ {Version? version,
+ Iterable<PackageRange>? dependencies,
+ Iterable<PackageRange>? devDependencies,
+ Iterable<PackageRange>? dependencyOverrides,
+ Map? fields,
+ SourceRegistry? sources,
+ Map<String, VersionConstraint>? sdkConstraints})
+ : _dependencies = dependencies == null
? null
: Map.fromIterable(dependencies, key: (range) => range.name),
_devDependencies = devDependencies == null
@@ -534,18 +317,22 @@
_sdkConstraints = sdkConstraints ??
UnmodifiableMapView({'dart': VersionConstraint.any}),
_includeDefaultSdkConstraint = false,
- fields = fields == null ? YamlMap() : YamlMap.wrap(fields),
- _sources = sources;
-
+ _sources = sources,
+ super(
+ fields == null ? YamlMap() : YamlMap.wrap(fields),
+ name: name,
+ version: version,
+ );
Pubspec.empty()
: _sources = null,
- _name = null,
- _version = Version.none,
_dependencies = {},
_devDependencies = {},
_sdkConstraints = {'dart': VersionConstraint.any},
_includeDefaultSdkConstraint = false,
- fields = YamlMap();
+ super(
+ YamlMap(),
+ version: Version.none,
+ );
/// Returns a Pubspec object for an already-parsed map representing its
/// contents.
@@ -555,11 +342,11 @@
///
/// [location] is the location from which this pubspec was loaded.
Pubspec.fromMap(Map fields, this._sources,
- {String expectedName, Uri location})
- : fields = fields is YamlMap
+ {String? expectedName, Uri? location})
+ : _includeDefaultSdkConstraint = true,
+ super(fields is YamlMap
? fields
- : YamlMap.wrap(fields, sourceUrl: location),
- _includeDefaultSdkConstraint = true {
+ : YamlMap.wrap(fields, sourceUrl: location)) {
// If [expectedName] is passed, ensure that the actual 'name' field exists
// and matches the expectation.
if (expectedName == null) return;
@@ -568,7 +355,7 @@
throw PubspecException(
'"name" field doesn\'t match expected name '
'"$expectedName".',
- this.fields.nodes['name'].span);
+ this.fields.nodes['name']!.span);
}
/// Parses the pubspec stored at [filePath] whose text is [contents].
@@ -576,7 +363,7 @@
/// If the pubspec doesn't define a version for itself, it defaults to
/// [Version.none].
factory Pubspec.parse(String contents, SourceRegistry sources,
- {String expectedName, Uri location}) {
+ {String? expectedName, Uri? location}) {
YamlNode pubspecNode;
try {
pubspecNode = loadYamlNode(contents, sourceUrl: location);
@@ -625,7 +412,7 @@
/// Parses the dependency field named [field], and returns the corresponding
/// map of dependency names to dependencies.
- Map<String, PackageRange> _parseDependencies(String field, YamlNode node) {
+ Map<String, PackageRange> _parseDependencies(String field, YamlNode? node) {
var dependencies = <String, PackageRange>{};
// Allow an empty dependencies key.
@@ -635,31 +422,28 @@
_error('"$field" field must be a map.', node.span);
}
- var map = node as YamlMap;
- var nonStringNode = map.nodes.keys
+ var nonStringNode = node.nodes.keys
.firstWhere((e) => e.value is! String, orElse: () => null);
if (nonStringNode != null) {
_error('A dependency name must be a string.', nonStringNode.span);
}
- map.nodes.forEach((nameNode, specNode) {
+ node.nodes.forEach((nameNode, specNode) {
var name = nameNode.value;
var spec = specNode.value;
if (fields['name'] != null && name == this.name) {
_error('A package may not list itself as a dependency.', nameNode.span);
}
- YamlNode descriptionNode;
- String sourceName;
+ YamlNode? descriptionNode;
+ String? sourceName;
VersionConstraint versionConstraint = VersionRange();
var features = const <String, FeatureDependency>{};
if (spec == null) {
- descriptionNode = nameNode;
- sourceName = _sources.defaultSource.name;
+ sourceName = _sources!.defaultSource.name;
} else if (spec is String) {
- descriptionNode = nameNode;
- sourceName = _sources.defaultSource.name;
+ sourceName = _sources!.defaultSource.name;
versionConstraint = _parseVersionConstraint(specNode);
} else if (spec is Map) {
// Don't write to the immutable YAML map.
@@ -682,7 +466,6 @@
} else if (sourceNames.isEmpty) {
// Default to a hosted dependency if no source is specified.
sourceName = 'hosted';
- descriptionNode = nameNode;
}
sourceName ??= sourceNames.single;
@@ -699,13 +482,18 @@
// Let the source validate the description.
var ref = _wrapFormatException('description', descriptionNode?.span, () {
- String pubspecPath;
- if (_location != null && _isFileUri(_location)) {
+ String? pubspecPath;
+ var location = _location;
+ if (location != null && _isFileUri(location)) {
pubspecPath = path.fromUri(_location);
}
- return _sources[sourceName].parseRef(name, descriptionNode?.value,
- containingPath: pubspecPath);
+ return _sources![sourceName]!.parseRef(
+ name,
+ descriptionNode?.value,
+ containingPath: pubspecPath,
+ languageVersion: languageVersion,
+ );
}, targetPackage: name);
dependencies[name] =
@@ -722,13 +510,13 @@
/// bound and it is compatible with [defaultUpperBoundConstraint].
///
/// If [ignoreUpperBound] the max constraint is ignored.
- VersionConstraint _parseVersionConstraint(YamlNode node,
- {VersionConstraint defaultUpperBoundConstraint,
+ VersionConstraint _parseVersionConstraint(YamlNode? node,
+ {VersionConstraint? defaultUpperBoundConstraint,
bool ignoreUpperBound = false}) {
if (node?.value == null) {
return defaultUpperBoundConstraint ?? VersionConstraint.any;
}
- if (node.value is! String) {
+ if (node!.value is! String) {
_error('A version constraint must be a string.', node.span);
}
@@ -751,13 +539,13 @@
/// Parses [node] to a map from feature names to whether those features are
/// enabled.
- Map<String, FeatureDependency> _parseDependencyFeatures(YamlNode node) {
+ Map<String, FeatureDependency> _parseDependencyFeatures(YamlNode? node) {
if (node?.value == null) return const {};
- if (node is! YamlMap) _error('Features must be a map.', node.span);
+ if (node is! YamlMap) _error('Features must be a map.', node!.span);
- return mapMap((node as YamlMap).nodes,
- key: (nameNode, _) => _validateFeatureName(nameNode),
- value: (_, valueNode) {
+ return mapMap(node.nodes,
+ key: (dynamic nameNode, dynamic _) => _validateFeatureName(nameNode),
+ value: (dynamic _, dynamic valueNode) {
var value = valueNode.value;
if (value is bool) {
return value
@@ -778,7 +566,7 @@
var name = node.value;
if (name is! String) {
_error('A feature name must be a string.', node.span);
- } else if (!_packageName.hasMatch(name)) {
+ } else if (!packageNameRegExp.hasMatch(name)) {
_error('A feature name must be a valid Dart identifier.', node.span);
}
@@ -788,8 +576,8 @@
/// Verifies that [node] is a list of strings and returns it.
///
/// If [validate] is passed, it's called for each string in [node].
- List<String> _parseStringList(YamlNode node,
- {void Function(String value, SourceSpan) validate}) {
+ List<String> _parseStringList(YamlNode? node,
+ {void Function(String value, SourceSpan)? validate}) {
var list = _parseList(node);
for (var element in list.nodes) {
var value = element.value;
@@ -803,7 +591,7 @@
}
/// Verifies that [node] is a list and returns it.
- YamlList _parseList(YamlNode node) {
+ YamlList _parseList(YamlNode? node) {
if (node == null || node.value == null) return YamlList();
if (node is YamlList) return node;
_error('Must be a list.', node.span);
@@ -819,11 +607,14 @@
/// If [targetPackage] is provided, the value is used to describe the
/// dependency that caused the problem.
T _wrapFormatException<T>(
- String description, SourceSpan span, T Function() fn,
- {String targetPackage}) {
+ String description, SourceSpan? span, T Function() fn,
+ {String? targetPackage}) {
try {
return fn();
} on FormatException catch (e) {
+ // If we already have a pub exception with a span, re-use that
+ if (e is PubspecException) rethrow;
+
var msg = 'Invalid $description';
if (targetPackage != null) {
msg = '$msg in the "$name" pubspec on the "$targetPackage" dependency';
@@ -834,20 +625,11 @@
}
/// Throws a [PubspecException] with the given message.
- @alwaysThrows
- void _error(String message, SourceSpan span) {
+ Never _error(String message, SourceSpan? span) {
throw PubspecException(message, span);
}
}
-/// An exception thrown when parsing a pubspec.
-///
-/// These exceptions are often thrown lazily while accessing pubspec properties.
-class PubspecException extends SourceSpanFormatException
- implements ApplicationException {
- PubspecException(String message, SourceSpan span) : super(message, span);
-}
-
/// Returns whether [uri] is a file URI.
///
/// This is slightly more complicated than just checking if the scheme is
diff --git a/lib/src/pubspec_parse.dart b/lib/src/pubspec_parse.dart
new file mode 100644
index 0000000..68f9ce7
--- /dev/null
+++ b/lib/src/pubspec_parse.dart
@@ -0,0 +1,262 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+import 'package:pub_semver/pub_semver.dart';
+import 'package:source_span/source_span.dart';
+import 'package:yaml/yaml.dart';
+
+import 'exceptions.dart' show ApplicationException;
+import 'utils.dart' show identifierRegExp, reservedWords;
+
+/// A regular expression matching allowed package names.
+///
+/// This allows dot-separated valid Dart identifiers. The dots are there for
+/// compatibility with Google's internal Dart packages, but they may not be used
+/// when publishing a package to pub.dartlang.org.
+final packageNameRegExp =
+ RegExp('^${identifierRegExp.pattern}(\\.${identifierRegExp.pattern})*\$');
+
+/// Helper class for pubspec parsing to:
+/// - extract the fields and methods that are reusable outside of `pub` client, and
+/// - help null-safety migration a bit.
+///
+/// This class should be eventually extracted to a separate library, or re-merged with `Pubspec`.
+abstract class PubspecBase {
+ /// All pubspec fields.
+ ///
+ /// This includes the fields from which other properties are derived.
+ final YamlMap fields;
+
+ PubspecBase(
+ this.fields, {
+ String? name,
+ Version? version,
+ }) : _name = name,
+ _version = version;
+
+ /// The package's name.
+ String get name => _name ??= _lookupName();
+
+ String _lookupName() {
+ final name = fields['name'];
+ if (name == null) {
+ throw PubspecException('Missing the required "name" field.', fields.span);
+ } else if (name is! String) {
+ throw PubspecException(
+ '"name" field must be a string.', fields.nodes['name']?.span);
+ } else if (!packageNameRegExp.hasMatch(name)) {
+ throw PubspecException('"name" field must be a valid Dart identifier.',
+ fields.nodes['name']?.span);
+ } else if (reservedWords.contains(name)) {
+ throw PubspecException('"name" field may not be a Dart reserved word.',
+ fields.nodes['name']?.span);
+ }
+
+ return name;
+ }
+
+ String? _name;
+
+ /// The package's version.
+ Version get version {
+ if (_version != null) return _version!;
+
+ final version = fields['version'];
+ if (version == null) {
+ _version = Version.none;
+ return _version!;
+ }
+
+ final span = fields.nodes['version']?.span;
+ if (version is num) {
+ var fixed = '$version.0';
+ if (version is int) {
+ fixed = '$fixed.0';
+ }
+ _error(
+ '"version" field must have three numeric components: major, '
+ 'minor, and patch. Instead of "$version", consider "$fixed".',
+ span);
+ }
+ if (version is! String) {
+ _error('"version" field must be a string.', span);
+ }
+
+ _version = _wrapFormatException(
+ 'version number', span, () => Version.parse(version));
+ return _version!;
+ }
+
+ Version? _version;
+
+ /// The URL of the server that the package should default to being published
+ /// to, "none" if the package should not be published, or `null` if it should
+ /// be published to the default server.
+ ///
+ /// If this does return a URL string, it will be a valid parseable URL.
+ String? get publishTo {
+ if (_parsedPublishTo) return _publishTo;
+
+ final publishTo = fields['publish_to'];
+ if (publishTo != null) {
+ final span = fields.nodes['publish_to']?.span;
+
+ if (publishTo is! String) {
+ _error('"publish_to" field must be a string.', span);
+ }
+
+ // It must be "none" or a valid URL.
+ if (publishTo != 'none') {
+ _wrapFormatException('"publish_to" field', span, () {
+ final url = Uri.parse(publishTo);
+ if (url.scheme.isEmpty) {
+ throw FormatException('must be an absolute URL.');
+ }
+ });
+ }
+ }
+
+ _parsedPublishTo = true;
+ _publishTo = publishTo;
+ return _publishTo;
+ }
+
+ bool _parsedPublishTo = false;
+ String? _publishTo;
+
+ /// The list of patterns covering _false-positive secrets_ in the package.
+ ///
+ /// This is a list of git-ignore style patterns for files that should be
+ /// ignored when trying to detect possible leaks of secrets during
+ /// package publication.
+ List<String> get falseSecrets {
+ if (_falseSecrets == null) {
+ final falseSecrets = <String>[];
+
+ // Throws a [PubspecException]
+ void _falseSecretsError(SourceSpan span) => _error(
+ '"false_secrets" field must be a list of git-ignore style patterns',
+ span,
+ );
+
+ final falseSecretsNode = fields.nodes['false_secrets'];
+ if (falseSecretsNode != null) {
+ if (falseSecretsNode is YamlList) {
+ for (final node in falseSecretsNode.nodes) {
+ final value = node.value;
+ if (value is! String) {
+ _falseSecretsError(node.span);
+ }
+ falseSecrets.add(value);
+ }
+ } else {
+ _falseSecretsError(falseSecretsNode.span);
+ }
+ }
+
+ _falseSecrets = List.unmodifiable(falseSecrets);
+ }
+ return _falseSecrets!;
+ }
+
+ List<String>? _falseSecrets;
+
+ /// The executables that should be placed on the user's PATH when this
+ /// package is globally activated.
+ ///
+ /// It is a map of strings to string. Each key is the name of the command
+ /// that will be placed on the user's PATH. The value is the name of the
+ /// .dart script (without extension) in the package's `bin` directory that
+ /// should be run for that command. Both key and value must be "simple"
+ /// strings: alphanumerics, underscores and hypens only. If a value is
+ /// omitted, it is inferred to use the same name as the key.
+ Map<String, String> get executables {
+ if (_executables != null) return _executables!;
+
+ _executables = {};
+ var yaml = fields['executables'];
+ if (yaml == null) return _executables!;
+
+ if (yaml is! Map) {
+ _error('"executables" field must be a map.',
+ fields.nodes['executables']?.span);
+ }
+
+ yaml.nodes.forEach((key, value) {
+ if (key.value is! String) {
+ _error('"executables" keys must be strings.', key.span);
+ }
+
+ final keyPattern = RegExp(r'^[a-zA-Z0-9_-]+$');
+ if (!keyPattern.hasMatch(key.value)) {
+ _error(
+ '"executables" keys may only contain letters, '
+ 'numbers, hyphens and underscores.',
+ key.span);
+ }
+
+ if (value.value == null) {
+ value = key;
+ } else if (value.value is! String) {
+ _error('"executables" values must be strings or null.', value.span);
+ }
+
+ final valuePattern = RegExp(r'[/\\]');
+ if (valuePattern.hasMatch(value.value)) {
+ _error('"executables" values may not contain path separators.',
+ value.span);
+ }
+
+ _executables![key.value] = value.value;
+ });
+
+ return _executables!;
+ }
+
+ Map<String, String>? _executables;
+
+ /// Whether the package is private and cannot be published.
+ ///
+ /// This is specified in the pubspec by setting "publish_to" to "none".
+ bool get isPrivate => publishTo == 'none';
+
+ /// Runs [fn] and wraps any [FormatException] it throws in a
+ /// [PubspecException].
+ ///
+ /// [description] should be a noun phrase that describes whatever's being
+ /// parsed or processed by [fn]. [span] should be the location of whatever's
+ /// being processed within the pubspec.
+ ///
+ /// If [targetPackage] is provided, the value is used to describe the
+ /// dependency that caused the problem.
+ T _wrapFormatException<T>(
+ String description, SourceSpan? span, T Function() fn,
+ {String? targetPackage}) {
+ try {
+ return fn();
+ } on FormatException catch (e) {
+ var msg = 'Invalid $description';
+ if (targetPackage != null) {
+ msg = '$msg in the "$name" pubspec on the "$targetPackage" dependency';
+ }
+ msg = '$msg: ${e.message}';
+ throw PubspecException(msg, span);
+ }
+ }
+
+ /// Throws a [PubspecException] with the given message.
+ @alwaysThrows
+ void _error(String message, SourceSpan? span) {
+ throw PubspecException(message, span);
+ }
+}
+
+/// An exception thrown when parsing a pubspec.
+///
+/// These exceptions are often thrown lazily while accessing pubspec properties.
+class PubspecException extends SourceSpanFormatException
+ implements ApplicationException {
+ PubspecException(String message, SourceSpan? span) : super(message, span);
+}
diff --git a/lib/src/pubspec_utils.dart b/lib/src/pubspec_utils.dart
index d58fb62..ee904a7 100644
--- a/lib/src/pubspec_utils.dart
+++ b/lib/src/pubspec_utils.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
+import 'dart:async';
import 'package:pub_semver/pub_semver.dart';
@@ -42,7 +42,7 @@
Future<Pubspec> constrainedToAtLeastNullSafetyPubspec(
Pubspec original, SystemCache cache) async {
/// Get the first version of [package] opting in to null-safety.
- Future<VersionRange> constrainToFirstWithNullSafety(
+ Future<VersionConstraint> constrainToFirstWithNullSafety(
PackageRange packageRange) async {
final ref = packageRange.toRef();
final available = await cache.source(ref.source).getVersions(ref);
@@ -65,7 +65,7 @@
Map<String, PackageRange> constrained,
) async {
final result = await Future.wait(constrained.keys.map((name) async {
- final packageRange = constrained[name];
+ final packageRange = constrained[name]!;
var unconstrainedRange = packageRange;
/// We only need to remove the upper bound if it is a hosted package.
@@ -106,7 +106,7 @@
/// not specified or empty, then all packages will have their upper bounds
/// removed.
Pubspec stripVersionUpperBounds(Pubspec original,
- {Iterable<String> stripOnly}) {
+ {Iterable<String>? stripOnly}) {
ArgumentError.checkNotNull(original, 'original');
stripOnly ??= [];
@@ -116,12 +116,12 @@
final result = <PackageRange>[];
for (final name in constrained.keys) {
- final packageRange = constrained[name];
+ final packageRange = constrained[name]!;
var unconstrainedRange = packageRange;
/// We only need to remove the upper bound if it is a hosted package.
if (packageRange.source is HostedSource &&
- (stripOnly.isEmpty || stripOnly.contains(packageRange.name))) {
+ (stripOnly!.isEmpty || stripOnly.contains(packageRange.name))) {
unconstrainedRange = PackageRange(
packageRange.name,
packageRange.source,
diff --git a/lib/src/rate_limited_scheduler.dart b/lib/src/rate_limited_scheduler.dart
index 6e62310..85d73cd 100644
--- a/lib/src/rate_limited_scheduler.dart
+++ b/lib/src/rate_limited_scheduler.dart
@@ -2,13 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:collection';
-import 'package:meta/meta.dart';
-import 'package:pedantic/pedantic.dart';
import 'package:pool/pool.dart';
/// Handles rate-limited scheduling of tasks.
@@ -65,7 +61,7 @@
final Set<J> _started = {};
RateLimitedScheduler(Future<V> Function(J) runJob,
- {@required int maxConcurrentOperations})
+ {required int maxConcurrentOperations})
: _runJob = runJob,
_pool = Pool(maxConcurrentOperations);
@@ -77,7 +73,7 @@
return;
}
final task = _queue.removeFirst();
- final completer = _cache[task.jobId];
+ final completer = _cache[task.jobId]!;
if (!_started.add(task.jobId)) {
return;
@@ -95,7 +91,9 @@
// become uncaught.
//
// They will still show up for other listeners of the future.
- await completer.future.catchError((_) {});
+ try {
+ await completer.future;
+ } catch (_) {}
}
/// Calls [callback] with a function that can pre-schedule jobs.
@@ -140,7 +138,7 @@
/// Returns the result of running [jobId] if that is already done.
/// Otherwise returns `null`.
- V peek(J jobId) => _results[jobId];
+ V? peek(J jobId) => _results[jobId];
}
class _Task<J> {
diff --git a/lib/src/solver.dart b/lib/src/solver.dart
index 18d3c23..74dbfa8 100644
--- a/lib/src/solver.dart
+++ b/lib/src/solver.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'lock_file.dart';
@@ -33,8 +31,8 @@
SolveType type,
SystemCache cache,
Package root, {
- LockFile lockFile,
- Iterable<String> unlock,
+ LockFile? lockFile,
+ Iterable<String> unlock = const [],
}) {
lockFile ??= LockFile.empty();
return VersionSolver(
@@ -42,7 +40,7 @@
cache,
root,
lockFile,
- unlock ?? [],
+ unlock,
).solve();
}
@@ -60,12 +58,12 @@
/// If [unlock] is empty [SolveType.get] interprets this as lock everything,
/// while [SolveType.upgrade] and [SolveType.downgrade] interprets an empty
/// [unlock] as unlock everything.
-Future<SolveResult> tryResolveVersions(
+Future<SolveResult?> tryResolveVersions(
SolveType type,
SystemCache cache,
Package root, {
- LockFile lockFile,
- Iterable<String> unlock,
+ LockFile? lockFile,
+ Iterable<String>? unlock,
}) async {
try {
return await resolveVersions(
@@ -73,7 +71,7 @@
cache,
root,
lockFile: lockFile,
- unlock: unlock,
+ unlock: unlock ?? [],
);
} on SolveFailure {
return null;
diff --git a/lib/src/solver/assignment.dart b/lib/src/solver/assignment.dart
index 645eafb..d4c7bdf 100644
--- a/lib/src/solver/assignment.dart
+++ b/lib/src/solver/assignment.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import '../package_name.dart';
import 'incompatibility.dart';
import 'term.dart';
@@ -19,7 +17,7 @@
/// The incompatibility that caused this assignment to be derived, or `null`
/// if the assignment isn't a derivation.
- final Incompatibility cause;
+ final Incompatibility? cause;
/// Whether this assignment is a decision, as opposed to a derivation.
bool get isDecision => cause == null;
diff --git a/lib/src/solver/failure.dart b/lib/src/solver/failure.dart
index 1a3897b..60f70c5 100644
--- a/lib/src/solver/failure.dart
+++ b/lib/src/solver/failure.dart
@@ -2,14 +2,11 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:collection/collection.dart';
import '../exceptions.dart';
import '../log.dart' as log;
import '../package_name.dart';
-import '../sdk.dart';
import '../utils.dart';
import 'incompatibility.dart';
import 'incompatibility_cause.dart';
@@ -30,7 +27,7 @@
///
/// If multiple [PackageNotFoundException]s caused the error, it's undefined
/// which one is returned.
- PackageNotFoundException get packageNotFound {
+ PackageNotFoundException? get packageNotFound {
for (var incompatibility in incompatibility.externalIncompatibilities) {
var cause = incompatibility.cause;
if (cause is PackageNotFoundCause) return cause.exception;
@@ -70,7 +67,7 @@
/// incompatibility, and why its terms are incompatible. The number is
/// optional and indicates the explicit number that should be associated with
/// the line so it can be referred to later on.
- final _lines = <Pair<String, int>>[];
+ final _lines = <Pair<String, int?>>[];
// A map from incompatibilities to the line numbers that were written for
// those incompatibilities.
@@ -82,51 +79,33 @@
/// Populates [_derivations] for [incompatibility] and its transitive causes.
void _countDerivations(Incompatibility incompatibility) {
- if (_derivations.containsKey(incompatibility)) {
- _derivations[incompatibility]++;
- } else {
- _derivations[incompatibility] = 1;
+ _derivations.update(incompatibility, (value) => value + 1, ifAbsent: () {
var cause = incompatibility.cause;
if (cause is ConflictCause) {
_countDerivations(cause.conflict);
_countDerivations(cause.other);
}
- }
+ return 1;
+ });
}
String write() {
var buffer = StringBuffer();
- // SDKs whose version constraints weren't matched.
- var sdkConstraintCauses = <Sdk>{};
-
- // SDKs implicated in any way in the solve failure.
- var sdkCauses = <Sdk>{};
-
- for (var incompatibility in _root.externalIncompatibilities) {
- var cause = incompatibility.cause;
- if (cause is PackageNotFoundCause && cause.sdk != null) {
- sdkCauses.add(cause.sdk);
- } else if (cause is SdkCause) {
- sdkCauses.add(cause.sdk);
- sdkConstraintCauses.add(cause.sdk);
- }
+ // Find all notices from incompatibility causes. This allows an
+ // [IncompatibilityCause] to provide a notice that is printed before the
+ // explanation of the conflict.
+ // Notably, this is used for stating which SDK version is currently
+ // installed, if an SDK is incompatible with a dependency.
+ final notices = _root.externalIncompatibilities
+ .map((c) => c.cause.notice)
+ .whereNotNull()
+ .toSet() // Avoid duplicates
+ .sortedBy((n) => n); // sort for consistency
+ for (final n in notices) {
+ buffer.writeln(n);
}
-
- // If the failure was caused in part by unsatisfied SDK constraints,
- // indicate the actual versions so we don't have to list them (possibly
- // multiple times) in the main body of the error message.
- //
- // Iterate through [sdks] to ensure that SDKs versions are printed in a
- // consistent order
- var wroteLine = false;
- for (var sdk in sdks.values) {
- if (!sdkConstraintCauses.contains(sdk)) continue;
- if (!sdk.isAvailable) continue;
- wroteLine = true;
- buffer.writeln('The current ${sdk.name} SDK version is ${sdk.version}.');
- }
- if (wroteLine) buffer.writeln();
+ if (notices.isNotEmpty) buffer.writeln();
if (_root.cause is ConflictCause) {
_visit(_root, const {});
@@ -160,15 +139,21 @@
buffer.writeln(wordWrap(message, prefix: ' ' * (padding + 2)));
}
- // Iterate through [sdks] to ensure that SDKs versions are printed in a
- // consistent order
- for (var sdk in sdks.values) {
- if (!sdkCauses.contains(sdk)) continue;
- if (sdk.isAvailable) continue;
- if (sdk.installMessage == null) continue;
+ // Iterate through all hints, these are intended to be actionable, such as:
+ // * How to install an SDK, and,
+ // * How to provide authentication.
+ // Hence, it makes sense to show these at the end of the explanation, as the
+ // user will ideally see these before reading the actual conflict and
+ // understand how to fix the issue.
+ _root.externalIncompatibilities
+ .map((c) => c.cause.hint)
+ .whereNotNull()
+ .toSet() // avoid duplicates
+ .sortedBy((hint) => hint) // sort hints for consistent ordering.
+ .forEach((hint) {
buffer.writeln();
- buffer.writeln(sdk.installMessage);
- }
+ buffer.writeln(hint);
+ });
return buffer.toString();
}
@@ -203,23 +188,24 @@
{bool conclusion = false}) {
// Add explicit numbers for incompatibilities that are written far away
// from their successors or that are used for multiple derivations.
- var numbered = conclusion || _derivations[incompatibility] > 1;
+ var numbered = conclusion || _derivations[incompatibility]! > 1;
var conjunction = conclusion || incompatibility == _root ? 'So,' : 'And';
var incompatibilityString =
log.bold(incompatibility.toString(detailsForIncompatibility));
- var cause = incompatibility.cause as ConflictCause;
- var detailsForCause = _detailsForCause(cause);
- if (cause.conflict.cause is ConflictCause &&
- cause.other.cause is ConflictCause) {
- var conflictLine = _lineNumbers[cause.conflict];
- var otherLine = _lineNumbers[cause.other];
+ var conflictClause = incompatibility.cause as ConflictCause;
+ var detailsForCause = _detailsForCause(conflictClause);
+ var cause = conflictClause.conflict.cause;
+ var otherCause = conflictClause.other.cause;
+ if (cause is ConflictCause && otherCause is ConflictCause) {
+ var conflictLine = _lineNumbers[conflictClause.conflict];
+ var otherLine = _lineNumbers[conflictClause.other];
if (conflictLine != null && otherLine != null) {
_write(
incompatibility,
'Because ' +
- cause.conflict.andToString(
- cause.other, detailsForCause, conflictLine, otherLine) +
+ conflictClause.conflict.andToString(conflictClause.other,
+ detailsForCause, conflictLine, otherLine) +
', $incompatibilityString.',
numbered: numbered);
} else if (conflictLine != null || otherLine != null) {
@@ -227,13 +213,13 @@
Incompatibility withoutLine;
int line;
if (conflictLine != null) {
- withLine = cause.conflict;
- withoutLine = cause.other;
+ withLine = conflictClause.conflict;
+ withoutLine = conflictClause.other;
line = conflictLine;
} else {
- withLine = cause.other;
- withoutLine = cause.conflict;
- line = otherLine;
+ withLine = conflictClause.other;
+ withoutLine = conflictClause.conflict;
+ line = otherLine!;
}
_visit(withoutLine, detailsForCause);
@@ -243,35 +229,38 @@
'($line), $incompatibilityString.',
numbered: numbered);
} else {
- var singleLineConflict = _isSingleLine(cause.conflict.cause);
- var singleLineOther = _isSingleLine(cause.other.cause);
+ var singleLineConflict = _isSingleLine(cause);
+ var singleLineOther = _isSingleLine(otherCause);
if (singleLineOther || singleLineConflict) {
- var first = singleLineOther ? cause.conflict : cause.other;
- var second = singleLineOther ? cause.other : cause.conflict;
+ var first =
+ singleLineOther ? conflictClause.conflict : conflictClause.other;
+ var second =
+ singleLineOther ? conflictClause.other : conflictClause.conflict;
_visit(first, detailsForCause);
_visit(second, detailsForCause);
_write(incompatibility, 'Thus, $incompatibilityString.',
numbered: numbered);
} else {
- _visit(cause.conflict, {}, conclusion: true);
+ _visit(conflictClause.conflict, {}, conclusion: true);
_lines.add(Pair('', null));
- _visit(cause.other, detailsForCause);
+ _visit(conflictClause.other, detailsForCause);
_write(
incompatibility,
'$conjunction because '
- '${cause.conflict.toString(detailsForCause)} '
- '(${_lineNumbers[cause.conflict]}), '
+ '${conflictClause.conflict.toString(detailsForCause)} '
+ '(${_lineNumbers[conflictClause.conflict]}), '
'$incompatibilityString.',
numbered: numbered);
}
}
- } else if (cause.conflict.cause is ConflictCause ||
- cause.other.cause is ConflictCause) {
- var derived =
- cause.conflict.cause is ConflictCause ? cause.conflict : cause.other;
- var ext =
- cause.conflict.cause is ConflictCause ? cause.other : cause.conflict;
+ } else if (cause is ConflictCause || otherCause is ConflictCause) {
+ var derived = cause is ConflictCause
+ ? conflictClause.conflict
+ : conflictClause.other;
+ var ext = cause is ConflictCause
+ ? conflictClause.other
+ : conflictClause.conflict;
var derivedLine = _lineNumbers[derived];
if (derivedLine != null) {
@@ -313,7 +302,7 @@
_write(
incompatibility,
'Because '
- '${cause.conflict.andToString(cause.other, detailsForCause)}, '
+ '${conflictClause.conflict.andToString(conflictClause.other, detailsForCause)}, '
'$incompatibilityString.',
numbered: numbered);
}
@@ -347,7 +336,7 @@
bool _isCollapsible(Incompatibility incompatibility) {
// If [incompatibility] is used for multiple derivations, it will need a
// line number and so will need to be written explicitly.
- if (_derivations[incompatibility] > 1) return false;
+ if (_derivations[incompatibility]! > 1) return false;
var cause = incompatibility.cause as ConflictCause;
// If [incompatibility] is derived from two derived incompatibilities,
diff --git a/lib/src/solver/incompatibility.dart b/lib/src/solver/incompatibility.dart
index 1dd6d96..9e39865 100644
--- a/lib/src/solver/incompatibility.dart
+++ b/lib/src/solver/incompatibility.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub_semver/pub_semver.dart';
import '../package_name.dart';
@@ -67,14 +65,12 @@
var byRef = byName.putIfAbsent(term.package.name, () => {});
var ref = term.package.toRef();
if (byRef.containsKey(ref)) {
- byRef[ref] = byRef[ref].intersect(term);
-
// If we have two terms that refer to the same package but have a null
// intersection, they're mutually exclusive, making this incompatibility
// irrelevant, since we already know that mutually exclusive version
// ranges are incompatible. We should never derive an irrelevant
// incompatibility.
- assert(byRef[ref] != null);
+ byRef[ref] = byRef[ref]!.intersect(term)!;
} else {
byRef[ref] = term;
}
@@ -100,7 +96,7 @@
/// If [details] is passed, it controls the amount of detail that's written
/// for packages with the given names.
@override
- String toString([Map<String, PackageDetail> details]) {
+ String toString([Map<String, PackageDetail>? details]) {
if (cause == IncompatibilityCause.dependency) {
assert(terms.length == 2);
@@ -223,7 +219,7 @@
/// If [thisLine] and/or [otherLine] are passed, they indicate line numbers
/// that should be associated with [this] and [other], respectively.
String andToString(Incompatibility other,
- [Map<String, PackageDetail> details, int thisLine, int otherLine]) {
+ [Map<String, PackageDetail>? details, int? thisLine, int? otherLine]) {
var requiresBoth = _tryRequiresBoth(other, details, thisLine, otherLine);
if (requiresBoth != null) return requiresBoth;
@@ -246,8 +242,8 @@
/// and Y", this returns that expression.
///
/// Otherwise, this returns `null`.
- String _tryRequiresBoth(Incompatibility other,
- [Map<String, PackageDetail> details, int thisLine, int otherLine]) {
+ String? _tryRequiresBoth(Incompatibility other,
+ [Map<String, PackageDetail>? details, int? thisLine, int? otherLine]) {
if (terms.length == 1 || other.terms.length == 1) return null;
var thisPositive = _singleTermWhere((term) => term.isPositive);
@@ -281,8 +277,8 @@
/// Z", this returns that expression.
///
/// Otherwise, this returns `null`.
- String _tryRequiresThrough(Incompatibility other,
- [Map<String, PackageDetail> details, int thisLine, int otherLine]) {
+ String? _tryRequiresThrough(Incompatibility other,
+ [Map<String, PackageDetail>? details, int? thisLine, int? otherLine]) {
if (terms.length == 1 || other.terms.length == 1) return null;
var thisNegative = _singleTermWhere((term) => !term.isPositive);
@@ -294,9 +290,9 @@
Incompatibility prior;
Term priorNegative;
- int priorLine;
+ int? priorLine;
Incompatibility latter;
- int latterLine;
+ int? latterLine;
if (thisNegative != null &&
otherPositive != null &&
thisNegative.package.name == otherPositive.package.name &&
@@ -358,14 +354,14 @@
/// forbidden", this returns that expression.
///
/// Otherwise, this returns `null`.
- String _tryRequiresForbidden(Incompatibility other,
- [Map<String, PackageDetail> details, int thisLine, int otherLine]) {
+ String? _tryRequiresForbidden(Incompatibility other,
+ [Map<String, PackageDetail>? details, int? thisLine, int? otherLine]) {
if (terms.length != 1 && other.terms.length != 1) return null;
Incompatibility prior;
Incompatibility latter;
- int priorLine;
- int latterLine;
+ int? priorLine;
+ int? latterLine;
if (terms.length == 1) {
prior = other;
latter = this;
@@ -439,8 +435,8 @@
/// term.
///
/// Otherwise, returns `null`.
- Term _singleTermWhere(bool Function(Term) filter) {
- Term found;
+ Term? _singleTermWhere(bool Function(Term) filter) {
+ Term? found;
for (var term in terms) {
if (!filter(term)) continue;
if (found != null) return null;
@@ -450,7 +446,7 @@
}
/// Returns a terse representation of [term]'s package ref.
- String _terseRef(Term term, Map<String, PackageDetail> details) =>
+ String _terseRef(Term term, Map<String, PackageDetail>? details) =>
term.package
.toRef()
.toString(details == null ? null : details[term.package.name]);
@@ -459,12 +455,12 @@
///
/// If [allowEvery] is `true`, this will return "every version of foo" instead
/// of "foo any".
- String _terse(Term term, Map<String, PackageDetail> details,
+ String _terse(Term? term, Map<String, PackageDetail>? details,
{bool allowEvery = false}) {
- if (allowEvery && term.constraint.isAny) {
+ if (allowEvery && term!.constraint.isAny) {
return 'every version of ${_terseRef(term, details)}';
} else {
- return term.package
+ return term!.package
.toString(details == null ? null : details[term.package.name]);
}
}
diff --git a/lib/src/solver/incompatibility_cause.dart b/lib/src/solver/incompatibility_cause.dart
index 45aa5ca..a2a2327 100644
--- a/lib/src/solver/incompatibility_cause.dart
+++ b/lib/src/solver/incompatibility_cause.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub_semver/pub_semver.dart';
import '../exceptions.dart';
@@ -12,6 +10,8 @@
/// The reason an [Incompatibility]'s terms are incompatible.
abstract class IncompatibilityCause {
+ const IncompatibilityCause._();
+
/// The incompatibility represents the requirement that the root package
/// exists.
static const IncompatibilityCause root = _Cause('root');
@@ -29,11 +29,26 @@
/// The incompatibility indicates that the package has an unknown source.
static const IncompatibilityCause unknownSource = _Cause('unknown source');
+
+ /// Human readable notice / information providing context for this
+ /// incompatibility.
+ ///
+ /// This may be multiple lines, and will be printed before the explanation.
+ /// This is used highlight information that is useful for understanding the
+ /// why this conflict happened.
+ String? get notice => null;
+
+ /// Human readable hint indicating how this incompatibility may be resolved.
+ ///
+ /// This may be multiple lines, and will be printed after the explanation.
+ /// This should only be included if it is actionable and likely to resolve the
+ /// issue for the user.
+ String? get hint => null;
}
/// The incompatibility was derived from two existing incompatibilities during
/// conflict resolution.
-class ConflictCause implements IncompatibilityCause {
+class ConflictCause extends IncompatibilityCause {
/// The incompatibility that was originally found to be in conflict, from
/// which the target incompatibility was derived.
final Incompatibility conflict;
@@ -42,14 +57,14 @@
/// from which the target incompatibility was derived.
final Incompatibility other;
- ConflictCause(this.conflict, this.other);
+ ConflictCause(this.conflict, this.other) : super._();
}
/// A class for stateless [IncompatibilityCause]s.
-class _Cause implements IncompatibilityCause {
+class _Cause extends IncompatibilityCause {
final String _name;
- const _Cause(this._name);
+ const _Cause(this._name) : super._();
@override
String toString() => _name;
@@ -57,27 +72,49 @@
/// The incompatibility represents a package's SDK constraint being
/// incompatible with the current SDK.
-class SdkCause implements IncompatibilityCause {
+class SdkCause extends IncompatibilityCause {
/// The union of all the incompatible versions' constraints on the SDK.
- final VersionConstraint constraint;
+ // TODO(zarah): Investigate if this can be non-nullable
+ final VersionConstraint? constraint;
/// The SDK with which the package was incompatible.
final Sdk sdk;
- SdkCause(this.constraint, this.sdk);
+ @override
+ String? get notice {
+ // If the SDK is not available, then we have an actionable [hint] printed
+ // after the explanation. So we don't need to state that the SDK is not
+ // available.
+ if (!sdk.isAvailable) {
+ return null;
+ }
+ // If the SDK is available and we have an incompatibility, then the user has
+ // the wrong SDK version (one that is not compatible with any solution).
+ // Thus, it makes sense to highlight the current SDK version.
+ return 'The current ${sdk.name} SDK version is ${sdk.version}.';
+ }
+
+ @override
+ String? get hint {
+ // If the SDK is available, then installing it won't help
+ if (sdk.isAvailable) {
+ return null;
+ }
+ // Return an install message for the SDK, if there is an install message.
+ return sdk.installMessage;
+ }
+
+ SdkCause(this.constraint, this.sdk) : super._();
}
/// The incompatibility represents a package that couldn't be found by its
/// source.
-class PackageNotFoundCause implements IncompatibilityCause {
+class PackageNotFoundCause extends IncompatibilityCause {
/// The exception indicating why the package couldn't be found.
final PackageNotFoundException exception;
- /// If the incompatibility was caused by an SDK being unavailable, this is
- /// that SDK.
- ///
- /// Otherwise `null`.
- Sdk get sdk => exception.missingSdk;
+ PackageNotFoundCause(this.exception) : super._();
- PackageNotFoundCause(this.exception);
+ @override
+ String? get hint => exception.hint;
}
diff --git a/lib/src/solver/package_lister.dart b/lib/src/solver/package_lister.dart
index 136b0db..8e1abed 100644
--- a/lib/src/solver/package_lister.dart
+++ b/lib/src/solver/package_lister.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:async/async.dart';
@@ -34,7 +32,7 @@
///
/// This is `null` if this package isn't locked or if the current version
/// solve isn't a `pub get`.
- final PackageId _locked;
+ final PackageId? _locked;
// The version of this package that, if retracted, is still allowed in the
// current version solve.
@@ -43,7 +41,7 @@
// present in `pubspec.lock` or pinned in `dependency_overrides`.
//
// This is `null` if there is no retracted version that can be allowed.
- final Version _allowedRetractedVersion;
+ final Version? _allowedRetractedVersion;
/// The source from which [_ref] comes.
final BoundSource _source;
@@ -78,25 +76,26 @@
/// The versions of [_ref] that have been downloaded and cached, or `null` if
/// they haven't been downloaded yet.
- List<PackageId> get cachedVersions => _cachedVersions;
- List<PackageId> _cachedVersions;
+ List<PackageId>? get cachedVersions => _cachedVersions;
+ List<PackageId>? _cachedVersions;
/// All versions of the package, sorted by [Version.compareTo].
Future<List<PackageId>> get _versions => _versionsMemo.runOnce(() async {
- _cachedVersions = await withDependencyType(
+ var cachedVersions = (await withDependencyType(
_dependencyType,
() => _source.getVersions(_ref,
- allowedRetractedVersion: _allowedRetractedVersion));
- _cachedVersions.sort((id1, id2) => id1.version.compareTo(id2.version));
- return _cachedVersions;
+ allowedRetractedVersion: _allowedRetractedVersion)))
+ ..sort((id1, id2) => id1.version.compareTo(id2.version));
+ _cachedVersions = cachedVersions;
+ return cachedVersions;
});
final _versionsMemo = AsyncMemoizer<List<PackageId>>();
/// The most recent version of this package (or the oldest, if we're
/// downgrading).
- Future<PackageId> get latest =>
+ Future<PackageId?> get latest =>
_latestMemo.runOnce(() => bestVersion(VersionConstraint.any));
- final _latestMemo = AsyncMemoizer<PackageId>();
+ final _latestMemo = AsyncMemoizer<PackageId?>();
/// Creates a package lister for the dependency identified by [ref].
PackageLister(
@@ -125,7 +124,7 @@
/// Returns the number of versions of this package that match [constraint].
Future<int> countVersions(VersionConstraint constraint) async {
- if (_locked != null && constraint.allows(_locked.version)) return 1;
+ if (_locked != null && constraint.allows(_locked!.version)) return 1;
try {
return (await _versions)
.where((id) => constraint.allows(id.version))
@@ -144,32 +143,32 @@
///
/// Throws a [PackageNotFoundException] if this lister's package doesn't
/// exist.
- Future<PackageId> bestVersion(VersionConstraint constraint) async {
- if (_locked != null && constraint.allows(_locked.version)) return _locked;
+ Future<PackageId?> bestVersion(VersionConstraint? constraint) async {
+ if (_locked != null && constraint!.allows(_locked!.version)) return _locked;
var versions = await _versions;
// If [constraint] has a minimum (or a maximum in downgrade mode), we can
// bail early once we're past it.
- var isPastLimit = (Version _) => false;
+ var isPastLimit = (Version? _) => false;
if (constraint is VersionRange) {
if (_isDowngrade) {
var max = constraint.max;
- if (max != null) isPastLimit = (version) => version > max;
+ if (max != null) isPastLimit = (version) => version! > max;
} else {
var min = constraint.min;
- if (min != null) isPastLimit = (version) => version < min;
+ if (min != null) isPastLimit = (version) => version! < min;
}
}
// Return the most preferable version that matches [constraint]: the latest
// non-prerelease version if one exists, or the latest prerelease version
// otherwise.
- PackageId bestPrerelease;
+ PackageId? bestPrerelease;
for (var id in _isDowngrade ? versions : versions.reversed) {
- if (isPastLimit != null && isPastLimit(id.version)) break;
+ if (isPastLimit(id.version)) break;
- if (!constraint.allows(id.version)) continue;
+ if (!constraint!.allows(id.version)) continue;
if (!id.version.isPreRelease) return id;
bestPrerelease ??= id;
}
@@ -210,7 +209,7 @@
if (_cachedVersions == null &&
_locked != null &&
- id.version == _locked.version) {
+ id.version == _locked!.version) {
if (_listedLockedVersion) return const [];
var depender = id.toRange();
@@ -252,7 +251,8 @@
var versions = await _versions;
var index = lowerBound(versions, id,
- compare: (id1, id2) => id1.version.compareTo(id2.version));
+ compare: (dynamic id1, dynamic id2) =>
+ id1.version.compareTo(id2.version));
assert(index < versions.length);
assert(versions[index].version == id.version);
@@ -289,7 +289,7 @@
_alreadyListedDependencies[package] ?? VersionConstraint.empty);
return _dependency(
- _ref.withConstraint(constraint), dependencies[package]);
+ _ref.withConstraint(constraint), dependencies[package]!);
}).toList();
}
@@ -303,7 +303,7 @@
/// version of [sdk], returns an [Incompatibility] indicating that.
///
/// Otherwise, returns `null`.
- Future<Incompatibility> _checkSdkConstraint(int index, Sdk sdk) async {
+ Future<Incompatibility?> _checkSdkConstraint(int index, Sdk sdk) async {
var versions = await _versions;
bool allowsSdk(Pubspec pubspec) => _matchesSdkConstraint(pubspec, sdk);
@@ -322,7 +322,7 @@
var sdkConstraint = await foldAsync(
slice(versions, bounds.first, bounds.last + 1), VersionConstraint.empty,
- (previous, version) async {
+ (dynamic previous, dynamic version) async {
var pubspec = await _describeSafe(version);
return previous.union(
pubspec.sdkConstraints[sdk.identifier] ?? VersionConstraint.any);
@@ -364,7 +364,7 @@
/// If a package is absent from the return value, that indicates indicate that
/// all versions above or below [index] (according to [upper]) have the same
/// dependency.
- Future<Map<String, Version>> _dependencyBounds(
+ Future<Map<String, Version?>> _dependencyBounds(
Map<String, PackageRange> dependencies, int index,
{bool upper = true}) async {
var versions = await _versions;
@@ -427,7 +427,7 @@
var constraint = pubspec.sdkConstraints[sdk.identifier];
if (constraint == null) return true;
- return sdk.isAvailable && constraint.allows(sdk.version);
+ return sdk.isAvailable && constraint.allows(sdk.version!);
}
}
@@ -447,7 +447,7 @@
@override
Future<List<PackageId>> getVersions(PackageRef ref,
- {Duration maxAge, Version allowedRetractedVersion}) {
+ {Duration? maxAge, Version? allowedRetractedVersion}) {
assert(ref.isRoot);
return Future.value([PackageId.root(_package)]);
}
@@ -463,11 +463,11 @@
@override
SystemCache get systemCache => throw _unsupported;
@override
- Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge) =>
+ Future<List<PackageId>> doGetVersions(PackageRef ref, Duration? maxAge) =>
throw _unsupported;
@override
Future<Pubspec> doDescribe(PackageId id) => throw _unsupported;
@override
- String getDirectory(PackageId id, {String relativeFrom}) =>
+ String getDirectory(PackageId id, {String? relativeFrom}) =>
throw _unsupported;
}
diff --git a/lib/src/solver/partial_solution.dart b/lib/src/solver/partial_solution.dart
index 57c22bf..40d2611 100644
--- a/lib/src/solver/partial_solution.dart
+++ b/lib/src/solver/partial_solution.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import '../package_name.dart';
import 'assignment.dart';
import 'incompatibility.dart';
@@ -27,7 +25,7 @@
/// negative [Assignment]s that refer to that package.
///
/// This is derived from [_assignments].
- final _positive = <String, Term>{};
+ final _positive = <String, Term?>{};
/// The union of all negative [Assignment]s for each package.
///
@@ -43,8 +41,8 @@
/// Returns all [PackageRange]s that have been assigned but are not yet
/// satisfied.
Iterable<PackageRange> get unsatisfied => _positive.values
- .where((term) => !_decisions.containsKey(term.package.name))
- .map((term) => term.package);
+ .where((term) => !_decisions.containsKey(term!.package.name))
+ .map((term) => term!.package);
// The current decision level—that is, the length of [decisions].
int get decisionLevel => _decisions.length;
@@ -70,7 +68,7 @@
}
/// Adds an assignment of [package] as a derivation.
- void derive(PackageName package, bool isPositive, Incompatibility cause) {
+ void derive(PackageRange package, bool isPositive, Incompatibility cause) {
_assign(Assignment.derivation(
package, isPositive, cause, decisionLevel, _assignments.length));
}
@@ -119,7 +117,7 @@
var negativeByRef = _negative[name];
var oldNegative = negativeByRef == null ? null : negativeByRef[ref];
var term =
- oldNegative == null ? assignment : assignment.intersect(oldNegative);
+ oldNegative == null ? assignment : assignment.intersect(oldNegative)!;
if (term.isPositive) {
_negative.remove(name);
@@ -134,7 +132,7 @@
///
/// Throws a [StateError] if [term] isn't satisfied by [this].
Assignment satisfier(Term term) {
- Term assignedTerm;
+ Term? assignedTerm;
for (var assignment in _assignments) {
if (assignment.package.name != term.package.name) continue;
@@ -153,7 +151,7 @@
: assignedTerm.intersect(assignment);
// As soon as we have enough assignments to satisfy [term], return them.
- if (assignedTerm.satisfies(term)) return assignment;
+ if (assignedTerm!.satisfies(term)) return assignment;
}
throw StateError('[BUG] $term is not satisfied.');
diff --git a/lib/src/solver/reformat_ranges.dart b/lib/src/solver/reformat_ranges.dart
index bdb64b8..5c763a6 100644
--- a/lib/src/solver/reformat_ranges.dart
+++ b/lib/src/solver/reformat_ranges.dart
@@ -2,8 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
+import 'package:meta/meta.dart';
import 'package:pub_semver/pub_semver.dart';
import '../package_name.dart';
@@ -48,7 +47,7 @@
var range = term.package.constraint as VersionRange;
var min = _reformatMin(versions, range);
- var tuple = _reformatMax(versions, range);
+ var tuple = reformatMax(versions, range);
var max = tuple?.first;
var includeMax = tuple?.last;
@@ -67,39 +66,46 @@
/// Returns the new minimum version to use for [range], or `null` if it doesn't
/// need to be reformatted.
-Version _reformatMin(List<PackageId> versions, VersionRange range) {
- if (range.min == null) return null;
+Version? _reformatMin(List<PackageId> versions, VersionRange range) {
+ var min = range.min;
+ if (min == null) return null;
if (!range.includeMin) return null;
- if (!range.min.isFirstPreRelease) return null;
+ if (!min.isFirstPreRelease) return null;
- var index = _lowerBound(versions, range.min);
+ var index = _lowerBound(versions, min);
var next = index == versions.length ? null : versions[index].version;
// If there's a real pre-release version of [range.min], use that as the min.
// Otherwise, use the release version.
- return next != null && equalsIgnoringPreRelease(range.min, next)
+ return next != null && equalsIgnoringPreRelease(min, next)
? next
- : Version(range.min.major, range.min.minor, range.min.patch);
+ : Version(min.major, min.minor, min.patch);
}
/// Returns the new maximum version to use for [range] and whether that maximum
/// is inclusive, or `null` if it doesn't need to be reformatted.
-Pair<Version, bool> _reformatMax(List<PackageId> versions, VersionRange range) {
- if (range.max == null) return null;
+@visibleForTesting
+Pair<Version, bool>? reformatMax(List<PackageId> versions, VersionRange range) {
+ // This corresponds to the logic in the constructor of [VersionRange] with
+ // `alwaysIncludeMaxPreRelease = false` for discovering when a max-bound
+ // should not include prereleases.
+
+ var max = range.max;
+ var min = range.min;
+ if (max == null) return null;
if (range.includeMax) return null;
- if (range.max.isPreRelease) return null;
- if (range.min != null &&
- range.min.isPreRelease &&
- equalsIgnoringPreRelease(range.min, range.max)) {
+ if (max.isPreRelease) return null;
+ if (max.build.isNotEmpty) return null;
+ if (min != null && min.isPreRelease && equalsIgnoringPreRelease(min, max)) {
return null;
}
- var index = _lowerBound(versions, range.max);
+ var index = _lowerBound(versions, max);
var previous = index == 0 ? null : versions[index - 1].version;
- return previous != null && equalsIgnoringPreRelease(previous, range.max)
+ return previous != null && equalsIgnoringPreRelease(previous, max)
? Pair(previous, true)
- : Pair(range.max.firstPreRelease, false);
+ : Pair(max.firstPreRelease, false);
}
/// Returns the first index in [ids] (which is sorted by version) whose version
diff --git a/lib/src/solver/report.dart b/lib/src/solver/report.dart
index 8bd3cc9..e3dd5dc 100644
--- a/lib/src/solver/report.dart
+++ b/lib/src/solver/report.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub_semver/pub_semver.dart';
@@ -74,7 +72,7 @@
}).length;
var suffix = '';
- if (_root.dir != null) {
+ if (!_root.isInMemory) {
final dir = path.normalize(_root.dir);
if (dir != '.') {
suffix = ' in $dir';
@@ -91,7 +89,7 @@
}
} else {
if (numChanged == 0) {
- if (_type == SolveType.GET) {
+ if (_type == SolveType.get) {
log.message('Got dependencies$suffix!');
} else {
log.message('No dependencies changed$suffix.');
@@ -153,7 +151,11 @@
if (id.source == null) continue;
final status =
await _cache.source(id.source).status(id, maxAge: Duration(days: 3));
- if (status.isDiscontinued) numDiscontinued++;
+ if (status.isDiscontinued &&
+ (_root.dependencyType(id.name) == DependencyType.direct ||
+ _root.dependencyType(id.name) == DependencyType.dev)) {
+ numDiscontinued++;
+ }
}
if (numDiscontinued > 0) {
if (numDiscontinued == 1) {
@@ -168,7 +170,7 @@
/// instruction to run `pub outdated` if outdated packages are detected.
void reportOutdated() {
final outdatedPackagesCount = _result.packages.where((id) {
- final versions = _result.availableVersions[id.name];
+ final versions = _result.availableVersions[id.name]!;
// A version is counted:
// - if there is a newer version which is not a pre-release and current
// version is also not a pre-release or,
@@ -199,7 +201,7 @@
{bool alwaysShow = false, bool highlightOverride = true}) async {
var newId = _dependencies[name];
var oldId = _previousLockFile.packages[name];
- var id = newId ?? oldId;
+ var id = newId ?? oldId!;
var isOverridden = _root.dependencyOverrides.containsKey(id.name);
@@ -240,11 +242,11 @@
// Unchanged.
icon = ' ';
}
- String message;
+ String? message;
// See if there are any newer versions of the package that we were
// unable to upgrade to.
- if (newId != null && _type != SolveType.DOWNGRADE) {
- var versions = _result.availableVersions[newId.name];
+ if (newId != null && _type != SolveType.downgrade) {
+ var versions = _result.availableVersions[newId.name]!;
var newerStable = false;
var newerUnstable = false;
@@ -270,7 +272,9 @@
} else {
message = '(retracted)';
}
- } else if (status.isDiscontinued) {
+ } else if (status.isDiscontinued &&
+ (_root.dependencyType(name) == DependencyType.direct ||
+ _root.dependencyType(name) == DependencyType.dev)) {
if (status.discontinuedReplacedBy == null) {
message = '(discontinued)';
} else {
@@ -288,7 +292,7 @@
}
}
- if (_type == SolveType.GET &&
+ if (_type == SolveType.get &&
!(alwaysShow || changed || addedOrRemoved || message != null)) {
return;
}
@@ -301,7 +305,7 @@
// If the package was upgraded, show what it was upgraded from.
if (changed) {
_output.write(' (was ');
- _writeId(oldId);
+ _writeId(oldId!);
_output.write(')');
}
@@ -320,7 +324,7 @@
_output.write(id.version);
if (id.source != _sources.defaultSource) {
- var description = id.source.formatDescription(id.description);
+ var description = id.source!.formatDescription(id.description);
_output.write(' from ${id.source} $description');
}
}
diff --git a/lib/src/solver/result.dart b/lib/src/solver/result.dart
index ebcdfd7..bc01162 100644
--- a/lib/src/solver/result.dart
+++ b/lib/src/solver/result.dart
@@ -2,15 +2,19 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:collection/collection.dart';
import 'package:pub_semver/pub_semver.dart';
+import '../http.dart';
+import '../io.dart';
import '../lock_file.dart';
+import '../log.dart' as log;
import '../package.dart';
import '../package_name.dart';
+import '../pub_embeddable_command.dart';
import '../pubspec.dart';
+import '../source/cached.dart';
+import '../source/hosted.dart';
import '../source_registry.dart';
import '../system_cache.dart';
import 'report.dart';
@@ -44,6 +48,9 @@
/// because it found an invalid solution.
final int attemptedSolutions;
+ /// The wall clock time the resolution took.
+ final Duration resolutionTime;
+
/// The [LockFile] representing the packages selected by this version
/// resolution.
LockFile get lockFile {
@@ -73,12 +80,22 @@
final LockFile _previousLockFile;
+ /// Downloads all cached packages in [packages].
+ Future<void> downloadCachedPackages(SystemCache cache) async {
+ await Future.wait(packages.map((id) async {
+ if (id.source == null) return;
+ final source = cache.source(id.source);
+ if (source is! CachedSource) return;
+ return await withDependencyType(_root.dependencyType(id.name), () async {
+ await source.downloadToSystemCache(id);
+ });
+ }));
+ }
+
/// Returns the names of all packages that were changed.
///
/// This includes packages that were added or removed.
Set<String> get changedPackages {
- if (packages == null) return null;
-
var changed = packages
.where((id) => _previousLockFile.packages[id.name] != id)
.map((id) => id.name)
@@ -89,8 +106,15 @@
.toSet());
}
- SolveResult(this._sources, this._root, this._previousLockFile, this.packages,
- this.pubspecs, this.availableVersions, this.attemptedSolutions);
+ SolveResult(
+ this._sources,
+ this._root,
+ this._previousLockFile,
+ this.packages,
+ this.pubspecs,
+ this.availableVersions,
+ this.attemptedSolutions,
+ this.resolutionTime);
/// Displays a report of what changes were made to the lockfile.
///
@@ -112,12 +136,58 @@
final report =
SolveReport(type, _sources, _root, _previousLockFile, this, cache);
report.summarize(dryRun: dryRun);
- if (type == SolveType.UPGRADE) {
+ if (type == SolveType.upgrade) {
await report.reportDiscontinued();
report.reportOutdated();
}
}
+ /// Send analytics about the package resolution.
+ void sendAnalytics(PubAnalytics pubAnalytics) {
+ ArgumentError.checkNotNull(pubAnalytics);
+ final analytics = pubAnalytics.analytics;
+ if (analytics == null) return;
+
+ final dependenciesForAnalytics = <PackageId>[];
+ for (final package in packages) {
+ // Only send analytics for packages from pub.dev.
+ if (HostedSource.isFromPubDev(package) ||
+ (package.source is HostedSource && runningFromTest)) {
+ dependenciesForAnalytics.add(package);
+ }
+ }
+ // Randomize the dependencies, such that even if some analytics events don't
+ // get sent, the results will still be representative.
+ shuffle(dependenciesForAnalytics);
+ for (final package in dependenciesForAnalytics) {
+ final dependencyKind = const {
+ DependencyType.dev: 'dev',
+ DependencyType.direct: 'direct',
+ DependencyType.none: 'transitive'
+ }[_root.dependencyType(package.name)]!;
+ analytics.sendEvent(
+ 'pub-get',
+ package.name,
+ label: package.version.canonicalizedVersion,
+ value: 1,
+ parameters: {
+ 'ni': '1', // We consider a pub-get a non-interactive event.
+ pubAnalytics.dependencyKindCustomDimensionName: dependencyKind,
+ },
+ );
+ log.fine(
+ 'Sending analytics hit for "pub-get" of ${package.name} version ${package.version} as dependency-kind $dependencyKind');
+ }
+
+ analytics.sendTiming(
+ 'resolution',
+ resolutionTime.inMilliseconds,
+ category: 'pub-get',
+ );
+ log.fine(
+ 'Sending analytics timing "pub-get" took ${resolutionTime.inMilliseconds} miliseconds');
+ }
+
@override
String toString() => 'Took $attemptedSolutions tries to resolve to\n'
'- ${packages.join("\n- ")}';
diff --git a/lib/src/solver/set_relation.dart b/lib/src/solver/set_relation.dart
index 09a1a80..2d88eb9 100644
--- a/lib/src/solver/set_relation.dart
+++ b/lib/src/solver/set_relation.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
/// An enum of possible relationships between two sets.
class SetRelation {
/// The second set contains all elements of the first, as well as possibly
diff --git a/lib/src/solver/term.dart b/lib/src/solver/term.dart
index f5f4662..266fabc 100644
--- a/lib/src/solver/term.dart
+++ b/lib/src/solver/term.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub_semver/pub_semver.dart';
import '../package_name.dart';
@@ -60,7 +58,9 @@
if (otherConstraint.allowsAll(constraint)) return SetRelation.subset;
// foo ^2.0.0 is disjoint with foo ^1.0.0
- if (!constraint.allowsAny(otherConstraint)) return SetRelation.disjoint;
+ if (!constraint.allowsAny(otherConstraint)) {
+ return SetRelation.disjoint;
+ }
// foo >=1.5.0 <3.0.0 overlaps foo ^1.0.0
return SetRelation.overlapping;
@@ -69,7 +69,9 @@
if (!_compatiblePackage(other.package)) return SetRelation.overlapping;
// not foo ^1.0.0 is disjoint with foo ^1.5.0
- if (constraint.allowsAll(otherConstraint)) return SetRelation.disjoint;
+ if (constraint.allowsAll(otherConstraint)) {
+ return SetRelation.disjoint;
+ }
// not foo ^1.5.0 overlaps foo ^1.0.0
// not foo ^2.0.0 is a superset of foo ^1.5.0
@@ -110,7 +112,7 @@
///
/// Throws an [ArgumentError] if [other] doesn't refer to a package with the
/// same name as [package].
- Term intersect(Term other) {
+ Term? intersect(Term other) {
if (package.name != other.package.name) {
throw ArgumentError.value(
other, 'other', 'should refer to package ${package.name}');
@@ -148,7 +150,7 @@
///
/// Throws an [ArgumentError] if [other] doesn't refer to a package with the
/// same name as [package].
- Term difference(Term other) => intersect(other.inverse); // A ∖ B → A ∩ not B
+ Term? difference(Term other) => intersect(other.inverse); // A ∖ B → A ∩ not B
/// Returns whether [other] is compatible with [package].
bool _compatiblePackage(PackageRange other) =>
@@ -157,7 +159,7 @@
/// Returns a new [Term] with the same package as [this] and with
/// [constraint], unless that would produce a term that allows no packages,
/// in which case this returns `null`.
- Term _nonEmptyTerm(VersionConstraint constraint, bool isPositive) =>
+ Term? _nonEmptyTerm(VersionConstraint constraint, bool isPositive) =>
constraint.isEmpty
? null
: Term(package.withConstraint(constraint), isPositive);
diff --git a/lib/src/solver/type.dart b/lib/src/solver/type.dart
index f0f37af..28a3230 100644
--- a/lib/src/solver/type.dart
+++ b/lib/src/solver/type.dart
@@ -2,21 +2,19 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
/// An enum for types of version resolution.
class SolveType {
/// As few changes to the lockfile as possible to be consistent with the
/// pubspec.
- static const GET = SolveType._('get');
+ static const get = SolveType._('get');
/// Upgrade all packages or specific packages to the highest versions
/// possible, regardless of the lockfile.
- static const UPGRADE = SolveType._('upgrade');
+ static const upgrade = SolveType._('upgrade');
/// Downgrade all packages or specific packages to the lowest versions
/// possible, regardless of the lockfile.
- static const DOWNGRADE = SolveType._('downgrade');
+ static const downgrade = SolveType._('downgrade');
final String _name;
diff --git a/lib/src/solver/version_solver.dart b/lib/src/solver/version_solver.dart
index ee1541d..d4e3a75 100644
--- a/lib/src/solver/version_solver.dart
+++ b/lib/src/solver/version_solver.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:math' as math;
@@ -78,6 +76,8 @@
/// The set of packages for which the lockfile should be ignored.
final Set<String> _unlock;
+ final _stopwatch = Stopwatch();
+
VersionSolver(this._type, this._systemCache, this._root, this._lockFile,
Iterable<String> unlock)
: _dependencyOverrides = _root.pubspec.dependencyOverrides,
@@ -86,14 +86,13 @@
/// Finds a set of dependencies that match the root package's constraints, or
/// throws an error if no such set is available.
Future<SolveResult> solve() async {
- var stopwatch = Stopwatch()..start();
-
+ _stopwatch.start();
_addIncompatibility(Incompatibility(
[Term(PackageRange.root(_root), false)], IncompatibilityCause.root));
try {
return await _systemCache.hosted.withPrefetching(() async {
- var next = _root.name;
+ String? next = _root.name;
while (next != null) {
_propagate(next);
next = await _choosePackageVersion();
@@ -103,7 +102,7 @@
});
} finally {
// Gather some solving metrics.
- log.solver('Version solving took ${stopwatch.elapsed} seconds.\n'
+ log.solver('Version solving took ${_stopwatch.elapsed} seconds.\n'
'Tried ${_solution.attemptedSolutions} solutions.');
}
}
@@ -123,7 +122,7 @@
// general incompatibilities as time goes on. If we look at those first,
// we can derive stronger assignments sooner and more eagerly find
// conflicts.
- for (var incompatibility in _incompatibilities[package].reversed) {
+ for (var incompatibility in _incompatibilities[package]!.reversed) {
var result = _propagateIncompatibility(incompatibility);
if (result == #conflict) {
// If [incompatibility] is satisfied by [_solution], we use
@@ -159,7 +158,7 @@
// The first entry in `incompatibility.terms` that's not yet satisfied by
// [_solution], if one exists. If we find more than one, [_solution] is
// inconclusive for [incompatibility] and we can't deduce anything.
- Term unsatisfied;
+ Term? unsatisfied;
for (var i = 0; i < incompatibility.terms.length; i++) {
var term = incompatibility.terms[i];
@@ -208,17 +207,17 @@
while (!incompatibility.isFailure) {
// The term in `incompatibility.terms` that was most recently satisfied by
// [_solution].
- Term mostRecentTerm;
+ Term? mostRecentTerm;
// The earliest assignment in [_solution] such that [incompatibility] is
// satisfied by [_solution] up to and including this assignment.
- Assignment mostRecentSatisfier;
+ Assignment? mostRecentSatisfier;
// The difference between [mostRecentSatisfier] and [mostRecentTerm];
// that is, the versions that are allowed by [mostRecentSatisfier] and not
// by [mostRecentTerm]. This is `null` if [mostRecentSatisfier] totally
// satisfies [mostRecentTerm].
- Term difference;
+ Term? difference;
// The decision level of the earliest assignment in [_solution] *before*
// [mostRecentSatisfier] such that [incompatibility] is satisfied by
@@ -251,7 +250,7 @@
// If [mostRecentSatisfier] doesn't satisfy [mostRecentTerm] on its
// own, then the next-most-recent satisfier may be the one that
// satisfies the remainder.
- difference = mostRecentSatisfier.difference(mostRecentTerm);
+ difference = mostRecentSatisfier.difference(mostRecentTerm!);
if (difference != null) {
previousSatisfierLevel = math.max(previousSatisfierLevel,
_solution.satisfier(difference.inverse).decisionLevel);
@@ -264,7 +263,7 @@
// than a derivation), then [incompatibility] is the root cause. We then
// backjump to [previousSatisfierLevel], where [incompatibility] is
// guaranteed to allow [_propagate] to produce more assignments.
- if (previousSatisfierLevel < mostRecentSatisfier.decisionLevel ||
+ if (previousSatisfierLevel < mostRecentSatisfier!.decisionLevel ||
mostRecentSatisfier.cause == null) {
_solution.backtrack(previousSatisfierLevel);
if (newIncompatibility) _addIncompatibility(incompatibility);
@@ -280,7 +279,7 @@
var newTerms = <Term>[
for (var term in incompatibility.terms)
if (term != mostRecentTerm) term,
- for (var term in mostRecentSatisfier.cause.terms)
+ for (var term in mostRecentSatisfier.cause!.terms)
if (term.package != mostRecentSatisfier.package) term,
];
@@ -299,7 +298,7 @@
if (difference != null) newTerms.add(difference.inverse);
incompatibility = Incompatibility(
- newTerms, ConflictCause(incompatibility, mostRecentSatisfier.cause));
+ newTerms, ConflictCause(incompatibility, mostRecentSatisfier.cause!));
newIncompatibility = true;
var partially = difference == null ? '' : ' partially';
@@ -318,7 +317,7 @@
/// Returns the name of the package whose incompatibilities should be
/// propagated by [_propagate], or `null` indicating that version solving is
/// complete and a solution has been found.
- Future<String> _choosePackageVersion() async {
+ Future<String?> _choosePackageVersion() async {
var unsatisfied = _solution.unsatisfied.toList();
if (unsatisfied.isEmpty) return null;
@@ -334,14 +333,14 @@
/// Prefer packages with as few remaining versions as possible, so that if a
/// conflict is necessary it's forced quickly.
- var package = await minByAsync(unsatisfied, (package) async {
+ var package = await minByAsync(unsatisfied, (PackageRange package) async {
return await _packageLister(package).countVersions(package.constraint);
});
if (package == null) {
return null; // when unsatisfied.isEmpty
}
- PackageId version;
+ PackageId? version;
try {
version = await _packageLister(package).bestVersion(package.constraint);
} on PackageNotFoundException catch (error) {
@@ -370,7 +369,7 @@
var conflict = false;
for (var incompatibility
- in await _packageLister(package).incompatibilitiesFor(version)) {
+ in await _packageLister(package).incompatibilitiesFor(version!)) {
_addIncompatibility(incompatibility);
// If an incompatibility is already satisfied, then selecting [version]
@@ -418,13 +417,15 @@
}
return SolveResult(
- _systemCache.sources,
- _root,
- _lockFile,
- decisions,
- pubspecs,
- await _getAvailableVersions(decisions),
- _solution.attemptedSolutions);
+ _systemCache.sources,
+ _root,
+ _lockFile,
+ decisions,
+ pubspecs,
+ await _getAvailableVersions(decisions),
+ _solution.attemptedSolutions,
+ _stopwatch.elapsed,
+ );
}
/// Generates a map containing all of the known available versions for each
@@ -484,15 +485,15 @@
_root.dependencyType(package.name),
overridden,
_getAllowedRetracted(ref.name),
- downgrade: _type == SolveType.DOWNGRADE);
+ downgrade: _type == SolveType.downgrade);
});
}
/// Gets the version of [package] currently locked in the lock file.
///
/// Returns `null` if it isn't in the lockfile (or has been unlocked).
- PackageId _getLocked(String package) {
- if (_type == SolveType.GET) {
+ PackageId? _getLocked(String? package) {
+ if (_type == SolveType.get) {
if (_unlock.contains(package)) {
return null;
}
@@ -502,9 +503,9 @@
// When downgrading, we don't want to force the latest versions of
// non-hosted packages, since they don't support multiple versions and thus
// can't be downgraded.
- if (_type == SolveType.DOWNGRADE) {
+ if (_type == SolveType.downgrade) {
var locked = _lockFile.packages[package];
- if (locked != null && !locked.source.hasMultipleVersions) return locked;
+ if (locked != null && !locked.source!.hasMultipleVersions) return locked;
}
if (_unlock.isEmpty || _unlock.contains(package)) return null;
@@ -512,16 +513,17 @@
}
/// Gets the version of [package] which can be allowed during version solving
- /// even if that version is marked as retracted.
+ /// even if that version is marked as retracted. Returns `null` if no such
+ /// version exists.
///
/// We only allow resolving to a retracted version if it is already in the
/// `pubspec.lock` or pinned in `dependency_overrides`.
- Version _getAllowedRetracted(String package) {
+ Version? _getAllowedRetracted(String? package) {
if (_dependencyOverrides.containsKey(package)) {
- var range = _dependencyOverrides[package];
+ var range = _dependencyOverrides[package]!;
if (range.constraint is Version) {
// We have a pinned dependency.
- return range.constraint;
+ return range.constraint as Version?;
}
}
return _lockFile.packages[package]?.version;
@@ -530,7 +532,7 @@
/// Logs [message] in the context of the current selected packages.
///
/// If [message] is omitted, just logs a description of leaf-most selection.
- void _log([String message]) {
+ void _log([String message = '']) {
// Indent for the previous selections.
log.solver(prefixLines(message, prefix: ' ' * _solution.decisionLevel));
}
diff --git a/lib/src/source.dart b/lib/src/source.dart
index 4fe2322..ecbc5eb 100644
--- a/lib/src/source.dart
+++ b/lib/src/source.dart
@@ -2,13 +2,13 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
+import 'package:collection/collection.dart' show IterableNullableExtension;
import 'package:pub_semver/pub_semver.dart';
import 'exceptions.dart';
+import 'language_version.dart';
import 'package_name.dart';
import 'pubspec.dart';
import 'system_cache.dart';
@@ -77,16 +77,27 @@
/// should be interpreted. This will be called during parsing to validate that
/// the given [description] is well-formed according to this source, and to
/// give the source a chance to canonicalize the description.
+ /// For simple hosted dependencies like `foo:` or `foo: ^1.2.3`, the
+ /// [description] may also be `null`.
///
/// [containingPath] is the path to the pubspec where this description
/// appears. It may be `null` if the description is coming from some in-memory
/// source (such as pulling down a pubspec from pub.dartlang.org).
///
+ /// [languageVersion] is the minimum Dart version parsed from the pubspec's
+ /// `environment` field. Source implementations may use this parameter to only
+ /// support specific syntax for some versions.
+ ///
/// The description in the returned [PackageRef] need bear no resemblance to
/// the original user-provided description.
///
/// Throws a [FormatException] if the description is not valid.
- PackageRef parseRef(String name, description, {String containingPath});
+ PackageRef parseRef(
+ String name,
+ description, {
+ String? containingPath,
+ required LanguageVersion languageVersion,
+ });
/// Parses a [PackageId] from a name and a serialized description.
///
@@ -99,13 +110,13 @@
///
/// Throws a [FormatException] if the description is not valid.
PackageId parseId(String name, Version version, description,
- {String containingPath});
+ {String? containingPath});
/// When a [LockFile] is serialized, it uses this method to get the
/// [description] in the right format.
///
/// [containingPath] is the containing directory of the root package.
- dynamic serializeDescription(String containingPath, description) {
+ dynamic serializeDescription(String? containingPath, description) {
return description;
}
@@ -166,7 +177,7 @@
/// selected even if it is marked as retracted. Otherwise, all the returned
/// IDs correspond to non-retracted versions.
Future<List<PackageId>> getVersions(PackageRef ref,
- {Duration maxAge, Version allowedRetractedVersion}) async {
+ {Duration? maxAge, Version? allowedRetractedVersion}) async {
if (ref.isRoot) {
throw ArgumentError('Cannot get versions for the root package.');
}
@@ -183,7 +194,7 @@
}
return null;
})))
- .where((element) => element != null)
+ .whereNotNull()
.toList();
return versions;
@@ -201,7 +212,7 @@
///
/// This method is effectively protected: subclasses must implement it, but
/// external code should not call this. Instead, call [getVersions].
- Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge);
+ Future<List<PackageId>> doGetVersions(PackageRef ref, Duration? maxAge);
/// A cache of pubspecs described by [describe].
final _pubspecs = <PackageId, Pubspec>{};
@@ -256,7 +267,7 @@
///
/// If id is a relative path id, the directory will be relative from
/// [relativeFrom]. Returns an absolute path if [relativeFrom] is not passed.
- String getDirectory(PackageId id, {String relativeFrom});
+ String getDirectory(PackageId id, {String? relativeFrom});
/// Returns metadata about a given package.
///
@@ -265,7 +276,7 @@
///
/// In the case of offline sources, [maxAge] is not used, since information is
/// per definiton cached.
- Future<PackageStatus> status(PackageId id, {Duration maxAge}) async =>
+ Future<PackageStatus> status(PackageId id, {Duration? maxAge}) async =>
// Default implementation has no metadata.
PackageStatus();
@@ -282,10 +293,11 @@
/// `null` if not [isDiscontinued]. Otherwise contains the
/// replacement string provided by the host or `null` if there is no
/// replacement.
- final String discontinuedReplacedBy;
+ final String? discontinuedReplacedBy;
final bool isDiscontinued;
final bool isRetracted;
- PackageStatus({isDiscontinued, this.discontinuedReplacedBy, isRetracted})
- : isDiscontinued = isDiscontinued ?? false,
- isRetracted = isRetracted ?? false;
+ PackageStatus(
+ {this.isDiscontinued = false,
+ this.discontinuedReplacedBy,
+ this.isRetracted = false});
}
diff --git a/lib/src/source/cached.dart b/lib/src/source/cached.dart
index c0d9ef1..0c8574d 100644
--- a/lib/src/source/cached.dart
+++ b/lib/src/source/cached.dart
@@ -2,11 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
-import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import '../io.dart';
@@ -43,7 +40,7 @@
}
@override
- String getDirectory(PackageId id, {String relativeFrom}) =>
+ String getDirectory(PackageId id, {String? relativeFrom}) =>
getDirectoryInCache(id);
String getDirectoryInCache(PackageId id);
@@ -82,5 +79,5 @@
/// cache (but that might itself have failed).
final bool success;
final PackageId package;
- RepairResult(this.package, {@required this.success});
+ RepairResult(this.package, {required this.success});
}
diff --git a/lib/src/source/git.dart b/lib/src/source/git.dart
index 5f1def9..3be752c 100644
--- a/lib/src/source/git.dart
+++ b/lib/src/source/git.dart
@@ -2,17 +2,17 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:io';
+import 'package:collection/collection.dart' show IterableNullableExtension;
import 'package:path/path.dart' as p;
import 'package:pool/pool.dart';
import 'package:pub_semver/pub_semver.dart';
import '../git.dart' as git;
import '../io.dart';
+import '../language_version.dart';
import '../log.dart' as log;
import '../package.dart';
import '../package_name.dart';
@@ -44,7 +44,12 @@
}
@override
- PackageRef parseRef(String name, description, {String containingPath}) {
+ PackageRef parseRef(
+ String name,
+ description, {
+ String? containingPath,
+ LanguageVersion? languageVersion,
+ }) {
dynamic url;
dynamic ref;
dynamic path;
@@ -73,7 +78,7 @@
@override
PackageId parseId(String name, Version version, description,
- {String containingPath}) {
+ {String? containingPath}) {
if (description is! Map) {
throw FormatException("The description must be a map with a 'url' "
'key.');
@@ -103,10 +108,10 @@
/// For the descriptions where `relative` attribute is `true`, tries to make
/// `url` relative to the specified [containingPath].
@override
- dynamic serializeDescription(String containingPath, description) {
+ dynamic serializeDescription(String? containingPath, description) {
final copy = Map.from(description);
copy.remove('relative');
- if (description['relative'] == true) {
+ if (description['relative'] == true && containingPath != null) {
copy['url'] = p.url.relative(description['url'],
from: Uri.file(containingPath).toString());
}
@@ -114,7 +119,7 @@
}
/// Throws a [FormatException] if [url] isn't a valid Git URL.
- Map<String, Object> _validatedUrl(dynamic url, String containingDir) {
+ Map<String, Object> _validatedUrl(dynamic url, String? containingDir) {
if (url is! String) {
throw FormatException("The 'url' field of the description must be a "
'string.');
@@ -248,7 +253,8 @@
}
@override
- Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge) async {
+ Future<List<PackageId>> doGetVersions(
+ PackageRef ref, Duration? maxAge) async {
return await _pool.withResource(() async {
await _ensureRepoCache(ref);
var path = _repoCachePath(ref);
@@ -301,7 +307,7 @@
// Git doesn't recognize backslashes in paths, even on Windows.
if (Platform.isWindows) pubspecPath = pubspecPath.replaceAll('\\', '/');
- List<String> lines;
+ late List<String> lines;
try {
lines = await git
.run(['show', '$revision:$pubspecPath'], workingDir: repoPath);
@@ -361,8 +367,8 @@
/// Returns the path to the revision-specific cache of [id].
@override
- String getDirectoryInCache(PackageId id) =>
- p.join(_revisionCachePath(id), id.description['path']);
+ String getDirectoryInCache(PackageId? id) =>
+ p.join(_revisionCachePath(id!), id.description['path']);
@override
List<Package> getCachedPackages() {
@@ -401,7 +407,7 @@
}
});
})
- .where((package) => package != null)
+ .whereNotNull()
.toList();
// Note that there may be multiple packages with the same name and version
@@ -516,7 +522,7 @@
['rev-parse', '--is-inside-git-dir'],
workingDir: dirPath,
);
- if (result?.join('\n') != 'true') {
+ if (result.join('\n') != 'true') {
isValid = false;
}
} on git.GitException {
diff --git a/lib/src/source/hosted.dart b/lib/src/source/hosted.dart
index 11f37b8..2cfc52a 100644
--- a/lib/src/source/hosted.dart
+++ b/lib/src/source/hosted.dart
@@ -2,16 +2,14 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:convert';
import 'dart:io' as io;
-import 'package:collection/collection.dart' show maxBy;
+import 'package:collection/collection.dart'
+ show maxBy, IterableNullableExtension;
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as p;
-import 'package:pedantic/pedantic.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:stack_trace/stack_trace.dart';
@@ -19,6 +17,7 @@
import '../exceptions.dart';
import '../http.dart';
import '../io.dart';
+import '../language_version.dart';
import '../log.dart' as log;
import '../package.dart';
import '../package_name.dart';
@@ -97,6 +96,13 @@
? _OfflineHostedSource(this, systemCache)
: BoundHostedSource(this, systemCache);
+ static String pubDevUrl = 'https://pub.dartlang.org';
+
+ static bool isFromPubDev(PackageId id) {
+ return id.source is HostedSource &&
+ (id.description as _HostedDescription).uri.toString() == pubDevUrl;
+ }
+
/// Gets the default URL for the package server for hosted dependencies.
Uri get defaultUrl {
// Changing this to pub.dev raises the following concerns:
@@ -120,27 +126,27 @@
}
}
- Uri _defaultUrl;
+ Uri? _defaultUrl;
/// Returns a reference to a hosted package named [name].
///
/// If [url] is passed, it's the URL of the pub server from which the package
/// should be downloaded. [url] most be normalized and validated using
/// [validateAndNormalizeHostedUrl].
- PackageRef refFor(String name, {Uri url}) =>
- PackageRef(name, this, _descriptionFor(name, url));
+ PackageRef refFor(String name, {Uri? url}) =>
+ PackageRef(name, this, _HostedDescription(name, url ?? defaultUrl));
/// Returns an ID for a hosted package named [name] at [version].
///
/// If [url] is passed, it's the URL of the pub server from which the package
/// should be downloaded. [url] most be normalized and validated using
/// [validateAndNormalizeHostedUrl].
- PackageId idFor(String name, Version version, {Uri url}) =>
- PackageId(name, this, version, _descriptionFor(name, url));
+ PackageId idFor(String name, Version version, {Uri? url}) => PackageId(
+ name, this, version, _HostedDescription(name, url ?? defaultUrl));
/// Returns the description for a hosted package named [name] with the
/// given package server [url].
- dynamic _descriptionFor(String name, [Uri url]) {
+ dynamic _serializedDescriptionFor(String name, [Uri? url]) {
if (url == null) {
return name;
}
@@ -153,54 +159,118 @@
}
@override
+ dynamic serializeDescription(String? containingPath, description) {
+ final desc = _asDescription(description);
+ return _serializedDescriptionFor(desc.packageName, desc.uri);
+ }
+
+ @override
String formatDescription(description) =>
- 'on ${_parseDescription(description).last}';
+ 'on ${_asDescription(description).uri}';
@override
bool descriptionsEqual(description1, description2) =>
- _parseDescription(description1) == _parseDescription(description2);
+ _asDescription(description1) == _asDescription(description2);
@override
- int hashDescription(description) => _parseDescription(description).hashCode;
+ int hashDescription(description) => _asDescription(description).hashCode;
/// Ensures that [description] is a valid hosted package description.
///
- /// There are two valid formats. A plain string refers to a package with the
- /// given name from the default host, while a map with keys "name" and "url"
- /// refers to a package with the given name from the host at the given URL.
+ /// Simple hosted dependencies only consist of a plain string, which is
+ /// resolved against the default host. In this case, [description] will be
+ /// null.
+ ///
+ /// Hosted dependencies may also specify a custom host from which the package
+ /// is fetched. There are two syntactic forms of those dependencies:
+ ///
+ /// 1. With an url and an optional name in a map: `hosted: {url: <url>}`
+ /// 2. With a direct url: `hosted: <url>`
@override
- PackageRef parseRef(String name, description, {String containingPath}) {
- _parseDescription(description);
- return PackageRef(name, this, description);
+ PackageRef parseRef(String name, description,
+ {String? containingPath, required LanguageVersion languageVersion}) {
+ return PackageRef(
+ name, this, _parseDescription(name, description, languageVersion));
}
@override
PackageId parseId(String name, Version version, description,
- {String containingPath}) {
- _parseDescription(description);
- return PackageId(name, this, version, description);
+ {String? containingPath}) {
+ // Old pub versions only wrote `description: <pkg>` into the lock file.
+ if (description is String) {
+ if (description != name) {
+ throw FormatException('The description should be the same as the name');
+ }
+ return PackageId(
+ name, this, version, _HostedDescription(name, defaultUrl));
+ }
+
+ final serializedDescription = (description as Map).cast<String, String>();
+
+ return PackageId(
+ name,
+ this,
+ version,
+ _HostedDescription(serializedDescription['name']!,
+ Uri.parse(serializedDescription['url']!)),
+ );
}
+ _HostedDescription _asDescription(desc) => desc as _HostedDescription;
+
/// Parses the description for a package.
///
/// If the package parses correctly, this returns a (name, url) pair. If not,
/// this throws a descriptive FormatException.
- Pair<String, Uri> _parseDescription(description) {
+ _HostedDescription _parseDescription(
+ String packageName,
+ description,
+ LanguageVersion languageVersion,
+ ) {
+ if (description == null) {
+ // Simple dependency without a `hosted` block, use the default server.
+ return _HostedDescription(packageName, defaultUrl);
+ }
+
+ final canUseShorthandSyntax = languageVersion.supportsShorterHostedSyntax;
+
if (description is String) {
- return Pair<String, Uri>(description, defaultUrl);
+ // Old versions of pub (pre Dart 2.15) interpret `hosted: foo` as
+ // `hosted: {name: foo, url: <default>}`.
+ // For later versions, we treat it as `hosted: {name: <inferred>,
+ // url: foo}` if a user opts in by raising their min SDK environment.
+ //
+ // Since the old behavior is very rarely used and we want to show a
+ // helpful error message if the new syntax is used without raising the SDK
+ // environment, we throw an error if something that looks like a URI is
+ // used as a package name.
+ if (canUseShorthandSyntax) {
+ return _HostedDescription(
+ packageName, validateAndNormalizeHostedUrl(description));
+ } else {
+ if (_looksLikePackageName.hasMatch(description)) {
+ // Valid use of `hosted: package` dependency with an old SDK
+ // environment.
+ return _HostedDescription(description, defaultUrl);
+ } else {
+ throw FormatException(
+ 'Using `hosted: <url>` is only supported with a minimum SDK '
+ 'constraint of ${LanguageVersion.firstVersionWithShorterHostedSyntax}.',
+ );
+ }
+ }
}
if (description is! Map) {
throw FormatException('The description must be a package name or map.');
}
- if (!description.containsKey('name')) {
- throw FormatException("The description map must contain a 'name' key.");
- }
-
var name = description['name'];
+ if (canUseShorthandSyntax) name ??= packageName;
+
if (name is! String) {
- throw FormatException("The 'name' key must have a string value.");
+ throw FormatException("The 'name' key must have a string value without "
+ 'a minimum Dart SDK constraint of ${LanguageVersion.firstVersionWithShorterHostedSyntax}.0 or higher.');
}
var url = defaultUrl;
@@ -212,8 +282,11 @@
url = validateAndNormalizeHostedUrl(u);
}
- return Pair<String, Uri>(name, url);
+ return _HostedDescription(name, url);
}
+
+ static final RegExp _looksLikePackageName =
+ RegExp(r'^[a-zA-Z_]+[a-zA-Z0-9_]*$');
}
/// Information about a package version retrieved from /api/packages/$package
@@ -225,6 +298,28 @@
_VersionInfo(this.pubspec, this.archiveUrl, this.status);
}
+/// The [PackageName.description] for a [HostedSource], storing the package name
+/// and resolved URI of the package server.
+class _HostedDescription {
+ final String packageName;
+ final Uri uri;
+
+ _HostedDescription(this.packageName, this.uri) {
+ ArgumentError.checkNotNull(packageName, 'packageName');
+ ArgumentError.checkNotNull(uri, 'uri');
+ }
+
+ @override
+ int get hashCode => Object.hash(packageName, uri);
+
+ @override
+ bool operator ==(Object other) {
+ return other is _HostedDescription &&
+ other.packageName == packageName &&
+ other.uri == uri;
+ }
+}
+
/// The [BoundSource] for [HostedSource].
class BoundHostedSource extends CachedSource {
@override
@@ -232,7 +327,8 @@
@override
final SystemCache systemCache;
- RateLimitedScheduler<PackageRef, Map<PackageId, _VersionInfo>> _scheduler;
+ late RateLimitedScheduler<PackageRef, Map<PackageId, _VersionInfo>?>
+ _scheduler;
BoundHostedSource(this.source, this.systemCache) {
_scheduler = RateLimitedScheduler(
@@ -255,9 +351,9 @@
var archiveUrl = map['archive_url'];
if (archiveUrl is String) {
final status = PackageStatus(
- isDiscontinued: body['isDiscontinued'] as bool ?? false,
- discontinuedReplacedBy: body['replacedBy'] as String,
- isRetracted: map['retracted'] as bool ?? false);
+ isDiscontinued: body['isDiscontinued'] ?? false,
+ discontinuedReplacedBy: body['replacedBy'],
+ isRetracted: map['retracted'] ?? false);
return MapEntry(
id, _VersionInfo(pubspec, Uri.parse(archiveUrl), status));
}
@@ -269,15 +365,15 @@
throw FormatException('versions must be a list');
}
- Future<Map<PackageId, _VersionInfo>> _fetchVersionsNoPrefetching(
+ Future<Map<PackageId, _VersionInfo>?> _fetchVersionsNoPrefetching(
PackageRef ref) async {
final serverUrl = _hostedUrl(ref.description);
final url = _listVersionsUrl(ref.description);
log.io('Get versions from $url.');
- String bodyText;
- Map body;
- Map<PackageId, _VersionInfo> result;
+ late final String bodyText;
+ late final dynamic body;
+ late final Map<PackageId, _VersionInfo> result;
try {
// TODO(sigurdm): Implement cancellation of requests. This probably
// requires resolution of: https://github.com/dart-lang/sdk/issues/22265.
@@ -286,39 +382,44 @@
serverUrl,
(client) => client.read(url, headers: pubApiHeaders),
);
- body = jsonDecode(bodyText);
+ final decoded = jsonDecode(bodyText);
+ if (decoded is! Map<String, dynamic>) {
+ throw FormatException('version listing must be a mapping');
+ }
+ body = decoded;
result = _versionInfoFromPackageListing(body, ref, url);
- } catch (error, stackTrace) {
- var parsed = source._parseDescription(ref.description);
- _throwFriendlyError(error, stackTrace, parsed.first, parsed.last);
+ } on Exception catch (error, stackTrace) {
+ final packageName = source._asDescription(ref.description).packageName;
+ _throwFriendlyError(error, stackTrace, packageName, serverUrl);
}
// Cache the response on disk.
// Don't cache overly big responses.
- if (body.length < 100 * 1024) {
+ if (bodyText.length < 100 * 1024) {
await _cacheVersionListingResponse(body, ref);
}
return result;
}
- Future<Map<PackageId, _VersionInfo>> _fetchVersions(PackageRef ref) async {
+ Future<Map<PackageId, _VersionInfo>?> _fetchVersions(PackageRef ref) async {
final preschedule =
- Zone.current[_prefetchingKey] as void Function(PackageRef);
+ Zone.current[_prefetchingKey] as void Function(PackageRef)?;
/// Prefetch the dependencies of the latest version, we are likely to need
/// them later.
- void prescheduleDependenciesOfLatest(Map<PackageId, _VersionInfo> listing) {
+ void prescheduleDependenciesOfLatest(
+ Map<PackageId, _VersionInfo>? listing) {
if (listing == null) return;
final latestVersion =
- maxBy(listing.keys.map((id) => id.version), (e) => e);
+ maxBy(listing.keys.map((id) => id.version), (e) => e)!;
final latestVersionId =
PackageId(ref.name, source, latestVersion, ref.description);
final dependencies =
- listing[latestVersionId]?.pubspec?.dependencies?.values ?? [];
+ listing[latestVersionId]?.pubspec.dependencies.values ?? [];
unawaited(withDependencyType(DependencyType.none, () async {
for (final packageRange in dependencies) {
if (packageRange.source is HostedSource) {
- preschedule(packageRange.toRef());
+ preschedule!(packageRange.toRef());
}
}
}));
@@ -341,6 +442,15 @@
return result;
}
+ /// An in-memory cache to store the cached version listing loaded from
+ /// [_versionListingCachePath].
+ ///
+ /// Invariant: Entries in this cache are the parsed version of the exact same
+ /// information cached on disk. I.e. if the entry is present in this cache,
+ /// there will not be a newer version on disk.
+ final Map<PackageRef, Pair<DateTime, Map<PackageId, _VersionInfo>>>
+ _responseCache = {};
+
/// If a cached version listing response for [ref] exists on disk and is less
/// than [maxAge] old it is parsed and returned.
///
@@ -348,29 +458,38 @@
///
/// If [maxAge] is not given, we will try to get the cached version no matter
/// how old it is.
- Future<Map<PackageId, _VersionInfo>> _cachedVersionListingResponse(
+ Future<Map<PackageId, _VersionInfo>?> _cachedVersionListingResponse(
PackageRef ref,
- {Duration maxAge}) async {
+ {Duration? maxAge}) async {
+ if (_responseCache.containsKey(ref)) {
+ final cacheAge = DateTime.now().difference(_responseCache[ref]!.first);
+ if (maxAge == null || maxAge > cacheAge) {
+ // The cached value is not too old.
+ return _responseCache[ref]!.last;
+ }
+ }
final cachePath = _versionListingCachePath(ref);
- final stat = await io.File(cachePath).stat();
+ final stat = io.File(cachePath).statSync();
final now = DateTime.now();
if (stat.type == io.FileSystemEntityType.file) {
if (maxAge == null || now.difference(stat.modified) < maxAge) {
try {
- final cachedDoc = jsonDecode(await readTextFileAsync(cachePath));
+ final cachedDoc = jsonDecode(readTextFile(cachePath));
final timestamp = cachedDoc['_fetchedAt'];
if (timestamp is String) {
- final cacheAge =
- DateTime.now().difference(DateTime.parse(timestamp));
+ final parsedTimestamp = DateTime.parse(timestamp);
+ final cacheAge = DateTime.now().difference(parsedTimestamp);
if (maxAge != null && cacheAge > maxAge) {
// Too old according to internal timestamp - delete.
tryDeleteEntry(cachePath);
} else {
- return _versionInfoFromPackageListing(
+ var res = _versionInfoFromPackageListing(
cachedDoc,
ref,
Uri.file(cachePath),
);
+ _responseCache[ref] = Pair(parsedTimestamp, res);
+ return res;
}
}
} on io.IOException {
@@ -389,7 +508,8 @@
}
/// Saves the (decoded) response from package-listing of [ref].
- Future<void> _cacheVersionListingResponse(Map body, PackageRef ref) async {
+ Future<void> _cacheVersionListingResponse(
+ Map<String, dynamic> body, PackageRef ref) async {
final path = _versionListingCachePath(ref);
try {
ensureDir(p.dirname(path));
@@ -402,6 +522,9 @@
},
),
);
+ // Delete the entry in the in-memory cache to maintain the invariant that
+ // cached information in memory is the same as that on the disk.
+ _responseCache.remove(ref);
} on io.IOException catch (e) {
// Not being able to write this cache is not fatal. Just move on...
log.fine('Failed writing cache file. $e');
@@ -409,7 +532,7 @@
}
@override
- Future<PackageStatus> status(PackageId id, {Duration maxAge}) async {
+ Future<PackageStatus> status(PackageId id, {Duration? maxAge}) async {
final ref = id.toRef();
// Did we already get info for this package?
var versionListing = _scheduler.peek(ref);
@@ -427,7 +550,7 @@
test: (error) => error is Exception,
);
- final listing = versionListing[id];
+ final listing = versionListing![id];
// If we don't have the specific version we return the empty response, since
// it is more or less harmless..
//
@@ -441,8 +564,8 @@
// The path where the response from the package-listing api is cached.
String _versionListingCachePath(PackageRef ref) {
- final parsed = source._parseDescription(ref.description);
- final dir = _urlToDirectory(parsed.last);
+ final parsed = source._asDescription(ref.description);
+ final dir = _urlToDirectory(parsed.uri);
// Use a dot-dir because older versions of pub won't choke on that
// name when iterating the cache (it is not listed by [listDir]).
return p.join(systemCacheRoot, dir, _versionListingDirectory,
@@ -454,7 +577,8 @@
/// Downloads a list of all versions of a package that are available from the
/// site.
@override
- Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge) async {
+ Future<List<PackageId>> doGetVersions(
+ PackageRef ref, Duration? maxAge) async {
var versionListing = _scheduler.peek(ref);
if (maxAge != null) {
// Do we have a cached version response on disk?
@@ -462,22 +586,22 @@
await _cachedVersionListingResponse(ref, maxAge: maxAge);
}
versionListing ??= await _scheduler.schedule(ref);
- return versionListing.keys.toList();
+ return versionListing!.keys.toList();
}
/// Parses [description] into its server and package name components, then
/// converts that to a Uri for listing versions of the given package.
Uri _listVersionsUrl(description) {
- final parsed = source._parseDescription(description);
- final hostedUrl = parsed.last;
- final package = Uri.encodeComponent(parsed.first);
+ final parsed = source._asDescription(description);
+ final hostedUrl = parsed.uri;
+ final package = Uri.encodeComponent(parsed.packageName);
return hostedUrl.resolve('api/packages/$package');
}
/// Parses [description] into server name component.
Uri _hostedUrl(description) {
- final parsed = source._parseDescription(description);
- return parsed.last;
+ final parsed = source._asDescription(description);
+ return parsed.uri;
}
/// Retrieves the pubspec for a specific version of a package that is
@@ -486,7 +610,7 @@
Future<Pubspec> describeUncached(PackageId id) async {
final versions = await _scheduler.schedule(id.toRef());
final url = _listVersionsUrl(id.description);
- return versions[id]?.pubspec ??
+ return versions![id]?.pubspec ??
(throw PackageNotFoundException('Could not find package $id at $url'));
}
@@ -509,9 +633,9 @@
/// package downloaded from that site.
@override
String getDirectoryInCache(PackageId id) {
- var parsed = source._parseDescription(id.description);
- var dir = _urlToDirectory(parsed.last);
- return p.join(systemCacheRoot, dir, '${parsed.first}-${id.version}');
+ var parsed = source._asDescription(id.description);
+ var dir = _urlToDirectory(parsed.uri);
+ return p.join(systemCacheRoot, dir, '${parsed.packageName}-${id.version}');
}
/// Re-downloads all packages that have been previously downloaded into the
@@ -564,6 +688,7 @@
packages.map((package) async {
var id = source.idFor(package.name, package.version, url: url);
try {
+ deleteEntry(package.dir);
await _download(id, package.dir);
return RepairResult(id, success: true);
} catch (error, stackTrace) {
@@ -584,7 +709,7 @@
/// Returns the best-guess package ID for [basename], which should be a
/// subdirectory in a hosted cache.
- PackageId _idForBasename(String basename, {Uri url}) {
+ PackageId _idForBasename(String basename, {Uri? url}) {
var components = split1(basename, '-');
var version = Version.none;
if (components.length > 1) {
@@ -621,7 +746,7 @@
return null;
}
})
- .where((e) => e != null)
+ .whereNotNull()
.toList();
}
@@ -642,20 +767,17 @@
// query-string as is the case with signed S3 URLs. And we wish to allow for
// such URLs to be used.
final versions = await _scheduler.schedule(id.toRef());
- final versionInfo = versions[id];
+ final versionInfo = versions![id];
final packageName = id.name;
final version = id.version;
if (versionInfo == null) {
throw PackageNotFoundException(
'Package $packageName has no version $version');
}
- final parsedDescription = source._parseDescription(id.description);
- final server = parsedDescription.last;
+ final parsedDescription = source._asDescription(id.description);
+ final server = parsedDescription.uri;
var url = versionInfo.archiveUrl;
- // To support old servers that has no archive_url we fall back to the
- // hard-coded path.
- url ??= Uri.parse('$server/packages/$packageName/versions/$version.tar.gz');
log.io('Get package from $url.');
log.message('Downloading ${log.bold(id.name)} ${id.version}...');
@@ -675,51 +797,74 @@
var tempDir = systemCache.createTempDir();
await extractTarGz(readBinaryFileAsSream(archivePath), tempDir);
- // Remove the existing directory if it exists. This will happen if
- // we're forcing a download to repair the cache.
- if (dirExists(destPath)) deleteEntry(destPath);
-
// Now that the get has succeeded, move it to the real location in the
- // cache. This ensures that we don't leave half-busted ghost
- // directories in the user's pub cache if a get fails.
- renameDir(tempDir, destPath);
+ // cache.
+ //
+ // If this fails with a "directory not empty" exception we assume that
+ // another pub process has installed the same package version while we
+ // downloaded.
+ tryRenameDir(tempDir, destPath);
});
}
- /// When an error occurs trying to read something about [package] from [url],
+ /// When an error occurs trying to read something about [package] from [hostedUrl],
/// this tries to translate into a more user friendly error message.
///
/// Always throws an error, either the original one or a better one.
- void _throwFriendlyError(
- error,
+ Never _throwFriendlyError(
+ Exception error,
StackTrace stackTrace,
String package,
- Uri url,
+ Uri hostedUrl,
) {
if (error is PubHttpException) {
if (error.response.statusCode == 404) {
throw PackageNotFoundException(
- 'could not find package $package at $url',
+ 'could not find package $package at $hostedUrl',
innerError: error,
innerTrace: stackTrace);
}
fail(
'${error.response.statusCode} ${error.response.reasonPhrase} trying '
- 'to find package $package at $url.',
+ 'to find package $package at $hostedUrl.',
error,
stackTrace);
} else if (error is io.SocketException) {
- fail('Got socket error trying to find package $package at $url.', error,
- stackTrace);
+ fail('Got socket error trying to find package $package at $hostedUrl.',
+ error, stackTrace);
} else if (error is io.TlsException) {
- fail('Got TLS error trying to find package $package at $url.', error,
- stackTrace);
+ fail('Got TLS error trying to find package $package at $hostedUrl.',
+ error, stackTrace);
+ } else if (error is AuthenticationException) {
+ String? hint;
+ var message = 'authentication failed';
+
+ assert(error.statusCode == 401 || error.statusCode == 403);
+ if (error.statusCode == 401) {
+ hint = '$hostedUrl package repository requested authentication!\n'
+ 'You can provide credentials using:\n'
+ ' pub token add $hostedUrl';
+ }
+ if (error.statusCode == 403) {
+ hint = 'Insufficient permissions to the resource at the $hostedUrl '
+ 'package repository.\nYou can modify credentials using:\n'
+ ' pub token add $hostedUrl';
+ message = 'authorization failed';
+ }
+
+ if (error.serverMessage?.isNotEmpty == true && hint != null) {
+ hint += '\n${error.serverMessage}';
+ }
+
+ throw PackageNotFoundException(message, hint: hint);
} else if (error is FormatException) {
throw PackageNotFoundException(
- 'Got badly formatted response trying to find package $package at $url',
- innerError: error,
- innerTrace: stackTrace);
+ 'Got badly formatted response trying to find package $package at $hostedUrl',
+ innerError: error,
+ innerTrace: stackTrace,
+ hint: 'Check that "$hostedUrl" is a valid package repository.',
+ );
} else {
// Otherwise re-throw the original exception.
throw error;
@@ -755,7 +900,7 @@
return replace(
url,
RegExp(r'[<>:"\\/|?*%]'),
- (match) => '%${match[0].codeUnitAt(0)}',
+ (match) => '%${match[0]!.codeUnitAt(0)}',
);
}
@@ -786,7 +931,7 @@
}
/// Returns the server URL for [description].
- Uri _serverFor(description) => source._parseDescription(description).last;
+ Uri _serverFor(description) => source._asDescription(description).uri;
/// Enables speculative prefetching of dependencies of packages queried with
/// [getVersions].
@@ -812,9 +957,12 @@
/// Gets the list of all versions of [ref] that are in the system cache.
@override
- Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge) async {
- var parsed = source._parseDescription(ref.description);
- var server = parsed.last;
+ Future<List<PackageId>> doGetVersions(
+ PackageRef ref,
+ Duration? maxAge,
+ ) async {
+ var parsed = source._asDescription(ref.description);
+ var server = parsed.uri;
log.io('Finding versions of ${ref.name} in '
'$systemCacheRoot/${_urlToDirectory(server)}');
@@ -834,7 +982,9 @@
// If there are no versions in the cache, report a clearer error.
if (versions.isEmpty) {
throw PackageNotFoundException(
- 'could not find package ${ref.name} in cache');
+ 'could not find package ${ref.name} in cache',
+ hint: 'Try again without --offline!',
+ );
}
return versions;
@@ -850,18 +1000,19 @@
@override
Future<Pubspec> describeUncached(PackageId id) {
throw PackageNotFoundException(
- '${id.name} ${id.version} is not available in your system cache');
+ '${id.name} ${id.version} is not available in cache',
+ hint: 'Try again without --offline!',
+ );
}
@override
- Future<PackageStatus> status(PackageId id, {Duration maxAge}) async {
+ Future<PackageStatus> status(PackageId id, {Duration? maxAge}) async {
// Do we have a cached version response on disk?
final versionListing = await _cachedVersionListingResponse(id.toRef());
if (versionListing == null) {
return PackageStatus();
}
- final listing = versionListing[id];
// If we don't have the specific version we return the empty response.
//
// This should not happen. But in production we want to avoid a crash, since
@@ -869,7 +1020,6 @@
//
// TODO(sigurdm): Consider representing the non-existence of the
// package-version in the return value.
- assert(listing != null);
return versionListing[id]?.status ?? PackageStatus();
}
}
diff --git a/lib/src/source/path.dart b/lib/src/source/path.dart
index b1dc26b..4679f98 100644
--- a/lib/src/source/path.dart
+++ b/lib/src/source/path.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:path/path.dart' as p;
@@ -11,6 +9,7 @@
import '../exceptions.dart';
import '../io.dart';
+import '../language_version.dart';
import '../package_name.dart';
import '../pubspec.dart';
import '../source.dart';
@@ -64,7 +63,12 @@
/// original path but resolved relative to the containing path. The
/// "relative" key will be `true` if the original path was relative.
@override
- PackageRef parseRef(String name, description, {String containingPath}) {
+ PackageRef parseRef(
+ String name,
+ description, {
+ String? containingPath,
+ LanguageVersion? languageVersion,
+ }) {
if (description is! String) {
throw FormatException('The description must be a path string.');
}
@@ -90,7 +94,7 @@
@override
PackageId parseId(String name, Version version, description,
- {String containingPath}) {
+ {String? containingPath}) {
if (description is! Map) {
throw FormatException('The description must be a map.');
}
@@ -126,9 +130,11 @@
///
/// For the descriptions where `relative` attribute is `true`, tries to make
/// `path` relative to the specified [containingPath].
+ ///
+ /// If [containingPath] is `null` they are serialized as absolute.
@override
- dynamic serializeDescription(String containingPath, description) {
- if (description['relative']) {
+ dynamic serializeDescription(String? containingPath, description) {
+ if (description['relative'] == true && containingPath != null) {
return {
'path': relativePathWithPosixSeparators(
p.relative(description['path'], from: containingPath)),
@@ -165,7 +171,8 @@
BoundPathSource(this.source, this.systemCache);
@override
- Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge) async {
+ Future<List<PackageId>> doGetVersions(
+ PackageRef ref, Duration? maxAge) async {
// There's only one package ID for a given path. We just need to find the
// version.
var pubspec = _loadPubspec(ref);
@@ -183,10 +190,10 @@
}
@override
- String getDirectory(PackageId id, {String relativeFrom}) {
+ String getDirectory(PackageId id, {String? relativeFrom}) {
return id.description['relative']
? p.relative(id.description['path'], from: relativeFrom)
- : id.description['path'];
+ : id.description['path']!;
}
/// Ensures that [description] is a valid path description and returns a
diff --git a/lib/src/source/sdk.dart b/lib/src/source/sdk.dart
index aff6acc..1458d1b 100644
--- a/lib/src/source/sdk.dart
+++ b/lib/src/source/sdk.dart
@@ -2,13 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:pub_semver/pub_semver.dart';
import '../exceptions.dart';
+import '../language_version.dart';
import '../package_name.dart';
import '../pubspec.dart';
import '../sdk.dart';
@@ -35,7 +34,8 @@
/// Parses an SDK dependency.
@override
- PackageRef parseRef(String name, description, {String containingPath}) {
+ PackageRef parseRef(String name, description,
+ {String? containingPath, LanguageVersion? languageVersion}) {
if (description is! String) {
throw FormatException('The description must be an SDK name.');
}
@@ -45,7 +45,7 @@
@override
PackageId parseId(String name, Version version, description,
- {String containingPath}) {
+ {String? containingPath}) {
if (description is! String) {
throw FormatException('The description must be an SDK name.');
}
@@ -72,7 +72,8 @@
BoundSdkSource(this.source, this.systemCache);
@override
- Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge) async {
+ Future<List<PackageId>> doGetVersions(
+ PackageRef ref, Duration? maxAge) async {
var pubspec = _loadPubspec(ref);
var id = PackageId(ref.name, source, pubspec.version, ref.description);
memoizePubspec(id, pubspec);
@@ -95,13 +96,15 @@
/// Throws a [PackageNotFoundException] if [package]'s SDK is unavailable or
/// doesn't contain the package.
String _verifiedPackagePath(PackageName package) {
- var identifier = package.description as String;
- var sdk = sdks[identifier];
+ var identifier = package.description as String?;
+ var sdk = sdks[identifier!];
if (sdk == null) {
throw PackageNotFoundException('unknown SDK "$identifier"');
} else if (!sdk.isAvailable) {
- throw PackageNotFoundException('the ${sdk.name} SDK is not available',
- missingSdk: sdk);
+ throw PackageNotFoundException(
+ 'the ${sdk.name} SDK is not available',
+ hint: sdk.installMessage,
+ );
}
var path = sdk.packagePath(package.name);
@@ -112,7 +115,7 @@
}
@override
- String getDirectory(PackageId id, {String relativeFrom}) {
+ String getDirectory(PackageId id, {String? relativeFrom}) {
try {
return _verifiedPackagePath(id);
} on PackageNotFoundException catch (error) {
diff --git a/lib/src/source/unknown.dart b/lib/src/source/unknown.dart
index d98d0e2..baa46ea 100644
--- a/lib/src/source/unknown.dart
+++ b/lib/src/source/unknown.dart
@@ -2,12 +2,11 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:pub_semver/pub_semver.dart';
+import '../language_version.dart';
import '../package_name.dart';
import '../pubspec.dart';
import '../source.dart';
@@ -44,12 +43,17 @@
int hashDescription(description) => description.hashCode;
@override
- PackageRef parseRef(String name, description, {String containingPath}) =>
+ PackageRef parseRef(
+ String name,
+ description, {
+ String? containingPath,
+ LanguageVersion? languageVersion,
+ }) =>
PackageRef(name, this, description);
@override
PackageId parseId(String name, Version version, description,
- {String containingPath}) =>
+ {String? containingPath}) =>
PackageId(name, this, version, description);
}
@@ -63,7 +67,7 @@
_BoundUnknownSource(this.source, this.systemCache);
@override
- Future<List<PackageId>> doGetVersions(PackageRef ref, Duration maxAge) =>
+ Future<List<PackageId>> doGetVersions(PackageRef ref, Duration? maxAge) =>
throw UnsupportedError(
"Cannot get package versions from unknown source '${source.name}'.");
@@ -73,7 +77,7 @@
/// Returns the directory where this package can be found locally.
@override
- String getDirectory(PackageId id, {String relativeFrom}) =>
+ String getDirectory(PackageId id, {String? relativeFrom}) =>
throw UnsupportedError(
"Cannot find a package from an unknown source '${source.name}'.");
}
diff --git a/lib/src/source_registry.dart b/lib/src/source_registry.dart
index 9c946eb..7e8aa84 100644
--- a/lib/src/source_registry.dart
+++ b/lib/src/source_registry.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'source.dart';
import 'source/git.dart';
import 'source/hosted.dart';
@@ -27,7 +25,7 @@
///
/// This defaults to [hosted].
Source get defaultSource => _default;
- Source _default;
+ late Source _default;
/// The registered sources, in name order.
List<Source> get all {
@@ -60,7 +58,7 @@
throw StateError('Default source $name is not in the registry');
}
- _default = _sources[name];
+ _default = _sources[name]!;
}
/// Registers a new source.
@@ -80,7 +78,7 @@
///
/// Returns an [UnknownSource] if no source with that name has been
/// registered. If [name] is null, returns the default source.
- Source operator [](String name) {
+ Source? operator [](String? name) {
if (name == null) return _default;
if (_sources.containsKey(name)) return _sources[name];
return UnknownSource(name);
diff --git a/lib/src/system_cache.dart b/lib/src/system_cache.dart
index 298e775..d6b5876 100644
--- a/lib/src/system_cache.dart
+++ b/lib/src/system_cache.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
import 'package:path/path.dart' as p;
@@ -23,7 +21,6 @@
import 'source/sdk.dart';
import 'source/unknown.dart';
import 'source_registry.dart';
-import 'utils.dart';
/// The system-wide cache of downloaded packages.
///
@@ -38,19 +35,20 @@
static String defaultDir = (() {
if (Platform.environment.containsKey('PUB_CACHE')) {
- return Platform.environment['PUB_CACHE'];
+ return Platform.environment['PUB_CACHE']!;
} else if (Platform.isWindows) {
// %LOCALAPPDATA% is preferred as the cache location over %APPDATA%, because the latter is synchronised between
// devices when the user roams between them, whereas the former is not.
// The default cache dir used to be in %APPDATA%, so to avoid breaking old installs,
// we use the old dir in %APPDATA% if it exists. Else, we use the new default location
// in %LOCALAPPDATA%.
- var appData = Platform.environment['APPDATA'];
+ // TODO(sigurdm): handle missing APPDATA.
+ var appData = Platform.environment['APPDATA']!;
var appDataCacheDir = p.join(appData, 'Pub', 'Cache');
if (dirExists(appDataCacheDir)) {
return appDataCacheDir;
}
- var localAppData = Platform.environment['LOCALAPPDATA'];
+ var localAppData = Platform.environment['LOCALAPPDATA']!;
return p.join(localAppData, 'Pub', 'Cache');
} else {
return '${Platform.environment['HOME']}/.pub-cache';
@@ -64,7 +62,7 @@
final sources = SourceRegistry();
/// The sources bound to this cache.
- final _boundSources = <Source, BoundSource>{};
+ final _boundSources = <Source?, BoundSource>{};
/// The built-in Git source bound to this cache.
BoundGitSource get git => _boundSources[sources.git] as BoundGitSource;
@@ -89,7 +87,7 @@
///
/// If [isOffline] is `true`, then the offline hosted source will be used.
/// Defaults to `false`.
- SystemCache({String rootDir, bool isOffline = false})
+ SystemCache({String? rootDir, bool isOffline = false})
: rootDir = rootDir ?? SystemCache.defaultDir,
tokenStore = TokenStore(dartConfigDir) {
for (var source in sources.all) {
@@ -102,8 +100,8 @@
}
/// Returns the version of [source] bound to this cache.
- BoundSource source(Source source) =>
- _boundSources.putIfAbsent(source, () => source.bind(this));
+ BoundSource source(Source? source) =>
+ _boundSources.putIfAbsent(source, () => source!.bind(this));
/// Loads the package identified by [id].
///
@@ -158,8 +156,8 @@
/// later stable version we return a prerelease version if it exists.
///
/// Returns `null`, if unable to find the package.
- Future<PackageId> getLatest(
- PackageName package, {
+ Future<PackageId?> getLatest(
+ PackageName? package, {
bool allowPrereleases = false,
}) async {
if (package == null) {
@@ -172,21 +170,14 @@
return null;
}
- final latest = maxAll(
- available.map((id) => id.version),
- allowPrereleases ? Comparable.compare : Version.prioritize,
- );
-
+ available.sort(allowPrereleases
+ ? (x, y) => x.version.compareTo(y.version)
+ : (x, y) => Version.prioritize(x.version, y.version));
if (package is PackageId &&
package.version.isPreRelease &&
- package.version > latest &&
- !allowPrereleases) {
- return getLatest(package, allowPrereleases: true);
+ package.version > available.last.version) {
+ available.sort((x, y) => x.version.compareTo(y.version));
}
-
- // There should be exactly one entry in [available] matching [latest]
- assert(available.where((id) => id.version == latest).length == 1);
-
- return available.firstWhere((id) => id.version == latest);
+ return available.last;
}
}
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index fc3984e..2a5768e 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -9,7 +9,6 @@
import 'dart:math' as math;
import 'package:crypto/crypto.dart' as crypto;
-import 'package:meta/meta.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:stack_trace/stack_trace.dart';
@@ -376,7 +375,7 @@
// If we're using verbose logging, be more verbose but more accurate when
// reporting timing information.
- var msString = log.verbosity.isLevelVisible(log.Level.FINE)
+ var msString = log.verbosity.isLevelVisible(log.Level.fine)
? _padLeft(ms.toString(), 3, '0')
: (ms ~/ 100).toString();
@@ -501,8 +500,7 @@
}
/// Throw a [ApplicationException] with [message].
-@alwaysThrows
-void fail(String message, [Object? innerError, StackTrace? innerTrace]) {
+Never fail(String message, [Object? innerError, StackTrace? innerTrace]) {
if (innerError != null) {
throw WrappedException(message, innerError, innerTrace);
} else {
@@ -514,7 +512,7 @@
/// failed because of invalid input data.
///
/// This will report the error and cause pub to exit with [exit_codes.DATA].
-void dataError(String message) => throw DataException(message);
+Never dataError(String message) => throw DataException(message);
/// Returns a UUID in v4 format as a `String`.
///
diff --git a/lib/src/validator.dart b/lib/src/validator.dart
index c6a7b4a..1b07560 100644
--- a/lib/src/validator.dart
+++ b/lib/src/validator.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:meta/meta.dart';
@@ -103,7 +101,7 @@
'Make sure your SDK constraint excludes old versions:\n'
'\n'
'environment:\n'
- ' sdk: \"$newSdkConstraint\"');
+ ' sdk: "$newSdkConstraint"');
}
/// Returns whether [version1] and [version2] are pre-releases of the same version.
@@ -123,8 +121,10 @@
/// package, in bytes. This is used to validate that it's not too big to
/// upload to the server.
static Future<void> runAll(
- Entrypoint entrypoint, Future<int> packageSize, Uri serverUrl,
- {List<String> hints, List<String> warnings, List<String> errors}) {
+ Entrypoint entrypoint, Future<int> packageSize, Uri? serverUrl,
+ {required List<String> hints,
+ required List<String> warnings,
+ required List<String> errors}) {
var validators = [
GitignoreValidator(entrypoint),
PubspecValidator(entrypoint),
@@ -149,9 +149,7 @@
PubspecTypoValidator(entrypoint),
LeakDetectionValidator(entrypoint),
];
- if (packageSize != null) {
- validators.add(SizeValidator(entrypoint, packageSize));
- }
+ validators.add(SizeValidator(entrypoint, packageSize));
return Future.wait(validators.map((validator) => validator.validate()))
.then((_) {
diff --git a/lib/src/validator/changelog.dart b/lib/src/validator/changelog.dart
index 2f93903..614eba2 100644
--- a/lib/src/validator/changelog.dart
+++ b/lib/src/validator/changelog.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:convert';
@@ -23,7 +21,7 @@
final changelog = entrypoint.root.changelogPath;
if (changelog == null) {
- warnings.add('Please add a`CHANGELOG.md` to your package. '
+ warnings.add('Please add a `CHANGELOG.md` to your package. '
'See https://dart.dev/tools/pub/publishing#important-files.');
return;
}
@@ -43,9 +41,6 @@
warnings.add('$changelog contains invalid UTF-8.\n'
'This will cause it to be displayed incorrectly on '
'the Pub site (https://pub.dev).');
- }
-
- if (contents == null) {
// Failed to decode contents, so there's nothing else to check.
return;
}
diff --git a/lib/src/validator/compiled_dartdoc.dart b/lib/src/validator/compiled_dartdoc.dart
index 670862c..3f3376a 100644
--- a/lib/src/validator/compiled_dartdoc.dart
+++ b/lib/src/validator/compiled_dartdoc.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:path/path.dart' as path;
diff --git a/lib/src/validator/dependency.dart b/lib/src/validator/dependency.dart
index c9f221a..5d158d1 100644
--- a/lib/src/validator/dependency.dart
+++ b/lib/src/validator/dependency.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:pub_semver/pub_semver.dart';
@@ -223,8 +221,9 @@
constraint = '^${(dep.constraint as VersionRange).min}';
} else {
constraint = '"${dep.constraint} '
- '<${(dep.constraint as VersionRange).min.nextBreaking}"';
+ '<${(dep.constraint as VersionRange).min!.nextBreaking}"';
}
+ // TODO: Handle the case where `dep.constraint.min` is null.
warnings
.add('Your dependency on "${dep.name}" should have an upper bound. For '
@@ -240,7 +239,7 @@
void _warnAboutPrerelease(String dependencyName, VersionRange constraint) {
final packageVersion = entrypoint.root.version;
if (constraint.min != null &&
- constraint.min.isPreRelease &&
+ constraint.min!.isPreRelease &&
!packageVersion.isPreRelease) {
warnings.add('Packages dependent on a pre-release of another package '
'should themselves be published as a pre-release version. '
diff --git a/lib/src/validator/dependency_override.dart b/lib/src/validator/dependency_override.dart
index 8942be8..24e4e84 100644
--- a/lib/src/validator/dependency_override.dart
+++ b/lib/src/validator/dependency_override.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:collection/collection.dart';
diff --git a/lib/src/validator/deprecated_fields.dart b/lib/src/validator/deprecated_fields.dart
index 150d599..e1aee4f 100644
--- a/lib/src/validator/deprecated_fields.dart
+++ b/lib/src/validator/deprecated_fields.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import '../entrypoint.dart';
diff --git a/lib/src/validator/directory.dart b/lib/src/validator/directory.dart
index 9828f64..409e243 100644
--- a/lib/src/validator/directory.dart
+++ b/lib/src/validator/directory.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:path/path.dart' as path;
diff --git a/lib/src/validator/executable.dart b/lib/src/validator/executable.dart
index e9881d2..2163e8c 100644
--- a/lib/src/validator/executable.dart
+++ b/lib/src/validator/executable.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:path/path.dart' as p;
diff --git a/lib/src/validator/flutter_constraint.dart b/lib/src/validator/flutter_constraint.dart
index 74c2a2e..d689a22 100644
--- a/lib/src/validator/flutter_constraint.dart
+++ b/lib/src/validator/flutter_constraint.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:pub_semver/pub_semver.dart';
diff --git a/lib/src/validator/flutter_plugin_format.dart b/lib/src/validator/flutter_plugin_format.dart
index 87fd3df..6f00f06 100644
--- a/lib/src/validator/flutter_plugin_format.dart
+++ b/lib/src/validator/flutter_plugin_format.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:pub_semver/pub_semver.dart';
diff --git a/lib/src/validator/gitignore.dart b/lib/src/validator/gitignore.dart
index df01214..4fb49b1 100644
--- a/lib/src/validator/gitignore.dart
+++ b/lib/src/validator/gitignore.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:io';
@@ -31,18 +29,27 @@
'--exclude-standard',
'--recurse-submodules'
], workingDir: entrypoint.root.dir);
+ final root = git.repoRoot(entrypoint.root.dir) ?? entrypoint.root.dir;
+ var beneath = p.posix.joinAll(
+ p.split(p.normalize(p.relative(entrypoint.root.dir, from: root))));
+ if (beneath == './') {
+ beneath = '';
+ }
String resolve(String path) {
if (Platform.isWindows) {
- return p.joinAll([entrypoint.root.dir, ...p.posix.split(path)]);
+ return p.joinAll([root, ...p.posix.split(path)]);
}
- return p.join(entrypoint.root.dir, path);
+ return p.join(root, path);
}
final unignoredByGitignore = Ignore.listFiles(
+ beneath: beneath,
listDir: (dir) {
var contents = Directory(resolve(dir)).listSync();
- return contents.map((entity) => p.posix.joinAll(
- p.split(p.relative(entity.path, from: entrypoint.root.dir))));
+ return contents
+ .where((e) => !(linkExists(e.path) && dirExists(e.path)))
+ .map((entity) => p.posix
+ .joinAll(p.split(p.relative(entity.path, from: root))));
},
ignoreForDir: (dir) {
final gitIgnore = resolve('$dir/.gitignore');
@@ -52,15 +59,19 @@
return rules.isEmpty ? null : Ignore(rules);
},
isDir: (dir) => dirExists(resolve(dir)),
- ).toSet();
-
+ ).map((file) {
+ final relative = p.relative(resolve(file), from: entrypoint.root.dir);
+ return Platform.isWindows
+ ? p.posix.joinAll(p.split(relative))
+ : relative;
+ }).toSet();
final ignoredFilesCheckedIn = checkedIntoGit
.where((file) => !unignoredByGitignore.contains(file))
.toList();
if (ignoredFilesCheckedIn.isNotEmpty) {
warnings.add('''
-${ignoredFilesCheckedIn.length} checked in ${pluralize('file', ignoredFilesCheckedIn.length)} ${ignoredFilesCheckedIn.length == 1 ? 'is' : 'are'} ignored by a `.gitignore`.
+${ignoredFilesCheckedIn.length} checked-in ${pluralize('file', ignoredFilesCheckedIn.length)} ${ignoredFilesCheckedIn.length == 1 ? 'is' : 'are'} ignored by a `.gitignore`.
Previous versions of Pub would include those in the published package.
Consider adjusting your `.gitignore` files to not ignore those files, and if you do not wish to
diff --git a/lib/src/validator/language_version.dart b/lib/src/validator/language_version.dart
index 6d71b22..e52a92a 100644
--- a/lib/src/validator/language_version.dart
+++ b/lib/src/validator/language_version.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:analyzer/dart/ast/ast.dart';
diff --git a/lib/src/validator/leak_detection.dart b/lib/src/validator/leak_detection.dart
index 53bf31d..7a398d4 100644
--- a/lib/src/validator/leak_detection.dart
+++ b/lib/src/validator/leak_detection.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:convert';
import 'dart:io';
@@ -75,7 +73,7 @@
errors.addAll(leaks.take(2).map((leak) => leak.toString()));
final files = leaks
- .map((leak) => leak.span.sourceUrl.toFilePath(windows: false))
+ .map((leak) => leak.span.sourceUrl!.toFilePath(windows: false))
.toSet()
.toList(growable: false)
..sort();
@@ -155,8 +153,8 @@
final List<String> testsWithNoLeaks;
LeakPattern._({
- @required this.kind,
- @required String pattern,
+ required this.kind,
+ required String pattern,
Iterable<Pattern> allowed = const <Pattern>[],
Map<int, double> entropyThresholds = const <int, double>{},
Iterable<String> testsWithLeaks = const <String>[],
@@ -177,17 +175,17 @@
Iterable<LeakMatch> findPossibleLeaks(String file, String content) sync* {
final source = SourceFile.fromString(content, url: file);
for (final m in _pattern.allMatches(content)) {
- if (_allowed.any((s) => m.group(0).contains(s))) {
+ if (_allowed.any((s) => m.group(0)!.contains(s))) {
continue;
}
if (_entropyThresholds.entries
- .any((entry) => _entropy(m.group(entry.key)) < entry.value)) {
+ .any((entry) => _entropy(m.group(entry.key)!) < entry.value)) {
continue;
}
yield LeakMatch(
this,
- source.span(m.start, m.start + m.group(0).length),
+ source.span(m.start, m.start + m.group(0)!.length),
);
}
}
@@ -554,7 +552,7 @@
'$_pemRequireLineBreak$_pemWSP',
'=(?:(?:[a-zA-Z0-9+/]$_pemWSP){4})',
_pemEnd('PGP PRIVATE KEY BLOCK'),
- ].join(''),
+ ].join(),
testsWithLeaks: [
'''
-----BEGIN PGP PRIVATE KEY BLOCK-----
@@ -607,7 +605,7 @@
_pemRequireLineBreak,
// Allow arbitrary whitespace and escaped line breaks
_pemWSP,
- ].join('');
+ ].join();
String _pemBase64Block() => [
// Require base64 character in blocks of 4, allow arbirary whitespace
@@ -629,10 +627,10 @@
// character, allow arbirary whitespace and escaped line breaks
// in between.
'(?:[a-zA-Z0-9+/]$_pemWSP){2}(?:=$_pemWSP){2}',
- ].join(''),
+ ].join(),
// End blocks
'))?',
- ].join('');
+ ].join();
String _pemEnd(String label) => [
// Require \n, \r, \\r, or \\n, backslash escaping is allowed if the key
@@ -641,10 +639,10 @@
// Allow arbitrary whitespace and escaped line breaks
_pemWSP,
'-----END $label-----',
- ].join('');
+ ].join();
String _pemKeyFormat(String label) => [
_pemBegin(label),
_pemBase64Block(),
_pemEnd(label),
- ].join('');
+ ].join();
diff --git a/lib/src/validator/license.dart b/lib/src/validator/license.dart
index edca16d..1a2c68a 100644
--- a/lib/src/validator/license.dart
+++ b/lib/src/validator/license.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:path/path.dart' as path;
diff --git a/lib/src/validator/name.dart b/lib/src/validator/name.dart
index d484ed8..07d945c 100644
--- a/lib/src/validator/name.dart
+++ b/lib/src/validator/name.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:path/path.dart' as path;
@@ -74,7 +72,7 @@
builder
..write(source.substring(lastMatchEnd, match.start + 1))
..write('_')
- ..write(match.group(1).toLowerCase());
+ ..write(match.group(1)!.toLowerCase());
lastMatchEnd = match.end;
}
builder.write(source.substring(lastMatchEnd));
diff --git a/lib/src/validator/null_safety_mixed_mode.dart b/lib/src/validator/null_safety_mixed_mode.dart
index 401043e..42f9f77 100644
--- a/lib/src/validator/null_safety_mixed_mode.dart
+++ b/lib/src/validator/null_safety_mixed_mode.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:path/path.dart' as p;
diff --git a/lib/src/validator/pubspec.dart b/lib/src/validator/pubspec.dart
index 20a7174..2a5e052 100644
--- a/lib/src/validator/pubspec.dart
+++ b/lib/src/validator/pubspec.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:path/path.dart' as p;
diff --git a/lib/src/validator/pubspec_field.dart b/lib/src/validator/pubspec_field.dart
index 482d696..8a5c23e 100644
--- a/lib/src/validator/pubspec_field.dart
+++ b/lib/src/validator/pubspec_field.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import '../entrypoint.dart';
diff --git a/lib/src/validator/pubspec_typo.dart b/lib/src/validator/pubspec_typo.dart
index 2e10ed6..9b04292 100644
--- a/lib/src/validator/pubspec_typo.dart
+++ b/lib/src/validator/pubspec_typo.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import '../entrypoint.dart';
import '../levenshtein.dart';
import '../validator.dart';
@@ -16,8 +14,6 @@
Future validate() async {
final fields = entrypoint.root.pubspec.fields;
- if (fields == null) return;
-
/// Limit the number of typo warnings so as not to drown out the other
/// warnings
var warningCount = 0;
@@ -73,4 +69,6 @@
'publish_to',
'false_secrets',
'flutter',
+ 'screenshots',
+ 'platforms',
];
diff --git a/lib/src/validator/readme.dart b/lib/src/validator/readme.dart
index 14d6b5e..85de479 100644
--- a/lib/src/validator/readme.dart
+++ b/lib/src/validator/readme.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:convert';
diff --git a/lib/src/validator/relative_version_numbering.dart b/lib/src/validator/relative_version_numbering.dart
index 6609074..eb4246c 100644
--- a/lib/src/validator/relative_version_numbering.dart
+++ b/lib/src/validator/relative_version_numbering.dart
@@ -2,10 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
+import 'package:collection/collection.dart' show IterableExtension;
+
import '../entrypoint.dart';
import '../exceptions.dart';
import '../null_safety_analysis.dart';
@@ -18,7 +18,7 @@
static const String semverUrl =
'https://dart.dev/tools/pub/versioning#semantic-versions';
- final Uri _server;
+ final Uri? _server;
RelativeVersionNumberingValidator(Entrypoint entrypoint, this._server)
: super(entrypoint);
@@ -35,9 +35,8 @@
existingVersions = [];
}
existingVersions.sort((a, b) => a.version.compareTo(b.version));
- final previousVersion = existingVersions.lastWhere(
- (id) => id.version < entrypoint.root.version,
- orElse: () => null);
+ final previousVersion = existingVersions
+ .lastWhereOrNull((id) => id.version < entrypoint.root.version);
if (previousVersion == null) return;
final previousPubspec =
diff --git a/lib/src/validator/sdk_constraint.dart b/lib/src/validator/sdk_constraint.dart
index 68de6bf..ff25e53 100644
--- a/lib/src/validator/sdk_constraint.dart
+++ b/lib/src/validator/sdk_constraint.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:pub_semver/pub_semver.dart';
@@ -52,7 +50,7 @@
'Expand it manually instead:\n'
'\n'
'environment:\n'
- ' sdk: \"$dartConstraintWithoutCaret\"');
+ ' sdk: "$dartConstraintWithoutCaret"');
}
if (dartConstraint.max == null) {
diff --git a/lib/src/validator/size.dart b/lib/src/validator/size.dart
index f873dfe..e989518 100644
--- a/lib/src/validator/size.dart
+++ b/lib/src/validator/size.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:math' as math;
@@ -12,7 +10,7 @@
import '../validator.dart';
/// The maximum size of the package to upload (100 MB).
-const _MAX_SIZE = 100 * 1024 * 1024;
+const _maxSize = 100 * 1024 * 1024;
/// A validator that validates that a package isn't too big.
class SizeValidator extends Validator {
@@ -23,7 +21,7 @@
@override
Future validate() {
return packageSize.then((size) {
- if (size <= _MAX_SIZE) return;
+ if (size <= _maxSize) return;
var sizeInMb = (size / math.pow(2, 20)).toStringAsPrecision(4);
// Current implementation of Package.listFiles skips hidden files
var ignoreExists = fileExists(entrypoint.root.path('.gitignore'));
diff --git a/lib/src/validator/strict_dependencies.dart b/lib/src/validator/strict_dependencies.dart
index 33e1210..881c55c 100644
--- a/lib/src/validator/strict_dependencies.dart
+++ b/lib/src/validator/strict_dependencies.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:analyzer/dart/ast/ast.dart';
@@ -47,9 +45,9 @@
}
for (var directive in directives) {
- Uri url;
+ Uri? url;
try {
- url = Uri.parse(directive.uri.stringValue);
+ url = Uri.parse(directive.uri.stringValue!);
} on FormatException catch (_) {
// Ignore a format exception. [url] will be null, and we'll emit an
// "Invalid URL" warning below.
diff --git a/pubspec.yaml b/pubspec.yaml
index 23fc0c8..a7d9bb4 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -6,10 +6,10 @@
dependencies:
# Note: Pub's test infrastructure assumes that any dependencies used in tests
# will be hosted dependencies.
- analyzer: ^1.5.0
+ analyzer: ^2.7.0
args: ^2.1.0
async: ^2.6.1
- cli_util: ^0.3.0
+ cli_util: ^0.3.5
collection: ^1.15.0
crypto: ^3.0.1
frontend_server_client: ^2.0.0
@@ -18,16 +18,17 @@
meta: ^1.3.0
oauth2: ^2.0.0
path: ^1.8.0
- pedantic: ^1.11.0
pool: ^1.5.0
- pub_semver: ^2.0.0
+ pub_semver: ^2.1.0
shelf: ^1.1.1
source_span: ^1.8.1
stack_trace: ^1.10.0
+ usage: ^4.0.2
yaml: ^3.1.0
yaml_edit: ^2.0.0
dev_dependencies:
+ lints: ^1.0.1
shelf_test_handler: ^2.0.0
test: ^1.17.3
test_descriptor: ^2.0.0
diff --git a/test/add/common/add_test.dart b/test/add/common/add_test.dart
index 51d5b71..82e098b 100644
--- a/test/add/common/add_test.dart
+++ b/test/add/common/add_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io' show File;
import 'package:path/path.dart' as p;
@@ -15,7 +13,7 @@
void main() {
test('URL encodes the package name', () async {
- await serveNoPackages();
+ await servePackages();
await d.appDir({}).create();
@@ -39,49 +37,48 @@
});
group('normally', () {
- test('fails if extra arguments are passed', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.2');
- });
-
- await d.dir(appPath, [
- d.pubspec({'name': 'myapp'})
- ]).create();
-
- await pubAdd(
- args: ['foo', '^1.2.2'],
- exitCode: exit_codes.USAGE,
- error: contains('Takes only a single argument.'));
-
- await d.dir(appPath, [
- d.pubspec({
- 'name': 'myapp',
- }),
- d.nothing('.dart_tool/package_config.json'),
- d.nothing('pubspec.lock'),
- d.nothing('.packages'),
- ]).validate();
- });
-
test('adds a package from a pub server', () async {
- await servePackages((builder) => builder.serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.appDir({}).create();
await pubAdd(args: ['foo:1.2.3']);
await d.cacheDir({'foo': '1.2.3'}).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
await d.appDir({'foo': '1.2.3'}).validate();
});
+ test('adds multiple package from a pub server', () async {
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
+ server.serve('bar', '1.1.0');
+ server.serve('baz', '2.5.3');
+
+ await d.appDir({}).create();
+
+ await pubAdd(args: ['foo:1.2.3', 'bar:1.1.0', 'baz:2.5.3']);
+
+ await d.cacheDir(
+ {'foo': '1.2.3', 'bar': '1.1.0', 'baz': '2.5.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ d.packageConfigEntry(name: 'bar', version: '1.1.0'),
+ d.packageConfigEntry(name: 'baz', version: '2.5.3'),
+ ]).validate();
+ await d
+ .appDir({'foo': '1.2.3', 'bar': '1.1.0', 'baz': '2.5.3'}).validate();
+ });
+
test(
'does not remove empty dev_dependencies while adding to normal dependencies',
() async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.2');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.2');
await d.dir(appPath, [
d.file('pubspec.yaml', '''
@@ -98,7 +95,9 @@
await pubAdd(args: ['foo:1.2.3']);
await d.cacheDir({'foo': '1.2.3'}).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
await d.dir(appPath, [
d.pubspec({
@@ -111,7 +110,8 @@
test('dry run does not actually add the package or modify the pubspec',
() async {
- await servePackages((builder) => builder.serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.appDir({}).create();
@@ -133,7 +133,8 @@
test(
'adds a package from a pub server even when dependencies key does not exist',
() async {
- await servePackages((builder) => builder.serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.dir(appPath, [
d.pubspec({'name': 'myapp'})
@@ -142,16 +143,17 @@
await pubAdd(args: ['foo:1.2.3']);
await d.cacheDir({'foo': '1.2.3'}).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
await d.appDir({'foo': '1.2.3'}).validate();
});
group('warns user to use pub upgrade if package exists', () {
test('if package is added without a version constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.2');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.2');
await d.appDir({'foo': '1.2.2'}).create();
@@ -166,10 +168,9 @@
});
test('if package is added with a specific version constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.2');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.2');
await d.appDir({'foo': '1.2.2'}).create();
@@ -184,10 +185,9 @@
});
test('if package is added with a version constraint range', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.2');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.2');
await d.appDir({'foo': '1.2.2'}).create();
@@ -203,10 +203,9 @@
});
test('removes dev_dependency and add to normal dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.2');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.2');
await d.dir(appPath, [
d.file('pubspec.yaml', '''
@@ -227,7 +226,9 @@
'adding it to dependencies instead.'));
await d.cacheDir({'foo': '1.2.3'}).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
await d.dir(appPath, [
d.pubspec({
@@ -239,10 +240,9 @@
group('dependency override', () {
test('passes if package does not specify a range', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.2');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.2');
await d.dir(appPath, [
d.pubspec({
@@ -255,7 +255,9 @@
await pubAdd(args: ['foo']);
await d.cacheDir({'foo': '1.2.2'}).validate();
- await d.appPackagesFile({'foo': '1.2.2'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.2'),
+ ]).validate();
await d.dir(appPath, [
d.pubspec({
'name': 'myapp',
@@ -266,9 +268,8 @@
});
test('passes if constraint matches git dependency override', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.git('foo.git',
[d.libDir('foo'), d.libPubspec('foo', '1.2.3')]).create();
@@ -297,9 +298,8 @@
});
test('passes if constraint matches path dependency override', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.2');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.2');
await d.dir(
'foo', [d.libDir('foo'), d.libPubspec('foo', '1.2.2')]).create();
@@ -327,9 +327,8 @@
});
test('fails with bad version constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.dir(appPath, [
d.pubspec({'name': 'myapp', 'dependencies': {}})
@@ -350,10 +349,9 @@
});
test('fails if constraint does not match override', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.2');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.2');
await d.dir(appPath, [
d.pubspec({
@@ -383,9 +381,8 @@
});
test('fails if constraint matches git dependency override', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.git('foo.git',
[d.libDir('foo'), d.libPubspec('foo', '1.0.0')]).create();
@@ -423,9 +420,8 @@
test('fails if constraint does not match path dependency override',
() async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.2');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.2');
await d.dir(
'foo', [d.libDir('foo'), d.libPubspec('foo', '1.0.0')]).create();
@@ -464,7 +460,8 @@
group('--dev', () {
test('--dev adds packages to dev_dependencies instead', () async {
- await servePackages((builder) => builder.serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.dir(appPath, [
d.pubspec({'name': 'myapp', 'dev_dependencies': {}})
@@ -472,7 +469,9 @@
await pubAdd(args: ['--dev', 'foo:1.2.3']);
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
await d.dir(appPath, [
d.pubspec({
@@ -484,10 +483,9 @@
group('warns user to use pub upgrade if package exists', () {
test('if package is added without a version constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.2');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.2');
await d.dir(appPath, [
d.pubspec({
@@ -512,10 +510,9 @@
});
test('if package is added with a specific version constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.2');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.2');
await d.dir(appPath, [
d.pubspec({
@@ -540,10 +537,9 @@
});
test('if package is added with a version constraint range', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.2');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.2');
await d.dir(appPath, [
d.pubspec({
@@ -570,10 +566,9 @@
group('dependency override', () {
test('passes if package does not specify a range', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.2');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.2');
await d.dir(appPath, [
d.pubspec({
@@ -586,7 +581,9 @@
await pubAdd(args: ['foo', '--dev']);
await d.cacheDir({'foo': '1.2.2'}).validate();
- await d.appPackagesFile({'foo': '1.2.2'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.2'),
+ ]).validate();
await d.dir(appPath, [
d.pubspec({
'name': 'myapp',
@@ -597,10 +594,8 @@
});
test('passes if constraint is git dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- });
-
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.git('foo.git',
[d.libDir('foo'), d.libPubspec('foo', '1.2.3')]).create();
@@ -628,9 +623,8 @@
});
test('passes if constraint matches path dependency override', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.2');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.2');
await d.dir(
'foo', [d.libDir('foo'), d.libPubspec('foo', '1.2.2')]).create();
@@ -658,10 +652,9 @@
});
test('fails if constraint does not match override', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.2');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.2');
await d.dir(appPath, [
d.pubspec({
@@ -691,9 +684,8 @@
});
test('fails if constraint matches git dependency override', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.git('foo.git',
[d.libDir('foo'), d.libPubspec('foo', '1.0.0')]).create();
@@ -731,9 +723,9 @@
test('fails if constraint does not match path dependency override',
() async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.2');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.2');
+
await d.dir(
'foo', [d.libDir('foo'), d.libPubspec('foo', '1.0.0')]).create();
@@ -772,10 +764,9 @@
test(
'prints information saying that package is already a dependency if it '
'already exists and exits with a usage exception', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.2');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.2');
await d.dir(appPath, [
d.pubspec({
@@ -807,9 +798,8 @@
/// Differs from the previous test because this tests YAML in flow format.
test('adds to empty ', () async {
- await servePackages((builder) {
- builder.serve('bar', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('bar', '1.0.0');
await d.dir(appPath, [
d.file('pubspec.yaml', '''
@@ -827,10 +817,9 @@
});
test('preserves comments', () async {
- await servePackages((builder) {
- builder.serve('bar', '1.0.0');
- builder.serve('foo', '1.0.0');
- });
+ await servePackages()
+ ..serve('bar', '1.0.0')
+ ..serve('foo', '1.0.0');
await d.dir(appPath, [
d.file('pubspec.yaml', '''
diff --git a/test/add/common/invalid_options.dart b/test/add/common/invalid_options.dart
index 17262d2..f5bf23d 100644
--- a/test/add/common/invalid_options.dart
+++ b/test/add/common/invalid_options.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -41,12 +39,10 @@
test('cannot use both --path and --host-<option> flags', () async {
// Make the default server serve errors. Only the custom server should
// be accessed.
- await serveNoPackages();
- globalPackageServer.serveErrors();
+ (await servePackages()).serveErrors();
- final server = await PackageServer.start((builder) {
- builder.serve('foo', '1.2.3');
- });
+ final server = await startPackageServer();
+ server.serve('foo', '1.2.3');
await d
.dir('bar', [d.libDir('bar'), d.libPubspec('foo', '0.0.1')]).create();
@@ -78,12 +74,10 @@
test('cannot use both --hosted-url and --git-<option> flags', () async {
// Make the default server serve errors. Only the custom server should
// be accessed.
- await serveNoPackages();
- globalPackageServer.serveErrors();
+ (await servePackages()).serveErrors();
- final server = await PackageServer.start((builder) {
- builder.serve('foo', '1.2.3');
- });
+ final server = await startPackageServer();
+ server.serve('foo', '1.2.3');
ensureGit();
diff --git a/test/add/common/version_constraint_test.dart b/test/add/common/version_constraint_test.dart
index 22df8bc..f058082 100644
--- a/test/add/common/version_constraint_test.dart
+++ b/test/add/common/version_constraint_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -12,86 +10,96 @@
void main() {
test('allows empty version constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '0.2.3');
- builder.serve('foo', '1.0.1');
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '2.0.0-dev');
- builder.serve('foo', '1.3.4-dev');
- });
+ await servePackages()
+ ..serve('foo', '0.2.3')
+ ..serve('foo', '1.0.1')
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '2.0.0-dev')
+ ..serve('foo', '1.3.4-dev');
await d.appDir({}).create();
await pubAdd(args: ['foo']);
await d.cacheDir({'foo': '1.2.3'}).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
await d.appDir({'foo': '^1.2.3'}).validate();
});
test('allows specific version constraint', () async {
- await servePackages((builder) => builder.serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.appDir({}).create();
await pubAdd(args: ['foo:1.2.3']);
await d.cacheDir({'foo': '1.2.3'}).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
await d.appDir({'foo': '1.2.3'}).validate();
});
test('allows specific pre-release version constraint', () async {
- await servePackages((builder) => builder.serve('foo', '1.2.3-dev'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3-dev');
await d.appDir({}).create();
await pubAdd(args: ['foo:1.2.3-dev']);
await d.cacheDir({'foo': '1.2.3-dev'}).validate();
- await d.appPackagesFile({'foo': '1.2.3-dev'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3-dev'),
+ ]).validate();
await d.appDir({'foo': '1.2.3-dev'}).validate();
});
test('allows the "any" version constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '0.2.3');
- builder.serve('foo', '1.0.1');
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '2.0.0-dev');
- builder.serve('foo', '1.3.4-dev');
- });
+ await servePackages()
+ ..serve('foo', '0.2.3')
+ ..serve('foo', '1.0.1')
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '2.0.0-dev')
+ ..serve('foo', '1.3.4-dev');
await d.appDir({}).create();
await pubAdd(args: ['foo:any']);
await d.cacheDir({'foo': '1.2.3'}).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
await d.appDir({'foo': 'any'}).validate();
});
test('allows version constraint range', () async {
- await servePackages((builder) => builder.serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.appDir({}).create();
await pubAdd(args: ['foo:>1.2.0 <2.0.0']);
await d.cacheDir({'foo': '1.2.3'}).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
await d.appDir({'foo': '>1.2.0 <2.0.0'}).validate();
});
test(
'empty constraint allows it to choose the latest version not in conflict',
() async {
- await servePackages((builder) {
- builder.serve('foo', '0.1.0');
- builder.serve('foo', '1.2.3', deps: {'bar': '2.0.4'});
- builder.serve('bar', '2.0.3');
- builder.serve('bar', '2.0.4');
- });
+ await servePackages()
+ ..serve('foo', '0.1.0')
+ ..serve('foo', '1.2.3', deps: {'bar': '2.0.4'})
+ ..serve('bar', '2.0.3')
+ ..serve('bar', '2.0.4');
await d.appDir({'bar': '2.0.3'}).create();
@@ -100,12 +108,16 @@
await d.appDir({'foo': '^0.1.0', 'bar': '2.0.3'}).validate();
await d.cacheDir({'foo': '0.1.0', 'bar': '2.0.3'}).validate();
- await d.appPackagesFile({'foo': '0.1.0', 'bar': '2.0.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '0.1.0'),
+ d.packageConfigEntry(name: 'bar', version: '2.0.3'),
+ ]).validate();
});
group('does not update pubspec if no available version found', () {
test('simple', () async {
- await servePackages((builder) => builder.serve('foo', '1.0.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.0.3');
await d.appDir({}).create();
@@ -126,11 +138,10 @@
});
test('transitive', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3', deps: {'bar': '2.0.4'});
- builder.serve('bar', '2.0.3');
- builder.serve('bar', '2.0.4');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3', deps: {'bar': '2.0.4'})
+ ..serve('bar', '2.0.3')
+ ..serve('bar', '2.0.4');
await d.appDir({'bar': '2.0.3'}).create();
diff --git a/test/add/common/version_resolution_test.dart b/test/add/common/version_resolution_test.dart
index a6ad690..0f44d2b 100644
--- a/test/add/common/version_resolution_test.dart
+++ b/test/add/common/version_resolution_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -15,10 +13,10 @@
test('unlocks transitive dependencies', () async {
/// The server used to only have the foo v3.2.1 as the latest,
/// so pub get will create a pubspec.lock to foo 3.2.1
- await servePackages((builder) {
- builder.serve('foo', '3.2.1');
- builder.serve('bar', '1.0.0', deps: {'foo': '^3.2.1'});
- });
+ final server = await servePackages();
+
+ server.serve('foo', '3.2.1');
+ server.serve('bar', '1.0.0', deps: {'foo': '^3.2.1'});
await d.appDir({'bar': '1.0.0'}).create();
await pubGet();
@@ -26,66 +24,69 @@
/// foo's package creator releases a newer version of foo, and we
/// want to test that this is what the user gets when they run
/// pub add foo.
- globalPackageServer.add((builder) {
- builder.serve('foo', '3.5.0');
- builder.serve('foo', '3.1.0');
- builder.serve('foo', '2.5.0');
- });
+ server.serve('foo', '3.5.0');
+ server.serve('foo', '3.1.0');
+ server.serve('foo', '2.5.0');
await pubAdd(args: ['foo']);
await d.appDir({'foo': '^3.5.0', 'bar': '1.0.0'}).validate();
await d.cacheDir({'foo': '3.5.0', 'bar': '1.0.0'}).validate();
- await d.appPackagesFile({'foo': '3.5.0', 'bar': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '3.5.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ ]).validate();
});
test('chooses the appropriate version to not break other dependencies',
() async {
/// The server used to only have the foo v3.2.1 as the latest,
/// so pub get will create a pubspec.lock to foo 3.2.1
- await servePackages((builder) {
- builder.serve('foo', '3.2.1');
- builder.serve('bar', '1.0.0', deps: {'foo': '^3.2.1'});
- });
+ final server = await servePackages();
+
+ server.serve('foo', '3.2.1');
+ server.serve('bar', '1.0.0', deps: {'foo': '^3.2.1'});
await d.appDir({'bar': '1.0.0'}).create();
await pubGet();
- globalPackageServer.add((builder) {
- builder.serve('foo', '4.0.0');
- builder.serve('foo', '2.0.0');
- });
+ server.serve('foo', '4.0.0');
+ server.serve('foo', '2.0.0');
await pubAdd(args: ['foo']);
await d.appDir({'foo': '^3.2.1', 'bar': '1.0.0'}).validate();
await d.cacheDir({'foo': '3.2.1', 'bar': '1.0.0'}).validate();
- await d.appPackagesFile({'foo': '3.2.1', 'bar': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '3.2.1'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ ]).validate();
});
test('may upgrade other packages if they allow a later version to be chosen',
() async {
/// The server used to only have the foo v3.2.1 as the latest,
/// so pub get will create a pubspec.lock to foo 3.2.1
- await servePackages((builder) {
- builder.serve('foo', '3.2.1');
- builder.serve('bar', '1.0.0', deps: {'foo': '^3.2.1'});
- });
+ final server = await servePackages();
+
+ server.serve('foo', '3.2.1');
+ server.serve('bar', '1.0.0', deps: {'foo': '^3.2.1'});
await d.appDir({'bar': '^1.0.0'}).create();
await pubGet();
- globalPackageServer.add((builder) {
- builder.serve('foo', '5.0.0');
- builder.serve('foo', '4.0.0');
- builder.serve('foo', '2.0.0');
- builder.serve('bar', '1.5.0', deps: {'foo': '^4.0.0'});
- });
+ server.serve('foo', '5.0.0');
+ server.serve('foo', '4.0.0');
+ server.serve('foo', '2.0.0');
+ server.serve('bar', '1.5.0', deps: {'foo': '^4.0.0'});
await pubAdd(args: ['foo']);
await d.appDir({'foo': '^4.0.0', 'bar': '^1.0.0'}).validate();
await d.cacheDir({'foo': '4.0.0', 'bar': '1.5.0'}).validate();
- await d.appPackagesFile({'foo': '4.0.0', 'bar': '1.5.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '4.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.5.0'),
+ ]).validate();
});
}
diff --git a/test/add/git/git_test.dart b/test/add/git/git_test.dart
index b120e38..d976172 100644
--- a/test/add/git/git_test.dart
+++ b/test/add/git/git_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -158,9 +156,8 @@
});
test('can be overriden by dependency override', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.2');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.2');
await d.git(
'foo.git', [d.libDir('foo'), d.libPubspec('foo', '1.0.0')]).create();
@@ -176,7 +173,9 @@
await pubAdd(args: ['foo', '--git-url', '../foo.git']);
await d.cacheDir({'foo': '1.2.2'}).validate();
- await d.appPackagesFile({'foo': '1.2.2'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.2'),
+ ]).validate();
await d.dir(appPath, [
d.pubspec({
'name': 'myapp',
@@ -187,4 +186,18 @@
})
]).validate();
});
+
+ test('fails if multiple packages passed for git source', () async {
+ ensureGit();
+
+ await d.git(
+ 'foo.git', [d.libDir('foo'), d.libPubspec('foo', '1.0.0')]).create();
+
+ await d.appDir({}).create();
+
+ await pubAdd(
+ args: ['foo', 'bar', 'baz', '--git-url', '../foo.git'],
+ exitCode: exit_codes.USAGE,
+ error: contains('Can only add a single git package at a time.'));
+ });
}
diff --git a/test/add/git/ref_test.dart b/test/add/git/ref_test.dart
index fadd80a..11dfc0b 100644
--- a/test/add/git/ref_test.dart
+++ b/test/add/git/ref_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/add/git/subdir_test.dart b/test/add/git/subdir_test.dart
index 3bf381a..8e8c39c 100644
--- a/test/add/git/subdir_test.dart
+++ b/test/add/git/subdir_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -32,10 +30,11 @@
])
])
]).validate();
-
- await d.appPackagesFile({
- 'sub': pathInCache('git/foo-${await repo.revParse('HEAD')}/subdir')
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(
+ name: 'sub',
+ path: pathInCache('git/foo-${await repo.revParse('HEAD')}/subdir')),
+ ]).validate();
await d.appDir({
'sub': {
@@ -70,9 +69,11 @@
])
]).validate();
- await d.appPackagesFile({
- 'sub': pathInCache('git/foo-${await repo.revParse('HEAD')}/sub/dir')
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(
+ name: 'sub',
+ path: pathInCache('git/foo-${await repo.revParse('HEAD')}/sub/dir')),
+ ]).validate();
await d.appDir({
'sub': {
diff --git a/test/add/hosted/non_default_pub_server_test.dart b/test/add/hosted/non_default_pub_server_test.dart
index 33b6753..60538e3 100644
--- a/test/add/hosted/non_default_pub_server_test.dart
+++ b/test/add/hosted/non_default_pub_server_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -14,13 +12,12 @@
test('adds a package from a non-default pub server', () async {
// Make the default server serve errors. Only the custom server should
// be accessed.
- await serveErrors();
+ (await servePackages()).serveErrors();
- var server = await PackageServer.start((builder) {
- builder.serve('foo', '0.2.5');
- builder.serve('foo', '1.1.0');
- builder.serve('foo', '1.2.3');
- });
+ final server = await servePackages();
+ server.serve('foo', '0.2.5');
+ server.serve('foo', '1.1.0');
+ server.serve('foo', '1.2.3');
await d.appDir({}).create();
@@ -29,7 +26,9 @@
await pubAdd(args: ['foo:1.2.3', '--hosted-url', url]);
await d.cacheDir({'foo': '1.2.3'}, port: server.port).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
await d.appDir({
'foo': {
'version': '1.2.3',
@@ -38,6 +37,49 @@
}).validate();
});
+ test('adds multiple packages from a non-default pub server', () async {
+ // Make the default server serve errors. Only the custom server should
+ // be accessed.
+ (await servePackages()).serveErrors();
+
+ final server = await servePackages();
+ server.serve('foo', '1.1.0');
+ server.serve('foo', '1.2.3');
+ server.serve('bar', '0.2.5');
+ server.serve('bar', '3.2.3');
+ server.serve('baz', '0.1.3');
+ server.serve('baz', '1.3.5');
+
+ await d.appDir({}).create();
+
+ final url = server.url;
+
+ await pubAdd(
+ args: ['foo:1.2.3', 'bar:3.2.3', 'baz:1.3.5', '--hosted-url', url]);
+
+ await d.cacheDir({'foo': '1.2.3', 'bar': '3.2.3', 'baz': '1.3.5'},
+ port: server.port).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ d.packageConfigEntry(name: 'bar', version: '3.2.3'),
+ d.packageConfigEntry(name: 'baz', version: '1.3.5'),
+ ]).validate();
+ await d.appDir({
+ 'foo': {
+ 'version': '1.2.3',
+ 'hosted': {'name': 'foo', 'url': url}
+ },
+ 'bar': {
+ 'version': '3.2.3',
+ 'hosted': {'name': 'bar', 'url': url}
+ },
+ 'baz': {
+ 'version': '1.3.5',
+ 'hosted': {'name': 'baz', 'url': url}
+ }
+ }).validate();
+ });
+
test('fails when adding from an invalid url', () async {
ensureGit();
@@ -66,13 +108,12 @@
() async {
// Make the default server serve errors. Only the custom server should
// be accessed.
- await serveErrors();
+ (await servePackages()).serveErrors();
- var server = await PackageServer.start((builder) {
- builder.serve('foo', '0.2.5');
- builder.serve('foo', '1.1.0');
- builder.serve('foo', '1.2.3');
- });
+ final server = await servePackages();
+ server.serve('foo', '0.2.5');
+ server.serve('foo', '1.1.0');
+ server.serve('foo', '1.2.3');
await d.appDir({}).create();
@@ -81,7 +122,9 @@
await pubAdd(args: ['foo', '--hosted-url', url]);
await d.cacheDir({'foo': '1.2.3'}, port: server.port).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
await d.appDir({
'foo': {
'version': '^1.2.3',
@@ -94,13 +137,12 @@
() async {
// Make the default server serve errors. Only the custom server should
// be accessed.
- await serveErrors();
+ (await servePackages()).serveErrors();
- var server = await PackageServer.start((builder) {
- builder.serve('foo', '0.2.5');
- builder.serve('foo', '1.1.0');
- builder.serve('foo', '1.2.3');
- });
+ final server = await servePackages();
+ server.serve('foo', '0.2.5');
+ server.serve('foo', '1.1.0');
+ server.serve('foo', '1.2.3');
await d.appDir({}).create();
@@ -109,7 +151,9 @@
await pubAdd(args: ['foo', '--hosted-url', url]);
await d.cacheDir({'foo': '1.2.3'}, port: server.port).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
await d.appDir({
'foo': {
'version': '^1.2.3',
@@ -123,13 +167,11 @@
'constraint', () async {
// Make the default server serve errors. Only the custom server should
// be accessed.
- await serveErrors();
-
- var server = await PackageServer.start((builder) {
- builder.serve('foo', '0.2.5');
- builder.serve('foo', '1.1.0');
- builder.serve('foo', '1.2.3');
- });
+ (await servePackages()).serveErrors();
+ final server = await servePackages();
+ server.serve('foo', '0.2.5');
+ server.serve('foo', '1.1.0');
+ server.serve('foo', '1.2.3');
await d.appDir({}).create();
@@ -138,7 +180,9 @@
await pubAdd(args: ['foo:any', '--hosted-url', url]);
await d.cacheDir({'foo': '1.2.3'}, port: server.port).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
await d.appDir({
'foo': {
'version': 'any',
diff --git a/test/add/path/absolute_path_test.dart b/test/add/path/absolute_path_test.dart
index dc74638..5e63679 100644
--- a/test/add/path/absolute_path_test.dart
+++ b/test/add/path/absolute_path_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -22,7 +20,9 @@
await pubAdd(args: ['foo', '--path', absolutePath]);
- await d.appPackagesFile({'foo': absolutePath}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: absolutePath),
+ ]).validate();
await d.appDir({
'foo': {'path': absolutePath}
@@ -43,6 +43,28 @@
}).validate();
});
+ test('fails when adding multiple packages through local path', () async {
+ ensureGit();
+
+ await d.git(
+ 'foo.git', [d.libDir('foo'), d.libPubspec('foo', '1.0.0')]).create();
+
+ await d.appDir({}).create();
+ final absolutePath = path.join(d.sandbox, 'foo');
+
+ await pubAdd(
+ args: ['foo:2.0.0', 'bar:0.1.3', 'baz:1.3.1', '--path', absolutePath],
+ error: contains('Can only add a single local package at a time.'),
+ exitCode: exit_codes.USAGE);
+
+ await d.appDir({}).validate();
+ await d.dir(appPath, [
+ d.nothing('.dart_tool/package_config.json'),
+ d.nothing('pubspec.lock'),
+ d.nothing('.packages'),
+ ]).validate();
+ });
+
test('fails when adding with an invalid version constraint', () async {
ensureGit();
@@ -90,9 +112,8 @@
});
test('can be overriden by dependency override', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.2');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.2');
await d
.dir('foo', [d.libDir('foo'), d.libPubspec('foo', '0.0.1')]).create();
@@ -108,7 +129,9 @@
await pubAdd(args: ['foo', '--path', absolutePath]);
await d.cacheDir({'foo': '1.2.2'}).validate();
- await d.appPackagesFile({'foo': '1.2.2'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.2'),
+ ]).validate();
await d.dir(appPath, [
d.pubspec({
'name': 'myapp',
diff --git a/test/add/path/relative_path_test.dart b/test/add/path/relative_path_test.dart
index 9d443e8..e08ba3c 100644
--- a/test/add/path/relative_path_test.dart
+++ b/test/add/path/relative_path_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io' show Platform;
import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -21,7 +19,9 @@
await pubAdd(args: ['foo', '--path', '../foo']);
- await d.appPackagesFile({'foo': '../foo'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../foo'),
+ ]).validate();
await d.appDir({
'foo': {'path': '../foo'}
@@ -40,7 +40,9 @@
output: contains('Changed 1 dependency in myapp!'),
);
- await d.appPackagesFile({'foo': '../foo'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../foo'),
+ ]).validate();
await d.appDir({
'foo': {'path': '../foo'}
@@ -104,9 +106,8 @@
});
test('can be overriden by dependency override', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.2');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.2');
await d
.dir('foo', [d.libDir('foo'), d.libPubspec('foo', '0.0.1')]).create();
@@ -121,7 +122,9 @@
await pubAdd(args: ['foo', '--path', '../foo']);
await d.cacheDir({'foo': '1.2.2'}).validate();
- await d.appPackagesFile({'foo': '1.2.2'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.2'),
+ ]).validate();
await d.dir(appPath, [
d.pubspec({
'name': 'myapp',
diff --git a/test/add/sdk/sdk_test.dart b/test/add/sdk/sdk_test.dart
index 1ded16e..ff7d442 100644
--- a/test/add/sdk/sdk_test.dart
+++ b/test/add/sdk/sdk_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -13,9 +11,8 @@
void main() {
setUp(() async {
- await servePackages((builder) {
- builder.serve('bar', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('bar', '1.0.0');
await d.dir('flutter', [
d.dir('packages', [
@@ -45,11 +42,12 @@
'foo': {'sdk': 'flutter', 'version': '^0.0.1'}
}
}),
- d.packagesFile({
- 'myapp': '.',
- 'foo': p.join(d.sandbox, 'flutter', 'packages', 'foo'),
- 'bar': '1.0.0'
- })
+ ]).validate();
+
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(
+ name: 'foo', path: p.join(d.sandbox, 'flutter', 'packages', 'foo')),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
]).validate();
});
@@ -68,11 +66,11 @@
'foo': {'sdk': 'flutter', 'version': '0.0.1'}
}
}),
- d.packagesFile({
- 'myapp': '.',
- 'foo': p.join(d.sandbox, 'flutter', 'packages', 'foo'),
- 'bar': '1.0.0'
- })
+ ]).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(
+ name: 'foo', path: p.join(d.sandbox, 'flutter', 'packages', 'foo')),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
]).validate();
});
@@ -82,11 +80,10 @@
args: ['baz', '--sdk', 'flutter'],
environment: {'FLUTTER_ROOT': p.join(d.sandbox, 'flutter')});
- await d.dir(appPath, [
- d.packagesFile({
- 'myapp': '.',
- 'baz': p.join(d.sandbox, 'flutter', 'bin', 'cache', 'pkg', 'baz')
- })
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(
+ name: 'baz',
+ path: p.join(d.sandbox, 'flutter', 'bin', 'cache', 'pkg', 'baz'))
]).validate();
});
diff --git a/test/cache/add/adds_latest_matching_version_test.dart b/test/cache/add/adds_latest_matching_version_test.dart
index d7e26c4..7bf9625 100644
--- a/test/cache/add/adds_latest_matching_version_test.dart
+++ b/test/cache/add/adds_latest_matching_version_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
import 'package:test/test.dart';
@@ -15,12 +13,11 @@
test(
'adds the latest version of the package matching the '
'version constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.2');
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '2.0.0-dev');
- builder.serve('foo', '2.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.2.2')
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '2.0.0-dev')
+ ..serve('foo', '2.0.0');
await runPub(
args: ['cache', 'add', 'foo', '-v', '>=1.0.0 <2.0.0'],
diff --git a/test/cache/add/adds_latest_version_test.dart b/test/cache/add/adds_latest_version_test.dart
index 6a8b795..cf34857 100644
--- a/test/cache/add/adds_latest_version_test.dart
+++ b/test/cache/add/adds_latest_version_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
void main() {
test('adds the latest stable version of the package', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.2');
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.4-dev');
- });
+ await servePackages()
+ ..serve('foo', '1.2.2')
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.4-dev');
await runPub(
args: ['cache', 'add', 'foo'], output: 'Downloading foo 1.2.3...');
diff --git a/test/cache/add/all_adds_all_matching_versions_test.dart b/test/cache/add/all_adds_all_matching_versions_test.dart
index bfffa7f..a05e8dc 100644
--- a/test/cache/add/all_adds_all_matching_versions_test.dart
+++ b/test/cache/add/all_adds_all_matching_versions_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,12 +9,11 @@
void main() {
test('"--all" adds all matching versions of the package', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.2');
- builder.serve('foo', '1.2.3-dev');
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '2.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.2.2')
+ ..serve('foo', '1.2.3-dev')
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '2.0.0');
await runPub(
args: ['cache', 'add', 'foo', '-v', '>=1.0.0 <2.0.0', '--all'],
diff --git a/test/cache/add/all_with_some_versions_present_test.dart b/test/cache/add/all_with_some_versions_present_test.dart
index da4da98..7b5b36d 100644
--- a/test/cache/add/all_with_some_versions_present_test.dart
+++ b/test/cache/add/all_with_some_versions_present_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,12 +9,11 @@
void main() {
test('"--all" adds all non-installed versions of the package', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.1');
- builder.serve('foo', '1.2.2');
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '2.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.2.1')
+ ..serve('foo', '1.2.2')
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '2.0.0');
// Install a couple of versions first.
await runPub(
diff --git a/test/cache/add/already_cached_test.dart b/test/cache/add/already_cached_test.dart
index 9bf8df3..8c74da9 100644
--- a/test/cache/add/already_cached_test.dart
+++ b/test/cache/add/already_cached_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,9 +9,8 @@
void main() {
test('does nothing if the package is already cached', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
// Run once to put it in the cache.
await runPub(
diff --git a/test/cache/add/bad_version_test.dart b/test/cache/add/bad_version_test.dart
index e0a57e0..4e93331 100644
--- a/test/cache/add/bad_version_test.dart
+++ b/test/cache/add/bad_version_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -11,16 +9,10 @@
void main() {
test('fails if the version constraint cannot be parsed', () {
- return runPub(args: ['cache', 'add', 'foo', '-v', '1.0'], error: '''
- Could not parse version "1.0". Unknown text at "1.0".
-
- Usage: pub cache add <package> [--version <constraint>] [--all]
- -h, --help Print this usage information.
- --all Install all matching versions.
- -v, --version Version constraint.
-
- Run "pub help" to see global options.
- See https://dart.dev/tools/pub/cmd/pub-cache for detailed documentation.
- ''', exitCode: exit_codes.USAGE);
+ return runPub(
+ args: ['cache', 'add', 'foo', '-v', '1.0'],
+ error: contains('Could not parse version "1.0". Unknown text at "1.0".'),
+ exitCode: exit_codes.USAGE,
+ );
});
}
diff --git a/test/cache/add/missing_package_arg_test.dart b/test/cache/add/missing_package_arg_test.dart
index 2274992..456342b 100644
--- a/test/cache/add/missing_package_arg_test.dart
+++ b/test/cache/add/missing_package_arg_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -11,16 +9,10 @@
void main() {
test('fails if no package was given', () {
- return runPub(args: ['cache', 'add'], error: '''
- No package to add given.
-
- Usage: pub cache add <package> [--version <constraint>] [--all]
- -h, --help Print this usage information.
- --all Install all matching versions.
- -v, --version Version constraint.
-
- Run "pub help" to see global options.
- See https://dart.dev/tools/pub/cmd/pub-cache for detailed documentation.
- ''', exitCode: exit_codes.USAGE);
+ return runPub(
+ args: ['cache', 'add'],
+ error: contains('No package to add given.'),
+ exitCode: exit_codes.USAGE,
+ );
});
}
diff --git a/test/cache/add/no_matching_version_test.dart b/test/cache/add/no_matching_version_test.dart
index d395f29..a860294 100644
--- a/test/cache/add/no_matching_version_test.dart
+++ b/test/cache/add/no_matching_version_test.dart
@@ -2,18 +2,15 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../test_pub.dart';
void main() {
test('fails if no version matches the version constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.2');
- builder.serve('foo', '1.2.3');
- });
+ await servePackages()
+ ..serve('foo', '1.2.2')
+ ..serve('foo', '1.2.3');
await runPub(
args: ['cache', 'add', 'foo', '-v', '>2.0.0'],
diff --git a/test/cache/add/package_not_found_test.dart b/test/cache/add/package_not_found_test.dart
index 4179319..caf45f4 100644
--- a/test/cache/add/package_not_found_test.dart
+++ b/test/cache/add/package_not_found_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -11,12 +9,13 @@
void main() {
test('fails if the package cound not be found on the source', () async {
- await serveNoPackages();
+ await servePackages();
await runPub(
args: ['cache', 'add', 'foo'],
- error: RegExp(r"Package doesn't exist \(could not find package foo at "
- r'http://.*\)\.'),
+ error: RegExp(
+ r'Package not available \(could not find package foo at http://.*\)\.',
+ ),
exitCode: exit_codes.UNAVAILABLE);
});
}
diff --git a/test/cache/add/unexpected_arguments_test.dart b/test/cache/add/unexpected_arguments_test.dart
index 66174db..1e4fa54 100644
--- a/test/cache/add/unexpected_arguments_test.dart
+++ b/test/cache/add/unexpected_arguments_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -11,16 +9,10 @@
void main() {
test('fails if there are extra arguments', () {
- return runPub(args: ['cache', 'add', 'foo', 'bar', 'baz'], error: '''
- Unexpected arguments "bar" and "baz".
-
- Usage: pub cache add <package> [--version <constraint>] [--all]
- -h, --help Print this usage information.
- --all Install all matching versions.
- -v, --version Version constraint.
-
- Run "pub help" to see global options.
- See https://dart.dev/tools/pub/cmd/pub-cache for detailed documentation.
- ''', exitCode: exit_codes.USAGE);
+ return runPub(
+ args: ['cache', 'add', 'foo', 'bar', 'baz'],
+ error: contains('Unexpected arguments "bar" and "baz".'),
+ exitCode: exit_codes.USAGE,
+ );
});
}
diff --git a/test/cache/clean_test.dart b/test/cache/clean_test.dart
index 1ba2ac7..7a79bc8 100644
--- a/test/cache/clean_test.dart
+++ b/test/cache/clean_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
@@ -19,9 +17,9 @@
});
test('running pub cache clean --force deletes cache', () async {
- await servePackages((b) => b
+ await servePackages()
..serve('foo', '1.1.2')
- ..serve('bar', '1.2.3'));
+ ..serve('bar', '1.2.3');
await d.appDir({'foo': 'any', 'bar': 'any'}).create();
await pubGet();
final cache = path.join(d.sandbox, cachePath);
@@ -34,9 +32,9 @@
test('running pub cache clean deletes cache only with confirmation',
() async {
- await servePackages((b) => b
+ await servePackages()
..serve('foo', '1.1.2')
- ..serve('bar', '1.2.3'));
+ ..serve('bar', '1.2.3');
await d.appDir({'foo': 'any', 'bar': 'any'}).create();
await pubGet();
final cache = path.join(d.sandbox, cachePath);
diff --git a/test/cache/list_test.dart b/test/cache/list_test.dart
index 9d8b9f3..a2c26a4 100644
--- a/test/cache/list_test.dart
+++ b/test/cache/list_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
diff --git a/test/cache/repair/empty_cache_test.dart b/test/cache/repair/empty_cache_test.dart
index 679e32a..13d68cc 100644
--- a/test/cache/repair/empty_cache_test.dart
+++ b/test/cache/repair/empty_cache_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../test_pub.dart';
diff --git a/test/cache/repair/git_test.dart b/test/cache/repair/git_test.dart
index abb0ab7..262343a 100644
--- a/test/cache/repair/git_test.dart
+++ b/test/cache/repair/git_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/io.dart';
diff --git a/test/cache/repair/handles_corrupted_binstub_test.dart b/test/cache/repair/handles_corrupted_binstub_test.dart
index b1c3556..0ca169f 100644
--- a/test/cache/repair/handles_corrupted_binstub_test.dart
+++ b/test/cache/repair/handles_corrupted_binstub_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
void main() {
test('handles a corrupted binstub script', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/cache/repair/handles_corrupted_global_lockfile_test.dart b/test/cache/repair/handles_corrupted_global_lockfile_test.dart
index 3952871..9a9af05 100644
--- a/test/cache/repair/handles_corrupted_global_lockfile_test.dart
+++ b/test/cache/repair/handles_corrupted_global_lockfile_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/cache/repair/handles_failure_test.dart b/test/cache/repair/handles_failure_test.dart
index 8016d30..d5637ca 100644
--- a/test/cache/repair/handles_failure_test.dart
+++ b/test/cache/repair/handles_failure_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -13,15 +11,14 @@
void main() {
test('handles failure to reinstall some packages', () async {
// Only serve two packages so repairing will have a failure.
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.5');
- });
+ final server = await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.5');
// Set up a cache with some packages.
await d.dir(cachePath, [
d.dir('hosted', [
- d.dir('localhost%58${globalServer.port}', [
+ d.dir('localhost%58${server.port}', [
d.dir('foo-1.2.3',
[d.libPubspec('foo', '1.2.3'), d.file('broken.txt')]),
d.dir('foo-1.2.4',
@@ -41,7 +38,7 @@
expect(pub.stderr, emits(startsWith('Failed to repair foo 1.2.4. Error:')));
expect(
pub.stderr,
- emits('Package doesn\'t exist '
+ emits('Package not available '
'(Package foo has no version 1.2.4).'));
expect(pub.stdout, emits('Reinstalled 2 packages.'));
diff --git a/test/cache/repair/handles_orphaned_binstub_test.dart b/test/cache/repair/handles_orphaned_binstub_test.dart
index 4954121..0754496 100644
--- a/test/cache/repair/handles_orphaned_binstub_test.dart
+++ b/test/cache/repair/handles_orphaned_binstub_test.dart
@@ -2,14 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
import '../../test_pub.dart';
-const _ORPHANED_BINSTUB = '''
+const _orphanedBinstub = '''
#!/usr/bin/env sh
# This file was created by pub v0.1.2-3.
# Package: foo
@@ -22,7 +20,7 @@
void main() {
test('handles an orphaned binstub script', () async {
await d.dir(cachePath, [
- d.dir('bin', [d.file(binStubName('script'), _ORPHANED_BINSTUB)])
+ d.dir('bin', [d.file(binStubName('script'), _orphanedBinstub)])
]).create();
await runPub(
diff --git a/test/cache/repair/hosted.dart b/test/cache/repair/hosted.dart
index 23d839b..ec3786b 100644
--- a/test/cache/repair/hosted.dart
+++ b/test/cache/repair/hosted.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -13,14 +11,13 @@
import '../../test_pub.dart';
void main() {
- setUp(() {
- return servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.4');
- builder.serve('foo', '1.2.5');
- builder.serve('bar', '1.2.3');
- builder.serve('bar', '1.2.4');
- });
+ setUp(() async {
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.4')
+ ..serve('foo', '1.2.5')
+ ..serve('bar', '1.2.3')
+ ..serve('bar', '1.2.4');
});
test('reinstalls previously cached hosted packages', () async {
diff --git a/test/cache/repair/recompiles_snapshots_test.dart b/test/cache/repair/recompiles_snapshots_test.dart
index 698e148..f3c3d6c 100644
--- a/test/cache/repair/recompiles_snapshots_test.dart
+++ b/test/cache/repair/recompiles_snapshots_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
void main() {
test('recompiles activated executable snapshots', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/cache/repair/updates_binstubs_test.dart b/test/cache/repair/updates_binstubs_test.dart
index bfb6400..e8cbfb4 100644
--- a/test/cache/repair/updates_binstubs_test.dart
+++ b/test/cache/repair/updates_binstubs_test.dart
@@ -2,14 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
import '../../test_pub.dart';
-const _OUTDATED_BINSTUB = '''
+const _outdatedBinstub = '''
#!/usr/bin/env sh
# This file was created by pub v0.1.2-3.
# Package: foo
@@ -21,19 +19,17 @@
void main() {
test('updates an outdated binstub script', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'executables': {'foo-script': 'script'}
- }, contents: [
- d.dir(
- 'bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'executables': {'foo-script': 'script'}
+ }, contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
await d.dir(cachePath, [
- d.dir('bin', [d.file(binStubName('foo-script'), _OUTDATED_BINSTUB)])
+ d.dir('bin', [d.file(binStubName('foo-script'), _outdatedBinstub)])
]).create();
// Repair them.
diff --git a/test/dependency_override_test.dart b/test/dependency_override_test.dart
index 3cac645..59f59e4 100644
--- a/test/dependency_override_test.dart
+++ b/test/dependency_override_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
@@ -14,11 +12,10 @@
void main() {
forBothPubGetAndUpgrade((command) {
test('chooses best version matching override constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- builder.serve('foo', '3.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0')
+ ..serve('foo', '3.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -30,13 +27,14 @@
await pubCommand(command);
- await d.appPackagesFile({'foo': '2.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.0.0'),
+ ]).validate();
});
test('treats override as implicit dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -47,18 +45,19 @@
await pubCommand(command);
- await d.appPackagesFile({'foo': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ ]).validate();
});
test('ignores other constraints on overridden package', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- builder.serve('foo', '3.0.0');
- builder.serve('bar', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0')
+ ..serve('foo', '3.0.0')
+ ..serve('bar', '1.0.0', pubspec: {
'dependencies': {'foo': '5.0.0-nonexistent'}
});
- });
await d.dir(appPath, [
d.pubspec({
@@ -70,14 +69,16 @@
await pubCommand(command);
- await d.appPackagesFile({'foo': '2.0.0', 'bar': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ ]).validate();
});
test('ignores SDK constraints', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'environment': {'sdk': '5.6.7-fblthp'}
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'environment': {'sdk': '5.6.7-fblthp'}
});
await d.dir(appPath, [
@@ -88,15 +89,15 @@
]).create();
await pubCommand(command);
-
- await d.appPackagesFile({'foo': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ ]).validate();
});
test('warns about overridden dependencies', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('bar', '1.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('bar', '1.0.0');
await d
.dir('baz', [d.libDir('baz'), d.libPubspec('baz', '0.0.1')]).create();
diff --git a/test/dependency_services/dependency_services_test.dart b/test/dependency_services/dependency_services_test.dart
index d341df4..0ab5825 100644
--- a/test/dependency_services/dependency_services_test.dart
+++ b/test/dependency_services/dependency_services_test.dart
@@ -1,39 +1,77 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
import 'package:test/test.dart';
+import 'package:test_process/test_process.dart';
import '../descriptor.dart' as d;
import '../golden_file.dart';
import '../test_pub.dart';
-Future<void> pipeline(String name, List<_PackageVersion> upgrades) async {
+late String snapshot;
+const _commandRunner = 'bin/dependency_services.dart';
+
+String _filter(String input) {
+ return input
+ .replaceAll(p.toUri(d.sandbox).toString(), r'file://$SANDBOX')
+ .replaceAll(d.sandbox, r'$SANDBOX')
+ .replaceAll(Platform.pathSeparator, '/')
+ .replaceAll(Platform.operatingSystem, r'$OS')
+ .replaceAll(globalServer.port.toString(), r'$PORT');
+}
+
+/// Runs `dart tool/test-bin/pub_command_runner.dart [args]` and appends the output to [buffer].
+Future<void> runDependencyServicesToBuffer(
+ List<String> args,
+ StringBuffer buffer, {
+ String? workingDirectory,
+ Map<String, String>? environment,
+ dynamic exitCode = 0,
+ String? stdin,
+}) async {
+ final process = await TestProcess.start(
+ Platform.resolvedExecutable,
+ ['--enable-asserts', snapshot, ...args],
+ environment: {
+ ...getPubTestEnvironment(),
+ ...?environment,
+ },
+ workingDirectory: workingDirectory ?? p.join(d.sandbox, appPath),
+ );
+ if (stdin != null) {
+ process.stdin.write(stdin);
+ await process.stdin.flush();
+ await process.stdin.close();
+ }
+ await process.shouldExit(exitCode);
+
+ buffer.writeln([
+ '\$ $_commandRunner ${args.join(' ')}',
+ ...await process.stdout.rest.map(_filter).toList(),
+ ...await process.stderr.rest.map((e) => '[E] ${_filter(e)}').toList(),
+ ].join('\n'));
+ buffer.write('\n');
+}
+
+Future<void> pipeline(
+ String name,
+ List<_PackageVersion> upgrades,
+ GoldenTestContext context,
+) async {
final buffer = StringBuffer();
- await runPubIntoBuffer([
- '__experimental-dependency-services',
- 'list',
- ], buffer);
- await runPubIntoBuffer([
- '__experimental-dependency-services',
- 'report',
- ], buffer);
+ await runDependencyServicesToBuffer(['list'], buffer);
+ await runDependencyServicesToBuffer(['report'], buffer);
final input = json.encode({
- 'changes': upgrades,
+ 'dependencyChanges': upgrades,
});
- await runPubIntoBuffer([
- '__experimental-dependency-services',
- 'apply',
- ], buffer, stdin: input);
+ await runDependencyServicesToBuffer(['apply'], buffer, stdin: input);
void catIntoBuffer(String path) {
buffer.writeln('$path:');
buffer.writeln(File(p.join(d.sandbox, path)).readAsStringSync());
@@ -41,19 +79,24 @@
catIntoBuffer(p.join(appPath, 'pubspec.yaml'));
catIntoBuffer(p.join(appPath, 'pubspec.lock'));
- expectMatchesGoldenFile(
- // TODO: Consider if expectMatchesGoldenFile should replace localhost:<port>
- buffer.toString().replaceAll(RegExp('localhost:\d+'), 'localhost:<port>'),
- 'test/dependency_services/goldens/dependency_report_$name.txt',
+ context.expectNextSection(
+ buffer.toString().replaceAll(RegExp(r'localhost:\d+'), 'localhost:<port>'),
);
}
Future<void> main() async {
- test('Removing transitive', () async {
- await servePackages((builder) => builder
+ setUpAll(() async {
+ final tempDir = Directory.systemTemp.createTempSync();
+ snapshot = p.join(tempDir.path, 'dependency_services.dart.snapshot');
+ final r = Process.runSync(
+ Platform.resolvedExecutable, ['--snapshot=$snapshot', _commandRunner]);
+ expect(r.exitCode, 0, reason: r.stderr);
+ });
+ testWithGolden('Removing transitive', (context) async {
+ (await servePackages())
..serve('foo', '1.2.3', deps: {'transitive': '^1.0.0'})
..serve('foo', '2.2.3')
- ..serve('transitive', '1.0.0'));
+ ..serve('transitive', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -64,17 +107,21 @@
})
]).create();
await pubGet();
- await pipeline('removing_transitive', [
- _PackageVersion('foo', Version.parse('2.2.3')),
- _PackageVersion('transitive', null)
- ]);
+ await pipeline(
+ 'removing_transitive',
+ [
+ _PackageVersion('foo', Version.parse('2.2.3')),
+ _PackageVersion('transitive', null)
+ ],
+ context,
+ );
});
- test('Adding transitive', () async {
- await servePackages((builder) => builder
+ testWithGolden('Adding transitive', (context) async {
+ (await servePackages())
..serve('foo', '1.2.3')
..serve('foo', '2.2.3', deps: {'transitive': '^1.0.0'})
- ..serve('transitive', '1.0.0'));
+ ..serve('transitive', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -85,19 +132,23 @@
})
]).create();
await pubGet();
- await pipeline('adding_transitive', [
- _PackageVersion('foo', Version.parse('2.2.3')),
- _PackageVersion('transitive', Version.parse('1.0.0'))
- ]);
+ await pipeline(
+ 'adding_transitive',
+ [
+ _PackageVersion('foo', Version.parse('2.2.3')),
+ _PackageVersion('transitive', Version.parse('1.0.0'))
+ ],
+ context,
+ );
});
}
class _PackageVersion {
String name;
- Version version;
+ Version? version;
_PackageVersion(this.name, this.version);
- Map<String, Object> toJson() => {
+ Map<String, Object?> toJson() => {
'name': name,
'version': version?.toString(),
};
diff --git a/test/deps/executables_test.dart b/test/deps/executables_test.dart
index f568511..ea864fd 100644
--- a/test/deps/executables_test.dart
+++ b/test/deps/executables_test.dart
@@ -2,13 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
-import 'package:pub/src/ascii_tree.dart' as tree;
-import 'package:pub/src/io.dart';
-import 'package:test/test.dart';
-
-import '../ascii_tree_test.dart';
import '../descriptor.dart' as d;
import '../golden_file.dart';
import '../test_pub.dart';
@@ -16,31 +9,29 @@
const _validMain = 'main() {}';
const _invalidMain = 'main() {';
-Future<void> variations(String name) async {
- final buffer = StringBuffer();
- buffer.writeln(stripColors(
- tree.fromFiles(listDir(d.sandbox, recursive: true), baseDir: d.sandbox)));
+extension on GoldenTestContext {
+ Future<void> runExecutablesTest() async {
+ await pubGet();
- await pubGet();
- await runPubIntoBuffer(['deps', '--executables'], buffer);
- await runPubIntoBuffer(['deps', '--executables', '--dev'], buffer);
- // The json ouput also lists the exectuables.
- await runPubIntoBuffer(['deps', '--json'], buffer);
- // The easiest way to update the golden files is to delete them and rerun the
- // test.
- expectMatchesGoldenFile(buffer.toString(), 'test/deps/goldens/$name.txt');
+ await tree();
+
+ await run(['deps', '--executables']);
+ await run(['deps', '--executables', '--dev']);
+ await run(['deps', '--json']);
+ }
}
void main() {
- test('skips non-Dart executables', () async {
+ testWithGolden('skips non-Dart executables', (ctx) async {
await d.dir(appPath, [
d.appPubspec(),
d.dir('bin', [d.file('foo.py'), d.file('bar.sh')])
]).create();
- await variations('non_dart_executables');
+
+ await ctx.runExecutablesTest();
});
- test('lists Dart executables, even without entrypoints', () async {
+ testWithGolden('lists Dart executables, without entrypoints', (ctx) async {
await d.dir(appPath, [
d.appPubspec(),
d.dir(
@@ -48,10 +39,11 @@
[d.file('foo.dart', _validMain), d.file('bar.dart', _invalidMain)],
)
]).create();
- await variations('dart_executables');
+
+ await ctx.runExecutablesTest();
});
- test('skips executables in sub directories', () async {
+ testWithGolden('skips executables in sub directories', (ctx) async {
await d.dir(appPath, [
d.appPubspec(),
d.dir('bin', [
@@ -59,10 +51,11 @@
d.dir('sub', [d.file('bar.dart', _validMain)])
])
]).create();
- await variations('nothing_in_sub_drectories');
+
+ await ctx.runExecutablesTest();
});
- test('lists executables from a dependency', () async {
+ testWithGolden('lists executables from a dependency', (ctx) async {
await d.dir('foo', [
d.libPubspec('foo', '1.0.0'),
d.dir('bin', [d.file('bar.dart', _validMain)])
@@ -74,10 +67,11 @@
})
]).create();
- await variations('from_dependency');
+ await ctx.runExecutablesTest();
});
- test('lists executables only from immediate dependencies', () async {
+ testWithGolden('lists executables only from immediate dependencies',
+ (ctx) async {
await d.dir(appPath, [
d.appPubspec({
'foo': {'path': '../foo'}
@@ -96,10 +90,10 @@
d.dir('bin', [d.file('qux.dart', _validMain)])
]).create();
- await variations('only_immediate');
+ await ctx.runExecutablesTest();
});
- test('applies formatting before printing executables', () async {
+ testWithGolden('applies formatting before printing executables', (ctx) async {
await d.dir(appPath, [
d.appPubspec({
'foo': {'path': '../foo'},
@@ -119,10 +113,10 @@
d.dir('bin', [d.file('qux.dart', _validMain)])
]).create();
- await variations('formatting');
+ await ctx.runExecutablesTest();
});
- test('dev dependencies', () async {
+ testWithGolden('dev dependencies', (ctx) async {
await d.dir('foo', [
d.libPubspec('foo', '1.0.0'),
d.dir('bin', [d.file('bar.dart', _validMain)])
@@ -136,10 +130,11 @@
}
})
]).create();
- await variations('dev_dependencies');
+
+ await ctx.runExecutablesTest();
});
- test('overriden dependencies executables', () async {
+ testWithGolden('overriden dependencies executables', (ctx) async {
await d.dir('foo-1.0', [
d.libPubspec('foo', '1.0.0'),
d.dir('bin', [d.file('bar.dart', _validMain)])
@@ -162,6 +157,7 @@
}
})
]).create();
- await variations('overrides');
+
+ await ctx.runExecutablesTest();
});
}
diff --git a/test/deps/goldens/dart_executables.txt b/test/deps/goldens/dart_executables.txt
deleted file mode 100644
index 9284ceb..0000000
--- a/test/deps/goldens/dart_executables.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-'-- myapp
- |-- bin
- | |-- bar.dart
- | '-- foo.dart
- '-- pubspec.yaml
-
-$ pub deps --executables
-myapp: bar, foo
-
-$ pub deps --executables --dev
-myapp: bar, foo
-
-$ pub deps --json
-{
- "root": "myapp",
- "packages": [
- {
- "name": "myapp",
- "version": "0.0.0",
- "kind": "root",
- "source": "root",
- "dependencies": []
- }
- ],
- "sdks": [
- {
- "name": "Dart",
- "version": "0.1.2+3"
- }
- ],
- "executables": [
- ":bar",
- ":foo"
- ]
-}
-
diff --git a/test/deps/goldens/from_dependency.txt b/test/deps/goldens/from_dependency.txt
deleted file mode 100644
index 30836e5..0000000
--- a/test/deps/goldens/from_dependency.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-|-- foo
-| |-- bin
-| | '-- bar.dart
-| '-- pubspec.yaml
-'-- myapp
- '-- pubspec.yaml
-
-$ pub deps --executables
-foo:bar
-
-$ pub deps --executables --dev
-foo:bar
-
-$ pub deps --json
-{
- "root": "myapp",
- "packages": [
- {
- "name": "myapp",
- "version": "0.0.0",
- "kind": "root",
- "source": "root",
- "dependencies": [
- "foo"
- ]
- },
- {
- "name": "foo",
- "version": "1.0.0",
- "kind": "direct",
- "source": "path",
- "dependencies": []
- }
- ],
- "sdks": [
- {
- "name": "Dart",
- "version": "0.1.2+3"
- }
- ],
- "executables": [
- "foo:bar"
- ]
-}
-
diff --git a/test/deps/goldens/non_dart_executables.txt b/test/deps/goldens/non_dart_executables.txt
deleted file mode 100644
index 646e21e..0000000
--- a/test/deps/goldens/non_dart_executables.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-'-- myapp
- |-- bin
- | |-- bar.sh
- | '-- foo.py
- '-- pubspec.yaml
-
-$ pub deps --executables
-
-$ pub deps --executables --dev
-
-$ pub deps --json
-{
- "root": "myapp",
- "packages": [
- {
- "name": "myapp",
- "version": "0.0.0",
- "kind": "root",
- "source": "root",
- "dependencies": []
- }
- ],
- "sdks": [
- {
- "name": "Dart",
- "version": "0.1.2+3"
- }
- ],
- "executables": []
-}
-
diff --git a/test/deps/goldens/nothing_in_sub_drectories.txt b/test/deps/goldens/nothing_in_sub_drectories.txt
deleted file mode 100644
index db3c77c..0000000
--- a/test/deps/goldens/nothing_in_sub_drectories.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-'-- myapp
- |-- bin
- | |-- foo.dart
- | '-- sub
- | '-- bar.dart
- '-- pubspec.yaml
-
-$ pub deps --executables
-myapp:foo
-
-$ pub deps --executables --dev
-myapp:foo
-
-$ pub deps --json
-{
- "root": "myapp",
- "packages": [
- {
- "name": "myapp",
- "version": "0.0.0",
- "kind": "root",
- "source": "root",
- "dependencies": []
- }
- ],
- "sdks": [
- {
- "name": "Dart",
- "version": "0.1.2+3"
- }
- ],
- "executables": [
- ":foo"
- ]
-}
-
diff --git a/test/deps_test.dart b/test/deps_test.dart
index 2d59ef8..7336f13 100644
--- a/test/deps_test.dart
+++ b/test/deps_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
@@ -12,21 +10,19 @@
void main() {
setUp(() async {
- await servePackages((builder) {
- builder.serve('normal', '1.2.3',
- deps: {'transitive': 'any', 'circular_a': 'any'});
- builder.serve('transitive', '1.2.3', deps: {'shared': 'any'});
- builder.serve('shared', '1.2.3', deps: {'other': 'any'});
- builder.serve('dev_only', '1.2.3');
- builder.serve('unittest', '1.2.3',
- deps: {'shared': 'any', 'dev_only': 'any'});
- builder.serve('other', '1.0.0', deps: {'myapp': 'any'});
- builder.serve('overridden', '1.0.0');
- builder.serve('overridden', '2.0.0');
- builder.serve('override_only', '1.2.3');
- builder.serve('circular_a', '1.2.3', deps: {'circular_b': 'any'});
- builder.serve('circular_b', '1.2.3', deps: {'circular_a': 'any'});
- });
+ await servePackages()
+ ..serve('normal', '1.2.3',
+ deps: {'transitive': 'any', 'circular_a': 'any'})
+ ..serve('transitive', '1.2.3', deps: {'shared': 'any'})
+ ..serve('shared', '1.2.3', deps: {'other': 'any'})
+ ..serve('dev_only', '1.2.3')
+ ..serve('unittest', '1.2.3', deps: {'shared': 'any', 'dev_only': 'any'})
+ ..serve('other', '1.0.0', deps: {'myapp': 'any'})
+ ..serve('overridden', '1.0.0')
+ ..serve('overridden', '2.0.0')
+ ..serve('override_only', '1.2.3')
+ ..serve('circular_a', '1.2.3', deps: {'circular_b': 'any'})
+ ..serve('circular_b', '1.2.3', deps: {'circular_a': 'any'});
await d.dir('from_path',
[d.libDir('from_path'), d.libPubspec('from_path', '1.2.3')]).create();
diff --git a/test/descriptor.dart b/test/descriptor.dart
index 3eee5d1..ee50851 100644
--- a/test/descriptor.dart
+++ b/test/descriptor.dart
@@ -2,12 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
/// Pub-specific test descriptors.
import 'dart:convert';
-import 'package:meta/meta.dart';
import 'package:oauth2/oauth2.dart' as oauth2;
import 'package:path/path.dart' as p;
import 'package:pub/src/language_version.dart';
@@ -27,11 +24,11 @@
export 'descriptor/tar.dart';
/// Creates a new [GitRepoDescriptor] with [name] and [contents].
-GitRepoDescriptor git(String name, [Iterable<Descriptor> contents]) =>
+GitRepoDescriptor git(String name, [List<Descriptor>? contents]) =>
GitRepoDescriptor(name, contents ?? <Descriptor>[]);
/// Creates a new [TarFileDescriptor] with [name] and [contents].
-TarFileDescriptor tar(String name, [Iterable<Descriptor> contents]) =>
+TarFileDescriptor tar(String name, [List<Descriptor>? contents]) =>
TarFileDescriptor(name, contents ?? <Descriptor>[]);
/// Describes a package that passes all validation.
@@ -67,14 +64,14 @@
///
/// [contents] may contain [Future]s that resolve to serializable objects,
/// which may in turn contain [Future]s recursively.
-Descriptor pubspec(Map<String, Object> contents) => YamlDescriptor(
+Descriptor pubspec(Map<String, Object?> contents) => YamlDescriptor(
'pubspec.yaml',
yaml({
...contents,
// TODO: Copy-pasting this into all call-sites, or use d.libPubspec
'environment': {
'sdk': '>=0.1.2 <1.0.0',
- ...contents['environment'] as Map ?? {},
+ ...(contents['environment'] ?? {}) as Map,
},
}),
);
@@ -84,8 +81,8 @@
/// Describes a file named `pubspec.yaml` for an application package with the
/// given [dependencies].
-Descriptor appPubspec([Map dependencies]) {
- var map = <String, dynamic>{
+Descriptor appPubspec([Map? dependencies]) {
+ var map = <String, Object>{
'name': 'myapp',
'environment': {
'sdk': '>=0.1.2 <1.0.0',
@@ -100,7 +97,7 @@
/// constraint on that version, otherwise it adds an SDK constraint allowing
/// the current SDK version.
Descriptor libPubspec(String name, String version,
- {Map deps, Map devDeps, String sdk}) {
+ {Map? deps, Map? devDeps, String? sdk}) {
var map = packageMap(name, version, deps, devDeps);
if (sdk != null) {
map['environment'] = {'sdk': sdk};
@@ -112,7 +109,7 @@
/// Describes a directory named `lib` containing a single dart file named
/// `<name>.dart` that contains a line of Dart code.
-Descriptor libDir(String name, [String code]) {
+Descriptor libDir(String name, [String? code]) {
// Default to printing the name if no other code was given.
code ??= name;
return dir('lib', [file('$name.dart', 'main() => "$code";')]);
@@ -130,8 +127,8 @@
/// If [repoName] is not given it is assumed to be equal to [packageName].
Descriptor gitPackageRevisionCacheDir(
String packageName, {
- int modifier,
- String repoName,
+ int? modifier,
+ String? repoName,
}) {
repoName = repoName ?? packageName;
var value = packageName;
@@ -159,7 +156,7 @@
/// validated since they will often lack the dependencies section that the
/// real pubspec being compared against has. You usually only need to pass
/// `true` for this if you plan to call [create] on the resulting descriptor.
-Descriptor cacheDir(Map packages, {int port, bool includePubspecs = false}) {
+Descriptor cacheDir(Map packages, {int? port, bool includePubspecs = false}) {
var contents = <Descriptor>[];
packages.forEach((name, versions) {
if (versions is! List) versions = [versions];
@@ -180,7 +177,7 @@
///
/// If [port] is passed, it's used as the port number of the local hosted server
/// that this cache represents. It defaults to [globalServer.port].
-Descriptor hostedCache(Iterable<Descriptor> contents, {int port}) {
+Descriptor hostedCache(Iterable<Descriptor> contents, {int? port}) {
return dir(cachePath, [
dir('hosted', [dir('localhost%58${port ?? globalServer.port}', contents)])
]);
@@ -190,7 +187,7 @@
/// credentials. The URL "/token" on [server] will be used as the token
/// endpoint for refreshing the access token.
Descriptor credentialsFile(PackageServer server, String accessToken,
- {String refreshToken, DateTime expiration}) {
+ {String? refreshToken, DateTime? expiration}) {
return dir(
configPath,
[
@@ -208,7 +205,7 @@
}
Descriptor legacyCredentialsFile(PackageServer server, String accessToken,
- {String refreshToken, DateTime expiration}) {
+ {String? refreshToken, DateTime? expiration}) {
return dir(
cachePath,
[
@@ -228,8 +225,8 @@
String _credentialsFileContent(
PackageServer server,
String accessToken, {
- String refreshToken,
- DateTime expiration,
+ String? refreshToken,
+ DateTime? expiration,
}) =>
oauth2.Credentials(
accessToken,
@@ -245,14 +242,12 @@
/// Describes the file in the system cache that contains credentials for
/// third party hosted pub servers.
Descriptor tokensFile([Map<String, dynamic> contents = const {}]) {
- return dir(configPath, [
- file('pub-tokens.json', contents != null ? jsonEncode(contents) : null)
- ]);
+ return dir(configPath, [file('pub-tokens.json', jsonEncode(contents))]);
}
/// Describes the application directory, containing only a pubspec specifying
/// the given [dependencies].
-DirectoryDescriptor appDir([Map dependencies]) =>
+DirectoryDescriptor appDir([Map? dependencies]) =>
dir(appPath, [appPubspec(dependencies)]);
/// Describes a `.packages` file.
@@ -266,7 +261,7 @@
/// entries (one per key in [dependencies]), each with a path that contains
/// either the version string (for a reference to the pub cache) or a
/// path to a path dependency, relative to the application directory.
-Descriptor packagesFile([Map<String, String> dependencies]) =>
+Descriptor packagesFile(Map<String, String> dependencies) =>
PackagesFileDescriptor(dependencies);
/// Describes a `.dart_tools/package_config.json` file.
@@ -282,13 +277,31 @@
}) =>
PackageConfigFileDescriptor(packages, generatorVersion);
+Descriptor appPackageConfigFile(
+ List<PackageConfigEntry> packages, {
+ String generatorVersion = '0.1.2+3',
+}) =>
+ dir(
+ appPath,
+ [
+ packageConfigFile(
+ [
+ packageConfigEntry(name: 'myapp', path: '.'),
+ ...packages,
+ ],
+ generatorVersion: generatorVersion,
+ ),
+ ],
+ );
+
/// Create a [PackageConfigEntry] which assumes package with [name] is either
/// a cached package with given [version] or a path dependency at given [path].
PackageConfigEntry packageConfigEntry({
- @required String name,
- String version,
- String path,
- String languageVersion,
+ required String name,
+ String? version,
+ String? path,
+ String? languageVersion,
+ PackageServer? server,
}) {
if (version != null && path != null) {
throw ArgumentError.value(
@@ -300,7 +313,7 @@
}
Uri rootUri;
if (version != null) {
- rootUri = p.toUri(globalPackageServer.pathInCache(name, version));
+ rootUri = p.toUri((server ?? globalServer).pathInCache(name, version));
} else {
rootUri = p.toUri(p.join('..', path));
}
diff --git a/test/descriptor/git.dart b/test/descriptor/git.dart
index 56cd59f..edfc7bd 100644
--- a/test/descriptor/git.dart
+++ b/test/descriptor/git.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'package:path/path.dart' as path;
@@ -17,7 +15,7 @@
/// Creates the Git repository and commits the contents.
@override
- Future create([String parent]) async {
+ Future create([String? parent]) async {
await super.create(parent);
await _runGitCommands(parent, [
['init'],
@@ -35,7 +33,7 @@
/// the previous structure to the Git repo.
///
/// [parent] defaults to [sandbox].
- Future commit([String parent]) async {
+ Future commit([String? parent]) async {
await super.create(parent);
await _runGitCommands(parent, [
['add', '.'],
@@ -47,7 +45,7 @@
/// referred to by [ref].
///
/// [parent] defaults to [sandbox].
- Future<String> revParse(String ref, [String parent]) async {
+ Future<String> revParse(String ref, [String? parent]) async {
var output = await _runGit(['rev-parse', ref], parent);
return output[0];
}
@@ -55,9 +53,9 @@
/// Runs a Git command in this repository.
///
/// [parent] defaults to [sandbox].
- Future runGit(List<String> args, [String parent]) => _runGit(args, parent);
+ Future runGit(List<String> args, [String? parent]) => _runGit(args, parent);
- Future<List<String>> _runGit(List<String> args, String parent) {
+ Future<List<String>> _runGit(List<String> args, String? parent) {
// Explicitly specify the committer information. Git needs this to commit
// and we don't want to rely on the buildbots having this already set up.
var environment = {
@@ -72,7 +70,7 @@
environment: environment);
}
- Future _runGitCommands(String parent, List<List<String>> commands) async {
+ Future _runGitCommands(String? parent, List<List<String>> commands) async {
for (var command in commands) {
await _runGit(command, parent);
}
diff --git a/test/descriptor/packages.dart b/test/descriptor/packages.dart
index 2a23e40..b670322 100644
--- a/test/descriptor/packages.dart
+++ b/test/descriptor/packages.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async' show Future;
import 'dart:convert' show JsonEncoder, json, utf8;
import 'dart:io' show File;
@@ -25,7 +23,7 @@
/// Describes a `.packages` file and its contents.
class PackagesFileDescriptor extends Descriptor {
/// A map from package names to either version strings or path to the package.
- final Map<String, String> _dependencies;
+ final Map<String, String>? _dependencies;
/// Describes a `.packages` file with the given dependencies.
///
@@ -34,11 +32,12 @@
PackagesFileDescriptor([this._dependencies]) : super('.packages');
@override
- Future create([String parent]) {
+ Future create([String? parent]) {
var contents = const <int>[];
- if (_dependencies != null) {
+ var dependencies = _dependencies;
+ if (dependencies != null) {
var mapping = <String, Uri>{};
- _dependencies.forEach((package, version) {
+ dependencies.forEach((package, version) {
String packagePath;
if (_isSemver(version)) {
// It's a cache reference.
@@ -58,7 +57,7 @@
}
@override
- Future validate([String parent]) async {
+ Future validate([String? parent]) async {
var fullPath = p.join(parent ?? sandbox, name);
if (!await File(fullPath).exists()) {
fail("File not found: '$fullPath'.");
@@ -68,14 +67,16 @@
var map = packages_file.parse(bytes, Uri.parse(_base));
- for (var package in _dependencies.keys) {
+ var dependencies = _dependencies!;
+
+ for (var package in dependencies.keys) {
if (!map.containsKey(package)) {
fail('.packages does not contain $package entry');
}
- var description = _dependencies[package];
+ var description = dependencies[package]!;
if (_isSemver(description)) {
- if (!map[package].path.contains(description)) {
+ if (!map[package]!.path.contains(description)) {
fail('.packages of $package has incorrect version. '
'Expected $description, found location: ${map[package]}.');
}
@@ -90,9 +91,9 @@
}
}
- if (map.length != _dependencies.length) {
+ if (map.length != dependencies.length) {
for (var key in map.keys) {
- if (!_dependencies.containsKey(key)) {
+ if (!dependencies.containsKey(key)) {
fail('.packages file contains unexpected entry: $key');
}
}
@@ -128,7 +129,7 @@
: super('.dart_tool/package_config.json');
@override
- Future<void> create([String parent]) async {
+ Future<void> create([String? parent]) async {
final packageConfigFile = File(p.join(parent ?? sandbox, name));
await packageConfigFile.parent.create();
await packageConfigFile.writeAsString(
@@ -137,13 +138,13 @@
}
@override
- Future<void> validate([String parent]) async {
+ Future<void> validate([String? parent]) async {
final packageConfigFile = p.join(parent ?? sandbox, name);
if (!await File(packageConfigFile).exists()) {
fail("File not found: '$packageConfigFile'.");
}
- Map<String, Object> rawJson = json.decode(
+ Map<String, dynamic> rawJson = json.decode(
await File(packageConfigFile).readAsString(),
);
PackageConfig config;
@@ -155,10 +156,20 @@
// Compare packages as sets to ignore ordering.
expect(
- config.packages.map((e) => e.toJson()).toSet(),
- equals(_packages.map((e) => e.toJson()).toSet()),
- reason:
- '"packages" property in "$packageConfigFile" does not expected values',
+ config.packages,
+ _packages
+ .map(
+ (p) => isA<PackageConfigEntry>()
+ .having((p0) => p0.name, 'name', p.name)
+ .having(
+ (p0) => p0.languageVersion,
+ 'languageVersion',
+ // If the expected entry has no language-version we don't check it.
+ p.languageVersion ?? anything)
+ .having((p0) => p0.rootUri, 'rootUri', p.rootUri)
+ .having((p0) => p0.packageUri, 'packageUri', p.packageUri),
+ )
+ .toSet(),
);
final expected = PackageConfig.fromJson(_config.toJson());
diff --git a/test/descriptor/tar.dart b/test/descriptor/tar.dart
index 1c4f89f..2a3488f 100644
--- a/test/descriptor/tar.dart
+++ b/test/descriptor/tar.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:io';
@@ -23,7 +21,7 @@
/// Creates the files and directories within this tar file, then archives
/// them, compresses them, and saves the result to [parentDir].
@override
- Future create([String parent]) {
+ Future create([String? parent]) {
return withTempDir((tempDir) async {
await Future.wait(contents.map((entry) => entry.create(tempDir)));
@@ -41,7 +39,7 @@
/// Validates that the `.tar.gz` file at [path] contains the expected
/// contents.
@override
- Future validate([String parent]) {
+ Future validate([String? parent]) {
throw UnimplementedError('TODO(nweiz): implement this');
}
diff --git a/test/descriptor/yaml.dart b/test/descriptor/yaml.dart
index 086da84..6840041 100644
--- a/test/descriptor/yaml.dart
+++ b/test/descriptor/yaml.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async' show Future;
import 'dart:convert' show utf8;
import 'dart:io';
@@ -29,7 +27,7 @@
Stream.fromIterable([utf8.encode(_contents)]);
@override
- Future validate([String parent]) async {
+ Future validate([String? parent]) async {
var fullPath = p.join(parent ?? sandbox, name);
if (!await File(fullPath).exists()) {
fail("File not found: '$fullPath'.");
diff --git a/test/descriptor_server.dart b/test/descriptor_server.dart
deleted file mode 100644
index a023518..0000000
--- a/test/descriptor_server.dart
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'dart:async';
-
-import 'package:path/path.dart' as p;
-import 'package:shelf/shelf.dart' as shelf;
-import 'package:shelf/shelf_io.dart' as shelf_io;
-import 'package:test/test.dart' hide fail;
-
-import 'descriptor.dart' as d;
-
-/// The global [DescriptorServer] that's used by default.
-///
-/// `null` if there's no global server in use. This can be set to replace the
-/// existing global server.
-DescriptorServer get globalServer => _globalServer;
-set globalServer(DescriptorServer value) {
- if (_globalServer == null) {
- addTearDown(() {
- _globalServer = null;
- });
- } else {
- expect(_globalServer.close(), completes);
- }
-
- _globalServer = value;
-}
-
-DescriptorServer _globalServer;
-
-/// Creates a global [DescriptorServer] to serve [contents] as static files.
-///
-/// This server will exist only for the duration of the pub run. It's accessible
-/// via [server]. Subsequent calls to [serve] replace the previous server.
-Future serve([List<d.Descriptor> contents]) async {
- globalServer = (await DescriptorServer.start())..contents.addAll(contents);
-}
-
-class DescriptorServer {
- /// The underlying server.
- final shelf.Server _server;
-
- /// A future that will complete to the port used for the server.
- int get port => _server.url.port;
-
- /// The list of paths that have been requested from this server.
- final requestedPaths = <String>[];
-
- /// The base directory descriptor of the directories served by [this].
- final d.DirectoryDescriptor _baseDir;
-
- /// The descriptors served by this server.
- ///
- /// This can safely be modified between requests.
- List<d.Descriptor> get contents => _baseDir.contents;
-
- /// Handlers for requests not easily described as files.
- final Map<Pattern, shelf.Handler> extraHandlers = {};
-
- /// Creates an HTTP server to serve [contents] as static files.
- ///
- /// This server exists only for the duration of the pub run. Subsequent calls
- /// to [serve] replace the previous server.
- static Future<DescriptorServer> start() async =>
- DescriptorServer._(await shelf_io.IOServer.bind('localhost', 0));
-
- /// Creates a server that reports an error if a request is ever received.
- static Future<DescriptorServer> errors() async =>
- DescriptorServer._(await shelf_io.IOServer.bind('localhost', 0));
-
- DescriptorServer._(this._server) : _baseDir = d.dir('serve-dir', []) {
- _server.mount((request) async {
- final pathWithInitialSlash = '/${request.url.path}';
- final key = extraHandlers.keys.firstWhere((pattern) {
- final match = pattern.matchAsPrefix(pathWithInitialSlash);
- return match != null && match.end == pathWithInitialSlash.length;
- }, orElse: () => null);
- if (key != null) return extraHandlers[key](request);
-
- var path = p.posix.fromUri(request.url.path);
- requestedPaths.add(path);
-
- try {
- var stream = await _validateStream(_baseDir.load(path));
- return shelf.Response.ok(stream);
- } catch (_) {
- return shelf.Response.notFound('File "$path" not found.');
- }
- });
- addTearDown(_server.close);
- }
-
- /// Closes this server.
- Future close() => _server.close();
-}
-
-/// Ensures that [stream] can emit at least one value successfully (or close
-/// without any values).
-///
-/// For example, reading asynchronously from a non-existent file will return a
-/// stream that fails on the first chunk. In order to handle that more
-/// gracefully, you may want to check that the stream looks like it's working
-/// before you pipe the stream to something else.
-///
-/// This lets you do that. It returns a [Future] that completes to a [Stream]
-/// emitting the same values and errors as [stream], but only if at least one
-/// value can be read successfully. If an error occurs before any values are
-/// emitted, the returned Future completes to that error.
-Future<Stream<T>> _validateStream<T>(Stream<T> stream) {
- var completer = Completer<Stream<T>>();
- var controller = StreamController<T>(sync: true);
-
- StreamSubscription subscription;
- subscription = stream.listen((value) {
- // We got a value, so the stream is valid.
- if (!completer.isCompleted) completer.complete(controller.stream);
- controller.add(value);
- }, onError: (error, [StackTrace stackTrace]) {
- // If the error came after values, it's OK.
- if (completer.isCompleted) {
- controller.addError(error, stackTrace);
- return;
- }
-
- // Otherwise, the error came first and the stream is invalid.
- completer.completeError(error, stackTrace);
-
- // We won't be returning the stream at all in this case, so unsubscribe
- // and swallow the error.
- subscription.cancel();
- }, onDone: () {
- // It closed with no errors, so the stream is valid.
- if (!completer.isCompleted) completer.complete(controller.stream);
- controller.close();
- });
-
- return completer.future;
-}
diff --git a/test/dev_dependency_test.dart b/test/dev_dependency_test.dart
index 471f53c..b192444 100644
--- a/test/dev_dependency_test.dart
+++ b/test/dev_dependency_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import 'descriptor.dart' as d;
@@ -29,7 +27,10 @@
await pubGet();
- await d.appPackagesFile({'foo': '../foo', 'bar': '../bar'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../foo'),
+ d.packageConfigEntry(name: 'bar', path: '../bar'),
+ ]).validate();
});
test("includes dev dependency's transitive dependencies", () async {
@@ -54,7 +55,10 @@
await pubGet();
- await d.appPackagesFile({'foo': '../foo', 'bar': '../bar'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../foo'),
+ d.packageConfigEntry(name: 'bar', path: '../bar'),
+ ]).validate();
});
test("ignores transitive dependency's dev dependencies", () async {
@@ -80,6 +84,8 @@
await pubGet();
- await d.appPackagesFile({'foo': '../foo'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../foo'),
+ ]).validate();
});
}
diff --git a/test/directory_option_test.dart b/test/directory_option_test.dart
index c993200..65193bf 100644
--- a/test/directory_option_test.dart
+++ b/test/directory_option_test.dart
@@ -2,33 +2,33 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:path/path.dart' as p;
import 'package:shelf/shelf.dart' as shelf;
-import 'package:test/test.dart';
import 'descriptor.dart';
import 'golden_file.dart';
import 'test_pub.dart';
Future<void> main() async {
- test('commands taking a --directory/-C parameter work', () async {
- await servePackages((b) => b
+ testWithGolden('commands taking a --directory/-C parameter work',
+ (ctx) async {
+ await servePackages()
..serve('foo', '1.0.0')
..serve('foo', '0.1.2')
- ..serve('bar', '1.2.3'));
- await credentialsFile(globalPackageServer, 'access token').create();
- globalPackageServer
- .extraHandlers[RegExp('/api/packages/test_pkg/uploaders')] = (request) {
- return shelf.Response.ok(
- jsonEncode({
- 'success': {'message': 'Good job!'}
- }),
- headers: {'content-type': 'application/json'});
- };
+ ..serve('bar', '1.2.3');
+ await credentialsFile(globalServer, 'access token').create();
+ globalServer.handle(
+ RegExp('/api/packages/test_pkg/uploaders'),
+ (request) {
+ return shelf.Response.ok(
+ jsonEncode({
+ 'success': {'message': 'Good job!'}
+ }),
+ headers: {'content-type': 'application/json'});
+ },
+ );
await validPackage.create();
await dir(appPath, [
@@ -56,42 +56,34 @@
})
]),
]).create();
- final buffer = StringBuffer();
- Future<void> run(List<String> args) async {
- await runPubIntoBuffer(
- args,
- buffer,
+
+ final cases = [
+ // Try --directory after command.
+ ['add', '--directory=$appPath', 'foo'],
+ // Try the top-level version also.
+ ['-C', appPath, 'add', 'bar'],
+ // When both top-level and after command, the one after command takes
+ // precedence.
+ ['-C', p.join(appPath, 'example'), 'get', '--directory=$appPath', 'bar'],
+ ['remove', 'bar', '-C', appPath],
+ ['get', 'bar', '-C', appPath],
+ ['get', 'bar', '-C', '$appPath/example'],
+ ['get', 'bar', '-C', '$appPath/example2'],
+ ['get', 'bar', '-C', '$appPath/broken_dir'],
+ ['downgrade', '-C', appPath],
+ ['upgrade', 'bar', '-C', appPath],
+ ['run', '-C', appPath, 'bin/app.dart'],
+ ['publish', '-C', appPath, '--dry-run'],
+ ['uploader', '-C', appPath, 'add', 'sigurdm@google.com'],
+ ['deps', '-C', appPath],
+ ];
+
+ for (var i = 0; i < cases.length; i++) {
+ await ctx.run(
+ cases[i],
workingDirectory: sandbox,
environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'},
);
}
-
- await run(['add', '--directory=$appPath', 'foo']);
- // Try the top-level version also.
- await run(['-C', appPath, 'add', 'bar']);
- // When both top-level and after command, the one after command takes
- // precedence.
- await run([
- '-C',
- p.join(appPath, 'example'),
- 'get',
- '--directory=$appPath',
- 'bar',
- ]);
- await run(['remove', 'bar', '-C', appPath]);
- await run(['get', 'bar', '-C', appPath]);
- await run(['get', 'bar', '-C', '$appPath/example']);
- await run(['get', 'bar', '-C', '$appPath/example2']);
- await run(['get', 'bar', '-C', '$appPath/broken_dir']);
- await run(['downgrade', '-C', appPath]);
- await run(['upgrade', 'bar', '-C', appPath]);
- await run(['run', '-C', appPath, 'bin/app.dart']);
- await run(['publish', '-C', appPath, '--dry-run']);
- await run(['uploader', '-C', appPath, 'add', 'sigurdm@google.com']);
- await run(['deps', '-C', appPath]);
- // TODO(sigurdm): we should also test `list-package-dirs` - it is a bit
- // hard on windows due to quoted back-slashes on windows.
- expectMatchesGoldenFile(
- buffer.toString(), 'test/goldens/directory_option.txt');
});
}
diff --git a/test/downgrade/does_not_show_other_versions_test.dart b/test/downgrade/does_not_show_other_versions_test.dart
index 485debb..884bbaf 100644
--- a/test/downgrade/does_not_show_other_versions_test.dart
+++ b/test/downgrade/does_not_show_other_versions_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
@@ -11,11 +9,10 @@
void main() {
test('does not show how many other versions are available', () async {
- await servePackages((builder) {
- builder.serve('downgraded', '1.0.0');
- builder.serve('downgraded', '2.0.0');
- builder.serve('downgraded', '3.0.0-dev');
- });
+ await servePackages()
+ ..serve('downgraded', '1.0.0')
+ ..serve('downgraded', '2.0.0')
+ ..serve('downgraded', '3.0.0-dev');
await d.appDir({'downgraded': '3.0.0-dev'}).create();
diff --git a/test/downgrade/doesnt_change_git_dependencies_test.dart b/test/downgrade/doesnt_change_git_dependencies_test.dart
index 41f0a51..1450af5 100644
--- a/test/downgrade/doesnt_change_git_dependencies_test.dart
+++ b/test/downgrade/doesnt_change_git_dependencies_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
diff --git a/test/downgrade/dry_run_does_not_apply_changes_test.dart b/test/downgrade/dry_run_does_not_apply_changes_test.dart
index 765cb35..38fbebe 100644
--- a/test/downgrade/dry_run_does_not_apply_changes_test.dart
+++ b/test/downgrade/dry_run_does_not_apply_changes_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
@@ -13,10 +11,9 @@
void main() {
test('--dry-run shows report but does not apply changes', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0');
// Create the first lockfile.
await d.appDir({'foo': '2.0.0'}).create();
diff --git a/test/downgrade/unlock_if_necessary_test.dart b/test/downgrade/unlock_if_necessary_test.dart
index b8aa83e..c8b55af 100644
--- a/test/downgrade/unlock_if_necessary_test.dart
+++ b/test/downgrade/unlock_if_necessary_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
@@ -13,24 +11,27 @@
test(
"downgrades one locked hosted package's dependencies if it's "
'necessary', () async {
- await servePackages((builder) {
- builder.serve('foo', '2.0.0', deps: {'foo_dep': 'any'});
- builder.serve('foo_dep', '2.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '2.0.0', deps: {'foo_dep': 'any'});
+ server.serve('foo_dep', '2.0.0');
await d.appDir({'foo': 'any'}).create();
await pubGet();
- await d.appPackagesFile({'foo': '2.0.0', 'foo_dep': '2.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.0.0'),
+ d.packageConfigEntry(name: 'foo_dep', version: '2.0.0'),
+ ]).validate();
- globalPackageServer.add((builder) {
- builder.serve('foo', '1.0.0', deps: {'foo_dep': '<2.0.0'});
- builder.serve('foo_dep', '1.0.0');
- });
+ server.serve('foo', '1.0.0', deps: {'foo_dep': '<2.0.0'});
+ server.serve('foo_dep', '1.0.0');
await pubDowngrade(args: ['foo']);
- await d.appPackagesFile({'foo': '1.0.0', 'foo_dep': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'foo_dep', version: '1.0.0'),
+ ]).validate();
});
}
diff --git a/test/downgrade/unlock_single_package_test.dart b/test/downgrade/unlock_single_package_test.dart
index 73c3467..1188e41 100644
--- a/test/downgrade/unlock_single_package_test.dart
+++ b/test/downgrade/unlock_single_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
@@ -11,51 +9,60 @@
void main() {
test('can unlock a single package only in downgrade', () async {
- await servePackages((builder) {
- builder.serve('foo', '2.1.0', deps: {'bar': '>1.0.0'});
- builder.serve('bar', '2.1.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '2.1.0', deps: {'bar': '>1.0.0'});
+ server.serve('bar', '2.1.0');
await d.appDir({'foo': 'any', 'bar': 'any'}).create();
await pubGet();
- await d.appPackagesFile({'foo': '2.1.0', 'bar': '2.1.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.1.0'),
+ d.packageConfigEntry(name: 'bar', version: '2.1.0'),
+ ]).validate();
- globalPackageServer.add((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': 'any'});
- builder.serve('bar', '1.0.0');
- });
+ server.serve('foo', '1.0.0', deps: {'bar': 'any'});
+ server.serve('bar', '1.0.0');
await pubDowngrade(args: ['bar']);
- await d.appPackagesFile({'foo': '2.1.0', 'bar': '2.1.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.1.0'),
+ d.packageConfigEntry(name: 'bar', version: '2.1.0'),
+ ]).validate();
- globalPackageServer.add((builder) {
- builder.serve('foo', '2.0.0', deps: {'bar': 'any'});
- builder.serve('bar', '2.0.0');
- });
+ server.serve('foo', '2.0.0', deps: {'bar': 'any'});
+ server.serve('bar', '2.0.0');
await pubDowngrade(args: ['bar']);
- await d.appPackagesFile({'foo': '2.1.0', 'bar': '2.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.1.0'),
+ d.packageConfigEntry(name: 'bar', version: '2.0.0'),
+ ]).validate();
await pubDowngrade();
- await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ ]).validate();
});
test('will not downgrade below constraint #2629', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- builder.serve('foo', '2.1.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0')
+ ..serve('foo', '2.1.0');
await d.appDir({'foo': '^2.0.0'}).create();
await pubGet();
-
- await d.appPackagesFile({'foo': '2.1.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.1.0'),
+ ]).validate();
await pubDowngrade(args: ['foo']);
- await d.appPackagesFile({'foo': '2.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.0.0'),
+ ]).validate();
});
}
diff --git a/test/embedding/embedding_test.dart b/test/embedding/embedding_test.dart
index 257bf4b..a9795ea 100644
--- a/test/embedding/embedding_test.dart
+++ b/test/embedding/embedding_test.dart
@@ -2,102 +2,329 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
+import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as path;
+import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import 'package:test_process/test_process.dart';
+
import '../descriptor.dart' as d;
import '../golden_file.dart';
import '../test_pub.dart';
-const _command_runner = 'tool/test-bin/pub_command_runner.dart';
+const _commandRunner = 'tool/test-bin/pub_command_runner.dart';
-String snapshot;
+late String snapshot;
+
+final logFile = p.join(d.sandbox, cachePath, 'log', 'pub_log.txt');
/// Runs `dart tool/test-bin/pub_command_runner.dart [args]` and appends the output to [buffer].
-Future<void> runEmbedding(List<String> args, StringBuffer buffer,
- {String workingDirextory,
- Map<String, String> environment,
- dynamic exitCode = 0}) async {
+Future<void> runEmbeddingToBuffer(
+ List<String> args,
+ StringBuffer buffer, {
+ String? workingDirectory,
+ Map<String, String>? environment,
+ dynamic exitCode = 0,
+}) async {
final process = await TestProcess.start(
Platform.resolvedExecutable,
- [snapshot, ...args],
- environment: environment,
- workingDirectory: workingDirextory,
+ ['--enable-asserts', snapshot, ...args],
+ environment: {
+ ...getPubTestEnvironment(),
+ ...?environment,
+ },
+ workingDirectory: workingDirectory,
);
await process.shouldExit(exitCode);
buffer.writeln([
- '\$ $_command_runner ${args.join(' ')}',
- ...await process.stdout.rest.toList(),
+ '\$ $_commandRunner ${args.join(' ')}',
+ ...await process.stdout.rest.map(_filter).toList(),
+ ...await process.stderr.rest.map((e) => '[E] ${_filter(e)}').toList(),
].join('\n'));
- final stdErr = await process.stderr.rest.toList();
- if (stdErr.isNotEmpty) {
- buffer.writeln(stdErr.map((e) => '[E] $e').join('\n'));
- }
buffer.write('\n');
}
+extension on GoldenTestContext {
+ /// Runs `dart tool/test-bin/pub_command_runner.dart [args]` and compare to
+ /// next section in golden file.
+ Future<void> runEmbedding(
+ List<String> args, {
+ String? workingDirectory,
+ Map<String, String>? environment,
+ dynamic exitCode = 0,
+ }) async {
+ final buffer = StringBuffer();
+ await runEmbeddingToBuffer(
+ args,
+ buffer,
+ workingDirectory: workingDirectory,
+ environment: environment,
+ exitCode: exitCode,
+ );
+
+ expectNextSection(buffer.toString());
+ }
+}
+
Future<void> main() async {
setUpAll(() async {
final tempDir = Directory.systemTemp.createTempSync();
snapshot = path.join(tempDir.path, 'command_runner.dart.snapshot');
final r = Process.runSync(
- Platform.resolvedExecutable, ['--snapshot=$snapshot', _command_runner]);
+ Platform.resolvedExecutable, ['--snapshot=$snapshot', _commandRunner]);
expect(r.exitCode, 0, reason: r.stderr);
});
tearDownAll(() {
File(snapshot).parent.deleteSync(recursive: true);
});
- test('help text', () async {
- final buffer = StringBuffer();
- await runEmbedding([''], buffer, exitCode: 64);
- await runEmbedding(['--help'], buffer);
- await runEmbedding(['pub'], buffer, exitCode: 64);
- await runEmbedding(['pub', '--help'], buffer);
- await runEmbedding(['pub', 'get', '--help'], buffer);
- await runEmbedding(['pub', 'global'], buffer, exitCode: 64);
- expectMatchesGoldenFile(
- buffer.toString(), 'test/embedding/goldens/helptext.txt');
- });
- test('run works, though hidden', () async {
- final buffer = StringBuffer();
+ testWithGolden('run works, though hidden', (ctx) async {
+ await servePackages();
await d.dir(appPath, [
d.pubspec({
'name': 'myapp',
'environment': {
- 'sdk': '>=2.0.0 <3.0.0',
+ 'sdk': '0.1.2+3',
},
}),
d.dir('bin', [
d.file('main.dart', '''
import 'dart:io';
main() {
- print("Hi");
+ print('Hi');
exit(123);
}
''')
]),
]).create();
- await runEmbedding(
+ await ctx.runEmbedding(
['pub', 'get'],
- buffer,
- workingDirextory: d.path(appPath),
+ workingDirectory: d.path(appPath),
);
- await runEmbedding(
+ await ctx.runEmbedding(
['pub', 'run', 'bin/main.dart'],
- buffer,
exitCode: 123,
- workingDirextory: d.path(appPath),
- );
- expectMatchesGoldenFile(
- buffer.toString(),
- 'test/embedding/goldens/run.txt',
+ workingDirectory: d.path(appPath),
);
});
+
+ testWithGolden(
+ 'logfile is written with --verbose and on unexpected exceptions',
+ (context) async {
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
+ await d.appDir({'foo': 'any'}).create();
+
+ // TODO(sigurdm) This logs the entire verbose trace to a golden file.
+ //
+ // This is fragile, and can break for all sorts of small reasons. We think
+ // this might be worth while having to have at least minimal testing of the
+ // verbose stack trace.
+ //
+ // But if you, future contributor, think this test is annoying: feel free to
+ // remove it, or rewrite it to filter out the stack-trace itself, only
+ // testing for creation of the file.
+ //
+ // It is a fragile test, and we acknowledge that it's usefulness can be
+ // debated...
+ await context.runEmbedding(
+ ['pub', '--verbose', 'get'],
+ workingDirectory: d.path(appPath),
+ );
+ context.expectNextSection(
+ _filter(
+ File(logFile).readAsStringSync(),
+ ),
+ );
+ await d.dir('empty').create();
+ await context.runEmbedding(
+ ['pub', 'fail'],
+ workingDirectory: d.path('empty'),
+ exitCode: 1,
+ );
+ context.expectNextSection(
+ _filter(
+ File(logFile).readAsStringSync(),
+ ),
+ );
+ });
+
+ test('analytics', () async {
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': 'any'})
+ ..serve('bar', '1.0.0');
+ await d.dir('dep', [
+ d.pubspec({
+ 'name': 'dep',
+ 'environment': {'sdk': '>=0.0.0 <3.0.0'}
+ })
+ ]).create();
+ final app = d.dir(appPath, [
+ d.appPubspec({
+ 'foo': '1.0.0',
+ // The path dependency should not go to analytics.
+ 'dep': {'path': '../dep'}
+ })
+ ]);
+ await app.create();
+
+ final buffer = StringBuffer();
+
+ await runEmbeddingToBuffer(
+ ['pub', 'get'],
+ buffer,
+ workingDirectory: app.io.path,
+ environment: {...getPubTestEnvironment(), '_PUB_LOG_ANALYTICS': 'true'},
+ );
+ final analytics = buffer
+ .toString()
+ .split('\n')
+ .where((line) => line.startsWith('[E] [analytics]: '))
+ .map((line) => json.decode(line.substring('[E] [analytics]: '.length)));
+ expect(analytics, {
+ {
+ 'hitType': 'event',
+ 'message': {
+ 'category': 'pub-get',
+ 'action': 'foo',
+ 'label': '1.0.0',
+ 'value': 1,
+ 'cd1': 'direct',
+ 'ni': '1',
+ }
+ },
+ {
+ 'hitType': 'event',
+ 'message': {
+ 'category': 'pub-get',
+ 'action': 'bar',
+ 'label': '1.0.0',
+ 'value': 1,
+ 'cd1': 'transitive',
+ 'ni': '1',
+ }
+ },
+ {
+ 'hitType': 'timing',
+ 'message': {
+ 'variableName': 'resolution',
+ 'time': isA<int>(),
+ 'category': 'pub-get',
+ 'label': null
+ }
+ },
+ });
+ // Don't write the logs to file on a normal run.
+ expect(File(logFile).existsSync(), isFalse);
+ });
+
+ test('`embedding --verbose pub` is verbose', () async {
+ await servePackages();
+ final buffer = StringBuffer();
+ await runEmbeddingToBuffer(['--verbose', 'pub', 'logout'], buffer);
+ expect(buffer.toString(), contains('FINE: Pub 0.1.2+3'));
+ });
+}
+
+String _filter(String input) {
+ return input
+ .replaceAll(p.toUri(d.sandbox).toString(), r'file://$SANDBOX')
+ .replaceAll(d.sandbox, r'$SANDBOX')
+ .replaceAll(Platform.pathSeparator, '/')
+ .replaceAll(Platform.operatingSystem, r'$OS')
+ .replaceAll(globalServer.port.toString(), r'$PORT')
+ .replaceAll(
+ RegExp(r'^Created:(.*)$', multiLine: true),
+ r'Created: $TIME',
+ )
+ .replaceAll(
+ RegExp(r'Generated by pub on (.*)$', multiLine: true),
+ r'Generated by pub on $TIME',
+ )
+ .replaceAll(
+ RegExp(r'X-Pub-Session-ID(.*)$', multiLine: true),
+ r'X-Pub-Session-ID: $ID',
+ )
+ .replaceAll(
+ RegExp(r'took (.*)$', multiLine: true),
+ r'took: $TIME',
+ )
+ .replaceAll(
+ RegExp(r'date: (.*)$', multiLine: true),
+ r'date: $TIME',
+ )
+ .replaceAll(
+ RegExp(r'Creating (.*) from stream\.$', multiLine: true),
+ r'Creating $FILE from stream',
+ )
+ .replaceAll(
+ RegExp(r'Created (.*) from stream\.$', multiLine: true),
+ r'Created $FILE from stream',
+ )
+ .replaceAll(
+ RegExp(r'Renaming directory $SANDBOX/cache/_temp/(.*?) to',
+ multiLine: true),
+ r'Renaming directory $SANDBOX/cache/_temp/',
+ )
+ .replaceAll(
+ RegExp(r'Extracting .tar.gz stream to (.*?)$', multiLine: true),
+ r'Extracting .tar.gz stream to $DIR',
+ )
+ .replaceAll(
+ RegExp(r'Extracted .tar.gz to (.*?)$', multiLine: true),
+ r'Extracted .tar.gz to $DIR',
+ )
+ .replaceAll(
+ RegExp(r'Reading binary file (.*?)$', multiLine: true),
+ r'Reading binary file $FILE.',
+ )
+ .replaceAll(
+ RegExp(r'Deleting directory (.*)$', multiLine: true),
+ r'Deleting directory $DIR',
+ )
+ .replaceAll(
+ RegExp(r'Deleting directory (.*)$', multiLine: true),
+ r'Deleting directory $DIR',
+ )
+ .replaceAll(
+ RegExp(r'Resolving dependencies finished (.*)$', multiLine: true),
+ r'Resolving dependencies finished ($TIME)',
+ )
+ .replaceAll(
+ RegExp(r'Created temp directory (.*)$', multiLine: true),
+ r'Created temp directory $DIR',
+ )
+ .replaceAll(
+ RegExp(r'Renaming directory (.*)$', multiLine: true),
+ r'Renaming directory $A to $B',
+ )
+ .replaceAll(
+ RegExp(r'"_fetchedAt":"(.*)"}$', multiLine: true),
+ r'"_fetchedAt": "$TIME"}',
+ )
+ .replaceAll(
+ RegExp(r'"generated": "(.*)",$', multiLine: true),
+ r'"generated": "$TIME",',
+ )
+ .replaceAll(
+ RegExp(r'( |^)(/|[A-Z]:)(.*)/tool/test-bin/pub_command_runner.dart',
+ multiLine: true),
+ r' tool/test-bin/pub_command_runner.dart',
+ )
+ .replaceAll(
+ RegExp(r'[ ]{4,}', multiLine: true),
+ r' ',
+ )
+ .replaceAll(
+ RegExp(r' [\d]+:[\d]+ ', multiLine: true),
+ r' $LINE:$COL ',
+ )
+ .replaceAll(
+ RegExp(r'Writing \d+ characters', multiLine: true),
+ r'Writing $N characters',
+ );
}
diff --git a/test/embedding/get_executable_for_command_test.dart b/test/embedding/get_executable_for_command_test.dart
index e174f3a..0edfa72 100644
--- a/test/embedding/get_executable_for_command_test.dart
+++ b/test/embedding/get_executable_for_command_test.dart
@@ -2,22 +2,31 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
import 'package:path/path.dart' show separator;
import 'package:path/path.dart' as p;
import 'package:pub/pub.dart';
+import 'package:pub/src/log.dart' as log;
+
import 'package:test/test.dart';
import '../descriptor.dart' as d;
import '../test_pub.dart';
-Future<void> testGetExecutable(String command, String root,
- {allowSnapshot = true, result, errorMessage}) async {
+Future<void> testGetExecutable(
+ String command,
+ String root, {
+ allowSnapshot = true,
+ executable,
+ packageConfig,
+ errorMessage,
+ CommandResolutionIssue? issue,
+}) async {
final _cachePath = getPubTestEnvironment()['PUB_CACHE'];
- if (result == null) {
+ final oldVerbosity = log.verbosity;
+ log.verbosity = log.Verbosity.none;
+ if (executable == null) {
expect(
() => getExecutableForCommand(
command,
@@ -27,18 +36,25 @@
),
throwsA(
isA<CommandResolutionFailedException>()
- .having((e) => e.message, 'message', errorMessage),
+ .having((e) => e.message, 'message', errorMessage)
+ .having((e) => e.issue, 'issue', issue),
),
);
} else {
- final path = await getExecutableForCommand(
+ final e = await getExecutableForCommand(
command,
root: root,
pubCacheDir: _cachePath,
allowSnapshot: allowSnapshot,
);
- expect(path, result);
- expect(File(p.join(root, path)).existsSync(), true);
+ expect(
+ e,
+ isA<DartExecutableWithPackageConfig>()
+ .having((e) => e.executable, 'executable', executable)
+ .having((e) => e.packageConfig, 'packageConfig', packageConfig),
+ );
+ expect(File(p.join(root, e.executable)).existsSync(), true);
+ log.verbosity = oldVerbosity;
}
}
@@ -50,13 +66,13 @@
final dir = d.path('foo');
await testGetExecutable('bar/bar.dart', dir,
- result: p.join('bar', 'bar.dart'));
+ executable: p.join('bar', 'bar.dart'));
await testGetExecutable(p.join('bar', 'bar.dart'), dir,
- result: p.join('bar', 'bar.dart'));
+ executable: p.join('bar', 'bar.dart'));
await testGetExecutable('${p.toUri(dir)}/bar/bar.dart', dir,
- result: p.join('bar', 'bar.dart'));
+ executable: p.join('bar', 'bar.dart'));
});
test('Looks for file when no pubspec.yaml', () async {
@@ -66,9 +82,11 @@
final dir = d.path('foo');
await testGetExecutable('bar/m.dart', dir,
- errorMessage: contains('Could not find file `bar/m.dart`'));
+ errorMessage: contains('Could not find file `bar/m.dart`'),
+ issue: CommandResolutionIssue.fileNotFound);
await testGetExecutable(p.join('bar', 'm.dart'), dir,
- errorMessage: contains('Could not find file `bar${separator}m.dart`'));
+ errorMessage: contains('Could not find file `bar${separator}m.dart`'),
+ issue: CommandResolutionIssue.fileNotFound);
});
test('Error message when pubspec is broken', () async {
@@ -95,13 +113,15 @@
contains(
'Error on line 1, column 9 of ${d.sandbox}${p.separator}foo${p.separator}pubspec.yaml: "name" field must be a valid Dart identifier.'),
contains(
- '{"name":"broken name","environment":{"sdk":">=0.1.2 <1.0.0"}}')));
+ '{"name":"broken name","environment":{"sdk":">=0.1.2 <1.0.0"}}')),
+ issue: CommandResolutionIssue.pubGetFailed);
});
test('Does `pub get` if there is a pubspec.yaml', () async {
await d.dir(appPath, [
d.pubspec({
'name': 'myapp',
+ 'environment': {'sdk': '>=$_currentVersion <3.0.0'},
'dependencies': {'foo': '^1.0.0'}
}),
d.dir('bin', [
@@ -109,23 +129,64 @@
])
]).create();
- await serveNoPackages();
+ await servePackages();
// The solver uses word-wrapping in its error message, so we use \s to
// accomodate.
- await testGetExecutable('bar/m.dart', d.path(appPath),
- errorMessage: matches(r'version\s+solving\s+failed'));
+ await testGetExecutable(
+ 'bar/m.dart',
+ d.path(appPath),
+ errorMessage: matches(r'version\s+solving\s+failed'),
+ issue: CommandResolutionIssue.pubGetFailed,
+ );
+ });
+
+ test('Reports parse failure', () async {
+ await d.dir(appPath, [
+ d.pubspec({
+ 'name': 'myapp',
+ 'environment': {'sdk': '>=$_currentVersion <3.0.0'},
+ }),
+ ]).create();
+ await testGetExecutable(
+ '::',
+ d.path(appPath),
+ errorMessage: contains(r'cannot contain multiple ":"'),
+ issue: CommandResolutionIssue.parseError,
+ );
+ });
+
+ test('Reports compilation failure', () async {
+ await d.dir(appPath, [
+ d.pubspec({
+ 'name': 'myapp',
+ 'environment': {'sdk': '>=$_currentVersion <3.0.0'},
+ }),
+ d.dir('bin', [
+ d.file('foo.dart', 'main() {'),
+ ])
+ ]).create();
+
+ await servePackages();
+ // The solver uses word-wrapping in its error message, so we use \s to
+ // accomodate.
+ await testGetExecutable(
+ ':foo',
+ d.path(appPath),
+ errorMessage: matches(r'foo.dart:1:8:'),
+ issue: CommandResolutionIssue.compilationFailed,
+ );
});
test('Finds files', () async {
- await servePackages((b) => b
- ..serve('foo', '1.0.0', pubspec: {
- 'environment': {'sdk': '>=$_currentVersion <3.0.0'}
- }, contents: [
- d.dir('bin', [
- d.file('foo.dart', 'main() {print(42);}'),
- d.file('tool.dart', 'main() {print(42);}')
- ])
- ]));
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'environment': {'sdk': '>=$_currentVersion <3.0.0'}
+ }, contents: [
+ d.dir('bin', [
+ d.file('foo.dart', 'main() {print(42);}'),
+ d.file('tool.dart', 'main() {print(42);}')
+ ])
+ ]);
await d.dir(appPath, [
d.pubspec({
@@ -148,46 +209,81 @@
]).create();
final dir = d.path(appPath);
- await testGetExecutable('myapp', dir,
- result: p.join('.dart_tool', 'pub', 'bin', 'myapp',
- 'myapp.dart-$_currentVersion.snapshot'));
- await testGetExecutable('myapp:myapp', dir,
- result: p.join('.dart_tool', 'pub', 'bin', 'myapp',
- 'myapp.dart-$_currentVersion.snapshot'));
- await testGetExecutable(':myapp', dir,
- result: p.join('.dart_tool', 'pub', 'bin', 'myapp',
- 'myapp.dart-$_currentVersion.snapshot'));
- await testGetExecutable(':tool', dir,
- result: p.join('.dart_tool', 'pub', 'bin', 'myapp',
- 'tool.dart-$_currentVersion.snapshot'));
- await testGetExecutable('foo', dir,
- allowSnapshot: false,
- result: endsWith('foo-1.0.0${separator}bin${separator}foo.dart'));
- await testGetExecutable('foo', dir,
- result:
- '.dart_tool${separator}pub${separator}bin${separator}foo${separator}foo.dart-$_currentVersion.snapshot');
- await testGetExecutable('foo:tool', dir,
- allowSnapshot: false,
- result: endsWith('foo-1.0.0${separator}bin${separator}tool.dart'));
- await testGetExecutable('foo:tool', dir,
- result:
- '.dart_tool${separator}pub${separator}bin${separator}foo${separator}tool.dart-$_currentVersion.snapshot');
+ await testGetExecutable(
+ 'myapp',
+ dir,
+ executable: p.join('.dart_tool', 'pub', 'bin', 'myapp',
+ 'myapp.dart-$_currentVersion.snapshot'),
+ packageConfig: p.join('.dart_tool', 'package_config.json'),
+ );
+ await testGetExecutable(
+ 'myapp:myapp',
+ dir,
+ executable: p.join('.dart_tool', 'pub', 'bin', 'myapp',
+ 'myapp.dart-$_currentVersion.snapshot'),
+ packageConfig: p.join('.dart_tool', 'package_config.json'),
+ );
+ await testGetExecutable(
+ ':myapp',
+ dir,
+ executable: p.join('.dart_tool', 'pub', 'bin', 'myapp',
+ 'myapp.dart-$_currentVersion.snapshot'),
+ packageConfig: p.join('.dart_tool', 'package_config.json'),
+ );
+ await testGetExecutable(
+ ':tool',
+ dir,
+ executable: p.join('.dart_tool', 'pub', 'bin', 'myapp',
+ 'tool.dart-$_currentVersion.snapshot'),
+ packageConfig: p.join('.dart_tool', 'package_config.json'),
+ );
+ await testGetExecutable(
+ 'foo',
+ dir,
+ allowSnapshot: false,
+ executable: endsWith('foo-1.0.0${separator}bin${separator}foo.dart'),
+ packageConfig: p.join('.dart_tool', 'package_config.json'),
+ );
+ await testGetExecutable(
+ 'foo',
+ dir,
+ executable:
+ '.dart_tool${separator}pub${separator}bin${separator}foo${separator}foo.dart-$_currentVersion.snapshot',
+ packageConfig: p.join('.dart_tool', 'package_config.json'),
+ );
+ await testGetExecutable(
+ 'foo:tool',
+ dir,
+ allowSnapshot: false,
+ executable: endsWith('foo-1.0.0${separator}bin${separator}tool.dart'),
+ packageConfig: p.join('.dart_tool', 'package_config.json'),
+ );
+ await testGetExecutable(
+ 'foo:tool',
+ dir,
+ executable:
+ '.dart_tool${separator}pub${separator}bin${separator}foo${separator}tool.dart-$_currentVersion.snapshot',
+ packageConfig: p.join('.dart_tool', 'package_config.json'),
+ );
await testGetExecutable(
'unknown:tool',
dir,
errorMessage: 'Could not find package `unknown` or file `unknown:tool`',
+ issue: CommandResolutionIssue.packageNotFound,
);
await testGetExecutable(
'foo:unknown',
dir,
errorMessage:
'Could not find `bin${separator}unknown.dart` in package `foo`.',
+ issue: CommandResolutionIssue.noBinaryFound,
);
await testGetExecutable(
'unknownTool',
dir,
errorMessage:
'Could not find package `unknownTool` or file `unknownTool`',
+ issue: CommandResolutionIssue.packageNotFound,
);
});
}
diff --git a/test/embedding/goldens/helptext.txt b/test/embedding/goldens/helptext.txt
deleted file mode 100644
index b5c206f..0000000
--- a/test/embedding/goldens/helptext.txt
+++ /dev/null
@@ -1,113 +0,0 @@
-$ tool/test-bin/pub_command_runner.dart
-[E] Could not find a command named "".
-[E]
-[E] Usage: pub_command_runner <command> [arguments]
-[E]
-[E] Global options:
-[E] -h, --help Print this usage information.
-[E]
-[E] Available commands:
-[E] pub Work with packages.
-[E]
-[E] Run "pub_command_runner help <command>" for more information about a command.
-
-$ tool/test-bin/pub_command_runner.dart --help
-Tests the embeddable pub command.
-
-Usage: pub_command_runner <command> [arguments]
-
-Global options:
--h, --help Print this usage information.
-
-Available commands:
- pub Work with packages.
-
-Run "pub_command_runner help <command>" for more information about a command.
-
-$ tool/test-bin/pub_command_runner.dart pub
-[E] Missing subcommand for "pub_command_runner pub".
-[E]
-[E] Usage: pub_command_runner pub [arguments...]
-[E] -h, --help Print this usage information.
-[E] --[no-]trace Print debugging information when an error occurs.
-[E] -v, --verbose Shortcut for "--verbosity=all".
-[E] -C, --directory=<dir> Run the subcommand in the directory<dir>.
-[E] (defaults to ".")
-[E]
-[E] Available subcommands:
-[E] add Add a dependency to pubspec.yaml.
-[E] cache Work with the system cache.
-[E] deps Print package dependencies.
-[E] downgrade Downgrade the current package's dependencies to oldest versions.
-[E] get Get the current package's dependencies.
-[E] global Work with global packages.
-[E] login Log into pub.dev.
-[E] logout Log out of pub.dev.
-[E] outdated Analyze your dependencies to find which ones can be upgraded.
-[E] publish Publish the current package to pub.dartlang.org.
-[E] remove Removes a dependency from the current package.
-[E] token Manage authentication tokens for hosted pub repositories.
-[E] upgrade Upgrade the current package's dependencies to latest versions.
-[E] uploader Manage uploaders for a package on pub.dartlang.org.
-[E]
-[E] Run "pub_command_runner help" to see global options.
-[E] See https://dart.dev/tools/pub/cmd/pub-global for detailed documentation.
-
-$ tool/test-bin/pub_command_runner.dart pub --help
-Work with packages.
-
-Usage: pub_command_runner pub [arguments...]
--h, --help Print this usage information.
- --[no-]trace Print debugging information when an error occurs.
--v, --verbose Shortcut for "--verbosity=all".
--C, --directory=<dir> Run the subcommand in the directory<dir>.
- (defaults to ".")
-
-Available subcommands:
- add Add a dependency to pubspec.yaml.
- cache Work with the system cache.
- deps Print package dependencies.
- downgrade Downgrade the current package's dependencies to oldest versions.
- get Get the current package's dependencies.
- global Work with global packages.
- login Log into pub.dev.
- logout Log out of pub.dev.
- outdated Analyze your dependencies to find which ones can be upgraded.
- publish Publish the current package to pub.dartlang.org.
- remove Removes a dependency from the current package.
- token Manage authentication tokens for hosted pub repositories.
- upgrade Upgrade the current package's dependencies to latest versions.
- uploader Manage uploaders for a package on pub.dartlang.org.
-
-Run "pub_command_runner help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-global for detailed documentation.
-
-$ tool/test-bin/pub_command_runner.dart pub get --help
-Get the current package's dependencies.
-
-Usage: pub_command_runner pub get <subcommand> [arguments...]
--h, --help Print this usage information.
- --[no-]offline Use cached packages instead of accessing the network.
--n, --dry-run Report what dependencies would change but don't change
- any.
- --[no-]precompile Build executables in immediate dependencies.
--C, --directory=<dir> Run this in the directory<dir>.
-
-Run "pub_command_runner help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-get for detailed documentation.
-
-$ tool/test-bin/pub_command_runner.dart pub global
-[E] Missing subcommand for "pub_command_runner pub global".
-[E]
-[E] Usage: pub_command_runner pub global [arguments...]
-[E] -h, --help Print this usage information.
-[E]
-[E] Available subcommands:
-[E] activate Make a package's executables globally available.
-[E] deactivate Remove a previously activated package.
-[E] list List globally activated packages.
-[E] run Run an executable from a globally activated package.
-[E]
-[E] Run "pub_command_runner help" to see global options.
-[E] See https://dart.dev/tools/pub/cmd/pub-global for detailed documentation.
-
diff --git a/test/embedding/goldens/run.txt b/test/embedding/goldens/run.txt
deleted file mode 100644
index 6f0f46a..0000000
--- a/test/embedding/goldens/run.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-$ tool/test-bin/pub_command_runner.dart pub get
-Resolving dependencies...
-Got dependencies!
-
-$ tool/test-bin/pub_command_runner.dart pub run bin/main.dart
-Hi
-
diff --git a/test/get/dry_run_does_not_apply_changes_test.dart b/test/get/dry_run_does_not_apply_changes_test.dart
index 1879f51..3e44bf9 100644
--- a/test/get/dry_run_does_not_apply_changes_test.dart
+++ b/test/get/dry_run_does_not_apply_changes_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
@@ -11,9 +9,8 @@
void main() {
test('--dry-run shows but does not apply changes', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.appDir({'foo': '1.0.0'}).create();
diff --git a/test/get/flutter_constraint_upper_bound_ignored_test.dart b/test/get/flutter_constraint_upper_bound_ignored_test.dart
index 9fc833c..7fd2edc 100644
--- a/test/get/flutter_constraint_upper_bound_ignored_test.dart
+++ b/test/get/flutter_constraint_upper_bound_ignored_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/get/gets_in_example_folder_test.dart b/test/get/gets_in_example_folder_test.dart
index d7f6c57..04f9d47 100644
--- a/test/get/gets_in_example_folder_test.dart
+++ b/test/get/gets_in_example_folder_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart = 2.11
-
import 'dart:io';
import 'package:path/path.dart' as p;
diff --git a/test/get/git/check_out_and_upgrade_test.dart b/test/get/git/check_out_and_upgrade_test.dart
index 846859b..42044af 100644
--- a/test/get/git/check_out_and_upgrade_test.dart
+++ b/test/get/git/check_out_and_upgrade_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/get/git/check_out_branch_test.dart b/test/get/git/check_out_branch_test.dart
index 0b58abf..104c8b9 100644
--- a/test/get/git/check_out_branch_test.dart
+++ b/test/get/git/check_out_branch_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/get/git/check_out_revision_test.dart b/test/get/git/check_out_revision_test.dart
index eed9f01..2428d7c 100644
--- a/test/get/git/check_out_revision_test.dart
+++ b/test/get/git/check_out_revision_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/get/git/check_out_test.dart b/test/get/git/check_out_test.dart
index 194e980..f3caaa2 100644
--- a/test/get/git/check_out_test.dart
+++ b/test/get/git/check_out_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
import 'package:path/path.dart' as p;
diff --git a/test/get/git/check_out_transitive_test.dart b/test/get/git/check_out_transitive_test.dart
index b7e71fa..0587c58 100644
--- a/test/get/git/check_out_transitive_test.dart
+++ b/test/get/git/check_out_transitive_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/get/git/check_out_twice_test.dart b/test/get/git/check_out_twice_test.dart
index f9cebd1..b6de388 100644
--- a/test/get/git/check_out_twice_test.dart
+++ b/test/get/git/check_out_twice_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/get/git/check_out_unfetched_revision_of_cached_repo_test.dart b/test/get/git/check_out_unfetched_revision_of_cached_repo_test.dart
index c5fc4aa..dae234d 100644
--- a/test/get/git/check_out_unfetched_revision_of_cached_repo_test.dart
+++ b/test/get/git/check_out_unfetched_revision_of_cached_repo_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
diff --git a/test/get/git/check_out_with_trailing_slash_test.dart b/test/get/git/check_out_with_trailing_slash_test.dart
index 16dc07c..5838986 100644
--- a/test/get/git/check_out_with_trailing_slash_test.dart
+++ b/test/get/git/check_out_with_trailing_slash_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/get/git/clean_invalid_git_repo_cache_test.dart b/test/get/git/clean_invalid_git_repo_cache_test.dart
index 6ea650b..ab386ab 100644
--- a/test/get/git/clean_invalid_git_repo_cache_test.dart
+++ b/test/get/git/clean_invalid_git_repo_cache_test.dart
@@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
import 'dart:io';
import 'package:path/path.dart' as path;
@@ -15,11 +14,10 @@
void _invalidateGitCache(String repo) {
final cacheDir =
path.join(d.sandbox, path.joinAll([cachePath, 'git', 'cache']));
- final Directory fooCacheDir =
- Directory(cacheDir).listSync().firstWhere((entity) {
+ final fooCacheDir = Directory(cacheDir).listSync().firstWhere((entity) {
return entity is Directory &&
entity.path.split(Platform.pathSeparator).last.startsWith(repo);
- });
+ }) as Directory;
fooCacheDir.deleteSync(recursive: true);
fooCacheDir.createSync();
diff --git a/test/get/git/dependency_name_match_pubspec_test.dart b/test/get/git/dependency_name_match_pubspec_test.dart
index 2accd62..1545fca 100644
--- a/test/get/git/dependency_name_match_pubspec_test.dart
+++ b/test/get/git/dependency_name_match_pubspec_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/get/git/different_repo_name_test.dart b/test/get/git/different_repo_name_test.dart
index 65e37eb..1d8f9c4 100644
--- a/test/get/git/different_repo_name_test.dart
+++ b/test/get/git/different_repo_name_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/get/git/doesnt_fetch_if_nothing_changes_test.dart b/test/get/git/doesnt_fetch_if_nothing_changes_test.dart
index ec214d4..3d9f040 100644
--- a/test/get/git/doesnt_fetch_if_nothing_changes_test.dart
+++ b/test/get/git/doesnt_fetch_if_nothing_changes_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
diff --git a/test/get/git/git_not_installed_test.dart b/test/get/git/git_not_installed_test.dart
index 13a5601..f00d795 100644
--- a/test/get/git/git_not_installed_test.dart
+++ b/test/get/git/git_not_installed_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
@TestOn('linux')
import 'dart:io';
diff --git a/test/get/git/lock_version_test.dart b/test/get/git/lock_version_test.dart
index 1e51d12..40b2708 100644
--- a/test/get/git/lock_version_test.dart
+++ b/test/get/git/lock_version_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
diff --git a/test/get/git/locked_revision_without_repo_test.dart b/test/get/git/locked_revision_without_repo_test.dart
index 49c1a11..c00c730 100644
--- a/test/get/git/locked_revision_without_repo_test.dart
+++ b/test/get/git/locked_revision_without_repo_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
diff --git a/test/get/git/path_test.dart b/test/get/git/path_test.dart
index 8bbd9e7..a323be7 100644
--- a/test/get/git/path_test.dart
+++ b/test/get/git/path_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
import 'package:pub/src/lock_file.dart';
@@ -39,9 +37,11 @@
])
]).validate();
- await d.appPackagesFile({
- 'sub': pathInCache('git/foo-${await repo.revParse('HEAD')}/subdir')
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(
+ name: 'sub',
+ path: pathInCache('git/foo-${await repo.revParse('HEAD')}/subdir')),
+ ]).validate();
});
test('depends on a package in a deep subdirectory', () async {
@@ -73,14 +73,17 @@
])
]).validate();
- await d.appPackagesFile({
- 'sub': pathInCache('git/foo-${await repo.revParse('HEAD')}/sub/dir%25')
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(
+ name: 'sub',
+ path:
+ pathInCache('git/foo-${await repo.revParse('HEAD')}/sub/dir%25')),
+ ]).validate();
final lockFile = LockFile.load(
p.join(d.sandbox, appPath, 'pubspec.lock'), SourceRegistry());
- expect(lockFile.packages['sub'].description['path'], 'sub/dir%25',
+ expect(lockFile.packages['sub']!.description['path'], 'sub/dir%25',
reason: 'use uris to specify the path relative to the repo');
});
@@ -117,14 +120,17 @@
])
]).validate();
- await d.appPackagesFile({
- 'sub': pathInCache('git/foo-${await repo.revParse('HEAD')}/sub/dir%25')
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(
+ name: 'sub',
+ path:
+ pathInCache('git/foo-${await repo.revParse('HEAD')}/sub/dir%25')),
+ ]).validate();
final lockFile = LockFile.load(
p.join(d.sandbox, appPath, 'pubspec.lock'), SourceRegistry());
- expect(lockFile.packages['sub'].description['path'], 'sub/dir%25',
+ expect(lockFile.packages['sub']!.description['path'], 'sub/dir%25',
reason: 'use uris to specify the path relative to the repo');
});
@@ -160,10 +166,14 @@
])
]).validate();
- await d.appPackagesFile({
- 'sub1': pathInCache('git/foo-${await repo.revParse('HEAD')}/subdir1'),
- 'sub2': pathInCache('git/foo-${await repo.revParse('HEAD')}/subdir2')
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(
+ name: 'sub1',
+ path: pathInCache('git/foo-${await repo.revParse('HEAD')}/subdir1')),
+ d.packageConfigEntry(
+ name: 'sub2',
+ path: pathInCache('git/foo-${await repo.revParse('HEAD')}/subdir2')),
+ ]).validate();
});
test('depends on packages in the same subdirectory at different revisions',
@@ -208,9 +218,11 @@
])
]).validate();
- await d.appPackagesFile({
- 'sub1': pathInCache('git/foo-$oldRevision/subdir'),
- 'sub2': pathInCache('git/foo-$newRevision/subdir')
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(
+ name: 'sub1', path: pathInCache('git/foo-$oldRevision/subdir')),
+ d.packageConfigEntry(
+ name: 'sub2', path: pathInCache('git/foo-$newRevision/subdir')),
+ ]).validate();
});
}
diff --git a/test/get/git/require_pubspec_name_test.dart b/test/get/git/require_pubspec_name_test.dart
index e0815b2..adc31e4 100644
--- a/test/get/git/require_pubspec_name_test.dart
+++ b/test/get/git/require_pubspec_name_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/get/git/require_pubspec_test.dart b/test/get/git/require_pubspec_test.dart
index fb1dd56..0f75c75 100644
--- a/test/get/git/require_pubspec_test.dart
+++ b/test/get/git/require_pubspec_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/get/git/stay_locked_if_compatible_test.dart b/test/get/git/stay_locked_if_compatible_test.dart
index 615a11b..d7f6eb9 100644
--- a/test/get/git/stay_locked_if_compatible_test.dart
+++ b/test/get/git/stay_locked_if_compatible_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/get/git/unlock_if_incompatible_test.dart b/test/get/git/unlock_if_incompatible_test.dart
index 1a97136..61b60e6 100644
--- a/test/get/git/unlock_if_incompatible_test.dart
+++ b/test/get/git/unlock_if_incompatible_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/get/hosted/avoid_network_requests_test.dart b/test/get/hosted/avoid_network_requests_test.dart
index 4a0cd90..c62fa7c 100644
--- a/test/get/hosted/avoid_network_requests_test.dart
+++ b/test/get/hosted/avoid_network_requests_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,14 +9,13 @@
void main() {
test('only requests versions that are needed during solving', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '1.1.0');
- builder.serve('foo', '1.2.0');
- builder.serve('bar', '1.0.0');
- builder.serve('bar', '1.1.0');
- builder.serve('bar', '1.2.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '1.1.0')
+ ..serve('foo', '1.2.0')
+ ..serve('bar', '1.0.0')
+ ..serve('bar', '1.1.0')
+ ..serve('bar', '1.2.0');
await d.appDir({'foo': 'any'}).create();
@@ -34,8 +31,10 @@
// Run the solver again.
await pubGet();
-
- await d.appPackagesFile({'foo': '1.2.0', 'bar': '1.2.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.2.0'),
+ ]).validate();
// The get should not have done any network requests since the lock file is
// up to date.
diff --git a/test/get/hosted/cached_pubspec_test.dart b/test/get/hosted/cached_pubspec_test.dart
index c4711c8..fa9decc 100644
--- a/test/get/hosted/cached_pubspec_test.dart
+++ b/test/get/hosted/cached_pubspec_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,7 +9,8 @@
void main() {
test('does not request a pubspec for a cached package', () async {
- await servePackages((builder) => builder.serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.appDir({'foo': '1.2.3'}).create();
@@ -20,16 +19,18 @@
// Clear the cache. We don't care about anything that was served during
// the initial get.
- globalServer.requestedPaths.clear();
+ server.requestedPaths.clear();
await d.cacheDir({'foo': '1.2.3'}).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
// Run the solver again now that it's cached.
await pubGet();
// The get should not have requested the pubspec since it's local already.
- expect(globalServer.requestedPaths,
+ expect(server.requestedPaths,
isNot(contains('packages/foo/versions/1.2.3.yaml')));
});
}
diff --git a/test/get/hosted/do_not_upgrade_on_removed_constraints_test.dart b/test/get/hosted/do_not_upgrade_on_removed_constraints_test.dart
index c635399..44fe075 100644
--- a/test/get/hosted/do_not_upgrade_on_removed_constraints_test.dart
+++ b/test/get/hosted/do_not_upgrade_on_removed_constraints_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -13,24 +11,29 @@
test(
"doesn't upgrade dependencies whose constraints have been "
'removed', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'shared_dep': 'any'});
- builder.serve('bar', '1.0.0', deps: {'shared_dep': '<2.0.0'});
- builder.serve('shared_dep', '1.0.0');
- builder.serve('shared_dep', '2.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'shared_dep': 'any'})
+ ..serve('bar', '1.0.0', deps: {'shared_dep': '<2.0.0'})
+ ..serve('shared_dep', '1.0.0')
+ ..serve('shared_dep', '2.0.0');
await d.appDir({'foo': 'any', 'bar': 'any'}).create();
await pubGet();
- await d.appPackagesFile(
- {'foo': '1.0.0', 'bar': '1.0.0', 'shared_dep': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ d.packageConfigEntry(name: 'shared_dep', version: '1.0.0'),
+ ]).validate();
await d.appDir({'foo': 'any'}).create();
await pubGet();
- await d.appPackagesFile({'foo': '1.0.0', 'shared_dep': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'shared_dep', version: '1.0.0'),
+ ]).validate();
});
}
diff --git a/test/get/hosted/does_no_network_requests_when_possible_test.dart b/test/get/hosted/does_no_network_requests_when_possible_test.dart
index bca2c4d..4324776 100644
--- a/test/get/hosted/does_no_network_requests_when_possible_test.dart
+++ b/test/get/hosted/does_no_network_requests_when_possible_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
void main() {
test('does not request versions if the lockfile is up to date', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '1.1.0');
- builder.serve('foo', '1.2.0');
- });
+ final server = await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '1.1.0')
+ ..serve('foo', '1.2.0');
await d.appDir({'foo': 'any'}).create();
@@ -24,16 +21,18 @@
// Clear the cache. We don't care about anything that was served during
// the initial get.
- globalServer.requestedPaths.clear();
+ server.requestedPaths.clear();
// Run the solver again now that it's cached.
await pubGet();
await d.cacheDir({'foo': '1.2.0'}).validate();
- await d.appPackagesFile({'foo': '1.2.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.0'),
+ ]).validate();
// The get should not have done any network requests since the lock file is
// up to date.
- expect(globalServer.requestedPaths, isEmpty);
+ expect(server.requestedPaths, isEmpty);
});
}
diff --git a/test/get/hosted/explain_bad_hosted_url_test.dart b/test/get/hosted/explain_bad_hosted_url_test.dart
index 6de6860..feebf67 100644
--- a/test/get/hosted/explain_bad_hosted_url_test.dart
+++ b/test/get/hosted/explain_bad_hosted_url_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -34,11 +32,12 @@
});
test('Allows PUB_HOSTED_URL to end with a slash', () async {
- await servePackages((b) => b.serve('foo', '1.0.0'));
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.appDir({'foo': 'any'}).create();
await pubGet(
- environment: {'PUB_HOSTED_URL': '${globalPackageServer.url}/'},
+ environment: {'PUB_HOSTED_URL': '${globalServer.url}/'},
);
});
}
diff --git a/test/get/hosted/get_stress_test.dart b/test/get/hosted/get_stress_test.dart
index 8a05104..026c0c1 100644
--- a/test/get/hosted/get_stress_test.dart
+++ b/test/get/hosted/get_stress_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,12 +9,11 @@
void main() {
test('gets more than 16 packages from a pub server', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- for (var i = 0; i < 20; i++) {
- builder.serve('pkg$i', '1.$i.0');
- }
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
+ for (var i = 0; i < 20; i++) {
+ server.serve('pkg$i', '1.$i.0');
+ }
await d.appDir({
'foo': '1.2.3',
@@ -29,10 +26,10 @@
'foo': '1.2.3',
for (var i = 0; i < 20; i++) 'pkg$i': '1.$i.0',
}).validate();
-
- await d.appPackagesFile({
- 'foo': '1.2.3',
- for (var i = 0; i < 20; i++) 'pkg$i': '1.$i.0',
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ for (var i = 0; i < 20; i++)
+ d.packageConfigEntry(name: 'pkg$i', version: '1.$i.0')
+ ]).validate();
});
}
diff --git a/test/get/hosted/get_test.dart b/test/get/hosted/get_test.dart
index 13f9ad8..f0270a3 100644
--- a/test/get/hosted/get_test.dart
+++ b/test/get/hosted/get_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/io.dart';
@@ -15,18 +13,21 @@
void main() {
test('gets a package from a pub server', () async {
- await servePackages((builder) => builder.serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.appDir({'foo': '1.2.3'}).create();
await pubGet();
await d.cacheDir({'foo': '1.2.3'}).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
});
test('URL encodes the package name', () async {
- await serveNoPackages();
+ await servePackages();
await d.appDir({'bad name!': '1.2.3'}).create();
@@ -43,11 +44,10 @@
test('gets a package from a non-default pub server', () async {
// Make the default server serve errors. Only the custom server should
// be accessed.
- await serveErrors();
+ (await servePackages()).serveErrors();
- var server = await PackageServer.start((builder) {
- builder.serve('foo', '1.2.3');
- });
+ var server = await startPackageServer();
+ server.serve('foo', '1.2.3');
await d.appDir({
'foo': {
@@ -59,18 +59,21 @@
await pubGet();
await d.cacheDir({'foo': '1.2.3'}, port: server.port).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3', server: server),
+ ]).validate();
});
group('categorizes dependency types in the lockfile', () {
- setUp(() => servePackages((builder) {
- builder.serve('foo', '1.2.3', deps: {'bar': 'any'});
- builder.serve('bar', '1.2.3');
- builder.serve('baz', '1.2.3', deps: {'qux': 'any'});
- builder.serve('qux', '1.2.3');
- builder.serve('zip', '1.2.3', deps: {'zap': 'any'});
- builder.serve('zap', '1.2.3');
- }));
+ setUp(() async {
+ await servePackages()
+ ..serve('foo', '1.2.3', deps: {'bar': 'any'})
+ ..serve('bar', '1.2.3')
+ ..serve('baz', '1.2.3', deps: {'qux': 'any'})
+ ..serve('qux', '1.2.3')
+ ..serve('zip', '1.2.3', deps: {'zap': 'any'})
+ ..serve('zap', '1.2.3');
+ });
test('for main, dev, and overridden dependencies', () async {
await d.dir(appPath, [
diff --git a/test/get/hosted/get_transitive_test.dart b/test/get/hosted/get_transitive_test.dart
index 4640c44..0ae18ac 100644
--- a/test/get/hosted/get_transitive_test.dart
+++ b/test/get/hosted/get_transitive_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,18 +9,20 @@
void main() {
test('gets packages transitively from a pub server', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3', deps: {'bar': '2.0.4'});
- builder.serve('bar', '2.0.3');
- builder.serve('bar', '2.0.4');
- builder.serve('bar', '2.0.5');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3', deps: {'bar': '2.0.4'})
+ ..serve('bar', '2.0.3')
+ ..serve('bar', '2.0.4')
+ ..serve('bar', '2.0.5');
await d.appDir({'foo': '1.2.3'}).create();
await pubGet();
await d.cacheDir({'foo': '1.2.3', 'bar': '2.0.4'}).validate();
- await d.appPackagesFile({'foo': '1.2.3', 'bar': '2.0.4'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ d.packageConfigEntry(name: 'bar', version: '2.0.4'),
+ ]).validate();
});
}
diff --git a/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test.dart b/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test.dart
index 14f1d98..585cfba 100644
--- a/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test.dart
+++ b/test/get/hosted/gets_a_package_with_busted_dev_dependencies_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -14,12 +12,11 @@
test(
'gets a dependency with broken dev dependencies from a pub '
'server', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3', pubspec: {
- 'dev_dependencies': {
- 'busted': {'not a real source': null}
- }
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.3', pubspec: {
+ 'dev_dependencies': {
+ 'busted': {'not a real source': null}
+ }
});
await d.appDir({'foo': '1.2.3'}).create();
@@ -27,6 +24,8 @@
await pubGet();
await d.cacheDir({'foo': '1.2.3'}).validate();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
});
}
diff --git a/test/get/hosted/resolve_constraints_test.dart b/test/get/hosted/resolve_constraints_test.dart
index cf3d434..466902e 100644
--- a/test/get/hosted/resolve_constraints_test.dart
+++ b/test/get/hosted/resolve_constraints_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,13 +9,12 @@
void main() {
test('resolves version constraints from a pub server', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3', deps: {'baz': '>=2.0.0'});
- builder.serve('bar', '2.3.4', deps: {'baz': '<3.0.0'});
- builder.serve('baz', '2.0.3');
- builder.serve('baz', '2.0.4');
- builder.serve('baz', '3.0.1');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3', deps: {'baz': '>=2.0.0'})
+ ..serve('bar', '2.3.4', deps: {'baz': '<3.0.0'})
+ ..serve('baz', '2.0.3')
+ ..serve('baz', '2.0.4')
+ ..serve('baz', '3.0.1');
await d.appDir({'foo': 'any', 'bar': 'any'}).create();
@@ -25,8 +22,10 @@
await d
.cacheDir({'foo': '1.2.3', 'bar': '2.3.4', 'baz': '2.0.4'}).validate();
-
- await d.appPackagesFile(
- {'foo': '1.2.3', 'bar': '2.3.4', 'baz': '2.0.4'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ d.packageConfigEntry(name: 'bar', version: '2.3.4'),
+ d.packageConfigEntry(name: 'baz', version: '2.0.4'),
+ ]).validate();
});
}
diff --git a/test/get/hosted/resolve_with_retracted_package_versions_test.dart b/test/get/hosted/resolve_with_retracted_package_versions_test.dart
index af714cf..d9b33a4 100644
--- a/test/get/hosted/resolve_with_retracted_package_versions_test.dart
+++ b/test/get/hosted/resolve_with_retracted_package_versions_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
@@ -15,28 +13,29 @@
void main() {
test('Do not consider retracted packages', () async {
- await servePackages((builder) => builder
+ final server = await servePackages()
..serve('foo', '1.0.0', deps: {'bar': '^1.0.0'})
..serve('bar', '1.0.0')
- ..serve('bar', '1.1.0'));
+ ..serve('bar', '1.1.0');
await d.appDir({'foo': '1.0.0'}).create();
- globalPackageServer
- .add((builder) => builder..retractPackageVersion('bar', '1.1.0'));
+ server.retractPackageVersion('bar', '1.1.0');
await pubGet();
await d.cacheDir({'foo': '1.0.0', 'bar': '1.0.0'}).validate();
- await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ ]).validate();
});
test('Error when the only available package version is retracted', () async {
- await servePackages((builder) => builder
+ final server = await servePackages()
..serve('foo', '1.0.0', deps: {'bar': '^1.0.0'})
- ..serve('bar', '1.0.0'));
+ ..serve('bar', '1.0.0');
await d.appDir({'foo': '1.0.0'}).create();
- globalPackageServer
- .add((builder) => builder..retractPackageVersion('bar', '1.0.0'));
+ server.retractPackageVersion('bar', '1.0.0');
await pubGet(
error:
'''Because every version of foo depends on bar ^1.0.0 which doesn't match any versions, foo is forbidden.
@@ -49,39 +48,51 @@
// In this case we expect a newer version to be published at some point which
// will then cause pub upgrade to choose that one.
test('Allow retracted version when it was already in pubspec.lock', () async {
- await servePackages((builder) => builder
+ final server = await servePackages()
..serve('foo', '1.0.0', deps: {'bar': '^1.0.0'})
..serve('bar', '1.0.0')
- ..serve('bar', '1.1.0'));
+ ..serve('bar', '1.1.0');
await d.appDir({'foo': '1.0.0'}).create();
await pubGet();
await d.cacheDir({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
- await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.1.0'),
+ ]).validate();
- globalPackageServer
- .add((builder) => builder..retractPackageVersion('bar', '1.1.0'));
+ server.retractPackageVersion('bar', '1.1.0');
await pubUpgrade();
await d.cacheDir({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
- await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.1.0'),
+ ]).validate();
- globalPackageServer.add((builder) => builder..serve('bar', '2.0.0'));
+ server.serve('bar', '2.0.0');
await pubUpgrade();
await d.cacheDir({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
- await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.1.0'),
+ ]).validate();
- globalPackageServer.add((builder) => builder..serve('bar', '1.2.0'));
+ server.serve('bar', '1.2.0');
await pubUpgrade();
await d.cacheDir({'foo': '1.0.0', 'bar': '1.2.0'}).validate();
- await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.2.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.2.0'),
+ ]).validate();
});
test('Offline versions of pub commands also handle retracted packages',
() async {
+ final server = await servePackages();
await populateCache({
'foo': ['1.0.0'],
'bar': ['1.0.0', '1.1.0']
- });
+ }, server);
await d.cacheDir({
'foo': '1.0.0',
@@ -89,25 +100,27 @@
}).validate();
final barVersionsCache =
- p.join(globalPackageServer.cachingPath, '.cache', 'bar-versions.json');
+ p.join(globalServer.cachingPath, '.cache', 'bar-versions.json');
expect(fileExists(barVersionsCache), isTrue);
deleteEntry(barVersionsCache);
- globalPackageServer
- .add((builder) => builder..retractPackageVersion('bar', '1.1.0'));
+ server.retractPackageVersion('bar', '1.1.0');
await pubGet();
await d.cacheDir({'bar': '1.1.0'}).validate();
// Now serve only errors - to validate we are truly offline.
- await serveErrors();
+ server.serveErrors();
await d.appDir({'foo': '1.0.0', 'bar': '^1.0.0'}).create();
await pubUpgrade(args: ['--offline']);
// We choose bar 1.1.0 since we already have it in pubspec.lock
- await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.1.0'),
+ ]).validate();
// Delete lockfile so that retracted versions are not considered.
final lockFile = p.join(d.sandbox, appPath, 'pubspec.lock');
@@ -115,15 +128,17 @@
deleteEntry(lockFile);
await pubGet(args: ['--offline']);
- await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ ]).validate();
});
test('Allow retracted version when pinned in dependency_overrides', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- builder.serve('foo', '3.0.0');
- });
+ final server = await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0')
+ ..serve('foo', '3.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -133,31 +148,31 @@
})
]).create();
- globalPackageServer
- .add((builder) => builder..retractPackageVersion('foo', '2.0.0'));
+ server.retractPackageVersion('foo', '2.0.0');
await pubGet();
- await d.appPackagesFile({'foo': '2.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.0.0'),
+ ]).validate();
});
test('Prefer retracted version in dependency_overrides over pubspec.lock',
() async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- builder.serve('foo', '3.0.0');
- });
+ final server = await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0')
+ ..serve('foo', '3.0.0');
await d.appDir({'foo': 'any'}).create();
await pubGet();
- globalPackageServer
- .add((builder) => builder..retractPackageVersion('foo', '2.0.0'));
- globalPackageServer
- .add((builder) => builder..retractPackageVersion('foo', '3.0.0'));
+ server.retractPackageVersion('foo', '2.0.0');
+ server.retractPackageVersion('foo', '3.0.0');
await pubUpgrade();
- await d.appPackagesFile({'foo': '3.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '3.0.0'),
+ ]).validate();
await d.dir(appPath, [
d.pubspec({
@@ -168,6 +183,8 @@
]).create();
await pubUpgrade();
- await d.appPackagesFile({'foo': '2.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.0.0'),
+ ]).validate();
});
}
diff --git a/test/get/hosted/stay_locked_if_compatible_test.dart b/test/get/hosted/stay_locked_if_compatible_test.dart
index 588f395..df04579 100644
--- a/test/get/hosted/stay_locked_if_compatible_test.dart
+++ b/test/get/hosted/stay_locked_if_compatible_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -13,20 +11,24 @@
test(
"doesn't upgrade a locked pub server package with a new "
'compatible constraint', () async {
- await servePackages((builder) => builder.serve('foo', '1.0.0'));
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.appDir({'foo': 'any'}).create();
await pubGet();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ ]).validate();
- await d.appPackagesFile({'foo': '1.0.0'}).validate();
-
- globalPackageServer.add((builder) => builder.serve('foo', '1.0.1'));
+ server.serve('foo', '1.0.1');
await d.appDir({'foo': '>=1.0.0'}).create();
await pubGet();
- await d.appPackagesFile({'foo': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ ]).validate();
});
}
diff --git a/test/get/hosted/stay_locked_if_new_is_satisfied_test.dart b/test/get/hosted/stay_locked_if_new_is_satisfied_test.dart
index 743c5f4..c75c435 100644
--- a/test/get/hosted/stay_locked_if_new_is_satisfied_test.dart
+++ b/test/get/hosted/stay_locked_if_new_is_satisfied_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -13,35 +11,34 @@
test(
"doesn't unlock dependencies if a new dependency is already "
'satisfied', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': '<2.0.0'});
- builder.serve('bar', '1.0.0', deps: {'baz': '<2.0.0'});
- builder.serve('baz', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', deps: {'bar': '<2.0.0'});
+ server.serve('bar', '1.0.0', deps: {'baz': '<2.0.0'});
+ server.serve('baz', '1.0.0');
await d.appDir({'foo': 'any'}).create();
await pubGet();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ d.packageConfigEntry(name: 'baz', version: '1.0.0'),
+ ]).validate();
- await d.appPackagesFile(
- {'foo': '1.0.0', 'bar': '1.0.0', 'baz': '1.0.0'}).validate();
-
- globalPackageServer.add((builder) {
- builder.serve('foo', '2.0.0', deps: {'bar': '<3.0.0'});
- builder.serve('bar', '2.0.0', deps: {'baz': '<3.0.0'});
- builder.serve('baz', '2.0.0');
- builder.serve('newdep', '2.0.0', deps: {'baz': '>=1.0.0'});
- });
+ server.serve('foo', '2.0.0', deps: {'bar': '<3.0.0'});
+ server.serve('bar', '2.0.0', deps: {'baz': '<3.0.0'});
+ server.serve('baz', '2.0.0');
+ server.serve('newdep', '2.0.0', deps: {'baz': '>=1.0.0'});
await d.appDir({'foo': 'any', 'newdep': 'any'}).create();
await pubGet();
- await d.appPackagesFile({
- 'foo': '1.0.0',
- 'bar': '1.0.0',
- 'baz': '1.0.0',
- 'newdep': '2.0.0'
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ d.packageConfigEntry(name: 'baz', version: '1.0.0'),
+ d.packageConfigEntry(name: 'newdep', version: '2.0.0'),
+ ]).validate();
});
}
diff --git a/test/get/hosted/stay_locked_test.dart b/test/get/hosted/stay_locked_test.dart
index c5c11ff..8b819ea 100644
--- a/test/get/hosted/stay_locked_test.dart
+++ b/test/get/hosted/stay_locked_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
@@ -15,24 +13,28 @@
test(
'keeps a hosted package locked to the version in the '
'lockfile', () async {
- await servePackages((builder) => builder.serve('foo', '1.0.0'));
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.appDir({'foo': 'any'}).create();
// This should lock the foo dependency to version 1.0.0.
await pubGet();
-
- await d.appPackagesFile({'foo': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ ]).validate();
// Delete the .dart_tool/package_config.json file to simulate a new checkout of the application.
deleteEntry(path.join(d.sandbox, packageConfigFilePath));
// Start serving a newer package as well.
- globalPackageServer.add((builder) => builder.serve('foo', '1.0.1'));
+ server.serve('foo', '1.0.1');
// This shouldn't upgrade the foo dependency due to the lockfile.
await pubGet();
- await d.appPackagesFile({'foo': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ ]).validate();
});
}
diff --git a/test/get/hosted/unlock_if_incompatible_test.dart b/test/get/hosted/unlock_if_incompatible_test.dart
index f9f8748..007231e 100644
--- a/test/get/hosted/unlock_if_incompatible_test.dart
+++ b/test/get/hosted/unlock_if_incompatible_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -13,18 +11,23 @@
test(
'upgrades a locked pub server package with a new incompatible '
'constraint', () async {
- await servePackages((builder) => builder.serve('foo', '1.0.0'));
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.appDir({'foo': 'any'}).create();
await pubGet();
- await d.appPackagesFile({'foo': '1.0.0'}).validate();
- globalPackageServer.add((builder) => builder.serve('foo', '1.0.1'));
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ ]).validate();
+ server.serve('foo', '1.0.1');
await d.appDir({'foo': '>1.0.0'}).create();
await pubGet();
- await d.appPackagesFile({'foo': '1.0.1'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.1'),
+ ]).validate();
});
}
diff --git a/test/get/hosted/unlock_if_new_is_unsatisfied_test.dart b/test/get/hosted/unlock_if_new_is_unsatisfied_test.dart
index feaf478..ae6a4e6 100644
--- a/test/get/hosted/unlock_if_new_is_unsatisfied_test.dart
+++ b/test/get/hosted/unlock_if_new_is_unsatisfied_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -13,42 +11,40 @@
test(
'unlocks dependencies if necessary to ensure that a new '
'dependency is satisfied', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': '<2.0.0'});
- builder.serve('bar', '1.0.0', deps: {'baz': '<2.0.0'});
- builder.serve('baz', '1.0.0', deps: {'qux': '<2.0.0'});
- builder.serve('qux', '1.0.0');
- });
+ final server = await servePackages();
+
+ server.serve('foo', '1.0.0', deps: {'bar': '<2.0.0'});
+ server.serve('bar', '1.0.0', deps: {'baz': '<2.0.0'});
+ server.serve('baz', '1.0.0', deps: {'qux': '<2.0.0'});
+ server.serve('qux', '1.0.0');
await d.appDir({'foo': 'any'}).create();
await pubGet();
- await d.appPackagesFile({
- 'foo': '1.0.0',
- 'bar': '1.0.0',
- 'baz': '1.0.0',
- 'qux': '1.0.0'
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ d.packageConfigEntry(name: 'baz', version: '1.0.0'),
+ d.packageConfigEntry(name: 'qux', version: '1.0.0'),
+ ]).validate();
- globalPackageServer.add((builder) {
- builder.serve('foo', '2.0.0', deps: {'bar': '<3.0.0'});
- builder.serve('bar', '2.0.0', deps: {'baz': '<3.0.0'});
- builder.serve('baz', '2.0.0', deps: {'qux': '<3.0.0'});
- builder.serve('qux', '2.0.0');
- builder.serve('newdep', '2.0.0', deps: {'baz': '>=1.5.0'});
- });
+ server.serve('foo', '2.0.0', deps: {'bar': '<3.0.0'});
+ server.serve('bar', '2.0.0', deps: {'baz': '<3.0.0'});
+ server.serve('baz', '2.0.0', deps: {'qux': '<3.0.0'});
+ server.serve('qux', '2.0.0');
+ server.serve('newdep', '2.0.0', deps: {'baz': '>=1.5.0'});
await d.appDir({'foo': 'any', 'newdep': 'any'}).create();
await pubGet();
- await d.appPackagesFile({
- 'foo': '2.0.0',
- 'bar': '2.0.0',
- 'baz': '2.0.0',
- 'qux': '1.0.0',
- 'newdep': '2.0.0'
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '2.0.0'),
+ d.packageConfigEntry(name: 'baz', version: '2.0.0'),
+ d.packageConfigEntry(name: 'qux', version: '1.0.0'),
+ d.packageConfigEntry(name: 'newdep', version: '2.0.0'),
+ ]).validate();
});
}
diff --git a/test/get/hosted/unlock_if_version_doesnt_exist_test.dart b/test/get/hosted/unlock_if_version_doesnt_exist_test.dart
index f42e12e..e4cc01b 100644
--- a/test/get/hosted/unlock_if_version_doesnt_exist_test.dart
+++ b/test/get/hosted/unlock_if_version_doesnt_exist_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
@@ -14,16 +12,23 @@
void main() {
test('upgrades a locked pub server package with a nonexistent version',
() async {
- await servePackages((builder) => builder.serve('foo', '1.0.0'));
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.appDir({'foo': 'any'}).create();
await pubGet();
- await d.appPackagesFile({'foo': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ ]).validate();
deleteEntry(p.join(d.sandbox, cachePath));
- globalPackageServer.replace((builder) => builder.serve('foo', '1.0.1'));
+ server.clearPackages();
+ server.serve('foo', '1.0.1');
+
await pubGet();
- await d.appPackagesFile({'foo': '1.0.1'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.1'),
+ ]).validate();
});
}
diff --git a/test/get/hosted/warn_about_discontinued_test.dart b/test/get/hosted/warn_about_discontinued_test.dart
index 3913b2c..7057f9b 100644
--- a/test/get/hosted/warn_about_discontinued_test.dart
+++ b/test/get/hosted/warn_about_discontinued_test.dart
@@ -2,36 +2,34 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
-import 'package:shelf/shelf.dart';
+import 'package:shelf/shelf.dart' as shelf;
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
import '../../test_pub.dart';
void main() {
- test('Warns about discontinued packages', () async {
- await servePackages((builder) => builder
- ..serve('foo', '1.2.3', deps: {'transitive': 'any'})
- ..serve('transitive', '1.0.0'));
+ test('Warns about discontinued dependencies', () async {
+ final server = await servePackages();
+ server.serve('foo', '1.2.3', deps: {'transitive': 'any'});
+ server.serve('transitive', '1.0.0');
await d.appDir({'foo': '1.2.3'}).create();
await pubGet();
- globalPackageServer.add((builder) => builder
+ server
..discontinue('foo')
- ..discontinue('transitive'));
+ ..discontinue('transitive');
// A pub get straight away will not trigger the warning, as we cache
// responses for a while.
await pubGet();
final fooVersionsCache =
- p.join(globalPackageServer.cachingPath, '.cache', 'foo-versions.json');
- final transitiveVersionsCache = p.join(
- globalPackageServer.cachingPath, '.cache', 'transitive-versions.json');
+ p.join(globalServer.cachingPath, '.cache', 'foo-versions.json');
+ final transitiveVersionsCache =
+ p.join(globalServer.cachingPath, '.cache', 'transitive-versions.json');
expect(fileExists(fooVersionsCache), isTrue);
expect(fileExists(transitiveVersionsCache), isTrue);
deleteEntry(fooVersionsCache);
@@ -40,7 +38,6 @@
await pubGet(output: '''
Resolving dependencies...
foo 1.2.3 (discontinued)
- transitive 1.0.0 (discontinued)
Got dependencies!
''');
expect(fileExists(fooVersionsCache), isTrue);
@@ -49,12 +46,12 @@
c['_fetchedAt'] =
DateTime.now().subtract(Duration(days: 5)).toIso8601String();
writeTextFile(fooVersionsCache, json.encode(c));
- globalPackageServer
- .add((builder) => builder.discontinue('foo', replacementText: 'bar'));
+
+ server.discontinue('foo', replacementText: 'bar');
+
await pubGet(output: '''
Resolving dependencies...
foo 1.2.3 (discontinued replaced by bar)
- transitive 1.0.0 (discontinued)
Got dependencies!''');
final c2 = json.decode(readTextFile(fooVersionsCache));
// Make a bad cached value to test that responses are actually from cache.
@@ -62,22 +59,19 @@
writeTextFile(fooVersionsCache, json.encode(c2));
await pubGet(output: '''
Resolving dependencies...
- transitive 1.0.0 (discontinued)
Got dependencies!''');
// Repairing the cache should reset the package listing caches.
await runPub(args: ['cache', 'repair']);
await pubGet(output: '''
Resolving dependencies...
foo 1.2.3 (discontinued replaced by bar)
- transitive 1.0.0 (discontinued)
Got dependencies!''');
// Test that --offline won't try to access the server for retrieving the
// status.
- await serveErrors();
+ server.serveErrors();
await pubGet(args: ['--offline'], output: '''
Resolving dependencies...
foo 1.2.3 (discontinued replaced by bar)
- transitive 1.0.0 (discontinued)
Got dependencies!''');
deleteEntry(fooVersionsCache);
deleteEntry(transitiveVersionsCache);
@@ -87,18 +81,91 @@
''');
});
+ test('Warns about discontinued dev dependencies', () async {
+ final builder = await servePackages();
+ builder
+ ..serve('foo', '1.2.3', deps: {'transitive': 'any'})
+ ..serve('transitive', '1.0.0');
+
+ await d.dir(appPath, [
+ d.file('pubspec.yaml', '''
+name: myapp
+dependencies:
+
+dev_dependencies:
+ foo: 1.2.3
+environment:
+ sdk: '>=0.1.2 <1.0.0'
+''')
+ ]).create();
+ await pubGet();
+
+ builder
+ ..discontinue('foo')
+ ..discontinue('transitive');
+ // A pub get straight away will not trigger the warning, as we cache
+ // responses for a while.
+ await pubGet();
+ final fooVersionsCache =
+ p.join(globalServer.cachingPath, '.cache', 'foo-versions.json');
+ expect(fileExists(fooVersionsCache), isTrue);
+ deleteEntry(fooVersionsCache);
+ // We warn only about the direct dependency here:
+ await pubGet(output: '''
+Resolving dependencies...
+ foo 1.2.3 (discontinued)
+Got dependencies!
+''');
+ expect(fileExists(fooVersionsCache), isTrue);
+ final c = json.decode(readTextFile(fooVersionsCache));
+ // Make the cache artificially old.
+ c['_fetchedAt'] =
+ DateTime.now().subtract(Duration(days: 5)).toIso8601String();
+ writeTextFile(fooVersionsCache, json.encode(c));
+ builder.discontinue('foo', replacementText: 'bar');
+ await pubGet(output: '''
+Resolving dependencies...
+ foo 1.2.3 (discontinued replaced by bar)
+Got dependencies!''');
+ final c2 = json.decode(readTextFile(fooVersionsCache));
+ // Make a bad cached value to test that responses are actually from cache.
+ c2['isDiscontinued'] = false;
+ writeTextFile(fooVersionsCache, json.encode(c2));
+ await pubGet(output: '''
+Resolving dependencies...
+Got dependencies!''');
+ // Repairing the cache should reset the package listing caches.
+ await runPub(args: ['cache', 'repair']);
+ await pubGet(output: '''
+Resolving dependencies...
+ foo 1.2.3 (discontinued replaced by bar)
+Got dependencies!''');
+ // Test that --offline won't try to access the server for retrieving the
+ // status.
+ builder.serveErrors();
+ await pubGet(args: ['--offline'], output: '''
+Resolving dependencies...
+ foo 1.2.3 (discontinued replaced by bar)
+Got dependencies!''');
+ deleteEntry(fooVersionsCache);
+ await pubGet(args: ['--offline'], output: '''
+Resolving dependencies...
+Got dependencies!
+''');
+ });
+
test('get does not fail when status listing fails', () async {
- await servePackages((builder) => builder..serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.appDir({'foo': '1.2.3'}).create();
await pubGet();
final fooVersionsCache =
- p.join(globalPackageServer.cachingPath, '.cache', 'foo-versions.json');
+ p.join(globalServer.cachingPath, '.cache', 'foo-versions.json');
expect(fileExists(fooVersionsCache), isTrue);
deleteEntry(fooVersionsCache);
// Serve 400 on all requests.
- globalPackageServer.extraHandlers
- ..clear()
- ..[RegExp('.*')] = (request) async => Response(400);
+ globalServer.handle(RegExp('.*'),
+ (shelf.Request request) => shelf.Response.notFound('Not found'));
/// Even if we fail to get status we still report success if versions don't unlock.
await pubGet();
diff --git a/test/get/hosted/warn_about_retracted_package_test.dart b/test/get/hosted/warn_about_retracted_package_test.dart
index 5258d7c..2336c7f 100644
--- a/test/get/hosted/warn_about_retracted_package_test.dart
+++ b/test/get/hosted/warn_about_retracted_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
@@ -13,38 +11,36 @@
void main() {
test('Report retracted packages', () async {
- await servePackages((builder) => builder
+ final server = await servePackages()
..serve('foo', '1.0.0', deps: {'bar': 'any'})
- ..serve('bar', '1.0.0'));
+ ..serve('bar', '1.0.0');
await d.appDir({'foo': '1.0.0'}).create();
await pubGet();
- globalPackageServer
- .add((builder) => builder..retractPackageVersion('bar', '1.0.0'));
+ server.retractPackageVersion('bar', '1.0.0');
// Delete the cache to trigger the report.
final barVersionsCache =
- p.join(globalPackageServer.cachingPath, '.cache', 'bar-versions.json');
+ p.join(server.cachingPath, '.cache', 'bar-versions.json');
expect(fileExists(barVersionsCache), isTrue);
deleteEntry(barVersionsCache);
await pubGet(output: contains('bar 1.0.0 (retracted)'));
});
test('Report retracted packages with newer version available', () async {
- await servePackages((builder) => builder
+ final server = await servePackages()
..serve('foo', '1.0.0', deps: {'bar': '^1.0.0'})
..serve('bar', '1.0.0')
..serve('bar', '2.0.0')
- ..serve('bar', '2.0.1-pre'));
+ ..serve('bar', '2.0.1-pre');
await d.appDir({'foo': '1.0.0'}).create();
await pubGet();
- globalPackageServer
- .add((builder) => builder..retractPackageVersion('bar', '1.0.0'));
+ server.retractPackageVersion('bar', '1.0.0');
// Delete the cache to trigger the report.
final barVersionsCache =
- p.join(globalPackageServer.cachingPath, '.cache', 'bar-versions.json');
+ p.join(server.cachingPath, '.cache', 'bar-versions.json');
expect(fileExists(barVersionsCache), isTrue);
deleteEntry(barVersionsCache);
await pubGet(output: contains('bar 1.0.0 (retracted, 2.0.0 available)'));
@@ -52,19 +48,18 @@
test('Report retracted packages with newer prerelease version available',
() async {
- await servePackages((builder) => builder
+ final server = await servePackages()
..serve('foo', '1.0.0', deps: {'bar': '^1.0.0-pre'})
..serve('bar', '1.0.0-pre')
- ..serve('bar', '2.0.1-pre'));
+ ..serve('bar', '2.0.1-pre');
await d.appDir({'foo': '1.0.0'}).create();
await pubGet();
- globalPackageServer
- .add((builder) => builder..retractPackageVersion('bar', '1.0.0-pre'));
+ server.retractPackageVersion('bar', '1.0.0-pre');
// Delete the cache to trigger the report.
final barVersionsCache =
- p.join(globalPackageServer.cachingPath, '.cache', 'bar-versions.json');
+ p.join(server.cachingPath, '.cache', 'bar-versions.json');
expect(fileExists(barVersionsCache), isTrue);
deleteEntry(barVersionsCache);
await pubGet(
diff --git a/test/get/package_name_test.dart b/test/get/package_name_test.dart
index f385cfe..b1328cc 100644
--- a/test/get/package_name_test.dart
+++ b/test/get/package_name_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -58,7 +56,8 @@
await pubGet();
await d.dir(appPath, [
- d.packagesFile({'foo.bar.baz': '.'}),
+ d.packageConfigFile(
+ [d.packageConfigEntry(name: 'foo.bar.baz', path: '.')])
]).validate();
});
}
diff --git a/test/get/path/absolute_path_test.dart b/test/get/path/absolute_path_test.dart
index 7304f52..e1897e9 100644
--- a/test/get/path/absolute_path_test.dart
+++ b/test/get/path/absolute_path_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
@@ -23,6 +21,8 @@
await pubGet();
- await d.appPackagesFile({'foo': path.join(d.sandbox, 'foo')}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: path.join(d.sandbox, 'foo')),
+ ]).validate();
});
}
diff --git a/test/get/path/absolute_symlink_test.dart b/test/get/path/absolute_symlink_test.dart
index b0cd147..83d3433 100644
--- a/test/get/path/absolute_symlink_test.dart
+++ b/test/get/path/absolute_symlink_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
@@ -26,8 +24,8 @@
await pubGet();
- await d.dir(appPath, [
- d.packagesFile({'myapp': '.', 'foo': fooPath})
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: fooPath),
]).validate();
await d.dir('moved').create();
@@ -37,9 +35,9 @@
renameInSandbox(appPath, path.join('moved', appPath));
await d.dir('moved', [
- d.dir(appPath, [
- d.packagesFile({'myapp': '.', 'foo': fooPath})
- ])
+ d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: fooPath),
+ ]),
]).validate();
});
}
diff --git a/test/get/path/empty_pubspec_test.dart b/test/get/path/empty_pubspec_test.dart
index 5b94d70..0f9843f 100644
--- a/test/get/path/empty_pubspec_test.dart
+++ b/test/get/path/empty_pubspec_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/get/path/no_pubspec_test.dart b/test/get/path/no_pubspec_test.dart
index d12477d..d328f25 100644
--- a/test/get/path/no_pubspec_test.dart
+++ b/test/get/path/no_pubspec_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/get/path/nonexistent_dir_test.dart b/test/get/path/nonexistent_dir_test.dart
index 993590f..7616087 100644
--- a/test/get/path/nonexistent_dir_test.dart
+++ b/test/get/path/nonexistent_dir_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/get/path/path_is_file_test.dart b/test/get/path/path_is_file_test.dart
index 119a794..6fafd82 100644
--- a/test/get/path/path_is_file_test.dart
+++ b/test/get/path/path_is_file_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
diff --git a/test/get/path/relative_path_test.dart b/test/get/path/relative_path_test.dart
index a1d7437..e56a453 100644
--- a/test/get/path/relative_path_test.dart
+++ b/test/get/path/relative_path_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/lock_file.dart';
import 'package:pub/src/source_registry.dart';
@@ -25,7 +23,9 @@
await pubGet();
- await d.appPackagesFile({'foo': '../foo'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../foo'),
+ ]).validate();
});
test('path is relative to containing pubspec', () async {
@@ -47,8 +47,10 @@
await pubGet();
- await d.appPackagesFile(
- {'foo': '../relative/foo', 'bar': '../relative/bar'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../relative/foo'),
+ d.packageConfigEntry(name: 'bar', path: '../relative/bar'),
+ ]).validate();
});
test('path is relative to containing pubspec when using --directory',
@@ -74,9 +76,10 @@
workingDirectory: d.sandbox,
output: contains('Changed 2 dependencies in myapp!'));
- await d.appPackagesFile(
- {'foo': '../relative/foo', 'bar': '../relative/bar'},
- ).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../relative/foo'),
+ d.packageConfigEntry(name: 'bar', path: '../relative/bar'),
+ ]).validate();
});
test('relative path preserved in the lockfile', () async {
@@ -93,7 +96,7 @@
var lockfilePath = path.join(d.sandbox, appPath, 'pubspec.lock');
var lockfile = LockFile.load(lockfilePath, SourceRegistry());
- var description = lockfile.packages['foo'].description;
+ var description = lockfile.packages['foo']!.description;
expect(description['relative'], isTrue);
expect(description['path'], path.join(d.sandbox, 'foo'));
diff --git a/test/get/path/relative_symlink_test.dart b/test/get/path/relative_symlink_test.dart
index e48ba41..9136a34 100644
--- a/test/get/path/relative_symlink_test.dart
+++ b/test/get/path/relative_symlink_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
// Pub uses NTFS junction points to create links in the packages directory.
// These (unlike the symlinks that are supported in Vista and later) do not
// support relative paths. So this test, by design, will not pass on Windows.
@@ -30,8 +28,8 @@
await pubGet();
- await d.dir(appPath, [
- d.packagesFile({'myapp': '.', 'foo': '../foo'})
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../foo'),
]).validate();
await d.dir('moved').create();
@@ -43,8 +41,8 @@
renameInSandbox(appPath, path.join('moved', appPath));
await d.dir('moved', [
- d.dir(appPath, [
- d.packagesFile({'myapp': '.', 'foo': '../foo'})
+ d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../foo'),
])
]).validate();
});
diff --git a/test/get/path/shared_dependency_symlink_test.dart b/test/get/path/shared_dependency_symlink_test.dart
index 7d1369c..d450838 100644
--- a/test/get/path/shared_dependency_symlink_test.dart
+++ b/test/get/path/shared_dependency_symlink_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
@@ -42,13 +40,10 @@
await pubGet();
- await d.dir(appPath, [
- d.packagesFile({
- 'myapp': '.',
- 'foo': '../foo',
- 'bar': '../bar',
- 'shared': '../shared'
- })
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../foo'),
+ d.packageConfigEntry(name: 'bar', path: '../bar'),
+ d.packageConfigEntry(name: 'shared', path: '../shared'),
]).validate();
});
}
diff --git a/test/get/path/shared_dependency_test.dart b/test/get/path/shared_dependency_test.dart
index 3525e6b..3ef91ae 100644
--- a/test/get/path/shared_dependency_test.dart
+++ b/test/get/path/shared_dependency_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -37,8 +35,11 @@
await pubGet();
- await d.appPackagesFile(
- {'foo': '../foo', 'bar': '../bar', 'shared': '../shared'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../foo'),
+ d.packageConfigEntry(name: 'bar', path: '../bar'),
+ d.packageConfigEntry(name: 'shared', path: '../shared'),
+ ]).validate();
});
test('shared dependency with paths that normalize the same', () async {
@@ -68,7 +69,10 @@
await pubGet();
- await d.appPackagesFile(
- {'foo': '../foo', 'bar': '../bar', 'shared': '../shared'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../foo'),
+ d.packageConfigEntry(name: 'bar', path: '../bar'),
+ d.packageConfigEntry(name: 'shared', path: '../shared'),
+ ]).validate();
});
}
diff --git a/test/get/preserve_lock_file_line_endings_test.dart b/test/get/preserve_lock_file_line_endings_test.dart
index 8f6dc26..bfd015a 100644
--- a/test/get/preserve_lock_file_line_endings_test.dart
+++ b/test/get/preserve_lock_file_line_endings_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/entrypoint.dart';
import 'package:test/test.dart';
diff --git a/test/get/sdk_constraint_required_test.dart b/test/get/sdk_constraint_required_test.dart
index 3cb0f86..3f1e5c0 100644
--- a/test/get/sdk_constraint_required_test.dart
+++ b/test/get/sdk_constraint_required_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -27,8 +25,8 @@
d.nothing('pubspec.lock'),
// The "packages" directory should not have been generated.
d.nothing('packages'),
- // The ".packages" file should not have been created.
- d.nothing('.packages'),
+ // The package config file should not have been created.
+ d.nothing('.dart_tool/package_config.json'),
]).validate();
});
}
diff --git a/test/get/switch_source_test.dart b/test/get/switch_source_test.dart
index 2dee748..7e56652 100644
--- a/test/get/switch_source_test.dart
+++ b/test/get/switch_source_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
@@ -11,7 +9,8 @@
void main() {
test('re-gets a package if its source has changed', () async {
- await servePackages((builder) => builder.serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.dir('foo',
[d.libDir('foo', 'foo 0.0.1'), d.libPubspec('foo', '0.0.1')]).create();
@@ -22,11 +21,15 @@
await pubGet();
- await d.appPackagesFile({'foo': '../foo'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../foo'),
+ ]).validate();
await d.appDir({'foo': 'any'}).create();
await pubGet();
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
});
}
diff --git a/test/get/unknown_sdk_test.dart b/test/get/unknown_sdk_test.dart
new file mode 100644
index 0000000..d0c1de3
--- /dev/null
+++ b/test/get/unknown_sdk_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:pub/src/exit_codes.dart' as exit_codes;
+import 'package:test/test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+void main() {
+ test('pub get barks at unknown sdk', () async {
+ await d.dir(appPath, [
+ d.pubspec({
+ 'environment': {'foo': '>=1.2.4 <2.0.0'}
+ })
+ ]).create();
+
+ await pubGet(
+ error: contains(
+ "Error on line 1, column 40 of pubspec.yaml: pubspec.yaml refers to an unknown sdk 'foo'."),
+ exitCode: exit_codes.DATA,
+ );
+ });
+}
diff --git a/test/get/with_empty_environment_test.dart b/test/get/with_empty_environment_test.dart
new file mode 100644
index 0000000..30768c4
--- /dev/null
+++ b/test/get/with_empty_environment_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:test/test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+void main() {
+ test(r'runs even with an empty environment (eg. no $HOME)', () async {
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
+
+ await d.appDir({'foo': 'any'}).create();
+
+ await pubGet(environment: {
+ '_PUB_TEST_CONFIG_DIR': null,
+ if (Platform.isWindows) ...{
+ 'SYSTEMROOT': Platform.environment['SYSTEMROOT'],
+ 'TMP': Platform.environment['TMP'],
+ },
+ }, includeParentEnvironment: false);
+ });
+}
diff --git a/test/global/activate/activate_git_after_hosted_test.dart b/test/global/activate/activate_git_after_hosted_test.dart
index 5dd32c1..c553041 100644
--- a/test/global/activate/activate_git_after_hosted_test.dart
+++ b/test/global/activate/activate_git_after_hosted_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -13,11 +11,10 @@
test('activating a Git package deactivates the hosted one', () async {
ensureGit();
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
+ ]);
await d.git('foo.git', [
d.libPubspec('foo', '1.0.0'),
diff --git a/test/global/activate/activate_hosted_after_git_test.dart b/test/global/activate/activate_hosted_after_git_test.dart
index a86b2cc..1546280 100644
--- a/test/global/activate/activate_hosted_after_git_test.dart
+++ b/test/global/activate/activate_hosted_after_git_test.dart
@@ -2,8 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
+import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,11 +10,10 @@
void main() {
test('activating a hosted package deactivates the Git one', () async {
- await servePackages((builder) {
- builder.serve('foo', '2.0.0', contents: [
- d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '2.0.0', contents: [
+ d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
+ ]);
await d.git('foo.git', [
d.libPubspec('foo', '1.0.0'),
@@ -24,8 +22,9 @@
await runPub(args: ['global', 'activate', '-sgit', '../foo.git']);
+ final locationUri = p.toUri(p.join(d.sandbox, 'foo.git'));
await runPub(args: ['global', 'activate', 'foo'], output: '''
- Package foo is currently active from Git repository "../foo.git".
+ Package foo is currently active from Git repository "$locationUri".
Resolving dependencies...
+ foo 2.0.0
Downloading foo 2.0.0...
diff --git a/test/global/activate/activate_hosted_after_path_test.dart b/test/global/activate/activate_hosted_after_path_test.dart
index 1e01735..4cd753f 100644
--- a/test/global/activate/activate_hosted_after_path_test.dart
+++ b/test/global/activate/activate_hosted_after_path_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
@@ -13,11 +11,10 @@
void main() {
test('activating a hosted package deactivates the path one', () async {
- await servePackages((builder) {
- builder.serve('foo', '2.0.0', contents: [
- d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '2.0.0', contents: [
+ d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
+ ]);
await d.dir('foo', [
d.libPubspec('foo', '1.0.0'),
diff --git a/test/global/activate/activate_hosted_twice_test.dart b/test/global/activate/activate_hosted_twice_test.dart
index 925a205..a4d1337 100644
--- a/test/global/activate/activate_hosted_twice_test.dart
+++ b/test/global/activate/activate_hosted_twice_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,7 +9,8 @@
void main() {
test('activating a hosted package twice will not precompile', () async {
- await servePackages((builder) => builder
+ final server = await servePackages();
+ server
..serve('foo', '1.0.0', deps: {
'bar': 'any'
}, contents: [
@@ -23,23 +22,15 @@
])
..serve('bar', '1.0.0', contents: [
d.dir('lib', [d.file('bar.dart', 'final version = "1.0.0";')])
- ]));
+ ]);
- await runPub(args: ['global', 'activate', 'foo'], output: '''
-Resolving dependencies...
-+ bar 1.0.0
-+ foo 1.0.0
-Downloading foo 1.0.0...
-Downloading bar 1.0.0...
-Building package executables...
-Built foo:foo.
-Activated foo 1.0.0.''');
+ await runPub(args: ['global', 'activate', 'foo'], output: anything);
await runPub(args: ['global', 'activate', 'foo'], output: '''
Package foo is currently active at version 1.0.0.
Resolving dependencies...
The package foo is already activated at newest available version.
-To recompile executables, first run `global deactivate foo`.
+To recompile executables, first run `dart pub global deactivate foo`.
Activated foo 1.0.0.''');
var pub = await pubRun(global: true, args: ['foo']);
@@ -48,10 +39,9 @@
await runPub(args: ['global', 'activate', 'foo']);
- globalPackageServer
- .add((builder) => builder.serve('bar', '2.0.0', contents: [
- d.dir('lib', [d.file('bar.dart', 'final version = "2.0.0";')])
- ]));
+ server.serve('bar', '2.0.0', contents: [
+ d.dir('lib', [d.file('bar.dart', 'final version = "2.0.0";')])
+ ]);
await runPub(args: ['global', 'activate', 'foo'], output: '''
Package foo is currently active at version 1.0.0.
diff --git a/test/global/activate/activate_path_after_hosted_test.dart b/test/global/activate/activate_path_after_hosted_test.dart
index c73cb01..01d493d 100644
--- a/test/global/activate/activate_path_after_hosted_test.dart
+++ b/test/global/activate/activate_path_after_hosted_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
@@ -12,12 +10,11 @@
import '../../test_pub.dart';
void main() {
- test('activating a hosted package deactivates the path one', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
- ]);
- });
+ test('activating a path package deactivates the hosted one', () async {
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('foo.dart', "main(args) => print('hosted');")])
+ ]);
await d.dir('foo', [
d.libPubspec('foo', '2.0.0'),
diff --git a/test/global/activate/bad_version_test.dart b/test/global/activate/bad_version_test.dart
index 651c342..c5c4635 100644
--- a/test/global/activate/bad_version_test.dart
+++ b/test/global/activate/bad_version_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/global/activate/cached_package_test.dart b/test/global/activate/cached_package_test.dart
index 7ddcf10..98db402 100644
--- a/test/global/activate/cached_package_test.dart
+++ b/test/global/activate/cached_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
void main() {
test('can activate an already cached package', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('foo.dart', 'main() => print("hi"); ')])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('foo.dart', 'main() => print("hi"); ')])
+ ]);
await runPub(args: ['cache', 'add', 'foo']);
diff --git a/test/global/activate/constraint_test.dart b/test/global/activate/constraint_test.dart
index b712d00..23386c0 100644
--- a/test/global/activate/constraint_test.dart
+++ b/test/global/activate/constraint_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,12 +9,11 @@
void main() {
test('chooses the highest version that matches the constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '1.0.1');
- builder.serve('foo', '1.1.0');
- builder.serve('foo', '1.2.3');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '1.0.1')
+ ..serve('foo', '1.1.0')
+ ..serve('foo', '1.2.3');
await runPub(args: ['global', 'activate', 'foo', '<1.1.0']);
diff --git a/test/global/activate/constraint_with_path_test.dart b/test/global/activate/constraint_with_path_test.dart
index 1a5beb7..359cd60 100644
--- a/test/global/activate/constraint_with_path_test.dart
+++ b/test/global/activate/constraint_with_path_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/global/activate/custom_hosted_url_test.dart b/test/global/activate/custom_hosted_url_test.dart
index 7443887..8b2f0fc 100644
--- a/test/global/activate/custom_hosted_url_test.dart
+++ b/test/global/activate/custom_hosted_url_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../test_pub.dart';
@@ -11,22 +9,21 @@
void main() {
test('activating a package from a custom pub server', () async {
// The default pub server (i.e. pub.dartlang.org).
- await servePackages((builder) {
- builder.serve('baz', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('baz', '1.0.0');
// The custom pub server.
- final customServer = await PackageServer.start((builder) {
- Map<String, dynamic> hostedDep(String name, String constraint) => {
- 'hosted': {
- 'url': builder.serverUrl,
- 'name': name,
- },
- 'version': constraint,
- };
- builder.serve('foo', '1.0.0', deps: {'bar': hostedDep('bar', 'any')});
- builder.serve('bar', '1.0.0', deps: {'baz': 'any'});
- });
+ final customServer = await startPackageServer();
+ Map<String, dynamic> hostedDep(String name, String constraint) => {
+ 'hosted': {
+ 'url': customServer.url,
+ 'name': name,
+ },
+ 'version': constraint,
+ };
+
+ customServer.serve('foo', '1.0.0', deps: {'bar': hostedDep('bar', 'any')});
+ customServer.serve('bar', '1.0.0', deps: {'baz': 'any'});
await runPub(
args: ['global', 'activate', 'foo', '-u', customServer.url],
diff --git a/test/global/activate/different_version_test.dart b/test/global/activate/different_version_test.dart
index 61ba228..8406b92 100644
--- a/test/global/activate/different_version_test.dart
+++ b/test/global/activate/different_version_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -13,14 +11,13 @@
test(
"discards the previous active version if it doesn't match the "
'constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('foo.dart', 'main() => print("hi"); ')])
+ await servePackages()
+ ..serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('foo.dart', 'main() => print("hi");')])
+ ])
+ ..serve('foo', '2.0.0', contents: [
+ d.dir('bin', [d.file('foo.dart', 'main() => print("hi2");')])
]);
- builder.serve('foo', '2.0.0', contents: [
- d.dir('bin', [d.file('foo.dart', 'main() => print("hi2"); ')])
- ]);
- });
// Activate 1.0.0.
await runPub(args: ['global', 'activate', 'foo', '1.0.0']);
diff --git a/test/global/activate/doesnt_snapshot_path_executables_test.dart b/test/global/activate/doesnt_snapshot_path_executables_test.dart
index b809ea7..2ca8d3a 100644
--- a/test/global/activate/doesnt_snapshot_path_executables_test.dart
+++ b/test/global/activate/doesnt_snapshot_path_executables_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/global/activate/empty_constraint_test.dart b/test/global/activate/empty_constraint_test.dart
index 9e0bde9..d893bcd 100644
--- a/test/global/activate/empty_constraint_test.dart
+++ b/test/global/activate/empty_constraint_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -11,10 +9,9 @@
void main() {
test('errors if the constraint matches no versions', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '1.0.1');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '1.0.1');
await runPub(
args: ['global', 'activate', 'foo', '>1.1.0'],
diff --git a/test/global/activate/feature_test.dart b/test/global/activate/feature_test.dart
index 2d30460..58119d1 100644
--- a/test/global/activate/feature_test.dart
+++ b/test/global/activate/feature_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
@Skip()
import 'package:test/test.dart';
@@ -12,8 +10,8 @@
void main() {
test('enables default-on features by default', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'dependencies': {'bar': '1.0.0'}
@@ -23,11 +21,9 @@
'dependencies': {'baz': '1.0.0'}
}
}
- });
-
- builder.serve('bar', '1.0.0');
- builder.serve('baz', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0')
+ ..serve('baz', '1.0.0');
await runPub(args: ['global', 'activate', 'foo'], output: contains('''
Resolving dependencies...
@@ -37,8 +33,8 @@
});
test('can enable default-off features', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'dependencies': {'bar': '1.0.0'}
@@ -48,11 +44,9 @@
'dependencies': {'baz': '1.0.0'}
}
}
- });
-
- builder.serve('bar', '1.0.0');
- builder.serve('baz', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0')
+ ..serve('baz', '1.0.0');
await runPub(
args: ['global', 'activate', 'foo', '--features', 'things'],
@@ -65,8 +59,8 @@
});
test('can disable default-on features', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'dependencies': {'bar': '1.0.0'}
@@ -76,11 +70,9 @@
'dependencies': {'baz': '1.0.0'}
}
}
- });
-
- builder.serve('bar', '1.0.0');
- builder.serve('baz', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0')
+ ..serve('baz', '1.0.0');
await runPub(
args: ['global', 'activate', 'foo', '--omit-features', 'stuff'],
@@ -91,8 +83,8 @@
});
test('supports multiple arguments', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'default': false,
@@ -103,11 +95,9 @@
'dependencies': {'baz': '1.0.0'}
}
}
- });
-
- builder.serve('bar', '1.0.0');
- builder.serve('baz', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0')
+ ..serve('baz', '1.0.0');
await runPub(
args: ['global', 'activate', 'foo', '--features', 'things,stuff'],
@@ -120,8 +110,8 @@
});
test('can both enable and disable', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'dependencies': {'bar': '1.0.0'}
@@ -131,11 +121,9 @@
'dependencies': {'baz': '1.0.0'}
}
}
- });
-
- builder.serve('bar', '1.0.0');
- builder.serve('baz', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0')
+ ..serve('baz', '1.0.0');
await runPub(args: [
'global',
diff --git a/test/global/activate/git_package_test.dart b/test/global/activate/git_package_test.dart
index 43cd218..ee88de7 100644
--- a/test/global/activate/git_package_test.dart
+++ b/test/global/activate/git_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/global/activate/ignores_active_version_test.dart b/test/global/activate/ignores_active_version_test.dart
index d405f54..777a631 100644
--- a/test/global/activate/ignores_active_version_test.dart
+++ b/test/global/activate/ignores_active_version_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,15 +9,14 @@
void main() {
test('ignores previously activated version', () async {
- await servePackages((builder) {
- builder.serve(
+ await servePackages()
+ ..serve(
'foo',
'1.2.3',
- );
- builder.serve('foo', '1.3.0', contents: [
+ )
+ ..serve('foo', '1.3.0', contents: [
d.dir('bin', [d.file('foo.dart', 'main() => print("hi"); ')])
]);
- });
// Activate 1.2.3.
await runPub(args: ['global', 'activate', 'foo', '1.2.3']);
diff --git a/test/global/activate/installs_dependencies_for_git_test.dart b/test/global/activate/installs_dependencies_for_git_test.dart
index 8e5b477..6018f50 100644
--- a/test/global/activate/installs_dependencies_for_git_test.dart
+++ b/test/global/activate/installs_dependencies_for_git_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,10 +9,9 @@
void main() {
test('activating a Git package installs its dependencies', () async {
- await servePackages((builder) {
- builder.serve('bar', '1.0.0', deps: {'baz': 'any'});
- builder.serve('baz', '1.0.0');
- });
+ await servePackages()
+ ..serve('bar', '1.0.0', deps: {'baz': 'any'})
+ ..serve('baz', '1.0.0');
await d.git('foo.git', [
d.libPubspec('foo', '1.0.0', deps: {'bar': 'any'}),
diff --git a/test/global/activate/installs_dependencies_for_path_test.dart b/test/global/activate/installs_dependencies_for_path_test.dart
index 0afe76e..4688f07 100644
--- a/test/global/activate/installs_dependencies_for_path_test.dart
+++ b/test/global/activate/installs_dependencies_for_path_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,10 +9,9 @@
void main() {
test('activating a path package installs dependencies', () async {
- await servePackages((builder) {
- builder.serve('bar', '1.0.0', deps: {'baz': 'any'});
- builder.serve('baz', '2.0.0');
- });
+ await servePackages()
+ ..serve('bar', '1.0.0', deps: {'baz': 'any'})
+ ..serve('baz', '2.0.0');
await d.dir('foo', [
d.libPubspec('foo', '0.0.0', deps: {'bar': 'any'}),
diff --git a/test/global/activate/installs_dependencies_test.dart b/test/global/activate/installs_dependencies_test.dart
index 0b26d8b..770ebcf 100644
--- a/test/global/activate/installs_dependencies_test.dart
+++ b/test/global/activate/installs_dependencies_test.dart
@@ -2,19 +2,16 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../test_pub.dart';
void main() {
test('activating a package installs its dependencies', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': 'any'});
- builder.serve('bar', '1.0.0', deps: {'baz': 'any'});
- builder.serve('baz', '1.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': 'any'})
+ ..serve('bar', '1.0.0', deps: {'baz': 'any'})
+ ..serve('baz', '1.0.0');
await runPub(
args: ['global', 'activate', 'foo'],
diff --git a/test/global/activate/missing_git_repo_test.dart b/test/global/activate/missing_git_repo_test.dart
index bbb2345..8db65c3 100644
--- a/test/global/activate/missing_git_repo_test.dart
+++ b/test/global/activate/missing_git_repo_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/global/activate/missing_package_arg_test.dart b/test/global/activate/missing_package_arg_test.dart
index 5923bd9..588ffcf 100644
--- a/test/global/activate/missing_package_arg_test.dart
+++ b/test/global/activate/missing_package_arg_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -12,8 +10,9 @@
void main() {
test('fails if no package was given', () {
return runPub(
- args: ['global', 'activate'],
- error: contains('No package to activate given.'),
- exitCode: exit_codes.USAGE);
+ args: ['global', 'activate'],
+ error: contains('No package to activate given.'),
+ exitCode: exit_codes.USAGE,
+ );
});
}
diff --git a/test/global/activate/outdated_binstub_test.dart b/test/global/activate/outdated_binstub_test.dart
index 43bed90..6d9e298 100644
--- a/test/global/activate/outdated_binstub_test.dart
+++ b/test/global/activate/outdated_binstub_test.dart
@@ -2,14 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
import '../../test_pub.dart';
-const _OUTDATED_BINSTUB = '''
+const _outdatedBinstub = '''
#!/usr/bin/env sh
# This file was created by pub v0.1.2-3.
# Package: foo
@@ -21,19 +19,17 @@
void main() {
test('an outdated binstub is replaced', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'executables': {'foo-script': 'script'}
- }, contents: [
- d.dir(
- 'bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'executables': {'foo-script': 'script'}
+ }, contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
await d.dir(cachePath, [
- d.dir('bin', [d.file(binStubName('foo-script'), _OUTDATED_BINSTUB)])
+ d.dir('bin', [d.file(binStubName('foo-script'), _outdatedBinstub)])
]).create();
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/activate/path_package_test.dart b/test/global/activate/path_package_test.dart
index 5153760..514176a 100644
--- a/test/global/activate/path_package_test.dart
+++ b/test/global/activate/path_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
@@ -57,14 +55,13 @@
});
test("Doesn't precompile binaries when activating from path", () async {
- await servePackages(
- (builder) => builder.serve(
- 'bar',
- '1.0.0',
- contents: [
- d.dir('bin', [d.file('bar.dart', "main() => print('bar');")])
- ],
- ),
+ final server = await servePackages();
+ server.serve(
+ 'bar',
+ '1.0.0',
+ contents: [
+ d.dir('bin', [d.file('bar.dart', "main() => print('bar');")])
+ ],
);
await d.dir('foo', [
diff --git a/test/global/activate/reactivating_git_upgrades_test.dart b/test/global/activate/reactivating_git_upgrades_test.dart
index 0ccbb65..68102da 100644
--- a/test/global/activate/reactivating_git_upgrades_test.dart
+++ b/test/global/activate/reactivating_git_upgrades_test.dart
@@ -2,8 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
+import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -31,11 +30,12 @@
await d.git('foo.git', [d.libPubspec('foo', '1.0.1')]).commit();
// Activating it again pulls down the latest commit.
+ final locationUri = p.toUri(p.join(d.sandbox, 'foo.git'));
await runPub(
args: ['global', 'activate', '-sgit', '../foo.git'],
output: allOf(
startsWith('Package foo is currently active from Git repository '
- '"../foo.git".\n'
+ '"$locationUri".\n'
'Resolving dependencies...\n'
'+ foo 1.0.1 from git ../foo.git at '),
// Specific revision number goes here.
diff --git a/test/global/activate/removes_old_lockfile_test.dart b/test/global/activate/removes_old_lockfile_test.dart
deleted file mode 100644
index 7d7a9e0..0000000
--- a/test/global/activate/removes_old_lockfile_test.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-void main() {
- test('removes the 1.6-style lockfile', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- });
-
- await d.dir(cachePath, [
- d.dir('global_packages', [
- d.file(
- 'foo.lock',
- 'packages: {foo: {description: foo, source: hosted, '
- 'version: "1.0.0"}}}')
- ])
- ]).create();
-
- await runPub(args: ['global', 'activate', 'foo']);
-
- await d.dir(cachePath, [
- d.dir('global_packages', [
- d.nothing('foo.lock'),
- d.dir('foo', [d.file('pubspec.lock', contains('1.0.0'))])
- ])
- ]).validate();
- });
-}
diff --git a/test/global/activate/snapshots_git_executables_test.dart b/test/global/activate/snapshots_git_executables_test.dart
index 81a0152..aee6a71 100644
--- a/test/global/activate/snapshots_git_executables_test.dart
+++ b/test/global/activate/snapshots_git_executables_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/global/activate/snapshots_hosted_executables_test.dart b/test/global/activate/snapshots_hosted_executables_test.dart
index e9d2a2d..bc2b332 100644
--- a/test/global/activate/snapshots_hosted_executables_test.dart
+++ b/test/global/activate/snapshots_hosted_executables_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,16 +9,15 @@
void main() {
test('snapshots the executables for a hosted package', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [
- d.file('hello.dart', "void main() => print('hello!');"),
- d.file('goodbye.dart', "void main() => print('goodbye!');"),
- d.file('shell.sh', 'echo shell'),
- d.dir('subdir', [d.file('sub.dart', "void main() => print('sub!');")])
- ])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [
+ d.file('hello.dart', "void main() => print('hello!');"),
+ d.file('goodbye.dart', "void main() => print('goodbye!');"),
+ d.file('shell.sh', 'echo shell'),
+ d.dir('subdir', [d.file('sub.dart', "void main() => print('sub!');")])
+ ])
+ ]);
await runPub(
args: ['global', 'activate', 'foo'],
diff --git a/test/global/activate/supports_version_solver_backtracking_test.dart b/test/global/activate/supports_version_solver_backtracking_test.dart
index e43e735..c8c138d 100644
--- a/test/global/activate/supports_version_solver_backtracking_test.dart
+++ b/test/global/activate/supports_version_solver_backtracking_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,14 +9,13 @@
void main() {
test('performs verison solver backtracking if necessary', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.1.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.1.0', pubspec: {
'environment': {'sdk': '>=0.1.2 <0.2.0'}
- });
- builder.serve('foo', '1.2.0', pubspec: {
+ })
+ ..serve('foo', '1.2.0', pubspec: {
'environment': {'sdk': '>=0.1.3 <0.2.0'}
});
- });
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/activate/uncached_package_test.dart b/test/global/activate/uncached_package_test.dart
index 3bdb185..1a18d70 100644
--- a/test/global/activate/uncached_package_test.dart
+++ b/test/global/activate/uncached_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,17 +9,16 @@
void main() {
test('installs and activates the best version of a package', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('foo.dart', 'main() => print("hi"); ')])
+ await servePackages()
+ ..serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('foo.dart', 'main() => print("hi");')])
+ ])
+ ..serve('foo', '1.2.3', contents: [
+ d.dir('bin', [d.file('foo.dart', 'main() => print("hi 1.2.3");')])
+ ])
+ ..serve('foo', '2.0.0-wildly.unstable', contents: [
+ d.dir('bin', [d.file('foo.dart', 'main() => print("hi unstable");')])
]);
- builder.serve('foo', '1.2.3', contents: [
- d.dir('bin', [d.file('foo.dart', 'main() => print("hi 1.2.3"); ')])
- ]);
- builder.serve('foo', '2.0.0-wildly.unstable', contents: [
- d.dir('bin', [d.file('foo.dart', 'main() => print("hi unstable"); ')])
- ]);
- });
await runPub(args: ['global', 'activate', 'foo'], output: '''
Resolving dependencies...
diff --git a/test/global/activate/unexpected_arguments_test.dart b/test/global/activate/unexpected_arguments_test.dart
index d7bb4cf..be6633d 100644
--- a/test/global/activate/unexpected_arguments_test.dart
+++ b/test/global/activate/unexpected_arguments_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/global/activate/unknown_package_test.dart b/test/global/activate/unknown_package_test.dart
index 6a4fe84..271545d 100644
--- a/test/global/activate/unknown_package_test.dart
+++ b/test/global/activate/unknown_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -11,7 +9,7 @@
void main() {
test('errors if the package could not be found', () async {
- await serveNoPackages();
+ await servePackages();
await runPub(
args: ['global', 'activate', 'foo'],
diff --git a/test/global/binstubs/binstub_runs_executable_test.dart b/test/global/binstubs/binstub_runs_executable_test.dart
index 284729b..98ab53b 100644
--- a/test/global/binstubs/binstub_runs_executable_test.dart
+++ b/test/global/binstubs/binstub_runs_executable_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import 'package:test_process/test_process.dart';
@@ -14,14 +12,12 @@
void main() {
test('the generated binstub runs a snapshotted executable', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'executables': {'foo-script': 'script'}
- }, contents: [
- d.dir(
- 'bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'executables': {'foo-script': 'script'}
+ }, contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/binstubs/binstub_runs_global_run_if_no_snapshot_test.dart b/test/global/binstubs/binstub_runs_global_run_if_no_snapshot_test.dart
index 25a6281..8024c3a 100644
--- a/test/global/binstubs/binstub_runs_global_run_if_no_snapshot_test.dart
+++ b/test/global/binstubs/binstub_runs_global_run_if_no_snapshot_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/binstub_runs_precompiled_snapshot_test.dart b/test/global/binstubs/binstub_runs_precompiled_snapshot_test.dart
index f59d8e2..cd477db 100644
--- a/test/global/binstubs/binstub_runs_precompiled_snapshot_test.dart
+++ b/test/global/binstubs/binstub_runs_precompiled_snapshot_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,13 +9,12 @@
void main() {
test('the binstubs runs a built snapshot if present', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'executables': {'foo-script': 'script'}
- }, contents: [
- d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'executables': {'foo-script': 'script'}
+ }, contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/binstubs/creates_executables_in_pubspec_test.dart b/test/global/binstubs/creates_executables_in_pubspec_test.dart
index 1529d3e..a6604ab 100644
--- a/test/global/binstubs/creates_executables_in_pubspec_test.dart
+++ b/test/global/binstubs/creates_executables_in_pubspec_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,17 +9,16 @@
void main() {
test('creates binstubs for each executable in the pubspec', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'executables': {'one': null, 'two-renamed': 'second'}
- }, contents: [
- d.dir('bin', [
- d.file('one.dart', "main(args) => print('one');"),
- d.file('second.dart', "main(args) => print('two');"),
- d.file('nope.dart', "main(args) => print('nope');")
- ])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'executables': {'one': null, 'two-renamed': 'second'}
+ }, contents: [
+ d.dir('bin', [
+ d.file('one.dart', "main(args) => print('one');"),
+ d.file('second.dart', "main(args) => print('two');"),
+ d.file('nope.dart', "main(args) => print('nope');")
+ ])
+ ]);
await runPub(
args: ['global', 'activate', 'foo'],
diff --git a/test/global/binstubs/does_not_warn_if_no_executables_test.dart b/test/global/binstubs/does_not_warn_if_no_executables_test.dart
index e172b1b..9814f15 100644
--- a/test/global/binstubs/does_not_warn_if_no_executables_test.dart
+++ b/test/global/binstubs/does_not_warn_if_no_executables_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,12 +9,10 @@
void main() {
test('does not warn if the package has no executables', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir(
- 'bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
+ ]);
await runPub(
args: ['global', 'activate', 'foo'],
diff --git a/test/global/binstubs/does_not_warn_if_on_path_test.dart b/test/global/binstubs/does_not_warn_if_on_path_test.dart
index 07cba16..9b11386 100644
--- a/test/global/binstubs/does_not_warn_if_on_path_test.dart
+++ b/test/global/binstubs/does_not_warn_if_on_path_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
import 'package:path/path.dart' as p;
@@ -14,14 +12,12 @@
void main() {
test('does not warn if the binstub directory is on the path', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'executables': {'script': null}
- }, contents: [
- d.dir(
- 'bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'executables': {'script': null}
+ }, contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
+ ]);
// Add the test's cache bin directory to the path.
var binDir = p.dirname(Platform.executable);
diff --git a/test/global/binstubs/explicit_and_no_executables_options_test.dart b/test/global/binstubs/explicit_and_no_executables_options_test.dart
index d493bd7..68bbd5b 100644
--- a/test/global/binstubs/explicit_and_no_executables_options_test.dart
+++ b/test/global/binstubs/explicit_and_no_executables_options_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/global/binstubs/explicit_executables_test.dart b/test/global/binstubs/explicit_executables_test.dart
index e032c32..e721f73 100644
--- a/test/global/binstubs/explicit_executables_test.dart
+++ b/test/global/binstubs/explicit_executables_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/missing_script_test.dart b/test/global/binstubs/missing_script_test.dart
index 96b5e89..433f9cf 100644
--- a/test/global/binstubs/missing_script_test.dart
+++ b/test/global/binstubs/missing_script_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
diff --git a/test/global/binstubs/name_collision_test.dart b/test/global/binstubs/name_collision_test.dart
index 54afc02..75b72ce 100644
--- a/test/global/binstubs/name_collision_test.dart
+++ b/test/global/binstubs/name_collision_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/name_collision_with_overwrite_test.dart b/test/global/binstubs/name_collision_with_overwrite_test.dart
index caed6d1..6e5a869 100644
--- a/test/global/binstubs/name_collision_with_overwrite_test.dart
+++ b/test/global/binstubs/name_collision_with_overwrite_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/no_executables_flag_test.dart b/test/global/binstubs/no_executables_flag_test.dart
index d7bc037..39f91cd 100644
--- a/test/global/binstubs/no_executables_flag_test.dart
+++ b/test/global/binstubs/no_executables_flag_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/outdated_binstub_runs_pub_global_test.dart b/test/global/binstubs/outdated_binstub_runs_pub_global_test.dart
index f4cd075..442dfbc 100644
--- a/test/global/binstubs/outdated_binstub_runs_pub_global_test.dart
+++ b/test/global/binstubs/outdated_binstub_runs_pub_global_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
import 'package:path/path.dart' as p;
@@ -15,7 +13,7 @@
import 'utils.dart';
/// The contents of the binstub for [executable], or `null` if it doesn't exist.
-String binStub(String executable) {
+String? binStub(String executable) {
final f = File(p.join(d.sandbox, cachePath, 'bin', binStubName(executable)));
if (f.existsSync()) {
return f.readAsStringSync();
@@ -26,23 +24,22 @@
void main() {
test("an outdated binstub runs 'pub global run', which replaces old binstub",
() async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'executables': {
- 'foo-script': 'script',
- 'foo-script2': 'script',
- 'foo-script-not-installed': 'script',
- 'foo-another-script': 'another-script',
- 'foo-another-script-not-installed': 'another-script'
- }
- }, contents: [
- d.dir('bin', [
- d.file('script.dart', r"main(args) => print('ok $args');"),
- d.file('another-script.dart',
- r"main(args) => print('not so good $args');")
- ])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'executables': {
+ 'foo-script': 'script',
+ 'foo-script2': 'script',
+ 'foo-script-not-installed': 'script',
+ 'foo-another-script': 'another-script',
+ 'foo-another-script-not-installed': 'another-script'
+ }
+ }, contents: [
+ d.dir('bin', [
+ d.file('script.dart', r"main(args) => print('ok $args');"),
+ d.file(
+ 'another-script.dart', r"main(args) => print('not so good $args');")
+ ])
+ ]);
await runPub(args: [
'global',
diff --git a/test/global/binstubs/outdated_snapshot_test.dart b/test/global/binstubs/outdated_snapshot_test.dart
index c1181b9..91bfff6 100644
--- a/test/global/binstubs/outdated_snapshot_test.dart
+++ b/test/global/binstubs/outdated_snapshot_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
@@ -15,14 +13,12 @@
void main() {
test("a binstub runs 'pub global run' for an outdated snapshot", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'executables': {'foo-script': 'script'}
- }, contents: [
- d.dir(
- 'bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'executables': {'foo-script': 'script'}
+ }, contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/binstubs/path_package_test.dart b/test/global/binstubs/path_package_test.dart
index d702054..0461e35 100644
--- a/test/global/binstubs/path_package_test.dart
+++ b/test/global/binstubs/path_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/reactivate_removes_old_executables_test.dart b/test/global/binstubs/reactivate_removes_old_executables_test.dart
index e7f6ade..80b50ff 100644
--- a/test/global/binstubs/reactivate_removes_old_executables_test.dart
+++ b/test/global/binstubs/reactivate_removes_old_executables_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/removes_even_if_not_in_pubspec_test.dart b/test/global/binstubs/removes_even_if_not_in_pubspec_test.dart
index ed215ae..4cd458e 100644
--- a/test/global/binstubs/removes_even_if_not_in_pubspec_test.dart
+++ b/test/global/binstubs/removes_even_if_not_in_pubspec_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/global/binstubs/removes_when_deactivated_test.dart b/test/global/binstubs/removes_when_deactivated_test.dart
index d241f27..975defe 100644
--- a/test/global/binstubs/removes_when_deactivated_test.dart
+++ b/test/global/binstubs/removes_when_deactivated_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,16 +9,15 @@
void main() {
test('removes binstubs when the package is deactivated', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'executables': {'one': null, 'two': null}
- }, contents: [
- d.dir('bin', [
- d.file('one.dart', "main(args) => print('one');"),
- d.file('two.dart', "main(args) => print('two');")
- ])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'executables': {'one': null, 'two': null}
+ }, contents: [
+ d.dir('bin', [
+ d.file('one.dart', "main(args) => print('one');"),
+ d.file('two.dart', "main(args) => print('two');")
+ ])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
await runPub(args: ['global', 'deactivate', 'foo']);
diff --git a/test/global/binstubs/runs_once_even_when_dart_is_batch_test.dart b/test/global/binstubs/runs_once_even_when_dart_is_batch_test.dart
index d53af96..99eeaaf 100644
--- a/test/global/binstubs/runs_once_even_when_dart_is_batch_test.dart
+++ b/test/global/binstubs/runs_once_even_when_dart_is_batch_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
import 'package:path/path.dart' as p;
@@ -16,18 +14,17 @@
test(
'runs only once even when dart on path is a batch file (as in flutter/bin)',
() async {
- await servePackages((builder) {
- builder.serve(
- 'foo',
- '1.0.0',
- contents: [
- d.dir('bin', [d.file('script.dart', 'main(args) => print(args);')]),
- ],
- pubspec: {
- 'executables': {'script': 'script'},
- },
- );
- });
+ final server = await servePackages();
+ server.serve(
+ 'foo',
+ '1.0.0',
+ contents: [
+ d.dir('bin', [d.file('script.dart', 'main(args) => print(args);')]),
+ ],
+ pubspec: {
+ 'executables': {'script': 'script'},
+ },
+ );
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/binstubs/unknown_explicit_executable_test.dart b/test/global/binstubs/unknown_explicit_executable_test.dart
index 0b27527..33b82e7 100644
--- a/test/global/binstubs/unknown_explicit_executable_test.dart
+++ b/test/global/binstubs/unknown_explicit_executable_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/global/binstubs/utils.dart b/test/global/binstubs/utils.dart
index e2346cc..59a8df0 100644
--- a/test/global/binstubs/utils.dart
+++ b/test/global/binstubs/utils.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
import 'package:path/path.dart' as p;
@@ -16,7 +14,7 @@
///
/// The `pub`/`pub.bat` command on the PATH will be the one in tool/test-bin not
/// the one from the sdk.
-Map getEnvironment() {
+Map<String, String> getEnvironment() {
var binDir = p.dirname(Platform.resolvedExecutable);
var separator = Platform.isWindows ? ';' : ':';
var pubBin = p.absolute('tool', 'test-bin');
diff --git a/test/global/binstubs/warns_if_not_on_path_test.dart b/test/global/binstubs/warns_if_not_on_path_test.dart
index fcfdb0c..d98bf76 100644
--- a/test/global/binstubs/warns_if_not_on_path_test.dart
+++ b/test/global/binstubs/warns_if_not_on_path_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,14 +9,12 @@
void main() {
test('warns if the binstub directory is not on the path', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'executables': {'some-dart-script': 'script'}
- }, contents: [
- d.dir(
- 'bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'executables': {'some-dart-script': 'script'}
+ }, contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('ok \$args');")])
+ ]);
await runPub(
args: ['global', 'activate', 'foo'],
diff --git a/test/global/deactivate/deactivate_and_reactivate_package_test.dart b/test/global/deactivate/deactivate_and_reactivate_package_test.dart
index ffad990..da33486 100644
--- a/test/global/deactivate/deactivate_and_reactivate_package_test.dart
+++ b/test/global/deactivate/deactivate_and_reactivate_package_test.dart
@@ -2,18 +2,15 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../test_pub.dart';
void main() {
test('activates a different version after deactivating', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0');
// Activate an old version.
await runPub(args: ['global', 'activate', 'foo', '1.0.0']);
diff --git a/test/global/deactivate/git_package_test.dart b/test/global/deactivate/git_package_test.dart
index 3aa047d..7fc2855 100644
--- a/test/global/deactivate/git_package_test.dart
+++ b/test/global/deactivate/git_package_test.dart
@@ -2,8 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
+import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -20,9 +19,10 @@
await runPub(args: ['global', 'activate', '-sgit', '../foo.git']);
+ final locationUri = p.toUri(p.join(d.sandbox, 'foo.git'));
await runPub(
args: ['global', 'deactivate', 'foo'],
output:
- 'Deactivated package foo 1.0.0 from Git repository "../foo.git".');
+ 'Deactivated package foo 1.0.0 from Git repository "$locationUri".');
});
}
diff --git a/test/global/deactivate/hosted_package_test.dart b/test/global/deactivate/hosted_package_test.dart
index 884e70f..fa91829 100644
--- a/test/global/deactivate/hosted_package_test.dart
+++ b/test/global/deactivate/hosted_package_test.dart
@@ -2,15 +2,14 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../test_pub.dart';
void main() {
test('deactivates an active hosted package', () async {
- await servePackages((builder) => builder.serve('foo', '1.0.0'));
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/deactivate/missing_package_arg_test.dart b/test/global/deactivate/missing_package_arg_test.dart
index 7d41b82..8de8ab1 100644
--- a/test/global/deactivate/missing_package_arg_test.dart
+++ b/test/global/deactivate/missing_package_arg_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -11,13 +9,10 @@
void main() {
test('fails if no package was given', () {
- return runPub(args: ['global', 'deactivate'], error: '''
- No package to deactivate given.
-
- Usage: pub global deactivate <package>
- -h, --help Print this usage information.
-
- Run "pub help" to see global options.
- ''', exitCode: exit_codes.USAGE);
+ return runPub(
+ args: ['global', 'deactivate'],
+ error: contains('No package to deactivate given.'),
+ exitCode: exit_codes.USAGE,
+ );
});
}
diff --git a/test/global/deactivate/path_package_test.dart b/test/global/deactivate/path_package_test.dart
index f28d8d1..1f50713 100644
--- a/test/global/deactivate/path_package_test.dart
+++ b/test/global/deactivate/path_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
diff --git a/test/global/deactivate/removes_precompiled_snapshots_test.dart b/test/global/deactivate/removes_precompiled_snapshots_test.dart
index 7d075b3..a7670e2 100644
--- a/test/global/deactivate/removes_precompiled_snapshots_test.dart
+++ b/test/global/deactivate/removes_precompiled_snapshots_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,7 +9,8 @@
void main() {
test('removes built snapshots', () async {
- await servePackages((builder) => builder.serve('foo', '1.0.0'));
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/deactivate/unexpected_arguments_test.dart b/test/global/deactivate/unexpected_arguments_test.dart
index d5748f2..dd1f11f 100644
--- a/test/global/deactivate/unexpected_arguments_test.dart
+++ b/test/global/deactivate/unexpected_arguments_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -12,13 +10,9 @@
void main() {
test('fails if there are extra arguments', () {
return runPub(
- args: ['global', 'deactivate', 'foo', 'bar', 'baz'], error: '''
- Unexpected arguments "bar" and "baz".
-
- Usage: pub global deactivate <package>
- -h, --help Print this usage information.
-
- Run "pub help" to see global options.
- ''', exitCode: exit_codes.USAGE);
+ args: ['global', 'deactivate', 'foo', 'bar', 'baz'],
+ error: contains('Unexpected arguments "bar" and "baz".'),
+ exitCode: exit_codes.USAGE,
+ );
});
}
diff --git a/test/global/deactivate/unknown_package_test.dart b/test/global/deactivate/unknown_package_test.dart
index ad0973e..35023ad 100644
--- a/test/global/deactivate/unknown_package_test.dart
+++ b/test/global/deactivate/unknown_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -11,7 +9,7 @@
void main() {
test('errors if the package is not activated', () async {
- await serveNoPackages();
+ await servePackages();
await runPub(
args: ['global', 'deactivate', 'foo'],
diff --git a/test/global/list_test.dart b/test/global/list_test.dart
index 8b7293a..00ca22c 100644
--- a/test/global/list_test.dart
+++ b/test/global/list_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
@@ -14,9 +12,8 @@
void main() {
test('lists an activated hosted package', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await runPub(args: ['global', 'activate', 'foo']);
@@ -33,9 +30,10 @@
await runPub(args: ['global', 'activate', '-sgit', '../foo.git']);
+ final locationUri = p.toUri(p.join(d.sandbox, 'foo.git'));
await runPub(
args: ['global', 'list'],
- output: 'foo 1.0.0 from Git repository "../foo.git"');
+ output: 'foo 1.0.0 from Git repository "$locationUri"');
});
test('lists an activated Path package', () async {
@@ -51,11 +49,10 @@
});
test('lists activated packages in alphabetical order', () async {
- await servePackages((builder) {
- builder.serve('aaa', '1.0.0');
- builder.serve('bbb', '1.0.0');
- builder.serve('ccc', '1.0.0');
- });
+ await servePackages()
+ ..serve('aaa', '1.0.0')
+ ..serve('bbb', '1.0.0')
+ ..serve('ccc', '1.0.0');
await runPub(args: ['global', 'activate', 'ccc']);
await runPub(args: ['global', 'activate', 'aaa']);
diff --git a/test/global/run/errors_if_outside_bin_test.dart b/test/global/run/errors_if_outside_bin_test.dart
index 497f26a..72bcd4f 100644
--- a/test/global/run/errors_if_outside_bin_test.dart
+++ b/test/global/run/errors_if_outside_bin_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -12,27 +10,17 @@
void main() {
test('errors if the script is in a subdirectory.', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('example', [d.file('script.dart', "main(args) => print('ok');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('example', [d.file('script.dart', "main(args) => print('ok');")])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
- await runPub(args: ['global', 'run', 'foo:example/script'], error: '''
-Cannot run an executable in a subdirectory of a global package.
-
-Usage: pub global run <package>:<executable> [args...]
--h, --help Print this usage information.
- --[no-]enable-asserts Enable assert statements.
- --enable-experiment=<experiment> Runs the executable in a VM with the
- given experiments enabled. (Will disable
- snapshotting, resulting in slower
- startup).
- --[no-]sound-null-safety Override the default null safety
- execution mode.
-
-Run "pub help" to see global options.
-''', exitCode: exit_codes.USAGE);
+ await runPub(
+ args: ['global', 'run', 'foo:example/script'],
+ error: contains(
+ 'Cannot run an executable in a subdirectory of a global package.'),
+ exitCode: exit_codes.USAGE,
+ );
});
}
diff --git a/test/global/run/fails_if_sdk_constraint_is_unmet_test.dart b/test/global/run/fails_if_sdk_constraint_is_unmet_test.dart
index 73b5556..3bef340 100644
--- a/test/global/run/fails_if_sdk_constraint_is_unmet_test.dart
+++ b/test/global/run/fails_if_sdk_constraint_is_unmet_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -12,11 +10,10 @@
void main() {
test("fails if the current SDK doesn't match the constraint", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
@@ -43,15 +40,14 @@
});
test('fails if SDK is downgraded below the constraints', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'environment': {
- 'sdk': '>=2.0.0 <3.0.0',
- },
- }, contents: [
- d.dir('bin', [d.file('script.dart', "main(args) => print('123-OK');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'environment': {
+ 'sdk': '>=2.0.0 <3.0.0',
+ },
+ }, contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('123-OK');")])
+ ]);
await runPub(
environment: {'_PUB_TEST_SDK_VERSION': '2.0.0'},
@@ -71,8 +67,8 @@
});
test('fails if SDK is downgraded below dependency SDK constraints', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {
'bar': '^1.0.0',
}, pubspec: {
'environment': {
@@ -80,13 +76,12 @@
},
}, contents: [
d.dir('bin', [d.file('script.dart', "main(args) => print('123-OK');")])
- ]);
- builder.serve('bar', '1.0.0', pubspec: {
+ ])
+ ..serve('bar', '1.0.0', pubspec: {
'environment': {
'sdk': '>=2.2.0 <3.0.0',
},
});
- });
await runPub(
environment: {'_PUB_TEST_SDK_VERSION': '2.2.0'},
diff --git a/test/global/run/implicit_executable_name_test.dart b/test/global/run/implicit_executable_name_test.dart
index a2f8c12..9757772 100644
--- a/test/global/run/implicit_executable_name_test.dart
+++ b/test/global/run/implicit_executable_name_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
void main() {
test('defaults to the package name if the script is omitted', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('foo.dart', "main(args) => print('foo');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('foo.dart', "main(args) => print('foo');")])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/run/missing_executable_arg_test.dart b/test/global/run/missing_executable_arg_test.dart
index 2bb8ec8..b64d387 100644
--- a/test/global/run/missing_executable_arg_test.dart
+++ b/test/global/run/missing_executable_arg_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -11,20 +9,10 @@
void main() {
test('fails if no executable was given', () {
- return runPub(args: ['global', 'run'], error: '''
-Must specify an executable to run.
-
-Usage: pub global run <package>:<executable> [args...]
--h, --help Print this usage information.
- --[no-]enable-asserts Enable assert statements.
- --enable-experiment=<experiment> Runs the executable in a VM with the
- given experiments enabled. (Will disable
- snapshotting, resulting in slower
- startup).
- --[no-]sound-null-safety Override the default null safety
- execution mode.
-
-Run "pub help" to see global options.
-''', exitCode: exit_codes.USAGE);
+ return runPub(
+ args: ['global', 'run'],
+ error: contains('Must specify an executable to run.'),
+ exitCode: exit_codes.USAGE,
+ );
});
}
diff --git a/test/global/run/missing_path_package_test.dart b/test/global/run/missing_path_package_test.dart
index f15d976..99cf30a 100644
--- a/test/global/run/missing_path_package_test.dart
+++ b/test/global/run/missing_path_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/io.dart';
diff --git a/test/global/run/nonexistent_script_test.dart b/test/global/run/nonexistent_script_test.dart
index dc0a738..8ff0a42 100644
--- a/test/global/run/nonexistent_script_test.dart
+++ b/test/global/run/nonexistent_script_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -12,9 +10,10 @@
void main() {
test('errors if the script does not exist.', () async {
- await servePackages((builder) => builder.serve('foo', '1.0.0', pubspec: {
- 'dev_dependencies': {'bar': '1.0.0'}
- }));
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'dev_dependencies': {'bar': '1.0.0'}
+ });
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/run/package_api_test.dart b/test/global/run/package_api_test.dart
index c95fc5b..5db401b 100644
--- a/test/global/run/package_api_test.dart
+++ b/test/global/run/package_api_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
@@ -12,10 +10,9 @@
void main() {
test('an immutable application sees a file: package config', () async {
- await servePackages((builder) {
- builder.serve('bar', '1.0.0');
-
- builder.serve('foo', '1.0.0', deps: {
+ await servePackages()
+ ..serve('bar', '1.0.0')
+ ..serve('foo', '1.0.0', deps: {
'bar': '1.0.0'
}, contents: [
d.dir('bin', [
@@ -33,7 +30,6 @@
""")
])
]);
- });
await runPub(args: ['global', 'activate', 'foo']);
@@ -45,12 +41,12 @@
'global_packages/foo/.dart_tool/package_config.json');
expect(pub.stdout, emits(p.toUri(packageConfigPath).toString()));
- var fooResourcePath = p.join(
- globalPackageServer.pathInCache('foo', '1.0.0'), 'lib/resource.txt');
+ var fooResourcePath =
+ p.join(globalServer.pathInCache('foo', '1.0.0'), 'lib/resource.txt');
expect(pub.stdout, emits(p.toUri(fooResourcePath).toString()));
- var barResourcePath = p.join(
- globalPackageServer.pathInCache('bar', '1.0.0'), 'lib/resource.txt');
+ var barResourcePath =
+ p.join(globalServer.pathInCache('bar', '1.0.0'), 'lib/resource.txt');
expect(pub.stdout, emits(p.toUri(barResourcePath).toString()));
await pub.shouldExit(0);
});
diff --git a/test/global/run/recompiles_if_snapshot_is_out_of_date_test.dart b/test/global/run/recompiles_if_snapshot_is_out_of_date_test.dart
index 4ace362..24e65bf 100644
--- a/test/global/run/recompiles_if_snapshot_is_out_of_date_test.dart
+++ b/test/global/run/recompiles_if_snapshot_is_out_of_date_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
@@ -13,11 +11,10 @@
void main() {
test('recompiles a script if the snapshot is out-of-date', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/run/reflects_changes_to_local_package_test.dart b/test/global/run/reflects_changes_to_local_package_test.dart
index 5bc9e55..864111b 100644
--- a/test/global/run/reflects_changes_to_local_package_test.dart
+++ b/test/global/run/reflects_changes_to_local_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/global/run/runs_git_script_test.dart b/test/global/run/runs_git_script_test.dart
index 8d120b4..900b586 100644
--- a/test/global/run/runs_git_script_test.dart
+++ b/test/global/run/runs_git_script_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/global/run/runs_path_script_test.dart b/test/global/run/runs_path_script_test.dart
index 90db648..7cc90d4 100644
--- a/test/global/run/runs_path_script_test.dart
+++ b/test/global/run/runs_path_script_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/global/run/runs_script_in_checked_mode_test.dart b/test/global/run/runs_script_in_checked_mode_test.dart
index 1b399c5..d0511cf 100644
--- a/test/global/run/runs_script_in_checked_mode_test.dart
+++ b/test/global/run/runs_script_in_checked_mode_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
void main() {
test('runs a script with assertions enabled', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('script.dart', 'main() { assert(false); }')])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('script.dart', 'main() { assert(false); }')])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/run/runs_script_in_unchecked_mode_test.dart b/test/global/run/runs_script_in_unchecked_mode_test.dart
index 005bad3..ca752b2 100644
--- a/test/global/run/runs_script_in_unchecked_mode_test.dart
+++ b/test/global/run/runs_script_in_unchecked_mode_test.dart
@@ -2,14 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
import '../../test_pub.dart';
-const SCRIPT = '''
+const _script = '''
main() {
assert(false);
print("no checks");
@@ -18,11 +16,10 @@
void main() {
test('runs a script in unchecked mode by default', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('script.dart', SCRIPT)])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('script.dart', _script)])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/run/runs_script_test.dart b/test/global/run/runs_script_test.dart
index bab4d1c..f3f0e99 100644
--- a/test/global/run/runs_script_test.dart
+++ b/test/global/run/runs_script_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,11 +9,10 @@
void main() {
test('runs a script in an activated package', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/run/runs_script_without_packages_file_test.dart b/test/global/run/runs_script_without_packages_file_test.dart
index aa5e691..dc225ba 100644
--- a/test/global/run/runs_script_without_packages_file_test.dart
+++ b/test/global/run/runs_script_without_packages_file_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
@@ -14,11 +12,10 @@
void main() {
test('runs a snapshotted script without a .dart_tool/package_config file',
() async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")])
+ ]);
await runPub(args: ['global', 'activate', 'foo']);
diff --git a/test/global/run/unknown_package_test.dart b/test/global/run/unknown_package_test.dart
index 55a875a..adcb666 100644
--- a/test/global/run/unknown_package_test.dart
+++ b/test/global/run/unknown_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -11,7 +9,7 @@
void main() {
test('errors if the package is not activated', () async {
- await serveNoPackages();
+ await servePackages();
await runPub(
args: ['global', 'run', 'foo:bar'],
diff --git a/test/global/run/uses_old_lockfile_test.dart b/test/global/run/uses_old_lockfile_test.dart
deleted file mode 100644
index 4ae12ef..0000000
--- a/test/global/run/uses_old_lockfile_test.dart
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-void main() {
- test('uses the 1.6-style lockfile if necessary', () async {
- await servePackages((builder) {
- builder.serve('bar', '1.0.0');
- builder.serve('foo', '1.0.0', deps: {
- 'bar': 'any'
- }, contents: [
- d.dir('bin', [
- d.file('script.dart', """
- import 'package:bar/bar.dart' as bar;
-
- main(args) => print(bar.main());""")
- ])
- ]);
- });
-
- await runPub(args: ['cache', 'add', 'foo']);
- await runPub(args: ['cache', 'add', 'bar']);
-
- await d.dir(cachePath, [
- d.dir('global_packages', [
- d.file('foo.lock', '''
-packages:
- foo:
- description: foo
- source: hosted
- version: "1.0.0"
- bar:
- description: bar
- source: hosted
- version: "1.0.0"''')
- ])
- ]).create();
-
- var pub = await pubRun(global: true, args: ['foo:script']);
- expect(pub.stdout, emitsThrough('bar 1.0.0'));
- await pub.shouldExit();
-
- await d.dir(cachePath, [
- d.dir('global_packages', [
- d.nothing('foo.lock'),
- d.dir('foo', [d.file('pubspec.lock', contains('1.0.0'))])
- ])
- ]).validate();
- });
-}
diff --git a/test/golden_file.dart b/test/golden_file.dart
index 055c5c5..7927776 100644
--- a/test/golden_file.dart
+++ b/test/golden_file.dart
@@ -2,35 +2,210 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
+import 'dart:async';
import 'dart:io';
-import 'package:path/path.dart' as path;
+import 'package:path/path.dart' as p;
+import 'package:pub/src/ascii_tree.dart' as ascii_tree;
+import 'package:pub/src/io.dart';
+import 'package:stack_trace/stack_trace.dart' show Trace;
import 'package:test/test.dart';
-/// Will test [actual] against the contests of the file at [goldenFilePath].
-///
-/// If the file doesn't exist, the file is instead created containing [actual].
-void expectMatchesGoldenFile(String actual, String goldenFilePath) {
- var goldenFile = File(goldenFilePath);
- if (goldenFile.existsSync()) {
- expect(
- actual, equals(goldenFile.readAsStringSync().replaceAll('\r\n', '\n')),
- reason: 'goldenFilePath: "$goldenFilePath"');
- } else {
- // This enables writing the updated file when run in otherwise hermetic
- // settings.
- //
- // This is to make updating the golden files easier in a bazel environment
- // See https://docs.bazel.build/versions/2.0.0/user-manual.html#run .
- final workspaceDirectory =
- Platform.environment['BUILD_WORKSPACE_DIRECTORY'];
- if (workspaceDirectory != null) {
- goldenFile = File(path.join(workspaceDirectory, goldenFilePath));
- }
- goldenFile
- ..createSync(recursive: true)
- ..writeAsStringSync(actual);
+import 'ascii_tree_test.dart';
+import 'descriptor.dart' as d;
+import 'test_pub.dart';
+
+final _isCI = () {
+ final p = RegExp(r'^1|(?:true)$', caseSensitive: false);
+ final ci = Platform.environment['CI'];
+ return ci != null && ci.isNotEmpty && p.hasMatch(ci);
+}();
+
+/// Find the current `_test.dart` filename invoked from stack-trace.
+String _findCurrentTestFilename() => Trace.current()
+ .frames
+ .lastWhere(
+ (frame) =>
+ frame.uri.isScheme('file') &&
+ p.basename(frame.uri.toFilePath()).endsWith('_test.dart'),
+ )
+ .uri
+ .toFilePath();
+
+class GoldenTestContext {
+ static const _endOfSection = ''
+ '--------------------------------'
+ ' END OF OUTPUT '
+ '---------------------------------\n\n';
+
+ late final String _currentTestFile;
+ late final String _testName;
+
+ late String _goldenFilePath;
+ late File _goldenFile;
+ late String _header;
+ final _results = <String>[];
+ late bool _goldenFileExists;
+ bool _generatedNewData = false; // track if new data is generated
+ int _nextSectionIndex = 0;
+
+ GoldenTestContext._(this._currentTestFile, this._testName) {
+ final rel = p.relative(
+ _currentTestFile.replaceAll(RegExp(r'\.dart$'), ''),
+ from: p.join(p.current, 'test'),
+ );
+ _goldenFilePath = p.join(
+ 'test',
+ 'testdata',
+ 'goldens',
+ rel,
+ // Sanitize the name, and add .txt
+ _testName.replaceAll(RegExp(r'[<>:"/\|?*%#]'), '~') + '.txt',
+ );
+ _goldenFile = File(_goldenFilePath);
+ _header = '# GENERATED BY: ${p.relative(_currentTestFile)}\n\n';
}
+
+ void _readGoldenFile() {
+ _goldenFileExists = _goldenFile.existsSync();
+
+ // Read the golden file for this test
+ if (_goldenFileExists) {
+ var text = _goldenFile.readAsStringSync().replaceAll('\r\n', '\n');
+ // Strip header line
+ if (text.startsWith('#') && text.contains('\n\n')) {
+ text = text.substring(text.indexOf('\n\n') + 2);
+ }
+ _results.addAll(text.split(_endOfSection));
+ }
+ }
+
+ /// Expect section [sectionIndex] to match [actual].
+ void _expectSection(int sectionIndex, String actual) {
+ if (_goldenFileExists &&
+ _results.length > sectionIndex &&
+ _results[sectionIndex].isNotEmpty) {
+ expect(
+ actual,
+ equals(_results[sectionIndex]),
+ reason: 'Expect matching section $sectionIndex from "$_goldenFilePath"',
+ );
+ } else {
+ while (_results.length <= sectionIndex) {
+ _results.add('');
+ }
+ _results[sectionIndex] = actual;
+ _generatedNewData = true;
+ }
+ }
+
+ void _writeGoldenFile() {
+ // If we generated new data, then we need to write a new file, and fail the
+ // test case, or mark it as skipped.
+ if (_generatedNewData) {
+ // This enables writing the updated file when run in otherwise hermetic
+ // settings.
+ //
+ // This is to make updating the golden files easier in a bazel environment
+ // See https://docs.bazel.build/versions/2.0.0/user-manual.html#run .
+ var goldenFile = _goldenFile;
+ final workspaceDirectory =
+ Platform.environment['BUILD_WORKSPACE_DIRECTORY'];
+ if (workspaceDirectory != null) {
+ goldenFile = File(p.join(workspaceDirectory, _goldenFilePath));
+ }
+ goldenFile
+ ..createSync(recursive: true)
+ ..writeAsStringSync(_header + _results.join(_endOfSection));
+
+ // If running in CI we should fail if the golden file doesn't already
+ // exist, or is missing entries.
+ // This typically happens if we forgot to commit a file to git.
+ if (_isCI) {
+ fail('Missing golden file: "$_goldenFilePath", '
+ 'try running tests again and commit the file');
+ } else {
+ // If not running in CI, then we consider the test as skipped, we've
+ // generated the file, but the user should run the tests again.
+ // Or push to CI in which case we'll run the tests again anyways.
+ markTestSkipped(
+ 'Generated golden file: "$_goldenFilePath" instead of running test',
+ );
+ }
+ }
+ }
+
+ /// Expect the next section in the golden file to match [actual].
+ ///
+ /// This will create the section if it is missing.
+ ///
+ /// **Warning**: Take care when using this in an async context, sections are
+ /// numbered based on the other in which calls are made. Hence, ensure
+ /// consistent ordering of calls.
+ void expectNextSection(String actual) =>
+ _expectSection(_nextSectionIndex++, actual);
+
+ /// Run `pub` [args] with [environment] variables in [workingDirectory], and
+ /// log stdout/stderr and exitcode to golden file.
+ Future<void> run(
+ List<String> args, {
+ Map<String, String>? environment,
+ String? workingDirectory,
+ }) async {
+ // Create new section index number (before doing anything async)
+ final sectionIndex = _nextSectionIndex++;
+ final s = StringBuffer();
+ s.writeln('## Section $sectionIndex');
+ await runPubIntoBuffer(
+ args,
+ s,
+ environment: environment,
+ workingDirectory: workingDirectory,
+ );
+
+ _expectSection(sectionIndex, s.toString());
+ }
+
+ /// Log directory tree structure under [directory] to golden file.
+ Future<void> tree([String? directory]) async {
+ // Create new section index number (before doing anything async)
+ final sectionIndex = _nextSectionIndex++;
+
+ final target = p.join(d.sandbox, directory ?? '.');
+
+ final s = StringBuffer();
+ s.writeln('## Section $sectionIndex');
+ if (directory != null) {
+ s.writeln('\$ cd $directory');
+ }
+ s.writeln('\$ tree');
+ s.writeln(stripColors(ascii_tree.fromFiles(
+ listDir(target, recursive: true),
+ baseDir: target,
+ )));
+
+ _expectSection(sectionIndex, s.toString());
+ }
+}
+
+/// Create a [test] with [GoldenTestContext] which allows running golden tests.
+///
+/// This will create a golden file containing output of calls to:
+/// * [GoldenTestContext.run]
+/// * [GoldenTestContext.tree]
+///
+/// The golden file with the recorded output will be created at:
+/// `test/testdata/goldens/path/to/myfile_test/<name>.txt`
+/// , when `path/to/myfile_test.dart` is the `_test.dart` file from which this
+/// function is called.
+void testWithGolden(
+ String name,
+ FutureOr<void> Function(GoldenTestContext ctx) fn,
+) {
+ final ctx = GoldenTestContext._(_findCurrentTestFilename(), name);
+ test(name, () async {
+ ctx._readGoldenFile();
+ await fn(ctx);
+ ctx._writeGoldenFile();
+ });
}
diff --git a/test/goldens/directory_option.txt b/test/goldens/directory_option.txt
deleted file mode 100644
index 356480c..0000000
--- a/test/goldens/directory_option.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-$ pub add --directory=myapp foo
-Resolving dependencies in myapp...
-+ foo 1.0.0
-Changed 1 dependency in myapp!
-
-$ pub -C myapp add bar
-Resolving dependencies in myapp...
-+ bar 1.2.3
-Changed 1 dependency in myapp!
-
-$ pub -C myapp/example get --directory=myapp bar
-Resolving dependencies in myapp...
-Got dependencies in myapp!
-
-$ pub remove bar -C myapp
-Resolving dependencies in myapp...
-These packages are no longer being depended on:
-- bar 1.2.3
-Changed 1 dependency in myapp!
-
-$ pub get bar -C myapp
-Resolving dependencies in myapp...
-Got dependencies in myapp!
-
-$ pub get bar -C myapp/example
-Resolving dependencies in myapp/example...
-+ foo 1.0.0
-+ test_pkg 1.0.0 from path myapp
-Changed 2 dependencies in myapp/example!
-
-$ pub get bar -C myapp/example2
-Resolving dependencies in myapp/example2...
-[ERR] Error on line 1, column 9 of myapp/pubspec.yaml: "name" field doesn't match expected name "myapp".
-[ERR] â•·
-[ERR] 1 │ {"name":"test_pkg","version":"1.0.0","homepage":"http://pub.dartlang.org","description":"A package, I guess.","environment":{"sdk":">=1.8.0 <=2.0.0"}, dependencies: { foo: ^1.0.0}}
-[ERR] │ ^^^^^^^^^^
-[ERR] ╵
-[Exit code] 65
-
-$ pub get bar -C myapp/broken_dir
-[ERR] Could not find a file named "pubspec.yaml" in "$SANDBOX/myapp/broken_dir".
-[Exit code] 66
-
-$ pub downgrade -C myapp
-Resolving dependencies in myapp...
- foo 1.0.0
-No dependencies changed in myapp.
-
-$ pub upgrade bar -C myapp
-Resolving dependencies in myapp...
- foo 1.0.0
-No dependencies changed in myapp.
-
-$ pub run -C myapp bin/app.dart
-Building package executable...
-Built test_pkg:app.
-Hi
-
-$ pub publish -C myapp --dry-run
-Publishing test_pkg 1.0.0 to http://localhost:$PORT:
-|-- CHANGELOG.md
-|-- LICENSE
-|-- README.md
-|-- bin
-| '-- app.dart
-|-- example
-| '-- pubspec.yaml
-|-- example2
-| '-- pubspec.yaml
-|-- lib
-| '-- test_pkg.dart
-'-- pubspec.yaml
-The server may enforce additional checks.
-[ERR]
-[ERR] Package has 0 warnings.
-
-$ pub uploader -C myapp add sigurdm@google.com
-Good job!
-
-$ pub deps -C myapp
-Dart SDK 1.12.0
-test_pkg 1.0.0
-'-- foo 1.0.0
-
diff --git a/test/goldens/help.txt b/test/goldens/help.txt
deleted file mode 100644
index 10997b4..0000000
--- a/test/goldens/help.txt
+++ /dev/null
@@ -1,386 +0,0 @@
-[command]
-> pub add --help
-[stdout]
-Add a dependency to pubspec.yaml.
-
-Usage: pub add <package>[:<constraint>] [options]
--h, --help Print this usage information.
--d, --dev Adds package to the development dependencies instead.
- --git-url Git URL of the package
- --git-ref Git branch or commit to be retrieved
- --git-path Path of git package in repository
- --hosted-url URL of package host server
- --path Local path
- --sdk SDK source for package
- --[no-]offline Use cached packages instead of accessing the network.
--n, --dry-run Report what dependencies would change but don't change
- any.
- --[no-]precompile Build executables in immediate dependencies.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-add for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub build --help
-[stdout]
-Deprecated command
-
-Usage: pub build <subcommand> [arguments...]
--h, --help Print this usage information.
-
-Run "pub help" to see global options.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub cache --help
-[stdout]
-Work with the system cache.
-
-Usage: pub cache [arguments...]
--h, --help Print this usage information.
-
-Available subcommands:
- add Install a package.
- repair Reinstall cached packages.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-cache for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub cache add --help
-[stdout]
-Install a package.
-
-Usage: pub cache add <package> [--version <constraint>] [--all]
--h, --help Print this usage information.
- --all Install all matching versions.
--v, --version Version constraint.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-cache for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub cache list --help
-[stdout]
-List packages in the system cache.
-
-Usage: pub cache list <subcommand> [arguments...]
--h, --help Print this usage information.
-
-Run "pub help" to see global options.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub cache repair --help
-[stdout]
-Reinstall cached packages.
-
-Usage: pub cache repair <subcommand> [arguments...]
--h, --help Print this usage information.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-cache for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub deps --help
-[stdout]
-Print package dependencies.
-
-Usage: pub deps [arguments...]
--h, --help Print this usage information.
--s, --style How output should be displayed.
- [compact, tree (default), list]
- --[no-]dev Whether to include dev dependencies.
- (defaults to on)
- --executables List all available executables.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-deps for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub downgrade --help
-[stdout]
-Downgrade the current package's dependencies to oldest versions.
-
-This doesn't modify the lockfile, so it can be reset with "pub get".
-
-Usage: pub downgrade [dependencies...]
--h, --help Print this usage information.
- --[no-]offline Use cached packages instead of accessing the network.
--n, --dry-run Report what dependencies would change but don't change
- any.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-downgrade for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub global --help
-[stdout]
-Work with global packages.
-
-Usage: pub global [arguments...]
--h, --help Print this usage information.
-
-Available subcommands:
- activate Make a package's executables globally available.
- deactivate Remove a previously activated package.
- list List globally activated packages.
- run Run an executable from a globally activated package.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-global for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub get --help
-[stdout]
-Get the current package's dependencies.
-
-Usage: pub get <subcommand> [arguments...]
--h, --help Print this usage information.
- --[no-]offline Use cached packages instead of accessing the network.
--n, --dry-run Report what dependencies would change but don't change
- any.
- --[no-]precompile Build executables in immediate dependencies.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-get for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub list-package-dirs --help
-[stdout]
-Print local paths to dependencies.
-
-Usage: pub list-package-dirs
--h, --help Print this usage information.
- --format How output should be displayed.
- [json]
-
-Run "pub help" to see global options.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub publish --help
-[stdout]
-Publish the current package to pub.dartlang.org.
-
-Usage: pub publish [options]
--h, --help Print this usage information.
--n, --dry-run Validate but do not publish the package.
--f, --force Publish without confirmation if there are no errors.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-lish for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub outdated --help
-[stdout]
-Analyze your dependencies to find which ones can be upgraded.
-
-Usage: pub outdated [options]
--h, --help Print this usage information.
- --[no-]color Whether to color the output.
- Defaults to color when connected to a
- terminal, and no-color otherwise.
- --[no-]dependency-overrides Show resolutions with `dependency_overrides`.
- (defaults to on)
- --[no-]dev-dependencies Take dev dependencies into account.
- (defaults to on)
- --json Output the results using a json format.
- --mode=<PROPERTY> Highlight versions with PROPERTY.
- Only packages currently missing that PROPERTY
- will be included unless --show-all.
- [outdated (default), null-safety]
- --[no-]prereleases Include prereleases in latest version.
- (defaults to on in --mode=null-safety).
- --[no-]show-all Include dependencies that are already
- fullfilling --mode.
- --[no-]transitive Show transitive dependencies.
- (defaults to off in --mode=null-safety).
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-outdated for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub remove --help
-[stdout]
-Removes a dependency from the current package.
-
-Usage: pub remove <package>
--h, --help Print this usage information.
- --[no-]offline Use cached packages instead of accessing the network.
--n, --dry-run Report what dependencies would change but don't change
- any.
- --[no-]precompile Build executables in immediate dependencies.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-remove for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub run --help
-[stdout]
-Run an executable from a package.
-
-Usage: pub run <executable> [arguments...]
--h, --help Print this usage information.
- --[no-]enable-asserts Enable assert statements.
- --enable-experiment=<experiment> Runs the executable in a VM with the
- given experiments enabled.
- (Will disable snapshotting, resulting in
- slower startup).
- --[no-]sound-null-safety Override the default null safety
- execution mode.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-run for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub serve --help
-[stdout]
-Deprecated command
-
-Usage: pub serve <subcommand> [arguments...]
--h, --help Print this usage information.
-
-Run "pub help" to see global options.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub upgrade --help
-[stdout]
-Upgrade the current package's dependencies to latest versions.
-
-Usage: pub upgrade [dependencies...]
--h, --help Print this usage information.
- --[no-]offline Use cached packages instead of accessing the network.
--n, --dry-run Report what dependencies would change but don't change
- any.
- --[no-]precompile Build executables in immediate dependencies.
- --null-safety Upgrade constraints in pubspec.yaml to null-safety
- versions
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-upgrade for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub uploader --help
-[stdout]
-Manage uploaders for a package on pub.dartlang.org.
-
-Usage: pub uploader [options] {add/remove} <email>
--h, --help Print this usage information.
- --package The package whose uploaders will be modified.
- (defaults to the current package)
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-uploader for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub login --help
-[stdout]
-Log into pub.dev.
-
-Usage: pub login
--h, --help Print this usage information.
-
-Run "pub help" to see global options.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub logout --help
-[stdout]
-Log out of pub.dev.
-
-Usage: pub logout <subcommand> [arguments...]
--h, --help Print this usage information.
-
-Run "pub help" to see global options.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub version --help
-[stdout]
-Print pub version.
-
-Usage: pub version
--h, --help Print this usage information.
-
-Run "pub help" to see global options.
-[stderr]
-
-[exitCode]
-0
-
diff --git a/test/goldens/upgrade_major_versions_example.txt b/test/goldens/upgrade_major_versions_example.txt
deleted file mode 100644
index 448a874..0000000
--- a/test/goldens/upgrade_major_versions_example.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-$ pub upgrade --major-versions --example
-Resolving dependencies...
-+ bar 2.0.0
-Changed 1 dependency!
-
-Changed 1 constraint in pubspec.yaml:
- bar: ^1.0.0 -> ^2.0.0
-Resolving dependencies in ./example...
-Got dependencies in ./example.
-[ERR] Running `upgrade --major-versions` only in `.`. Run `dart pub upgrade --major-versions --directory example/` separately.
-
-$ pub upgrade --major-versions --directory example
-Resolving dependencies in example...
- bar 2.0.0
-> foo 2.0.0 (was 1.0.0)
- myapp 0.0.0 from path .
-Changed 1 dependency in example!
-
-Changed 1 constraint in pubspec.yaml:
- foo: ^1.0.0 -> ^2.0.0
-
diff --git a/test/goldens/usage_exception.txt b/test/goldens/usage_exception.txt
deleted file mode 100644
index 5c7ead7..0000000
--- a/test/goldens/usage_exception.txt
+++ /dev/null
@@ -1,66 +0,0 @@
-[command]
-> pub
-[stdout]
-Pub is a package manager for Dart.
-
-Usage: pub <command> [arguments]
-
-Global options:
--h, --help Print this usage information.
- --version Print pub version.
- --[no-]trace Print debugging information when an error occurs.
- --verbosity Control output verbosity.
-
- [all] Show all output including internal tracing messages.
- [error] Show only errors.
- [io] Also show IO operations.
- [normal] Show errors, warnings, and user messages.
- [solver] Show steps during version resolution.
- [warning] Show only errors and warnings.
-
--v, --verbose Shortcut for "--verbosity=all".
-
-Available commands:
- add Add a dependency to pubspec.yaml.
- cache Work with the system cache.
- deps Print package dependencies.
- downgrade Downgrade the current package's dependencies to oldest versions.
- get Get the current package's dependencies.
- global Work with global packages.
- login Log into pub.dev.
- logout Log out of pub.dev.
- outdated Analyze your dependencies to find which ones can be upgraded.
- publish Publish the current package to pub.dartlang.org.
- remove Removes a dependency from the current package.
- run Run an executable from a package.
- upgrade Upgrade the current package's dependencies to latest versions.
- uploader Manage uploaders for a package on pub.dartlang.org.
- version Print pub version.
-
-Run "pub help <command>" for more information about a command.
-See https://dart.dev/tools/pub/cmd for detailed documentation.
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub global
-[stdout]
-
-[stderr]
-Missing subcommand for "pub global".
-
-Usage: pub global [arguments...]
--h, --help Print this usage information.
-
-Available subcommands:
- activate Make a package's executables globally available.
- deactivate Remove a previously activated package.
- list List globally activated packages.
- run Run an executable from a globally activated package.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-global for detailed documentation.
-[exitCode]
-64
diff --git a/test/goldens/version.txt b/test/goldens/version.txt
deleted file mode 100644
index a093c93..0000000
--- a/test/goldens/version.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-[command]
-> pub --version
-[stdout]
-Pub 0.1.2+3
-[stderr]
-
-[exitCode]
-0
-
-[command]
-> pub version
-[stdout]
-Pub 0.1.2+3
-[stderr]
-
-[exitCode]
-0
diff --git a/test/help_test.dart b/test/help_test.dart
new file mode 100644
index 0000000..e66f8a4
--- /dev/null
+++ b/test/help_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:args/command_runner.dart';
+import 'package:pub/src/command_runner.dart' show PubCommandRunner;
+
+import 'golden_file.dart';
+
+/// Extract all commands and subcommands.
+///
+/// Result will be an iterable of lists, illustrated as follows:
+/// ```
+/// [
+/// [pub]
+/// [pub, get]
+/// ...
+/// ]
+/// ```
+Iterable<List<String>> _extractCommands(
+ List<String> parents,
+ Iterable<Command> cmds,
+) sync* {
+ if (parents.isNotEmpty) {
+ yield parents;
+ }
+ // Track that we don't add more than once, we don't want to test aliases
+ final names = <String>{};
+ yield* cmds
+ .where((sub) => !sub.hidden && names.add(sub.name))
+ .map((sub) => _extractCommands(
+ [...parents, sub.name],
+ sub.subcommands.values,
+ ))
+ .expand((cmds) => cmds);
+}
+
+/// Tests for `pub ... --help`.
+Future<void> main() async {
+ final cmds = _extractCommands([], PubCommandRunner().commands.values);
+ for (final c in cmds) {
+ testWithGolden('pub ${c.join(' ')} --help', (ctx) async {
+ await ctx.run([...c, '--help']);
+ });
+ }
+}
diff --git a/test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart b/test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
index f5ad35c..7fb22a3 100644
--- a/test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
+++ b/test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -11,6 +9,7 @@
import 'package:test/test.dart';
import '../descriptor.dart' as d;
+import '../golden_file.dart';
import '../test_pub.dart';
void main() {
@@ -18,15 +17,18 @@
test(
'fails gracefully if the package server responds with broken package listings',
() async {
- await servePackages((b) => b..serve('foo', '1.2.3'));
- globalPackageServer.extraHandlers[RegExp('/api/packages/.*')] =
- expectAsync1((request) {
- expect(request.method, 'GET');
- return Response(200,
- body: jsonEncode({
- 'notTheRight': {'response': 'type'}
- }));
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
+ server.expect(
+ 'GET',
+ RegExp('/api/packages/.*'),
+ expectAsync1((request) {
+ return Response(200,
+ body: jsonEncode({
+ 'notTheRight': {'response': 'type'}
+ }));
+ }),
+ );
await d.appDir({'foo': '1.2.3'}).create();
await pubCommand(command,
@@ -38,4 +40,80 @@
exitCode: exit_codes.DATA);
});
});
+
+ testWithGolden('bad_json', (ctx) async {
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
+ server.expect('GET', RegExp('/api/packages/.*'), (request) {
+ return Response(200,
+ body: jsonEncode({
+ 'notTheRight': {'response': 'type'}
+ }));
+ });
+ await d.appDir({'foo': '1.2.3'}).create();
+
+ await ctx.run(['get']);
+ });
+
+ testWithGolden('403', (ctx) async {
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
+ server.expect('GET', RegExp('/api/packages/.*'), (request) {
+ return Response(403,
+ body: jsonEncode({
+ 'notTheRight': {'response': 'type'}
+ }));
+ });
+ await d.appDir({'foo': '1.2.3'}).create();
+
+ await ctx.run(['get']);
+ });
+
+ testWithGolden('401', (ctx) async {
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
+ server.expect('GET', RegExp('/api/packages/.*'), (request) {
+ return Response(401,
+ body: jsonEncode({
+ 'notTheRight': {'response': 'type'}
+ }));
+ });
+ await d.appDir({'foo': '1.2.3'}).create();
+
+ await ctx.run(['get']);
+ });
+
+ testWithGolden('403-with-message', (ctx) async {
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
+ server.expect('GET', RegExp('/api/packages/.*'), (request) {
+ return Response(403,
+ headers: {
+ 'www-authenticate': 'Bearer realm="pub", message="<message>"',
+ },
+ body: jsonEncode({
+ 'notTheRight': {'response': 'type'}
+ }));
+ });
+ await d.appDir({'foo': '1.2.3'}).create();
+
+ await ctx.run(['get']);
+ });
+
+ testWithGolden('401-with-message', (ctx) async {
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
+ server.expect('GET', RegExp('/api/packages/.*'), (request) {
+ return Response(401,
+ headers: {
+ 'www-authenticate': 'Bearer realm="pub", message="<message>"',
+ },
+ body: jsonEncode({
+ 'notTheRight': {'response': 'type'}
+ }));
+ });
+ await d.appDir({'foo': '1.2.3'}).create();
+
+ await ctx.run(['get']);
+ });
}
diff --git a/test/hosted/fail_gracefully_on_invalid_url_test.dart b/test/hosted/fail_gracefully_on_invalid_url_test.dart
index 9cbfbe8..94922c0 100644
--- a/test/hosted/fail_gracefully_on_invalid_url_test.dart
+++ b/test/hosted/fail_gracefully_on_invalid_url_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/hosted/fail_gracefully_on_missing_package_test.dart b/test/hosted/fail_gracefully_on_missing_package_test.dart
index 882d11c..7c6290d 100644
--- a/test/hosted/fail_gracefully_on_missing_package_test.dart
+++ b/test/hosted/fail_gracefully_on_missing_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -13,7 +11,7 @@
void main() {
forBothPubGetAndUpgrade((command) {
test('fails gracefully if the package does not exist', () async {
- await serveNoPackages();
+ await servePackages();
await d.appDir({'foo': '1.2.3'}).create();
diff --git a/test/hosted/fail_gracefully_on_url_resolve_test.dart b/test/hosted/fail_gracefully_on_url_resolve_test.dart
index 9e3abcd..7a91e7a 100644
--- a/test/hosted/fail_gracefully_on_url_resolve_test.dart
+++ b/test/hosted/fail_gracefully_on_url_resolve_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/hosted/fail_gracefully_with_hint_test.dart b/test/hosted/fail_gracefully_with_hint_test.dart
new file mode 100644
index 0000000..4f1a326
--- /dev/null
+++ b/test/hosted/fail_gracefully_with_hint_test.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:pub/src/exit_codes.dart' as exit_codes;
+import 'package:test/test.dart';
+
+import '../descriptor.dart' as d;
+import '../golden_file.dart';
+import '../test_pub.dart';
+
+void main() {
+ testWithGolden('hint: try without --offline', (ctx) async {
+ // Run the server so that we know what URL to use in the system cache.
+ (await servePackages()).serveErrors();
+
+ await d.appDir({'foo': 'any'}).create();
+
+ await pubGet(
+ args: ['--offline'],
+ exitCode: exit_codes.UNAVAILABLE,
+ error: contains('Try again without --offline!'),
+ );
+ });
+
+ testWithGolden('supports two hints', (ctx) async {
+ // Run the server so that we know what URL to use in the system cache.
+ (await servePackages()).serveErrors();
+
+ await d.hostedCache([
+ d.dir('foo-1.2.3', [
+ d.pubspec({
+ 'name': 'foo',
+ 'version': '1.2.3',
+ 'environment': {
+ 'flutter': 'any', // generates hint -> flutter pub get
+ },
+ }),
+ ]),
+ d.dir('foo-1.2.4', [
+ d.pubspec({
+ 'name': 'foo',
+ 'version': '1.2.4',
+ 'dependencies': {
+ 'bar': 'any', // generates hint -> try without --offline
+ },
+ }),
+ ]),
+ ]).create();
+
+ await d.appDir({'foo': 'any'}).create();
+
+ await pubGet(
+ args: ['--offline'],
+ exitCode: exit_codes.UNAVAILABLE,
+ error: allOf(
+ contains('Try again without --offline!'),
+ contains('flutter pub get'), // hint that
+ ),
+ );
+
+ await ctx.run(['get', '--offline']);
+ });
+}
diff --git a/test/hosted/metadata_test.dart b/test/hosted/metadata_test.dart
index 6ba59f5..c705ac7 100644
--- a/test/hosted/metadata_test.dart
+++ b/test/hosted/metadata_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
import 'package:test/test.dart';
@@ -14,9 +12,8 @@
void main() {
forBothPubGetAndUpgrade((command) {
test('sends metadata headers for a direct dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.appDir({'foo': '1.0.0'}).create();
@@ -35,9 +32,8 @@
});
test('sends metadata headers for a dev dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -61,9 +57,8 @@
});
test('sends metadata headers for a transitive dependency', () async {
- await servePackages((builder) {
- builder.serve('bar', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('bar', '1.0.0');
await d.appDir({
'foo': {'path': '../foo'}
@@ -84,9 +79,8 @@
});
test("doesn't send metadata headers to a foreign server", () async {
- var server = await PackageServer.start((builder) {
- builder.serve('foo', '1.0.0');
- });
+ var server = await startPackageServer()
+ ..serve('foo', '1.0.0');
await d.appDir({
'foo': {
@@ -99,9 +93,7 @@
});
test("doesn't send metadata headers when CI=true", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- });
+ (await servePackages()).serve('foo', '1.0.0');
await d.appDir({'foo': '1.0.0'}).create();
diff --git a/test/hosted/offline_test.dart b/test/hosted/offline_test.dart
index ef738c8..ca3dc80 100644
--- a/test/hosted/offline_test.dart
+++ b/test/hosted/offline_test.dart
@@ -2,22 +2,19 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
import '../descriptor.dart' as d;
import '../test_pub.dart';
-Future<void> populateCache(Map<String, List<String>> versions) async {
- await servePackages((b) {
- for (final entry in versions.entries) {
- for (final version in entry.value) {
- b.serve(entry.key, version);
- }
+Future<void> populateCache(
+ Map<String, List<String>> versions, PackageServer server) async {
+ for (final entry in versions.entries) {
+ for (final version in entry.value) {
+ server.serve(entry.key, version);
}
- });
+ }
for (final entry in versions.entries) {
for (final version in entry.value) {
await d.appDir({entry.key: version}).create();
@@ -29,37 +26,41 @@
void main() {
forBothPubGetAndUpgrade((command) {
test('upgrades a package using the cache', () async {
+ final server = await servePackages();
await populateCache({
'foo': ['1.2.2', '1.2.3'],
'bar': ['1.2.3']
- });
+ }, server);
// Now serve only errors - to validate we are truly offline.
- await serveErrors();
+ server.serveErrors();
await d.appDir({'foo': 'any', 'bar': 'any'}).create();
- String warning;
+ String? warning;
if (command == RunCommand.upgrade) {
warning = 'Warning: Upgrading when offline may not update you '
'to the latest versions of your dependencies.';
}
await pubCommand(command, args: ['--offline'], warning: warning);
-
- await d.appPackagesFile({'foo': '1.2.3', 'bar': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ d.packageConfigEntry(name: 'bar', version: '1.2.3'),
+ ]).validate();
});
test('supports prerelease versions', () async {
+ final server = await servePackages();
await populateCache({
'foo': ['1.2.3-alpha.1']
- });
+ }, server);
// Now serve only errors - to validate we are truly offline.
- await serveErrors();
+ server.serveErrors();
await d.appDir({'foo': 'any'}).create();
- String warning;
+ String? warning;
if (command == RunCommand.upgrade) {
warning = 'Warning: Upgrading when offline may not update you '
'to the latest versions of your dependencies.';
@@ -67,12 +68,15 @@
await pubCommand(command, args: ['--offline'], warning: warning);
- await d.appPackagesFile({'foo': '1.2.3-alpha.1'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3-alpha.1'),
+ ]).validate();
});
test('fails gracefully if a dependency is not cached', () async {
// Run the server so that we know what URL to use in the system cache.
- await serveErrors();
+ final server = await servePackages();
+ server.serveErrors();
await d.appDir({'foo': 'any'}).create();
@@ -82,16 +86,19 @@
error: equalsIgnoringWhitespace("""
Because myapp depends on foo any which doesn't exist (could not find
package foo in cache), version solving failed.
+
+ Try again without --offline!
"""));
});
test('fails gracefully if no cached versions match', () async {
+ final server = await servePackages();
await populateCache({
'foo': ['1.2.2', '1.2.3']
- });
+ }, server);
// Run the server so that we know what URL to use in the system cache.
- await serveErrors();
+ server.serveErrors();
await d.appDir({'foo': '>2.0.0'}).create();
@@ -105,8 +112,10 @@
test(
'fails gracefully if a dependency is not cached and a lockfile '
'exists', () async {
+ final server = await servePackages();
+
// Run the server so that we know what URL to use in the system cache.
- await serveErrors();
+ server.serveErrors();
await d.appDir({'foo': 'any'}).create();
@@ -118,15 +127,19 @@
error: equalsIgnoringWhitespace("""
Because myapp depends on foo any which doesn't exist (could not find
package foo in cache), version solving failed.
+
+ Try again without --offline!
"""));
});
test('downgrades to the version in the cache if necessary', () async {
+ final server = await servePackages();
+
await populateCache({
'foo': ['1.2.2', '1.2.3']
- });
+ }, server);
// Run the server so that we know what URL to use in the system cache.
- await serveErrors();
+ server.serveErrors();
await d.appDir({'foo': 'any'}).create();
@@ -134,15 +147,19 @@
await pubCommand(command, args: ['--offline']);
- await d.appPackagesFile({'foo': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.3'),
+ ]).validate();
});
test('skips invalid cached versions', () async {
+ final server = await servePackages();
+
await populateCache({
'foo': ['1.2.2', '1.2.3']
- });
+ }, server);
// Run the server so that we know what URL to use in the system cache.
- await serveErrors();
+ server.serveErrors();
await d.hostedCache([
d.dir('foo-1.2.3', [d.file('pubspec.yaml', '{')]),
@@ -153,15 +170,19 @@
await pubCommand(command, args: ['--offline']);
- await d.appPackagesFile({'foo': '1.2.2'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.2'),
+ ]).validate();
});
test('skips invalid locked versions', () async {
+ final server = await servePackages();
+
await populateCache({
'foo': ['1.2.2', '1.2.3']
- });
+ }, server);
// Run the server so that we know what URL to use in the system cache.
- await serveErrors();
+ server.serveErrors();
await d.hostedCache([
d.dir('foo-1.2.3', [d.file('pubspec.yaml', '{')])
@@ -173,7 +194,9 @@
await pubCommand(command, args: ['--offline']);
- await d.appPackagesFile({'foo': '1.2.2'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.2.2'),
+ ]).validate();
});
});
}
diff --git a/test/hosted/remove_removed_dependency_test.dart b/test/hosted/remove_removed_dependency_test.dart
index 9d530d7..a0446c0 100644
--- a/test/hosted/remove_removed_dependency_test.dart
+++ b/test/hosted/remove_removed_dependency_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
@@ -12,22 +10,25 @@
void main() {
forBothPubGetAndUpgrade((command) {
test("removes a dependency that's removed from the pubspec", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('bar', '1.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('bar', '1.0.0');
await d.appDir({'foo': 'any', 'bar': 'any'}).create();
await pubCommand(command);
-
- await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ ]).validate();
await d.appDir({'foo': 'any'}).create();
await pubCommand(command);
- await d.appPackagesFile({'foo': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ ]).validate();
});
});
}
diff --git a/test/hosted/remove_removed_transitive_dependency_test.dart b/test/hosted/remove_removed_transitive_dependency_test.dart
index 43ac01c..182ec3f 100644
--- a/test/hosted/remove_removed_transitive_dependency_test.dart
+++ b/test/hosted/remove_removed_transitive_dependency_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
@@ -14,31 +12,30 @@
test(
"removes a transitive dependency that's no longer depended "
'on', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'shared_dep': 'any'});
- builder.serve('bar', '1.0.0',
- deps: {'shared_dep': 'any', 'bar_dep': 'any'});
- builder.serve('shared_dep', '1.0.0');
- builder.serve('bar_dep', '1.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'shared_dep': 'any'})
+ ..serve('bar', '1.0.0', deps: {'shared_dep': 'any', 'bar_dep': 'any'})
+ ..serve('shared_dep', '1.0.0')
+ ..serve('bar_dep', '1.0.0');
await d.appDir({'foo': 'any', 'bar': 'any'}).create();
await pubCommand(command);
-
- await d.appPackagesFile({
- 'foo': '1.0.0',
- 'bar': '1.0.0',
- 'shared_dep': '1.0.0',
- 'bar_dep': '1.0.0',
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ d.packageConfigEntry(name: 'shared_dep', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar_dep', version: '1.0.0'),
+ ]).validate();
await d.appDir({'foo': 'any'}).create();
await pubCommand(command);
- await d
- .appPackagesFile({'foo': '1.0.0', 'shared_dep': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'shared_dep', version: '1.0.0'),
+ ]).validate();
});
});
}
diff --git a/test/hosted/short_syntax_test.dart b/test/hosted/short_syntax_test.dart
new file mode 100644
index 0000000..5d4cf28
--- /dev/null
+++ b/test/hosted/short_syntax_test.dart
@@ -0,0 +1,89 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:path/path.dart' as p;
+import 'package:test/test.dart';
+import 'package:yaml/yaml.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+void main() {
+ setUp(() async {
+ final server = await servePackages();
+ server.serve('foo', '1.2.3', pubspec: {
+ 'environment': {'sdk': '^2.0.0'}
+ });
+ });
+ forBothPubGetAndUpgrade((command) {
+ Future<void> testWith(dynamic dependency) async {
+ await d.dir(appPath, [
+ d.libPubspec(
+ 'app',
+ '1.0.0',
+ deps: {'foo': dependency},
+ sdk: '^2.15.0',
+ ),
+ ]).create();
+
+ await pubCommand(
+ command,
+ exitCode: 0,
+ environment: {'_PUB_TEST_SDK_VERSION': '2.15.0'},
+ );
+
+ final lockFile = loadYaml(
+ await File(p.join(d.sandbox, appPath, 'pubspec.lock')).readAsString(),
+ );
+
+ expect(lockFile['packages']['foo'], {
+ 'dependency': 'direct main',
+ 'source': 'hosted',
+ 'description': {
+ 'name': 'foo',
+ 'url': globalServer.url,
+ },
+ 'version': '1.2.3',
+ });
+ }
+
+ test('supports hosted: <url> syntax', () async {
+ return testWith({'hosted': globalServer.url});
+ });
+
+ test('supports hosted map without name', () {
+ return testWith({
+ 'hosted': {'url': globalServer.url},
+ });
+ });
+
+ test('interprets hosted string as name for older versions', () async {
+ await d.dir(appPath, [
+ d.libPubspec(
+ 'app',
+ '1.0.0',
+ deps: {
+ 'foo': {'hosted': 'foo', 'version': '^1.2.3'}
+ },
+ sdk: '^2.0.0',
+ ),
+ ]).create();
+
+ await pubCommand(
+ command,
+ exitCode: 0,
+ environment: {'_PUB_TEST_SDK_VERSION': '2.15.0'},
+ );
+
+ final lockFile = loadYaml(
+ await File(p.join(d.sandbox, appPath, 'pubspec.lock')).readAsString(),
+ );
+
+ expect(
+ lockFile['packages']['foo']['description']['url'], globalServer.url);
+ });
+ });
+}
diff --git a/test/hosted/version_negotiation_test.dart b/test/hosted/version_negotiation_test.dart
index 3d12703..44dbe7a 100644
--- a/test/hosted/version_negotiation_test.dart
+++ b/test/hosted/version_negotiation_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:shelf/shelf.dart' as shelf;
import 'package:test/test.dart';
@@ -18,11 +16,11 @@
await d.appDir({
'foo': {
- 'hosted': {'name': 'foo', 'url': globalPackageServer.url}
+ 'hosted': {'name': 'foo', 'url': globalServer.url}
}
}).create();
- globalPackageServer.expect('GET', '/api/packages/foo', (request) {
+ globalServer.expect('GET', '/api/packages/foo', (request) {
expect(
request.headers['accept'], equals('application/vnd.pub.v2+json'));
return shelf.Response(404);
@@ -37,13 +35,13 @@
await d.appDir({
'foo': {
- 'hosted': {'name': 'foo', 'url': globalPackageServer.url}
+ 'hosted': {'name': 'foo', 'url': globalServer.url}
}
}).create();
var pub = await startPub(args: [command.name]);
- globalPackageServer.expect(
+ globalServer.expect(
'GET', '/api/packages/foo', (request) => shelf.Response(406));
await pub.shouldExit(1);
diff --git a/test/hosted/will_normalize_hosted_url_test.dart b/test/hosted/will_normalize_hosted_url_test.dart
index f2da266..6cc3888 100644
--- a/test/hosted/will_normalize_hosted_url_test.dart
+++ b/test/hosted/will_normalize_hosted_url_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:http/http.dart' as http;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:shelf/shelf.dart';
@@ -15,47 +13,50 @@
void main() {
forBothPubGetAndUpgrade((command) {
test('does not require slash on bare domain', () async {
- await servePackages((b) => b..serve('foo', '1.2.3'));
- // All the tests in this file assumes that [globalPackageServer.url]
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
+ // All the tests in this file assumes that [globalServer.url]
// will be on the form:
// http://localhost:<port>
// In particular, that it doesn't contain anything path segment.
- expect(Uri.parse(globalPackageServer.url).path, isEmpty);
+ expect(Uri.parse(globalServer.url).path, isEmpty);
await d.dir(appPath, [
d.appPubspec({
'foo': {
- 'hosted': {'name': 'foo', 'url': globalPackageServer.url},
+ 'hosted': {'name': 'foo', 'url': globalServer.url},
},
}),
]).create();
await pubCommand(
command,
- silent: contains('${globalPackageServer.url}/api/packages/foo'),
+ silent: contains('${globalServer.url}/api/packages/foo'),
);
});
test('normalizes extra slash', () async {
- await servePackages((b) => b..serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.dir(appPath, [
d.appPubspec({
'foo': {
- 'hosted': {'name': 'foo', 'url': globalPackageServer.url + '/'},
+ 'hosted': {'name': 'foo', 'url': globalServer.url + '/'},
},
}),
]).create();
await pubCommand(
command,
- silent: contains('${globalPackageServer.url}/api/packages/foo'),
+ silent: contains('${globalServer.url}/api/packages/foo'),
);
});
test('cannot normalize double slash', () async {
- await servePackages((b) => b..serve('foo', '1.2.3'));
- globalPackageServer.expect(
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
+ globalServer.expect(
'GET',
'//api/packages/foo',
(request) => Response.notFound(''),
@@ -64,15 +65,14 @@
await d.dir(appPath, [
d.appPubspec({
'foo': {
- 'hosted': {'name': 'foo', 'url': globalPackageServer.url + '//'},
+ 'hosted': {'name': 'foo', 'url': globalServer.url + '//'},
},
}),
]).create();
await pubCommand(
command,
- error: contains(
- 'could not find package foo at ${globalPackageServer.url}//'),
+ error: contains('could not find package foo at ${globalServer.url}//'),
exitCode: exit_codes.UNAVAILABLE,
);
});
@@ -82,27 +82,31 @@
/// This is a bit of a hack, to easily test if hosted pub URLs with a path
/// segment works and if the slashes are normalized.
void _proxyMyFolderToRoot() {
- globalPackageServer.extraHandlers[RegExp('/my-folder/.*')] = (r) async {
- if (r.method != 'GET' && r.method != 'HEAD') {
- return Response.forbidden(null);
- }
- final path = r.requestedUri.path.substring('/my-folder/'.length);
- final res = await http.get(
- Uri.parse(globalPackageServer.url + '/$path'),
- );
- return Response(res.statusCode, body: res.bodyBytes, headers: {
- 'Content-Type': res.headers['Content-Type'],
- });
- };
+ globalServer.handle(
+ RegExp('/my-folder/.*'),
+ (r) async {
+ if (r.method != 'GET' && r.method != 'HEAD') {
+ return Response.forbidden(null);
+ }
+ final path = r.requestedUri.path.substring('/my-folder/'.length);
+ final res = await http.get(
+ Uri.parse(globalServer.url + '/$path'),
+ );
+ return Response(res.statusCode, body: res.bodyBytes, headers: {
+ 'Content-Type': res.headers['content-type']!,
+ });
+ },
+ );
}
test('will use normalized url with path', () async {
- await servePackages((b) => b..serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
_proxyMyFolderToRoot();
// testing with a normalized URL
- final testUrl = globalPackageServer.url + '/my-folder/';
- final normalizedUrl = globalPackageServer.url + '/my-folder/';
+ final testUrl = globalServer.url + '/my-folder/';
+ final normalizedUrl = globalServer.url + '/my-folder/';
await d.dir(appPath, [
d.appPubspec({
@@ -120,12 +124,13 @@
});
test('will normalize url with path by adding slash', () async {
- await servePackages((b) => b..serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
_proxyMyFolderToRoot();
// Testing with a URL that is missing the slash.
- final testUrl = globalPackageServer.url + '/my-folder';
- final normalizedUrl = globalPackageServer.url + '/my-folder/';
+ final testUrl = globalServer.url + '/my-folder';
+ final normalizedUrl = globalServer.url + '/my-folder/';
await d.dir(appPath, [
d.appPubspec({
diff --git a/test/ignore_test.dart b/test/ignore_test.dart
index 75238b5..a8ab8ac 100644
--- a/test/ignore_test.dart
+++ b/test/ignore_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
import 'package:pub/src/ignore.dart';
@@ -41,10 +39,10 @@
return [path.substring(0, nextSlash == -1 ? path.length : nextSlash)];
}
- Ignore ignoreForDir(String dir) => c.patterns[dir] == null
+ Ignore? ignoreForDir(String dir) => c.patterns[dir] == null
? null
: Ignore(
- c.patterns[dir],
+ c.patterns[dir]!,
onInvalidPattern: (_, __) => hasWarning = true,
ignoreCase: ignoreCase,
);
@@ -87,17 +85,18 @@
for (final c in testData) {
c.paths.forEach((path, expected) {
- if (c.ignoreCase == null) {
+ var ignoreCase = c.ignoreCase;
+ if (ignoreCase == null) {
_testIgnorePath(c, path, expected, false);
_testIgnorePath(c, path, expected, true);
} else {
- _testIgnorePath(c, path, expected, c.ignoreCase);
+ _testIgnorePath(c, path, expected, ignoreCase);
}
});
}
});
- ProcessResult runGit(List<String> args, {String workingDirectory}) {
+ ProcessResult runGit(List<String> args, {String? workingDirectory}) {
final executable = Platform.isWindows ? 'cmd' : 'git';
args = Platform.isWindows ? ['/c', 'git', ...args] : args;
return Process.runSync(executable, args,
@@ -105,24 +104,24 @@
}
group('git', () {
- Directory tmp;
+ Directory? tmp;
setUpAll(() async {
tmp = await Directory.systemTemp.createTemp('package-ignore-test-');
- final ret = runGit(['init'], workingDirectory: tmp.path);
+ final ret = runGit(['init'], workingDirectory: tmp!.path);
expect(ret.exitCode, equals(0),
reason:
'Running "git init" failed. StdErr: ${ret.stderr} StdOut: ${ret.stdout}');
});
tearDownAll(() async {
- await tmp.delete(recursive: true);
+ await tmp!.delete(recursive: true);
tmp = null;
});
tearDown(() async {
- runGit(['clean', '-f', '-d', '-x'], workingDirectory: tmp.path);
+ runGit(['clean', '-f', '-d', '-x'], workingDirectory: tmp!.path);
});
void _testIgnorePath(
@@ -137,7 +136,7 @@
expect(
runGit(
['config', '--local', 'core.ignoreCase', ignoreCase.toString()],
- workingDirectory: tmp.path,
+ workingDirectory: tmp!.path,
).exitCode,
anyOf(0, 1),
reason: 'Running "git config --local core.ignoreCase ..." failed',
@@ -145,17 +144,17 @@
for (final directory in c.patterns.keys) {
final resolvedDirectory =
- directory == '' ? tmp.uri : tmp.uri.resolve(directory + '/');
+ directory == '' ? tmp!.uri : tmp!.uri.resolve(directory + '/');
Directory.fromUri(resolvedDirectory).createSync(recursive: true);
final gitIgnore =
File.fromUri(resolvedDirectory.resolve('.gitignore'));
gitIgnore.writeAsStringSync(
- c.patterns[directory].join('\n') + '\n',
+ c.patterns[directory]!.join('\n') + '\n',
);
}
final process = runGit(
- ['-C', tmp.path, 'check-ignore', '--no-index', path],
- workingDirectory: tmp.path);
+ ['-C', tmp!.path, 'check-ignore', '--no-index', path],
+ workingDirectory: tmp!.path);
expect(process.exitCode, anyOf(0, 1),
reason: 'Running "git check-ignore" failed');
final ignored = process.exitCode == 0;
@@ -172,11 +171,12 @@
for (final c in testData) {
c.paths.forEach((path, expected) {
- if (c.ignoreCase == null) {
+ var ignoreCase = c.ignoreCase;
+ if (ignoreCase == null) {
_testIgnorePath(c, path, expected, false);
_testIgnorePath(c, path, expected, true);
} else {
- _testIgnorePath(c, path, expected, c.ignoreCase);
+ _testIgnorePath(c, path, expected, ignoreCase);
}
});
}
@@ -200,7 +200,7 @@
final bool skipOnWindows;
/// Test with `core.ignoreCase` set to `true`, `false` or both (if `null`).
- final bool ignoreCase;
+ final bool? ignoreCase;
TestData(
this.name,
@@ -977,6 +977,13 @@
'folder/a.txt': true,
}),
+ TestData('folder/* does not ignore `folder` itself', {
+ '.': ['folder/*', '!folder/a.txt'],
+ }, {
+ 'folder/a.txt': false,
+ 'folder/b.txt': true,
+ }),
+
// Case sensitivity
TestData(
'simple',
diff --git a/test/io_test.dart b/test/io_test.dart
index b54bc91..2c529cd 100644
--- a/test/io_test.dart
+++ b/test/io_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:convert';
import 'dart:io';
@@ -463,14 +461,14 @@
}
void testExistencePredicate(String name, bool Function(String path) predicate,
- {bool forFile,
- bool forFileSymlink,
- bool forMultiLevelFileSymlink,
- bool forDirectory,
- bool forDirectorySymlink,
- bool forMultiLevelDirectorySymlink,
- bool forBrokenSymlink,
- bool forMultiLevelBrokenSymlink}) {
+ {required bool forFile,
+ required bool forFileSymlink,
+ required bool forMultiLevelFileSymlink,
+ required bool forDirectory,
+ required bool forDirectorySymlink,
+ required bool forMultiLevelDirectorySymlink,
+ required bool forBrokenSymlink,
+ required bool forMultiLevelBrokenSymlink}) {
group(name, () {
test('returns $forFile for a file', () {
expect(withTempDir((temp) {
diff --git a/test/levenshtein_test.dart b/test/levenshtein_test.dart
index 6d113c7..67361af 100644
--- a/test/levenshtein_test.dart
+++ b/test/levenshtein_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/levenshtein.dart';
import 'package:test/test.dart';
diff --git a/test/lish/archives_and_uploads_a_package_test.dart b/test/lish/archives_and_uploads_a_package_test.dart
index 2efeb4a..88e4862 100644
--- a/test/lish/archives_and_uploads_a_package_test.dart
+++ b/test/lish/archives_and_uploads_a_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:path/path.dart' as p;
@@ -21,14 +19,44 @@
test('archives and uploads a package', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- handleUploadForm(globalPackageServer);
- handleUpload(globalPackageServer);
+ handleUploadForm(globalServer);
+ handleUpload(globalServer);
- globalPackageServer.expect('GET', '/create', (request) {
+ globalServer.expect('GET', '/create', (request) {
+ return shelf.Response.ok(jsonEncode({
+ 'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
+ }));
+ });
+
+ expect(pub.stdout, emits(startsWith('Uploading...')));
+ expect(pub.stdout, emits('Package test_pkg 1.0.0 uploaded!'));
+ await pub.shouldExit(exit_codes.SUCCESS);
+ });
+
+ test('publishes to hosted-url with path', () async {
+ await servePackages();
+ await d.tokensFile({
+ 'version': 1,
+ 'hosted': [
+ {'url': globalServer.url + '/sub/folder', 'env': 'TOKEN'},
+ ]
+ }).create();
+ var pub = await startPublish(
+ globalServer,
+ path: '/sub/folder',
+ authMethod: 'token',
+ environment: {'TOKEN': 'access token'},
+ );
+
+ await confirmPublish(pub);
+ handleUploadForm(globalServer, path: '/sub/folder');
+ handleUpload(globalServer);
+
+ globalServer.expect('GET', '/create', (request) {
return shelf.Response.ok(jsonEncode({
'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
}));
@@ -55,14 +83,14 @@
await d.dir(p.join(appPath, 'empty')).create();
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- handleUploadForm(globalPackageServer);
- handleUpload(globalPackageServer);
+ handleUploadForm(globalServer);
+ handleUpload(globalServer);
- globalPackageServer.expect('GET', '/create', (request) {
+ globalServer.expect('GET', '/create', (request) {
return shelf.Response.ok(jsonEncode({
'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
}));
diff --git a/test/lish/cloud_storage_upload_doesnt_redirect_test.dart b/test/lish/cloud_storage_upload_doesnt_redirect_test.dart
index f2e542f..0f792d5 100644
--- a/test/lish/cloud_storage_upload_doesnt_redirect_test.dart
+++ b/test/lish/cloud_storage_upload_doesnt_redirect_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:shelf/shelf.dart' as shelf;
import 'package:test/test.dart';
@@ -16,13 +14,13 @@
test("cloud storage upload doesn't redirect", () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- handleUploadForm(globalPackageServer);
+ handleUploadForm(globalServer);
- globalPackageServer.expect('POST', '/upload', (request) async {
+ globalServer.expect('POST', '/upload', (request) async {
await request.read().drain();
return shelf.Response(200);
});
diff --git a/test/lish/cloud_storage_upload_provides_an_error_test.dart b/test/lish/cloud_storage_upload_provides_an_error_test.dart
index a67d85b..5dec03d 100644
--- a/test/lish/cloud_storage_upload_provides_an_error_test.dart
+++ b/test/lish/cloud_storage_upload_provides_an_error_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:shelf/shelf.dart' as shelf;
import 'package:test/test.dart';
@@ -16,13 +14,13 @@
test('cloud storage upload provides an error', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- handleUploadForm(globalPackageServer);
+ handleUploadForm(globalServer);
- globalPackageServer.expect('POST', '/upload', (request) {
+ globalServer.expect('POST', '/upload', (request) {
return request.read().drain().then((_) {
return shelf.Response.notFound(
'<Error><Message>Your request sucked.</Message></Error>',
diff --git a/test/lish/does_not_include_dot_file.dart b/test/lish/does_not_include_dot_file.dart
index 6dfa622..cec8ab0 100644
--- a/test/lish/does_not_include_dot_file.dart
+++ b/test/lish/does_not_include_dot_file.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -32,14 +30,14 @@
test('Check if package doesn\'t include dot-files', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- handleUploadForm(globalPackageServer);
- handleUpload(globalPackageServer);
+ handleUploadForm(globalServer);
+ handleUpload(globalServer);
- globalPackageServer.expect('GET', '/create', (request) {
+ globalServer.expect('GET', '/create', (request) {
return shelf.Response.ok(jsonEncode({
'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
}));
diff --git a/test/lish/does_not_publish_if_private_test.dart b/test/lish/does_not_publish_if_private_test.dart
index 9ab8712..52321c2 100644
--- a/test/lish/does_not_publish_if_private_test.dart
+++ b/test/lish/does_not_publish_if_private_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/lish/does_not_publish_if_private_with_server_arg_test.dart b/test/lish/does_not_publish_if_private_with_server_arg_test.dart
index c33b1a3..689609b 100644
--- a/test/lish/does_not_publish_if_private_with_server_arg_test.dart
+++ b/test/lish/does_not_publish_if_private_with_server_arg_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/lish/dot_folder_name_test.dart b/test/lish/dot_folder_name_test.dart
new file mode 100644
index 0000000..9f64839
--- /dev/null
+++ b/test/lish/dot_folder_name_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:pub/src/exit_codes.dart' as exit_codes;
+import 'package:test/test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+void main() {
+ test('Can publish files in a .folder', () async {
+ await d.git(appPath).create();
+ await d.validPackage.create();
+ await d.dir(appPath, [
+ d.dir('.vscode', [d.file('a')]),
+ d.file('.pubignore', '!.vscode/')
+ ]).create();
+
+ await runPub(
+ args: ['lish', '--dry-run'],
+ output: contains('''
+|-- .vscode
+| '-- a'''),
+ exitCode: exit_codes.SUCCESS,
+ );
+ });
+}
diff --git a/test/lish/dry_run_warns_about_server_checks.dart b/test/lish/dry_run_warns_about_server_checks.dart
index 8e12f9b..ad7abe0 100644
--- a/test/lish/dry_run_warns_about_server_checks.dart
+++ b/test/lish/dry_run_warns_about_server_checks.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
diff --git a/test/lish/force_cannot_be_combined_with_dry_run_test.dart b/test/lish/force_cannot_be_combined_with_dry_run_test.dart
index def3f7a..9d2233c 100644
--- a/test/lish/force_cannot_be_combined_with_dry_run_test.dart
+++ b/test/lish/force_cannot_be_combined_with_dry_run_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -14,17 +12,10 @@
setUp(d.validPackage.create);
test('--force cannot be combined with --dry-run', () async {
- await runPub(args: ['lish', '--force', '--dry-run'], error: '''
-Cannot use both --force and --dry-run.
-
-Usage: pub publish [options]
--h, --help Print this usage information.
--n, --dry-run Validate but do not publish the package.
--f, --force Publish without confirmation if there are no errors.
--C, --directory=<dir> Run this in the directory<dir>.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-lish for detailed documentation.
-''', exitCode: exit_codes.USAGE);
+ await runPub(
+ args: ['lish', '--force', '--dry-run'],
+ error: contains('Cannot use both --force and --dry-run.'),
+ exitCode: exit_codes.USAGE,
+ );
});
}
diff --git a/test/lish/force_does_not_publish_if_private_test.dart b/test/lish/force_does_not_publish_if_private_test.dart
index 9ca4bf6..0d4ad59 100644
--- a/test/lish/force_does_not_publish_if_private_test.dart
+++ b/test/lish/force_does_not_publish_if_private_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/lish/force_does_not_publish_if_there_are_errors_test.dart b/test/lish/force_does_not_publish_if_there_are_errors_test.dart
index 26978ad..481f627 100644
--- a/test/lish/force_does_not_publish_if_there_are_errors_test.dart
+++ b/test/lish/force_does_not_publish_if_there_are_errors_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -23,7 +21,7 @@
]).create();
await servePackages();
- var pub = await startPublish(globalPackageServer, args: ['--force']);
+ var pub = await startPublish(globalServer, args: ['--force']);
await pub.shouldExit(exit_codes.DATA);
expect(
diff --git a/test/lish/force_publishes_if_tests_are_no_warnings_or_errors_test.dart b/test/lish/force_publishes_if_tests_are_no_warnings_or_errors_test.dart
index 59c8233..c5d8957 100644
--- a/test/lish/force_publishes_if_tests_are_no_warnings_or_errors_test.dart
+++ b/test/lish/force_publishes_if_tests_are_no_warnings_or_errors_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -19,13 +17,13 @@
test('--force publishes if there are no warnings or errors', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer, args: ['--force']);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer, args: ['--force']);
- handleUploadForm(globalPackageServer);
- handleUpload(globalPackageServer);
+ handleUploadForm(globalServer);
+ handleUpload(globalServer);
- globalPackageServer.expect('GET', '/create', (request) {
+ globalServer.expect('GET', '/create', (request) {
return shelf.Response.ok(jsonEncode({
'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
}));
diff --git a/test/lish/force_publishes_if_there_are_warnings_test.dart b/test/lish/force_publishes_if_there_are_warnings_test.dart
index c217b29..9fb3d53 100644
--- a/test/lish/force_publishes_if_there_are_warnings_test.dart
+++ b/test/lish/force_publishes_if_there_are_warnings_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -24,13 +22,13 @@
await d.dir(appPath, [d.pubspec(pkg)]).create();
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer, args: ['--force']);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer, args: ['--force']);
- handleUploadForm(globalPackageServer);
- handleUpload(globalPackageServer);
+ handleUploadForm(globalServer);
+ handleUpload(globalServer);
- globalPackageServer.expect('GET', '/create', (request) {
+ globalServer.expect('GET', '/create', (request) {
return shelf.Response.ok(jsonEncode({
'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
}));
diff --git a/test/lish/many_files_test.dart b/test/lish/many_files_test.dart
index 02db6b2..36f4ed7 100644
--- a/test/lish/many_files_test.dart
+++ b/test/lish/many_files_test.dart
@@ -2,11 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'dart:io';
-import 'dart:math' as math;
import 'package:path/path.dart' as p;
import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -38,7 +35,7 @@
int argMax;
if (Platform.isWindows) {
// On Windows, the maximum argument list length is 8^5 bytes.
- argMax = math.pow(8, 5);
+ argMax = 32768; // 8^5
} else {
// On POSIX, the maximum argument list length can be retrieved
// automatically.
@@ -76,14 +73,14 @@
}
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- handleUploadForm(globalPackageServer);
- handleUpload(globalPackageServer);
+ handleUploadForm(globalServer);
+ handleUpload(globalServer);
- globalPackageServer.expect('GET', '/create', (request) {
+ globalServer.expect('GET', '/create', (request) {
return shelf.Response.ok(jsonEncode({
'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
}));
diff --git a/test/lish/package_creation_provides_a_malformed_error_test.dart b/test/lish/package_creation_provides_a_malformed_error_test.dart
index d78e495..7ab0bcd 100644
--- a/test/lish/package_creation_provides_a_malformed_error_test.dart
+++ b/test/lish/package_creation_provides_a_malformed_error_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:shelf/shelf.dart' as shelf;
@@ -18,15 +16,15 @@
test('package creation provides a malformed error', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- handleUploadForm(globalPackageServer);
- handleUpload(globalPackageServer);
+ handleUploadForm(globalServer);
+ handleUpload(globalServer);
var body = {'error': 'Your package was too boring.'};
- globalPackageServer.expect('GET', '/create', (request) {
+ globalServer.expect('GET', '/create', (request) {
return shelf.Response.notFound(jsonEncode(body));
});
diff --git a/test/lish/package_creation_provides_a_malformed_success_test.dart b/test/lish/package_creation_provides_a_malformed_success_test.dart
index 67c10ef..089d09e 100644
--- a/test/lish/package_creation_provides_a_malformed_success_test.dart
+++ b/test/lish/package_creation_provides_a_malformed_success_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:shelf/shelf.dart' as shelf;
@@ -18,15 +16,15 @@
test('package creation provides a malformed success', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- handleUploadForm(globalPackageServer);
- handleUpload(globalPackageServer);
+ handleUploadForm(globalServer);
+ handleUpload(globalServer);
var body = {'success': 'Your package was awesome.'};
- globalPackageServer.expect('GET', '/create', (request) {
+ globalServer.expect('GET', '/create', (request) {
return shelf.Response.ok(jsonEncode(body));
});
diff --git a/test/lish/package_creation_provides_an_error_test.dart b/test/lish/package_creation_provides_an_error_test.dart
index 49166c1..f5ff128 100644
--- a/test/lish/package_creation_provides_an_error_test.dart
+++ b/test/lish/package_creation_provides_an_error_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:shelf/shelf.dart' as shelf;
@@ -18,14 +16,14 @@
test('package creation provides an error', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- handleUploadForm(globalPackageServer);
- handleUpload(globalPackageServer);
+ handleUploadForm(globalServer);
+ handleUpload(globalServer);
- globalPackageServer.expect('GET', '/create', (request) {
+ globalServer.expect('GET', '/create', (request) {
return shelf.Response.notFound(jsonEncode({
'error': {'message': 'Your package was too boring.'}
}));
diff --git a/test/lish/package_creation_provides_invalid_json_test.dart b/test/lish/package_creation_provides_invalid_json_test.dart
index 8cdfd5b..2cd6212 100644
--- a/test/lish/package_creation_provides_invalid_json_test.dart
+++ b/test/lish/package_creation_provides_invalid_json_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:shelf/shelf.dart' as shelf;
import 'package:test/test.dart';
@@ -16,14 +14,14 @@
test('package creation provides invalid JSON', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- handleUploadForm(globalPackageServer);
- handleUpload(globalPackageServer);
+ handleUploadForm(globalServer);
+ handleUpload(globalServer);
- globalPackageServer.expect('GET', '/create', (request) {
+ globalServer.expect('GET', '/create', (request) {
return shelf.Response.ok('{not json');
});
diff --git a/test/lish/package_validation_has_a_warning_and_continues_test.dart b/test/lish/package_validation_has_a_warning_and_continues_test.dart
index ec55be9..c39dbc4 100644
--- a/test/lish/package_validation_has_a_warning_and_continues_test.dart
+++ b/test/lish/package_validation_has_a_warning_and_continues_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:pub/src/exit_codes.dart' as exit_codes;
@@ -24,13 +22,13 @@
await d.dir(appPath, [d.pubspec(pkg)]).create();
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
pub.stdin.writeln('y');
- handleUploadForm(globalPackageServer);
- handleUpload(globalPackageServer);
+ handleUploadForm(globalServer);
+ handleUpload(globalServer);
- globalPackageServer.expect('GET', '/create', (request) {
+ globalServer.expect('GET', '/create', (request) {
return shelf.Response.ok(jsonEncode({
'success': {'message': 'Package test_pkg 1.0.0 uploaded!'}
}));
diff --git a/test/lish/package_validation_has_a_warning_and_is_canceled_test.dart b/test/lish/package_validation_has_a_warning_and_is_canceled_test.dart
index fbdacc4..0d5a563 100644
--- a/test/lish/package_validation_has_a_warning_and_is_canceled_test.dart
+++ b/test/lish/package_validation_has_a_warning_and_is_canceled_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -20,7 +18,7 @@
await d.dir(appPath, [d.pubspec(pkg)]).create();
await servePackages();
- var pub = await startPublish(globalPackageServer);
+ var pub = await startPublish(globalServer);
pub.stdin.writeln('n');
await pub.shouldExit(exit_codes.DATA);
diff --git a/test/lish/package_validation_has_an_error_test.dart b/test/lish/package_validation_has_an_error_test.dart
index 9fab3a5..14c83c0 100644
--- a/test/lish/package_validation_has_an_error_test.dart
+++ b/test/lish/package_validation_has_an_error_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -23,7 +21,7 @@
]).create();
await servePackages();
- var pub = await startPublish(globalPackageServer);
+ var pub = await startPublish(globalServer);
await pub.shouldExit(exit_codes.DATA);
expect(
diff --git a/test/lish/preview_errors_if_private_test.dart b/test/lish/preview_errors_if_private_test.dart
index c816c6e..fb7160a 100644
--- a/test/lish/preview_errors_if_private_test.dart
+++ b/test/lish/preview_errors_if_private_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/lish/preview_package_validation_has_a_warning_test.dart b/test/lish/preview_package_validation_has_a_warning_test.dart
index c3aa01d..69f59af 100644
--- a/test/lish/preview_package_validation_has_a_warning_test.dart
+++ b/test/lish/preview_package_validation_has_a_warning_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -21,7 +19,7 @@
await d.dir(appPath, [d.pubspec(pkg)]).create();
await servePackages();
- var pub = await startPublish(globalPackageServer, args: ['--dry-run']);
+ var pub = await startPublish(globalServer, args: ['--dry-run']);
await pub.shouldExit(exit_codes.DATA);
expect(
diff --git a/test/lish/preview_package_validation_has_no_warnings_test.dart b/test/lish/preview_package_validation_has_no_warnings_test.dart
index 586708c..179c648 100644
--- a/test/lish/preview_package_validation_has_no_warnings_test.dart
+++ b/test/lish/preview_package_validation_has_no_warnings_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -19,8 +17,8 @@
packageMap('test_pkg', '1.0.0', null, null, {'sdk': '>=1.8.0 <2.0.0'});
await d.dir(appPath, [d.pubspec(pkg)]).create();
- await servePackages((_) {});
- var pub = await startPublish(globalPackageServer, args: ['--dry-run']);
+ await servePackages();
+ var pub = await startPublish(globalServer, args: ['--dry-run']);
await pub.shouldExit(exit_codes.SUCCESS);
expect(pub.stderr, emitsThrough('Package has 0 warnings.'));
diff --git a/test/lish/server_arg_does_not_override_private_test.dart b/test/lish/server_arg_does_not_override_private_test.dart
index baba7d6..58a1af1 100644
--- a/test/lish/server_arg_does_not_override_private_test.dart
+++ b/test/lish/server_arg_does_not_override_private_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/lish/server_arg_overrides_publish_to_url_test.dart b/test/lish/server_arg_overrides_publish_to_url_test.dart
index 508c0b3..1597146 100644
--- a/test/lish/server_arg_overrides_publish_to_url_test.dart
+++ b/test/lish/server_arg_overrides_publish_to_url_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -15,16 +13,15 @@
test('an explicit --server argument overrides a "publish_to" url', () async {
// Create a real server that can reject requests because validators will
// try to ping it, and will use multiple retries when doing so.
- final packageServer = await DescriptorServer.start();
- final fakePackageServer = 'http://localhost:${packageServer.port}';
+ final packageServer = await startPackageServer();
var pkg = packageMap('test_pkg', '1.0.0');
pkg['publish_to'] = 'http://pubspec.com';
await d.dir(appPath, [d.pubspec(pkg)]).create();
await runPub(
- args: ['lish', '--dry-run', '--server', fakePackageServer],
- output: contains(fakePackageServer),
+ args: ['lish', '--dry-run', '--server', packageServer.url],
+ output: contains(packageServer.url),
exitCode: exit_codes.DATA);
await packageServer.close();
diff --git a/test/lish/upload_form_fields_has_a_non_string_value_test.dart b/test/lish/upload_form_fields_has_a_non_string_value_test.dart
index 3ecb2fb..78a54fa 100644
--- a/test/lish/upload_form_fields_has_a_non_string_value_test.dart
+++ b/test/lish/upload_form_fields_has_a_non_string_value_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:test/test.dart';
@@ -16,9 +14,9 @@
setUp(d.validPackage.create);
test('upload form fields has a non-string value', () async {
- await servePackages((_) {});
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await servePackages();
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
@@ -26,7 +24,7 @@
'url': 'http://example.com/upload',
'fields': {'field': 12}
};
- handleUploadForm(globalPackageServer, body);
+ handleUploadForm(globalServer, body: body);
expect(pub.stderr, emits('Invalid server response:'));
expect(pub.stderr, emits(jsonEncode(body)));
await pub.shouldExit(1);
diff --git a/test/lish/upload_form_fields_is_not_a_map_test.dart b/test/lish/upload_form_fields_is_not_a_map_test.dart
index fed0f38..d18c1ee 100644
--- a/test/lish/upload_form_fields_is_not_a_map_test.dart
+++ b/test/lish/upload_form_fields_is_not_a_map_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:test/test.dart';
@@ -17,13 +15,13 @@
test('upload form fields is not a map', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
var body = {'url': 'http://example.com/upload', 'fields': 12};
- handleUploadForm(globalPackageServer, body);
+ handleUploadForm(globalServer, body: body);
expect(pub.stderr, emits('Invalid server response:'));
expect(pub.stderr, emits(jsonEncode(body)));
await pub.shouldExit(1);
diff --git a/test/lish/upload_form_is_missing_fields_test.dart b/test/lish/upload_form_is_missing_fields_test.dart
index a49b0d6..b0032f8 100644
--- a/test/lish/upload_form_is_missing_fields_test.dart
+++ b/test/lish/upload_form_is_missing_fields_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:test/test.dart';
@@ -17,13 +15,13 @@
test('upload form is missing fields', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
var body = {'url': 'http://example.com/upload'};
- handleUploadForm(globalPackageServer, body);
+ handleUploadForm(globalServer, body: body);
expect(pub.stderr, emits('Invalid server response:'));
expect(pub.stderr, emits(jsonEncode(body)));
await pub.shouldExit(1);
diff --git a/test/lish/upload_form_is_missing_url_test.dart b/test/lish/upload_form_is_missing_url_test.dart
index 50f5fa5..eae43ea 100644
--- a/test/lish/upload_form_is_missing_url_test.dart
+++ b/test/lish/upload_form_is_missing_url_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:test/test.dart';
@@ -17,8 +15,8 @@
test('upload form is missing url', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
@@ -26,7 +24,7 @@
'fields': {'field1': 'value1', 'field2': 'value2'}
};
- handleUploadForm(globalPackageServer, body);
+ handleUploadForm(globalServer, body: body);
expect(pub.stderr, emits('Invalid server response:'));
expect(pub.stderr, emits(jsonEncode(body)));
await pub.shouldExit(1);
diff --git a/test/lish/upload_form_provides_an_error_test.dart b/test/lish/upload_form_provides_an_error_test.dart
index c5fd41e..35932b8 100644
--- a/test/lish/upload_form_provides_an_error_test.dart
+++ b/test/lish/upload_form_provides_an_error_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:shelf/shelf.dart' as shelf;
@@ -16,15 +14,13 @@
setUp(d.validPackage.create);
test('upload form provides an error', () async {
- await servePackages((_) {});
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await servePackages();
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- globalPackageServer.extraHandlers['/api/packages/versions/new'] =
- expectAsync1((request) {
- expect(request.method, 'GET');
+ globalServer.expect('GET', '/api/packages/versions/new', (request) async {
return shelf.Response.notFound(jsonEncode({
'error': {'message': 'your request sucked'}
}));
diff --git a/test/lish/upload_form_provides_invalid_json_test.dart b/test/lish/upload_form_provides_invalid_json_test.dart
index a4fa5d7..a046755 100644
--- a/test/lish/upload_form_provides_invalid_json_test.dart
+++ b/test/lish/upload_form_provides_invalid_json_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:shelf/shelf.dart' as shelf;
import 'package:test/test.dart';
@@ -15,12 +13,12 @@
test('upload form provides invalid JSON', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- globalPackageServer.expect('GET', '/api/packages/versions/new',
+ globalServer.expect('GET', '/api/packages/versions/new',
(request) => shelf.Response.ok('{not json'));
expect(
diff --git a/test/lish/upload_form_url_is_not_a_string_test.dart b/test/lish/upload_form_url_is_not_a_string_test.dart
index 99909a4..f69fd1f 100644
--- a/test/lish/upload_form_url_is_not_a_string_test.dart
+++ b/test/lish/upload_form_url_is_not_a_string_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:test/test.dart';
@@ -17,8 +15,8 @@
test('upload form url is not a string', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
@@ -27,7 +25,7 @@
'fields': {'field1': 'value1', 'field2': 'value2'}
};
- handleUploadForm(globalPackageServer, body);
+ handleUploadForm(globalServer, body: body);
expect(pub.stderr, emits('Invalid server response:'));
expect(pub.stderr, emits(jsonEncode(body)));
await pub.shouldExit(1);
diff --git a/test/lish/uses_publish_to_url_test.dart b/test/lish/uses_publish_to_url_test.dart
index e7f9cf3..47496f7 100644
--- a/test/lish/uses_publish_to_url_test.dart
+++ b/test/lish/uses_publish_to_url_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/lish/utils.dart b/test/lish/utils.dart
index 5f18444..f134e4a 100644
--- a/test/lish/utils.dart
+++ b/test/lish/utils.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:shelf/shelf.dart' as shelf;
@@ -11,8 +9,8 @@
import '../test_pub.dart';
-void handleUploadForm(PackageServer server, [Map body]) {
- server.expect('GET', '/api/packages/versions/new', (request) {
+void handleUploadForm(PackageServer server, {Map? body, String path = ''}) {
+ server.expect('GET', '$path/api/packages/versions/new', (request) {
expect(
request.headers, containsPair('authorization', 'Bearer access token'));
diff --git a/test/list_package_dirs/ignores_updated_pubspec_test.dart b/test/list_package_dirs/ignores_updated_pubspec_test.dart
index edec570..2524681 100644
--- a/test/list_package_dirs/ignores_updated_pubspec_test.dart
+++ b/test/list_package_dirs/ignores_updated_pubspec_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/io.dart';
diff --git a/test/list_package_dirs/includes_dev_dependencies_test.dart b/test/list_package_dirs/includes_dev_dependencies_test.dart
index 10f4f56..61cc56b 100644
--- a/test/list_package_dirs/includes_dev_dependencies_test.dart
+++ b/test/list_package_dirs/includes_dev_dependencies_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/io.dart';
diff --git a/test/list_package_dirs/lists_dependency_directories_test.dart b/test/list_package_dirs/lists_dependency_directories_test.dart
index 5d5b982..2cd9664 100644
--- a/test/list_package_dirs/lists_dependency_directories_test.dart
+++ b/test/list_package_dirs/lists_dependency_directories_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/io.dart';
@@ -14,7 +12,8 @@
void main() {
test('prints the local paths to all packages in the lockfile', () async {
- await servePackages((builder) => builder.serve('bar', '1.0.0'));
+ final server = await servePackages()
+ ..serve('bar', '1.0.0');
await d
.dir('foo', [d.libDir('foo'), d.libPubspec('foo', '1.0.0')]).create();
@@ -39,7 +38,7 @@
'packages': {
'foo': path.join(d.sandbox, 'foo', 'lib'),
'bar': path.join(d.sandbox, cachePath, 'hosted',
- 'localhost%58${globalServer.port}', 'bar-1.0.0', 'lib'),
+ 'localhost%58${server.port}', 'bar-1.0.0', 'lib'),
'myapp': canonicalize(path.join(d.sandbox, appPath, 'lib'))
},
'input_files': [
diff --git a/test/list_package_dirs/lockfile_error_test.dart b/test/list_package_dirs/lockfile_error_test.dart
index 16860f4..f4440ec 100644
--- a/test/list_package_dirs/lockfile_error_test.dart
+++ b/test/list_package_dirs/lockfile_error_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/io.dart';
diff --git a/test/list_package_dirs/missing_pubspec_test.dart b/test/list_package_dirs/missing_pubspec_test.dart
index d3c61de..83a58c2 100644
--- a/test/list_package_dirs/missing_pubspec_test.dart
+++ b/test/list_package_dirs/missing_pubspec_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/io.dart';
diff --git a/test/list_package_dirs/no_lockfile_test.dart b/test/list_package_dirs/no_lockfile_test.dart
index 9e1078b..5939099 100644
--- a/test/list_package_dirs/no_lockfile_test.dart
+++ b/test/list_package_dirs/no_lockfile_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/list_package_dirs/pubspec_error_test.dart b/test/list_package_dirs/pubspec_error_test.dart
index 321e555..c282c5c 100644
--- a/test/list_package_dirs/pubspec_error_test.dart
+++ b/test/list_package_dirs/pubspec_error_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/io.dart';
diff --git a/test/lock_file_test.dart b/test/lock_file_test.dart
index 18edc94..4360c7c 100644
--- a/test/lock_file_test.dart
+++ b/test/lock_file_test.dart
@@ -2,8 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
+import 'package:pub/src/language_version.dart';
import 'package:pub/src/lock_file.dart';
import 'package:pub/src/package_name.dart';
import 'package:pub/src/source.dart';
@@ -22,14 +21,15 @@
throw UnsupportedError('Cannot download fake packages.');
@override
- PackageRef parseRef(String name, description, {String containingPath}) {
+ PackageRef parseRef(String name, description,
+ {String? containingPath, LanguageVersion? languageVersion}) {
if (!description.endsWith(' desc')) throw FormatException('Bad');
return PackageRef(name, this, description);
}
@override
PackageId parseId(String name, Version version, description,
- {String containingPath}) {
+ {String? containingPath}) {
if (!description.endsWith(' desc')) throw FormatException('Bad');
return PackageId(name, this, version, description);
}
@@ -79,13 +79,13 @@
expect(lockFile.packages.length, equals(2));
- var bar = lockFile.packages['bar'];
+ var bar = lockFile.packages['bar']!;
expect(bar.name, equals('bar'));
expect(bar.version, equals(Version(1, 2, 3)));
expect(bar.source, equals(fakeSource));
expect(bar.description, equals('bar desc'));
- var foo = lockFile.packages['foo'];
+ var foo = lockFile.packages['foo']!;
expect(foo.name, equals('foo'));
expect(foo.version, equals(Version(2, 3, 4)));
expect(foo.source, equals(fakeSource));
@@ -100,7 +100,7 @@
version: 1.2.3
description: foo desc
''', sources);
- var foo = lockFile.packages['foo'];
+ var foo = lockFile.packages['foo']!;
expect(foo.source, equals(sources['bad']));
});
@@ -261,7 +261,7 @@
});
expect(
- loadYaml(lockfile.serialize(null)),
+ loadYaml(lockfile.serialize('')),
equals({
'sdks': {'dart': 'any'},
'packages': {
diff --git a/test/must_pub_get_test.dart b/test/must_pub_get_test.dart
index edea182..71d9c16 100644
--- a/test/must_pub_get_test.dart
+++ b/test/must_pub_get_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:convert';
import 'dart:io';
@@ -16,12 +14,14 @@
import 'descriptor.dart' as d;
import 'test_pub.dart';
+late PackageServer server;
+
void main() {
setUp(() async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- });
+ server = await servePackages();
+
+ server.serve('foo', '1.0.0');
+ server.serve('foo', '2.0.0');
await d.dir(appPath, [
d.appPubspec(),
@@ -213,7 +213,7 @@
d.appPubspec({'foo': '1.0.0'})
]).create();
- await pubGet();
+ await pubGet(args: ['--legacy-packages-file']);
deleteEntry(p.join(d.sandbox, cachePath));
@@ -235,7 +235,7 @@
})
]).create();
- await pubGet();
+ await pubGet(args: ['--legacy-packages-file']);
await createPackagesFile(appPath);
@@ -257,7 +257,7 @@
})
]).create();
- await pubGet();
+ await pubGet(args: ['--legacy-packages-file']);
await d.dir(appPath, [
d.file('.packages', '''
@@ -284,7 +284,7 @@
})
]).create();
- await pubGet();
+ await pubGet(args: ['--legacy-packages-file']);
await createPackagesFile(appPath, dependenciesInSandBox: ['foo']);
@@ -334,10 +334,8 @@
setUp(() async {
// Avoid using a path dependency because it triggers the full validation
// logic. We want to be sure SDK-validation works without that logic.
- globalPackageServer.add((builder) {
- builder.serve('foo', '3.0.0', pubspec: {
- 'environment': {'sdk': '>=1.0.0 <2.0.0'}
- });
+ server.serve('foo', '3.0.0', pubspec: {
+ 'environment': {'sdk': '>=1.0.0 <2.0.0'}
});
await d.dir(appPath, [
@@ -362,10 +360,8 @@
'current Flutter SDK', () async {
// Avoid using a path dependency because it triggers the full validation
// logic. We want to be sure SDK-validation works without that logic.
- globalPackageServer.add((builder) {
- builder.serve('foo', '3.0.0', pubspec: {
- 'environment': {'flutter': '>=1.0.0 <2.0.0'}
- });
+ server.serve('foo', '3.0.0', pubspec: {
+ 'environment': {'flutter': '>=1.0.0 <2.0.0'}
});
await d.dir('flutter', [d.file('version', '1.2.3')]).create();
@@ -456,7 +452,7 @@
group("doesn't require the user to run pub get first if", () {
group(
'the pubspec is older than the lockfile which is older than the '
- 'packages file, even if the contents are wrong', () {
+ 'package-config, even if the contents are wrong', () {
setUp(() async {
await d.dir(appPath, [
d.appPubspec({'foo': '1.0.0'})
@@ -465,7 +461,6 @@
await _touch('pubspec.yaml');
await _touch('pubspec.lock');
- await _touch('.packages');
await _touch('.dart_tool/package_config.json');
});
@@ -524,10 +519,8 @@
group("an overridden dependency's SDK constraint is unmatched", () {
setUp(() async {
- globalPackageServer.add((builder) {
- builder.serve('bar', '1.0.0', pubspec: {
- 'environment': {'sdk': '0.0.0-fake'}
- });
+ server.serve('bar', '1.0.0', pubspec: {
+ 'environment': {'sdk': '0.0.0-fake'}
});
await d.dir(appPath, [
@@ -549,10 +542,8 @@
() async {
// Avoid using a path dependency because it triggers the full validation
// logic. We want to be sure SDK-validation works without that logic.
- globalPackageServer.add((builder) {
- builder.serve('foo', '3.0.0', pubspec: {
- 'environment': {'flutter': '>=1.0.0 <2.0.0'}
- });
+ server.serve('foo', '3.0.0', pubspec: {
+ 'environment': {'flutter': '>=1.0.0 <2.0.0'}
});
await d.dir('flutter', [d.file('version', '1.2.3')]).create();
@@ -608,14 +599,11 @@
File(p.join(d.sandbox, 'myapp/pubspec.yaml')).lastModifiedSync();
var lockFileModified =
File(p.join(d.sandbox, 'myapp/pubspec.lock')).lastModifiedSync();
- var packagesModified =
- File(p.join(d.sandbox, 'myapp/.packages')).lastModifiedSync();
var packageConfigModified =
File(p.join(d.sandbox, 'myapp/.dart_tool/package_config.json'))
.lastModifiedSync();
expect(!pubspecModified.isAfter(lockFileModified), isTrue);
- expect(!lockFileModified.isAfter(packagesModified), isTrue);
expect(!lockFileModified.isAfter(packageConfigModified), isTrue);
});
}
diff --git a/test/no_packages_dir_test.dart b/test/no_packages_dir_test.dart
index cdd6351..3a88bc5 100644
--- a/test/no_packages_dir_test.dart
+++ b/test/no_packages_dir_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import 'descriptor.dart' as d;
diff --git a/test/oauth2/logout_test.dart b/test/oauth2/logout_test.dart
index 81d4125..a12a652 100644
--- a/test/oauth2/logout_test.dart
+++ b/test/oauth2/logout_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
@@ -13,7 +11,7 @@
test('with an existing credentials file, deletes it.', () async {
await servePackages();
await d
- .credentialsFile(globalPackageServer, 'access token',
+ .credentialsFile(globalServer, 'access token',
refreshToken: 'refresh token',
expiration: DateTime.now().add(Duration(hours: 1)))
.create();
@@ -30,7 +28,7 @@
await servePackages();
await d
.credentialsFile(
- globalPackageServer,
+ globalServer,
'access token',
refreshToken: 'refresh token',
expiration: DateTime.now().add(Duration(hours: 1)),
@@ -39,7 +37,7 @@
await d
.legacyCredentialsFile(
- globalPackageServer,
+ globalServer,
'access token',
refreshToken: 'refresh token',
expiration: DateTime.now().add(Duration(hours: 1)),
diff --git a/test/oauth2/utils.dart b/test/oauth2/utils.dart
index b7d765e..dab8c92 100644
--- a/test/oauth2/utils.dart
+++ b/test/oauth2/utils.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:convert';
@@ -24,10 +22,10 @@
var line = await pub.stdout.next;
var match =
- RegExp(r'[?&]redirect_uri=([0-9a-zA-Z.%+-]+)[$&]').firstMatch(line);
+ RegExp(r'[?&]redirect_uri=([0-9a-zA-Z.%+-]+)[$&]').firstMatch(line)!;
expect(match, isNotNull);
- var redirectUrl = Uri.parse(Uri.decodeComponent(match.group(1)));
+ var redirectUrl = Uri.parse(Uri.decodeComponent(match.group(1)!));
redirectUrl = _addQueryParameters(redirectUrl, {'code': 'access code'});
// Expect the /token request
@@ -61,8 +59,8 @@
}
/// Convert a [Map] from parameter names to values to a URL query string.
-String _mapToQuery(Map<String, String> map) {
- var pairs = <List<String>>[];
+String _mapToQuery(Map<String, String?> map) {
+ var pairs = <List<String?>>[];
map.forEach((key, value) {
key = Uri.encodeQueryComponent(key);
value = (value == null || value.isEmpty)
diff --git a/test/oauth2/with_a_malformed_credentials_authenticates_again_test.dart b/test/oauth2/with_a_malformed_credentials_authenticates_again_test.dart
index 5585526..75b47ab 100644
--- a/test/oauth2/with_a_malformed_credentials_authenticates_again_test.dart
+++ b/test/oauth2/with_a_malformed_credentials_authenticates_again_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:shelf/shelf.dart' as shelf;
import 'package:test/test.dart';
@@ -21,11 +19,11 @@
await d.dir(
configPath, [d.file('pub-credentials.json', '{bad json')]).create();
- var pub = await startPublish(globalPackageServer);
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- await authorizePub(pub, globalPackageServer, 'new access token');
+ await authorizePub(pub, globalServer, 'new access token');
- globalPackageServer.expect('GET', '/api/packages/versions/new', (request) {
+ globalServer.expect('GET', '/api/packages/versions/new', (request) {
expect(request.headers,
containsPair('authorization', 'Bearer new access token'));
@@ -36,6 +34,6 @@
// do so rather than killing it so it'll write out the credentials file.
await pub.shouldExit(1);
- await d.credentialsFile(globalPackageServer, 'new access token').validate();
+ await d.credentialsFile(globalServer, 'new access token').validate();
});
}
diff --git a/test/oauth2/with_a_pre_existing_credentials_does_not_authenticate_test.dart b/test/oauth2/with_a_pre_existing_credentials_does_not_authenticate_test.dart
index ad6559f..3c22994 100644
--- a/test/oauth2/with_a_pre_existing_credentials_does_not_authenticate_test.dart
+++ b/test/oauth2/with_a_pre_existing_credentials_does_not_authenticate_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
@@ -14,8 +12,8 @@
await d.validPackage.create();
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
diff --git a/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart b/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart
index 3354bbc..624f427 100644
--- a/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart
+++ b/test/oauth2/with_a_server_rejected_refresh_token_authenticates_again_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:convert';
@@ -23,14 +21,14 @@
await servePackages();
await d
- .credentialsFile(globalPackageServer, 'access token',
+ .credentialsFile(globalServer, 'access token',
refreshToken: 'bad refresh token',
expiration: DateTime.now().subtract(Duration(hours: 1)))
.create();
- var pub = await startPublish(globalPackageServer);
+ var pub = await startPublish(globalServer);
- globalPackageServer.expect('POST', '/token', (request) {
+ globalServer.expect('POST', '/token', (request) {
return request.read().drain().then((_) {
return shelf.Response(400,
body: jsonEncode({'error': 'invalid_request'}),
@@ -41,11 +39,10 @@
await confirmPublish(pub);
await expectLater(pub.stdout, emits(startsWith('Uploading...')));
- await authorizePub(pub, globalPackageServer, 'new access token');
+ await authorizePub(pub, globalServer, 'new access token');
var done = Completer();
- globalPackageServer.expect('GET', '/api/packages/versions/new',
- (request) async {
+ globalServer.expect('GET', '/api/packages/versions/new', (request) async {
expect(request.headers,
containsPair('authorization', 'Bearer new access token'));
diff --git a/test/oauth2/with_an_expired_credentials_refreshes_and_saves_test.dart b/test/oauth2/with_an_expired_credentials_refreshes_and_saves_test.dart
index 16062a7..7fbbb9f 100644
--- a/test/oauth2/with_an_expired_credentials_refreshes_and_saves_test.dart
+++ b/test/oauth2/with_an_expired_credentials_refreshes_and_saves_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:shelf/shelf.dart' as shelf;
@@ -20,15 +18,15 @@
await servePackages();
await d
- .credentialsFile(globalPackageServer, 'access token',
+ .credentialsFile(globalServer, 'access token',
refreshToken: 'refresh token',
expiration: DateTime.now().subtract(Duration(hours: 1)))
.create();
- var pub = await startPublish(globalPackageServer);
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- globalPackageServer.expect('POST', '/token', (request) {
+ globalServer.expect('POST', '/token', (request) {
return request.readAsString().then((body) {
expect(
body, matches(RegExp(r'(^|&)refresh_token=refresh\+token(&|$)')));
@@ -40,7 +38,7 @@
});
});
- globalPackageServer.expect('GET', '/api/packages/versions/new', (request) {
+ globalServer.expect('GET', '/api/packages/versions/new', (request) {
expect(request.headers,
containsPair('authorization', 'Bearer new access token'));
@@ -50,7 +48,7 @@
await pub.shouldExit();
await d
- .credentialsFile(globalPackageServer, 'new access token',
+ .credentialsFile(globalServer, 'new access token',
refreshToken: 'refresh token')
.validate();
});
diff --git a/test/oauth2/with_an_expired_credentials_without_a_refresh_token_authenticates_again_test.dart b/test/oauth2/with_an_expired_credentials_without_a_refresh_token_authenticates_again_test.dart
index 6437a5c..803c529 100644
--- a/test/oauth2/with_an_expired_credentials_without_a_refresh_token_authenticates_again_test.dart
+++ b/test/oauth2/with_an_expired_credentials_without_a_refresh_token_authenticates_again_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:shelf/shelf.dart' as shelf;
import 'package:test/test.dart';
@@ -19,20 +17,20 @@
await servePackages();
await d
- .credentialsFile(globalPackageServer, 'access token',
+ .credentialsFile(globalServer, 'access token',
expiration: DateTime.now().subtract(Duration(hours: 1)))
.create();
- var pub = await startPublish(globalPackageServer);
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
await expectLater(
pub.stderr,
emits("Pub's authorization to upload packages has expired and "
"can't be automatically refreshed."));
- await authorizePub(pub, globalPackageServer, 'new access token');
+ await authorizePub(pub, globalServer, 'new access token');
- globalPackageServer.expect('GET', '/api/packages/versions/new', (request) {
+ globalServer.expect('GET', '/api/packages/versions/new', (request) {
expect(request.headers,
containsPair('authorization', 'Bearer new access token'));
@@ -43,6 +41,6 @@
// do so rather than killing it so it'll write out the credentials file.
await pub.shouldExit(1);
- await d.credentialsFile(globalPackageServer, 'new access token').validate();
+ await d.credentialsFile(globalServer, 'new access token').validate();
});
}
diff --git a/test/oauth2/with_no_credentials_authenticates_and_saves_credentials_test.dart b/test/oauth2/with_no_credentials_authenticates_and_saves_credentials_test.dart
index 2106960..961a465 100644
--- a/test/oauth2/with_no_credentials_authenticates_and_saves_credentials_test.dart
+++ b/test/oauth2/with_no_credentials_authenticates_and_saves_credentials_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:shelf/shelf.dart' as shelf;
import 'package:test/test.dart';
@@ -18,11 +16,11 @@
await d.validPackage.create();
await servePackages();
- var pub = await startPublish(globalPackageServer);
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- await authorizePub(pub, globalPackageServer);
+ await authorizePub(pub, globalServer);
- globalPackageServer.expect('GET', '/api/packages/versions/new', (request) {
+ globalServer.expect('GET', '/api/packages/versions/new', (request) {
expect(request.headers,
containsPair('authorization', 'Bearer access token'));
@@ -33,6 +31,6 @@
// do so rather than killing it so it'll write out the credentials file.
await pub.shouldExit(1);
- await d.credentialsFile(globalPackageServer, 'access token').validate();
+ await d.credentialsFile(globalServer, 'access token').validate();
});
}
diff --git a/test/oauth2/with_server_rejected_credentials_authenticates_again_test.dart b/test/oauth2/with_server_rejected_credentials_authenticates_again_test.dart
index 9ef5e69..2e3b62f 100644
--- a/test/oauth2/with_server_rejected_credentials_authenticates_again_test.dart
+++ b/test/oauth2/with_server_rejected_credentials_authenticates_again_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:shelf/shelf.dart' as shelf;
@@ -18,12 +16,12 @@
'credentials.json', () async {
await d.validPackage.create();
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPublish(globalPackageServer);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPublish(globalServer);
await confirmPublish(pub);
- globalPackageServer.expect('GET', '/api/packages/versions/new', (request) {
+ globalServer.expect('GET', '/api/packages/versions/new', (request) {
return shelf.Response(401,
body: jsonEncode({
'error': {'message': 'your token sucks'}
diff --git a/test/outdated/goldens/bad_arguments.txt b/test/outdated/goldens/bad_arguments.txt
deleted file mode 100644
index b184530..0000000
--- a/test/outdated/goldens/bad_arguments.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-$ pub outdated random_argument
-[ERR] Command "outdated" does not take any arguments.
-[ERR]
-[ERR] Usage: pub outdated [options]
-[ERR] -h, --help Print this usage information.
-[ERR] --[no-]color Whether to color the output.
-[ERR] Defaults to color when connected to a
-[ERR] terminal, and no-color otherwise.
-[ERR] --[no-]dependency-overrides Show resolutions with `dependency_overrides`.
-[ERR] (defaults to on)
-[ERR] --[no-]dev-dependencies Take dev dependencies into account.
-[ERR] (defaults to on)
-[ERR] --json Output the results using a json format.
-[ERR] --mode=<PROPERTY> Highlight versions with PROPERTY.
-[ERR] Only packages currently missing that PROPERTY
-[ERR] will be included unless --show-all.
-[ERR] [outdated (default), null-safety]
-[ERR] --[no-]prereleases Include prereleases in latest version.
-[ERR] (defaults to on in --mode=null-safety).
-[ERR] --[no-]show-all Include dependencies that are already
-[ERR] fullfilling --mode.
-[ERR] --[no-]transitive Show transitive dependencies.
-[ERR] (defaults to off in --mode=null-safety).
-[ERR] -C, --directory=<dir> Run this in the directory<dir>.
-[ERR]
-[ERR] Run "pub help" to see global options.
-[ERR] See https://dart.dev/tools/pub/cmd/pub-outdated for detailed documentation.
-[Exit code] 64
-
-$ pub outdated --bad_flag
-[ERR] Could not find an option named "bad_flag".
-[ERR]
-[ERR] Usage: pub outdated [options]
-[ERR] -h, --help Print this usage information.
-[ERR] --[no-]color Whether to color the output.
-[ERR] Defaults to color when connected to a
-[ERR] terminal, and no-color otherwise.
-[ERR] --[no-]dependency-overrides Show resolutions with `dependency_overrides`.
-[ERR] (defaults to on)
-[ERR] --[no-]dev-dependencies Take dev dependencies into account.
-[ERR] (defaults to on)
-[ERR] --json Output the results using a json format.
-[ERR] --mode=<PROPERTY> Highlight versions with PROPERTY.
-[ERR] Only packages currently missing that PROPERTY
-[ERR] will be included unless --show-all.
-[ERR] [outdated (default), null-safety]
-[ERR] --[no-]prereleases Include prereleases in latest version.
-[ERR] (defaults to on in --mode=null-safety).
-[ERR] --[no-]show-all Include dependencies that are already
-[ERR] fullfilling --mode.
-[ERR] --[no-]transitive Show transitive dependencies.
-[ERR] (defaults to off in --mode=null-safety).
-[ERR] -C, --directory=<dir> Run this in the directory<dir>.
-[ERR]
-[ERR] Run "pub help" to see global options.
-[ERR] See https://dart.dev/tools/pub/cmd/pub-outdated for detailed documentation.
-[Exit code] 64
-
diff --git a/test/outdated/goldens/no_pubspec.txt b/test/outdated/goldens/no_pubspec.txt
deleted file mode 100644
index ec3a40a..0000000
--- a/test/outdated/goldens/no_pubspec.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-$ pub outdated
-[ERR] Could not find a file named "pubspec.yaml" in "$SANDBOX/myapp".
-[Exit code] 66
-
diff --git a/test/outdated/outdated_test.dart b/test/outdated/outdated_test.dart
index 925e0de..31113c7 100644
--- a/test/outdated/outdated_test.dart
+++ b/test/outdated/outdated_test.dart
@@ -2,75 +2,67 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
-import 'package:test/test.dart';
import '../descriptor.dart' as d;
import '../golden_file.dart';
import '../test_pub.dart';
-/// Try running 'pub outdated' with a number of different sets of arguments.
-///
-/// Compare the stdout and stderr output to the file in goldens/$[name].
-Future<void> variations(String name, {Map<String, String> environment}) async {
- final buffer = StringBuffer();
- for (final args in [
- ['outdated', '--json'],
- ['outdated', '--no-color'],
- ['outdated', '--no-color', '--no-transitive'],
- ['outdated', '--no-color', '--up-to-date'],
- ['outdated', '--no-color', '--prereleases'],
- ['outdated', '--no-color', '--no-dev-dependencies'],
- ['outdated', '--no-color', '--no-dependency-overrides'],
- ['outdated', '--no-color', '--mode=null-safety'],
- ['outdated', '--no-color', '--mode=null-safety', '--transitive'],
- ['outdated', '--no-color', '--mode=null-safety', '--no-prereleases'],
- ['outdated', '--json', '--mode=null-safety'],
- ['outdated', '--json', '--no-dev-dependencies'],
- ]) {
- await runPubIntoBuffer(args, buffer, environment: environment);
+extension on GoldenTestContext {
+ /// Try running 'pub outdated' with a number of different sets of arguments.
+ /// And compare to results from test/testdata/goldens/...
+ Future<void> runOutdatedTests({
+ Map<String, String>? environment,
+ String? workingDirectory,
+ }) async {
+ const commands = [
+ ['outdated', '--json'],
+ ['outdated', '--no-color'],
+ ['outdated', '--no-color', '--no-transitive'],
+ ['outdated', '--no-color', '--up-to-date'],
+ ['outdated', '--no-color', '--prereleases'],
+ ['outdated', '--no-color', '--no-dev-dependencies'],
+ ['outdated', '--no-color', '--no-dependency-overrides'],
+ ['outdated', '--no-color', '--mode=null-safety'],
+ ['outdated', '--no-color', '--mode=null-safety', '--transitive'],
+ ['outdated', '--no-color', '--mode=null-safety', '--no-prereleases'],
+ ['outdated', '--json', '--mode=null-safety'],
+ ['outdated', '--json', '--no-dev-dependencies'],
+ ];
+ for (final args in commands) {
+ await run(
+ args,
+ environment: environment,
+ workingDirectory: workingDirectory,
+ );
+ }
}
- // The easiest way to update the golden files is to delete them and rerun the
- // test.
- expectMatchesGoldenFile(buffer.toString(), 'test/outdated/goldens/$name.txt');
}
Future<void> main() async {
- test('help text', () async {
- final buffer = StringBuffer();
- await runPubIntoBuffer(
- ['outdated', '--help'],
- buffer,
- );
- expectMatchesGoldenFile(
- buffer.toString(), 'test/outdated/goldens/helptext.txt');
- });
-
- test('no pubspec', () async {
+ testWithGolden('no pubspec', (ctx) async {
await d.dir(appPath, []).create();
- final buffer = StringBuffer();
- await runPubIntoBuffer(['outdated'], buffer);
- expectMatchesGoldenFile(
- buffer.toString(), 'test/outdated/goldens/no_pubspec.txt');
+ await ctx.run(['outdated']);
});
- test('no lockfile', () async {
+ testWithGolden('no lockfile', (ctx) async {
await d.appDir({'foo': '^1.0.0', 'bar': '^1.0.0'}).create();
- await servePackages((builder) => builder
+ await servePackages()
..serve('foo', '1.2.3')
..serve('bar', '1.2.3')
- ..serve('bar', '2.0.0'));
- await variations('no_lockfile');
+ ..serve('bar', '2.0.0');
+
+ await ctx.runOutdatedTests();
});
- test('no dependencies', () async {
+ testWithGolden('no dependencies', (ctx) async {
await d.appDir().create();
await pubGet();
- await variations('no_dependencies');
+
+ await ctx.runOutdatedTests();
});
- test('newer versions available', () async {
- await servePackages((builder) => builder
+ testWithGolden('newer versions available', (ctx) async {
+ final builder = await servePackages();
+ builder
..serve('foo', '1.2.3', deps: {'transitive': '^1.0.0'})
..serve('bar', '1.0.0')
..serve('builder', '1.2.3', deps: {
@@ -78,7 +70,7 @@
'dev_trans': '^1.0.0',
})
..serve('transitive', '1.2.3')
- ..serve('dev_trans', '1.0.0'));
+ ..serve('dev_trans', '1.0.0');
await d.dir('local_package', [
d.libDir('local_package'),
@@ -97,7 +89,7 @@
})
]).create();
await pubGet();
- globalPackageServer.add((builder) => builder
+ builder
..serve('foo', '1.3.0', deps: {'transitive': '>=1.0.0<3.0.0'})
..serve('foo', '2.0.0',
deps: {'transitive': '>=1.0.0<3.0.0', 'transitive2': '^1.0.0'})
@@ -113,14 +105,13 @@
..serve('transitive', '2.0.0')
..serve('transitive2', '1.0.0')
..serve('transitive3', '1.0.0')
- ..serve('dev_trans', '2.0.0'));
- await variations('newer_versions');
+ ..serve('dev_trans', '2.0.0');
+ await ctx.runOutdatedTests();
});
- test('circular dependency on root', () async {
- await servePackages(
- (builder) => builder..serve('foo', '1.2.3', deps: {'app': '^1.0.0'}),
- );
+ testWithGolden('circular dependency on root', (ctx) async {
+ final server = await servePackages();
+ server.serve('foo', '1.2.3', deps: {'app': '^1.0.0'});
await d.dir(appPath, [
d.pubspec({
@@ -134,13 +125,11 @@
await pubGet();
- globalPackageServer.add(
- (builder) => builder..serve('foo', '1.3.0', deps: {'app': '^1.0.1'}),
- );
- await variations('circular_dependencies');
+ server.serve('foo', '1.3.0', deps: {'app': '^1.0.1'});
+ await ctx.runOutdatedTests();
});
- test('mutually incompatible newer versions', () async {
+ testWithGolden('mutually incompatible newer versions', (ctx) async {
await d.dir(appPath, [
d.pubspec({
'name': 'app',
@@ -152,17 +141,17 @@
})
]).create();
- await servePackages((builder) => builder
+ await servePackages()
..serve('foo', '1.0.0', deps: {'bar': '^1.0.0'})
..serve('bar', '1.0.0', deps: {'foo': '^1.0.0'})
..serve('foo', '2.0.0', deps: {'bar': '^1.0.0'})
- ..serve('bar', '2.0.0', deps: {'foo': '^1.0.0'}));
+ ..serve('bar', '2.0.0', deps: {'foo': '^1.0.0'});
await pubGet();
- await variations('mutually_incompatible');
+ await ctx.runOutdatedTests();
});
- test('null safety compliance', () async {
+ testWithGolden('null safety compliance', (ctx) async {
await d.dir(appPath, [
d.pubspec({
'name': 'app',
@@ -179,70 +168,69 @@
}),
]).create();
- await servePackages(
- (builder) => builder
- ..serve('foo', '1.0.0', deps: {
- 'bar': '^1.0.0'
- }, pubspec: {
- 'environment': {'sdk': '>=2.9.0 < 3.0.0'}
- })
- ..serve('bar', '1.0.0', pubspec: {
- 'environment': {'sdk': '>=2.9.0 < 3.0.0'}
- })
- ..serve('foo', '2.0.0-nullsafety.0', deps: {
- 'bar': '^2.0.0'
- }, pubspec: {
- 'environment': {'sdk': '>=2.12.0 < 3.0.0'}
- })
- ..serve('foo', '2.0.0', deps: {
- 'bar': '^1.0.0'
- }, pubspec: {
- 'environment': {'sdk': '>=2.12.0 < 3.0.0'}
- })
- ..serve('bar', '2.0.0', pubspec: {
- 'environment': {'sdk': '>=2.13.0 < 3.0.0'}
- })
- ..serve('file_opts_out', '1.0.0', pubspec: {
- 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
- }, contents: [
- d.dir('lib', [d.file('main.dart', '// @dart = 2.9\n')])
- ])
- ..serve('file_opts_out', '2.0.0', pubspec: {
- 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
- })
- ..serve('fails_analysis', '1.0.0', pubspec: {
- 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
- }, contents: [
- d.dir('lib', [d.file('main.dart', 'syntax error\n')])
- ])
- ..serve('fails_analysis', '2.0.0', pubspec: {
- 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
- })
- ..serve('file_in_dependency_opts_out', '1.0.0', deps: {
- 'file_opts_out': '^1.0.0'
- }, pubspec: {
- 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
- })
- ..serve('file_in_dependency_opts_out', '2.0.0', pubspec: {
- 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
- })
- ..serve('fails_analysis_in_dependency', '1.0.0', deps: {
- 'fails_analysis': '^1.0.0'
- }, pubspec: {
- 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
- })
- ..serve('fails_analysis_in_dependency', '2.0.0', pubspec: {
- 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
- }),
- );
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {
+ 'bar': '^1.0.0'
+ }, pubspec: {
+ 'environment': {'sdk': '>=2.9.0 < 3.0.0'}
+ })
+ ..serve('bar', '1.0.0', pubspec: {
+ 'environment': {'sdk': '>=2.9.0 < 3.0.0'}
+ })
+ ..serve('foo', '2.0.0-nullsafety.0', deps: {
+ 'bar': '^2.0.0'
+ }, pubspec: {
+ 'environment': {'sdk': '>=2.12.0 < 3.0.0'}
+ })
+ ..serve('foo', '2.0.0', deps: {
+ 'bar': '^1.0.0'
+ }, pubspec: {
+ 'environment': {'sdk': '>=2.12.0 < 3.0.0'}
+ })
+ ..serve('bar', '2.0.0', pubspec: {
+ 'environment': {'sdk': '>=2.13.0 < 3.0.0'}
+ })
+ ..serve('file_opts_out', '1.0.0', pubspec: {
+ 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+ }, contents: [
+ d.dir('lib', [d.file('main.dart', '// @dart = 2.9\n')])
+ ])
+ ..serve('file_opts_out', '2.0.0', pubspec: {
+ 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+ })
+ ..serve('fails_analysis', '1.0.0', pubspec: {
+ 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+ }, contents: [
+ d.dir('lib', [d.file('main.dart', 'syntax error\n')])
+ ])
+ ..serve('fails_analysis', '2.0.0', pubspec: {
+ 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+ })
+ ..serve('file_in_dependency_opts_out', '1.0.0', deps: {
+ 'file_opts_out': '^1.0.0'
+ }, pubspec: {
+ 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+ })
+ ..serve('file_in_dependency_opts_out', '2.0.0', pubspec: {
+ 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+ })
+ ..serve('fails_analysis_in_dependency', '1.0.0', deps: {
+ 'fails_analysis': '^1.0.0'
+ }, pubspec: {
+ 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+ })
+ ..serve('fails_analysis_in_dependency', '2.0.0', pubspec: {
+ 'environment': {'sdk': '>=2.12.0 < 3.0.0'},
+ });
await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '2.13.0'});
- await variations('null_safety',
- environment: {'_PUB_TEST_SDK_VERSION': '2.13.0'});
+ await ctx.runOutdatedTests(environment: {
+ '_PUB_TEST_SDK_VERSION': '2.13.0',
+ });
});
- test('null-safety no resolution', () async {
- await servePackages((builder) => builder
+ testWithGolden('null-safety no resolution', (ctx) async {
+ await servePackages()
..serve('foo', '1.0.0', pubspec: {
'environment': {'sdk': '>=2.9.0 < 3.0.0'}
})
@@ -258,7 +246,7 @@
'foo': '^1.0.0'
}, pubspec: {
'environment': {'sdk': '>=2.12.0 < 3.0.0'}
- }));
+ });
await d.dir(appPath, [
d.pubspec({
@@ -274,12 +262,13 @@
await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '2.13.0'});
- await variations('null_safety_no_resolution',
- environment: {'_PUB_TEST_SDK_VERSION': '2.13.0'});
+ await ctx.runOutdatedTests(environment: {
+ '_PUB_TEST_SDK_VERSION': '2.13.0',
+ });
});
- test('null-safety already migrated', () async {
- await servePackages((builder) => builder
+ testWithGolden('null-safety already migrated', (ctx) async {
+ await servePackages()
..serve('foo', '1.0.0', pubspec: {
'environment': {'sdk': '>=2.9.0 < 3.0.0'}
})
@@ -296,7 +285,7 @@
})
..serve('devTransitive', '1.0.0', pubspec: {
'environment': {'sdk': '>=2.9.0 < 3.0.0'}
- }));
+ });
await d.dir(appPath, [
d.pubspec({
@@ -314,21 +303,20 @@
await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '2.13.0'});
- await variations('null_safety_already_migrated',
- environment: {'_PUB_TEST_SDK_VERSION': '2.13.0'});
+ await ctx.runOutdatedTests(environment: {
+ '_PUB_TEST_SDK_VERSION': '2.13.0',
+ });
});
- test('overridden dependencies', () async {
+ testWithGolden('overridden dependencies', (ctx) async {
ensureGit();
- await servePackages(
- (builder) => builder
- ..serve('foo', '1.0.0')
- ..serve('foo', '2.0.0', deps: {'bar': '^1.0.0'})
- ..serve('bar', '1.0.0')
- ..serve('bar', '2.0.0')
- ..serve('baz', '1.0.0')
- ..serve('baz', '2.0.0'),
- );
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0', deps: {'bar': '^1.0.0'})
+ ..serve('bar', '1.0.0')
+ ..serve('bar', '2.0.0')
+ ..serve('baz', '1.0.0')
+ ..serve('baz', '2.0.0');
await d.git('foo.git', [
d.libPubspec('foo', '1.0.1'),
@@ -359,18 +347,16 @@
await pubGet();
- await variations('dependency_overrides');
+ await ctx.runOutdatedTests();
});
- test('overridden dependencies - no resolution', () async {
+ testWithGolden('overridden dependencies - no resolution', (ctx) async {
ensureGit();
- await servePackages(
- (builder) => builder
- ..serve('foo', '1.0.0', deps: {'bar': '^2.0.0'})
- ..serve('foo', '2.0.0', deps: {'bar': '^1.0.0'})
- ..serve('bar', '1.0.0', deps: {'foo': '^1.0.0'})
- ..serve('bar', '2.0.0', deps: {'foo': '^2.0.0'}),
- );
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': '^2.0.0'})
+ ..serve('foo', '2.0.0', deps: {'bar': '^1.0.0'})
+ ..serve('bar', '1.0.0', deps: {'foo': '^1.0.0'})
+ ..serve('bar', '2.0.0', deps: {'foo': '^2.0.0'});
await d.dir(appPath, [
d.pubspec({
@@ -389,13 +375,13 @@
await pubGet();
- await variations('dependency_overrides_no_solution');
+ await ctx.runOutdatedTests();
});
- test(
+ testWithGolden(
'latest version reported while locked on a prerelease can be a prerelease',
- () async {
- await servePackages((builder) => builder
+ (ctx) async {
+ await servePackages()
..serve('foo', '0.9.0')
..serve('foo', '1.0.0-dev.1')
..serve('foo', '1.0.0-dev.2')
@@ -404,7 +390,7 @@
..serve('bar', '1.0.0-dev.2')
..serve('mop', '0.10.0-dev')
..serve('mop', '0.10.0')
- ..serve('mop', '1.0.0-dev'));
+ ..serve('mop', '1.0.0-dev');
await d.dir(appPath, [
d.pubspec({
'name': 'app',
@@ -419,11 +405,11 @@
await pubGet();
- await variations('prereleases');
+ await ctx.runOutdatedTests();
});
- test('Handles SDK dependencies', () async {
- await servePackages((builder) => builder
+ testWithGolden('Handles SDK dependencies', (ctx) async {
+ await servePackages()
..serve('foo', '1.0.0', pubspec: {
'environment': {'sdk': '>=2.10.0 <3.0.0'}
})
@@ -432,7 +418,7 @@
})
..serve('foo', '2.0.0', pubspec: {
'environment': {'sdk': '>=2.12.0 <3.0.0'}
- }));
+ });
await d.dir('flutter-root', [
d.file('version', '1.2.3'),
@@ -471,7 +457,7 @@
'_PUB_TEST_SDK_VERSION': '2.13.0'
});
- await variations('handles_sdk_dependencies', environment: {
+ await ctx.runOutdatedTests(environment: {
'FLUTTER_ROOT': d.path('flutter-root'),
'_PUB_TEST_SDK_VERSION': '2.13.0',
// To test that the reproduction command is reflected correctly.
@@ -479,11 +465,8 @@
});
});
- test("doesn't allow arguments. Handles bad flags", () async {
- final sb = StringBuffer();
- await runPubIntoBuffer(['outdated', 'random_argument'], sb);
- await runPubIntoBuffer(['outdated', '--bad_flag'], sb);
- expectMatchesGoldenFile(
- sb.toString(), 'test/outdated/goldens/bad_arguments.txt');
+ testWithGolden('does not allow arguments - handles bad flags', (ctx) async {
+ await ctx.run(['outdated', 'random_argument']);
+ await ctx.run(['outdated', '--bad_flag']);
});
}
diff --git a/test/package_config_file_test.dart b/test/package_config_file_test.dart
index 8cb03f0..763ce42 100644
--- a/test/package_config_file_test.dart
+++ b/test/package_config_file_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -14,13 +12,12 @@
void main() {
forBothPubGetAndUpgrade((command) {
test('package_config.json file is created', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3',
- deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])]);
- builder.serve('bar', '3.2.1', contents: [d.dir('lib', [])]);
- builder.serve('baz', '2.2.2',
+ await servePackages()
+ ..serve('foo', '1.2.3',
+ deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])])
+ ..serve('bar', '3.2.1', contents: [d.dir('lib', [])])
+ ..serve('baz', '2.2.2',
deps: {'bar': '3.2.1'}, contents: [d.dir('lib', [])]);
- });
await d.dir(appPath, [
d.appPubspec({'foo': '1.2.3'}),
@@ -56,13 +53,12 @@
});
test('package_config.json file is overwritten', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3',
- deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])]);
- builder.serve('bar', '3.2.1', contents: [d.dir('lib', [])]);
- builder.serve('baz', '2.2.2',
+ await servePackages()
+ ..serve('foo', '1.2.3',
+ deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])])
+ ..serve('bar', '3.2.1', contents: [d.dir('lib', [])])
+ ..serve('baz', '2.2.2',
deps: {'bar': '3.2.1'}, contents: [d.dir('lib', [])]);
- });
await d.dir(appPath, [
d.appPubspec({'foo': '1.2.3'}),
@@ -119,6 +115,8 @@
args: ['--offline'], error: equalsIgnoringWhitespace("""
Because myapp depends on foo any which doesn't exist (could not find
package foo in cache), version solving failed.
+
+ Try again without --offline!
"""), exitCode: exit_codes.UNAVAILABLE);
await d.dir(appPath, [
@@ -129,11 +127,10 @@
test(
'.dart_tool/package_config.json file has relative path to path dependency',
() async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3',
- deps: {'baz': 'any'}, contents: [d.dir('lib', [])]);
- builder.serve('baz', '9.9.9', deps: {}, contents: [d.dir('lib', [])]);
- });
+ await servePackages()
+ ..serve('foo', '1.2.3',
+ deps: {'baz': 'any'}, contents: [d.dir('lib', [])])
+ ..serve('baz', '9.9.9', deps: {}, contents: [d.dir('lib', [])]);
await d.dir('local_baz', [
d.libDir('baz', 'baz 3.2.1'),
@@ -180,18 +177,17 @@
});
test('package_config.json has language version', () async {
- await servePackages((builder) {
- builder.serve(
- 'foo',
- '1.2.3',
- pubspec: {
- 'environment': {
- 'sdk': '>=0.0.1 <=0.2.2+2', // tests runs with '0.1.2+3'
- },
+ final server = await servePackages();
+ server.serve(
+ 'foo',
+ '1.2.3',
+ pubspec: {
+ 'environment': {
+ 'sdk': '>=0.0.1 <=0.2.2+2', // tests runs with '0.1.2+3'
},
- contents: [d.dir('lib', [])],
- );
- });
+ },
+ contents: [d.dir('lib', [])],
+ );
await d.dir(appPath, [
d.pubspec({
@@ -225,18 +221,17 @@
});
test('package_config.json has 2.7 default language version', () async {
- await servePackages((builder) {
- builder.serve(
- 'foo',
- '1.2.3',
- pubspec: {
- 'environment': {
- 'sdk': 'any',
- },
+ final server = await servePackages();
+ server.serve(
+ 'foo',
+ '1.2.3',
+ pubspec: {
+ 'environment': {
+ 'sdk': 'any',
},
- contents: [d.dir('lib', [])],
- );
- });
+ },
+ contents: [d.dir('lib', [])],
+ );
await d.dir(appPath, [
d.pubspec({
diff --git a/test/package_list_files_test.dart b/test/package_list_files_test.dart
index 7891270..091001b 100644
--- a/test/package_list_files_test.dart
+++ b/test/package_list_files_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
import 'package:path/path.dart' as p;
@@ -15,8 +13,8 @@
import 'descriptor.dart' as d;
import 'test_pub.dart';
-String root;
-Entrypoint entrypoint;
+late String root;
+Entrypoint? entrypoint;
void main() {
test('lists files recursively', () async {
@@ -35,7 +33,7 @@
createEntrypoint();
expect(
- entrypoint.root.listFiles(),
+ entrypoint!.root.listFiles(),
unorderedEquals([
p.join(root, 'pubspec.yaml'),
p.join(root, 'file1.txt'),
@@ -71,7 +69,7 @@
createEntrypoint();
expect(
- () => entrypoint.root.listFiles(),
+ () => entrypoint!.root.listFiles(),
throwsA(
isA<DataException>().having(
(e) => e.message,
@@ -123,7 +121,7 @@
createEntrypoint();
expect(
- () => entrypoint.root.listFiles(),
+ () => entrypoint!.root.listFiles(),
throwsA(
isA<DataException>().having(
(e) => e.message,
@@ -151,7 +149,7 @@
createEntrypoint();
expect(
- () => entrypoint.root.listFiles(),
+ () => entrypoint!.root.listFiles(),
throwsA(
isA<DataException>().having(
(e) => e.message,
@@ -169,13 +167,13 @@
d.file('.foo', ''),
]).create();
createEntrypoint();
- expect(entrypoint.root.listFiles(), {
+ expect(entrypoint!.root.listFiles(), {
p.join(root, '.foo'),
p.join(root, 'pubspec.yaml'),
});
});
group('with git', () {
- d.GitRepoDescriptor repo;
+ late d.GitRepoDescriptor repo;
setUp(() async {
ensureGit();
repo = d.git(appPath, [d.appPubspec()]);
@@ -193,7 +191,7 @@
])
]).create();
- expect(entrypoint.root.listFiles(), {
+ expect(entrypoint!.root.listFiles(), {
p.join(root, 'pubspec.yaml'),
p.join(root, 'file1.txt'),
p.join(root, 'file2.txt'),
@@ -213,7 +211,7 @@
])
]).create();
- expect(entrypoint.root.listFiles(), {
+ expect(entrypoint!.root.listFiles(), {
p.join(root, 'pubspec.yaml'),
p.join(root, 'file2.text'),
p.join(root, 'subdir', 'subfile2.text')
@@ -246,7 +244,7 @@
createEntrypoint(p.join(appPath, 'rep', 'sub'));
- expect(entrypoint.root.listFiles(), {
+ expect(entrypoint!.root.listFiles(), {
p.join(root, 'pubspec.yaml'),
p.join(root, 'file2.text'),
p.join(root, 'file4.gak'),
@@ -254,6 +252,23 @@
});
});
+ test("Don't ignore packages/ before the package root", () async {
+ await d.dir(appPath, [
+ d.dir('packages', [
+ d.dir('app', [
+ d.appPubspec(),
+ d.dir('packages', [d.file('a.txt')]),
+ ]),
+ ]),
+ ]).create();
+
+ createEntrypoint(p.join(appPath, 'packages', 'app'));
+
+ expect(entrypoint!.root.listFiles(), {
+ p.join(root, 'pubspec.yaml'),
+ });
+ });
+
group('with a submodule', () {
setUp(() async {
await d.git('submodule', [
@@ -269,7 +284,7 @@
});
test('respects its .gitignore with useGitIgnore', () {
- expect(entrypoint.root.listFiles(), {
+ expect(entrypoint!.root.listFiles(), {
p.join(root, 'pubspec.yaml'),
p.join(root, 'submodule', 'file2.text'),
});
@@ -282,7 +297,7 @@
d.dir('subdir', [d.file('pubspec.lock')])
]).create();
- expect(entrypoint.root.listFiles(), {p.join(root, 'pubspec.yaml')});
+ expect(entrypoint!.root.listFiles(), {p.join(root, 'pubspec.yaml')});
});
test('ignores packages directories', () async {
@@ -293,7 +308,7 @@
])
]).create();
- expect(entrypoint.root.listFiles(), {p.join(root, 'pubspec.yaml')});
+ expect(entrypoint!.root.listFiles(), {p.join(root, 'pubspec.yaml')});
});
test('allows pubspec.lock directories', () async {
@@ -303,7 +318,7 @@
])
]).create();
- expect(entrypoint.root.listFiles(), {
+ expect(entrypoint!.root.listFiles(), {
p.join(root, 'pubspec.yaml'),
p.join(root, 'pubspec.lock', 'file.txt')
});
@@ -324,7 +339,7 @@
])
]).create();
- expect(entrypoint.root.listFiles(beneath: 'subdir'), {
+ expect(entrypoint!.root.listFiles(beneath: 'subdir'), {
p.join(root, 'subdir', 'subfile1.txt'),
p.join(root, 'subdir', 'subfile2.txt'),
p.join(root, 'subdir', 'subsubdir', 'subsubfile1.txt'),
@@ -343,7 +358,7 @@
d.dir('lib', [d.file('not_ignored.dart', 'content')]),
]).create();
createEntrypoint();
- expect(entrypoint.root.listFiles(), {
+ expect(entrypoint!.root.listFiles(), {
p.join(root, 'LICENSE'),
p.join(root, 'CHANGELOG.md'),
p.join(root, 'README.md'),
@@ -395,7 +410,7 @@
]).create();
createEntrypoint();
- expect(entrypoint.root.listFiles(), {
+ expect(entrypoint!.root.listFiles(), {
p.join(root, 'pubspec.yaml'),
p.join(root, 'not_ignored_by_gitignore.txt'),
p.join(root, 'ignored_by_gitignore.txt'),
@@ -410,7 +425,7 @@
});
}
-void createEntrypoint([String path]) {
+void createEntrypoint([String? path]) {
path ??= appPath;
root = p.join(d.sandbox, path);
entrypoint = Entrypoint(root, SystemCache(rootDir: root));
diff --git a/test/package_server.dart b/test/package_server.dart
index ec960ca..952c189 100644
--- a/test/package_server.dart
+++ b/test/package_server.dart
@@ -2,162 +2,158 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:convert';
+import 'dart:io';
import 'package:path/path.dart' as p;
+import 'package:pub/src/third_party/tar/tar.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:shelf/shelf.dart' as shelf;
+import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:test/test.dart';
import 'package:test/test.dart' as test show expect;
import 'descriptor.dart' as d;
import 'test_pub.dart';
-/// The current global [PackageServer].
-PackageServer get globalPackageServer => _globalPackageServer;
-PackageServer _globalPackageServer;
-
-/// Creates an HTTP server that replicates the structure of pub.dartlang.org and
-/// makes it the current [globalServer].
-///
-/// Calls [callback] with a [PackageServerBuilder] that's used to specify
-/// which packages to serve.
-Future servePackages([void Function(PackageServerBuilder) callback]) async {
- _globalPackageServer = await PackageServer.start(callback ?? (_) {});
- globalServer = _globalPackageServer._inner;
-
- addTearDown(() {
- _globalPackageServer = null;
- });
-}
-
-/// Like [servePackages], but instead creates an empty server with no packages
-/// registered.
-///
-/// This will always replace a previous server.
-Future serveNoPackages() => servePackages((_) {});
-
-/// Sets up the global package server to report an error on any request.
-///
-/// If no server has been set up, an empty server will be started.
-Future serveErrors() async {
- if (globalPackageServer == null) {
- await serveNoPackages();
- }
- globalPackageServer.serveErrors();
-}
-
class PackageServer {
/// The inner [DescriptorServer] that this uses to serve its descriptors.
- final DescriptorServer _inner;
+ final shelf.Server _inner;
- /// The [d.DirectoryDescriptor] describing the server layout of
- /// `/api/packages` on the test server.
- ///
- /// This contains metadata for packages that are being served via
- /// [servePackages].
- final _servedApiPackageDir = d.dir('packages', []);
+ /// Handlers of requests. Last matching handler will be used.
+ final List<_PatternAndHandler> _handlers = [];
- /// The [d.DirectoryDescriptor] describing the server layout of `/packages` on
- /// the test server.
- ///
- /// This contains the tarballs for packages that are being served via
- /// [servePackages].
- final _servedPackageDir = d.dir('packages', []);
+ // A list of all the requests recieved up till now.
+ final List<String> requestedPaths = <String>[];
- /// The current [PackageServerBuilder] that a user uses to specify which
- /// package to serve.
- ///
- /// This is preserved so that additional packages can be added.
- PackageServerBuilder _builder;
+ PackageServer._(this._inner) {
+ _inner.mount((request) {
+ final path = request.url.path;
+ requestedPaths.add(path);
- /// The port used for the server.
- int get port => _inner.port;
+ final pathWithInitialSlash = '/$path';
+ for (final entry in _handlers.reversed) {
+ final match = entry.pattern.matchAsPrefix(pathWithInitialSlash);
+ if (match != null && match.end == pathWithInitialSlash.length) {
+ final a = entry.handler(request);
+ return a;
+ }
+ }
+ return shelf.Response.notFound('Could not find ${request.url}');
+ });
+ }
- /// The URL for the server.
- String get url => 'http://localhost:$port';
+ static final _versionInfoPattern = RegExp(r'/api/packages/([a-zA-Z_0-9]*)');
+ static final _downloadPattern =
+ RegExp(r'/packages/([^/]*)/versions/([^/]*).tar.gz');
- /// Handlers for requests not easily described as packages.
- Map<Pattern, shelf.Handler> get extraHandlers => _inner.extraHandlers;
+ static Future<PackageServer> start() async {
+ final server =
+ PackageServer._(await shelf_io.IOServer.bind('localhost', 0));
+ server.handle(
+ _versionInfoPattern,
+ (shelf.Request request) {
+ final parts = request.url.pathSegments;
+ assert(parts[0] == 'api');
+ assert(parts[1] == 'packages');
+ final name = parts[2];
- /// From now on report errors on any request.
- void serveErrors() => extraHandlers
- ..clear()
- ..[RegExp('.*')] = (request) {
- fail('The HTTP server received an unexpected request:\n'
- '${request.method} ${request.requestedUri}');
- };
+ final package = server._packages[name];
+ if (package == null) {
+ return shelf.Response.notFound('No package named $name');
+ }
+ return shelf.Response.ok(jsonEncode({
+ 'name': name,
+ 'uploaders': ['nweiz@google.com'],
+ 'versions': package.versions.values
+ .map((version) => packageVersionApiMap(
+ server._inner.url.toString(),
+ version.pubspec,
+ retracted: version.isRetracted,
+ ))
+ .toList(),
+ if (package.isDiscontinued) 'isDiscontinued': true,
+ if (package.discontinuedReplacementText != null)
+ 'replacedBy': package.discontinuedReplacementText,
+ }));
+ },
+ );
- /// Creates an HTTP server that replicates the structure of pub.dartlang.org.
- ///
- /// Calls [callback] with a [PackageServerBuilder] that's used to specify
- /// which packages to serve.
- static Future<PackageServer> start(
- void Function(PackageServerBuilder) callback) async {
- var descriptorServer = await DescriptorServer.start();
- var server = PackageServer._(descriptorServer);
- descriptorServer.contents
- ..add(d.dir('api', [server._servedApiPackageDir]))
- ..add(server._servedPackageDir);
- server.add(callback);
+ server.handle(
+ _downloadPattern,
+ (shelf.Request request) {
+ final parts = request.url.pathSegments;
+ assert(parts[0] == 'packages');
+ final name = parts[1];
+ assert(parts[2] == 'versions');
+ final package = server._packages[name];
+ if (package == null) {
+ return shelf.Response.notFound('No package $name');
+ }
+
+ final version = Version.parse(
+ parts[3].substring(0, parts[3].length - '.tar.gz'.length));
+ assert(parts[3].endsWith('.tar.gz'));
+
+ for (final packageVersion in package.versions.values) {
+ if (packageVersion.version == version) {
+ return shelf.Response.ok(packageVersion.contents());
+ }
+ }
+ return shelf.Response.notFound('No version $version of $name');
+ },
+ );
return server;
}
- PackageServer._(this._inner) {
- _builder = PackageServerBuilder._(this);
+ Future<void> close() async {
+ await _inner.close();
}
- /// Add to the current set of packages that are being served.
- void add(void Function(PackageServerBuilder) callback) {
- callback(_builder);
+ /// The port used for the server.
+ int get port => _inner.url.port;
- _servedApiPackageDir.contents.clear();
- _servedPackageDir.contents.clear();
+ /// The URL for the server.
+ String get url => _inner.url.toString();
- _builder._packages.forEach((name, package) {
- _servedApiPackageDir.contents.addAll([
- d.file(
- name,
- jsonEncode({
- 'name': name,
- 'uploaders': ['nweiz@google.com'],
- 'versions': package.versions.values
- .map((version) => packageVersionApiMap(url, version.pubspec,
- retracted: version.isRetracted))
- .toList(),
- if (package.isDiscontinued) 'isDiscontinued': true,
- if (package.discontinuedReplacementText != null)
- 'replacedBy': package.discontinuedReplacementText,
- })),
- d.dir(name, [
- d.dir('versions', package.versions.values.map((version) {
- return d.file(
- version.version.toString(),
- jsonEncode(packageVersionApiMap(url, version.pubspec,
- retracted: version.isRetracted, full: true)));
- }))
- ])
- ]);
+ /// From now on report errors on any request.
+ void serveErrors() => _handlers
+ ..clear()
+ ..add(
+ _PatternAndHandler(
+ RegExp('.*'),
+ (request) {
+ fail('The HTTP server received an unexpected request:\n'
+ '${request.method} ${request.requestedUri}');
+ },
+ ),
+ );
- _servedPackageDir.contents.add(d.dir(name, [
- d.dir(
- 'versions',
- package.versions.values.map((version) =>
- d.tar('${version.version}.tar.gz', version.contents)))
- ]));
- });
+ void handle(Pattern pattern, shelf.Handler handler) {
+ _handlers.add(
+ _PatternAndHandler(
+ pattern,
+ handler,
+ ),
+ );
}
// Installs a handler at [pattern] that expects to be called exactly once with
// the given [method].
+ //
+ // The handler is installed as the start to give it priority over more general
+ // handlers.
void expect(String method, Pattern pattern, shelf.Handler handler) {
- extraHandlers[pattern] = expectAsync1((request) {
- test.expect(request.method, method);
- return handler(request);
- });
+ handle(
+ pattern,
+ expectAsync1(
+ (request) {
+ test.expect(request.method, method);
+ return handler(request);
+ },
+ ),
+ );
}
/// Returns the path of [package] at [version], installed from this server, in
@@ -169,26 +165,9 @@
String get cachingPath =>
p.join(d.sandbox, cachePath, 'hosted', 'localhost%58$port');
- /// Replace the current set of packages that are being served.
- void replace(void Function(PackageServerBuilder) callback) {
- _builder._clear();
- add(callback);
- }
-}
-
-/// A builder for specifying which packages should be served by [servePackages].
-class PackageServerBuilder {
/// A map from package names to the concrete packages to serve.
final _packages = <String, _ServedPackage>{};
- /// The package server that this builder is associated with.
- final PackageServer _server;
-
- /// The URL for the server that this builder is associated with.
- String get serverUrl => _server.url;
-
- PackageServerBuilder._(this._server);
-
/// Specifies that a package named [name] with [version] should be served.
///
/// If [deps] is passed, it's used as the "dependencies" field of the pubspec.
@@ -197,9 +176,9 @@
/// If [contents] is passed, it's used as the contents of the package. By
/// default, a package just contains a dummy lib directory.
void serve(String name, String version,
- {Map<String, dynamic> deps,
- Map<String, dynamic> pubspec,
- Iterable<d.Descriptor> contents}) {
+ {Map<String, dynamic>? deps,
+ Map<String, dynamic>? pubspec,
+ List<d.Descriptor>? contents}) {
var pubspecFields = <String, dynamic>{'name': name, 'version': version};
if (pubspec != null) pubspecFields.addAll(pubspec);
if (deps != null) pubspecFields['dependencies'] = deps;
@@ -208,40 +187,84 @@
contents = [d.file('pubspec.yaml', yaml(pubspecFields)), ...contents];
var package = _packages.putIfAbsent(name, () => _ServedPackage());
- package.versions[version] = _ServedPackageVersion(pubspecFields, contents);
+ package.versions[version] = _ServedPackageVersion(
+ pubspecFields,
+ contents: () {
+ final entries = <TarEntry>[];
+
+ void addDescriptor(d.Descriptor descriptor, String path) {
+ if (descriptor is d.DirectoryDescriptor) {
+ for (final e in descriptor.contents) {
+ addDescriptor(e, p.posix.join(path, descriptor.name));
+ }
+ } else {
+ entries.add(
+ TarEntry(
+ TarHeader(
+ // Ensure paths in tar files use forward slashes
+ name: p.posix.join(path, descriptor.name),
+ // We want to keep executable bits, but otherwise use the default
+ // file mode
+ mode: 420,
+ // size: 100,
+ modified: DateTime.now(),
+ userName: 'pub',
+ groupName: 'pub',
+ ),
+ (descriptor as d.FileDescriptor).readAsBytes(),
+ ),
+ );
+ }
+ }
+
+ for (final e in contents ?? <d.Descriptor>[]) {
+ addDescriptor(e, '');
+ }
+ return Stream.fromIterable(entries)
+ .transform(tarWriterWith(format: OutputFormat.gnuLongName))
+ .transform(gzip.encoder);
+ },
+ );
}
// Mark a package discontinued.
void discontinue(String name,
- {bool isDiscontinued = true, String replacementText}) {
- _packages[name]
+ {bool isDiscontinued = true, String? replacementText}) {
+ _packages[name]!
..isDiscontinued = isDiscontinued
..discontinuedReplacementText = replacementText;
}
/// Clears all existing packages from this builder.
- void _clear() {
+ void clearPackages() {
_packages.clear();
}
void retractPackageVersion(String name, String version) {
- _packages[name].versions[version].isRetracted = true;
+ _packages[name]!.versions[version]!.isRetracted = true;
}
}
class _ServedPackage {
final versions = <String, _ServedPackageVersion>{};
bool isDiscontinued = false;
- String discontinuedReplacementText;
+ String? discontinuedReplacementText;
}
/// A package that's intended to be served.
class _ServedPackageVersion {
final Map pubspec;
- final List<d.Descriptor> contents;
+ final Stream<List<int>> Function() contents;
bool isRetracted = false;
Version get version => Version.parse(pubspec['version']);
- _ServedPackageVersion(this.pubspec, this.contents);
+ _ServedPackageVersion(this.pubspec, {required this.contents});
+}
+
+class _PatternAndHandler {
+ Pattern pattern;
+ shelf.Handler handler;
+
+ _PatternAndHandler(this.pattern, this.handler);
}
diff --git a/test/packages_file_test.dart b/test/packages_file_test.dart
index ce87d7c..c245a9a 100644
--- a/test/packages_file_test.dart
+++ b/test/packages_file_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -13,21 +11,20 @@
void main() {
forBothPubGetAndUpgrade((command) {
- test('.packages file is created', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3',
- deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])]);
- builder.serve('bar', '3.2.1', contents: [d.dir('lib', [])]);
- builder.serve('baz', '2.2.2',
+ test('.packages file is created with flag', () async {
+ await servePackages()
+ ..serve('foo', '1.2.3',
+ deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])])
+ ..serve('bar', '3.2.1', contents: [d.dir('lib', [])])
+ ..serve('baz', '2.2.2',
deps: {'bar': '3.2.1'}, contents: [d.dir('lib', [])]);
- });
await d.dir(appPath, [
d.appPubspec({'foo': '1.2.3'}),
d.dir('lib')
]).create();
- await pubCommand(command);
+ await pubCommand(command, args: ['--legacy-packages-file']);
await d.dir(appPath, [
d.packagesFile(
@@ -35,14 +32,13 @@
]).validate();
});
- test('.packages file is overwritten', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3',
- deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])]);
- builder.serve('bar', '3.2.1', contents: [d.dir('lib', [])]);
- builder.serve('baz', '2.2.2',
+ test('.packages file is overwritten with flag', () async {
+ await servePackages()
+ ..serve('foo', '1.2.3',
+ deps: {'baz': '2.2.2'}, contents: [d.dir('lib', [])])
+ ..serve('bar', '3.2.1', contents: [d.dir('lib', [])])
+ ..serve('baz', '2.2.2',
deps: {'bar': '3.2.1'}, contents: [d.dir('lib', [])]);
- });
await d.dir(appPath, [
d.appPubspec({'foo': '1.2.3'}),
@@ -55,7 +51,7 @@
await oldFile.create();
await oldFile.validate(); // Sanity-check that file was created correctly.
- await pubCommand(command);
+ await pubCommand(command, args: ['--legacy-packages-file']);
await d.dir(appPath, [
d.packagesFile(
@@ -63,27 +59,32 @@
]).validate();
});
- test('.packages file is not created if pub command fails', () async {
+ test('.packages file is not created if pub command fails with flag',
+ () async {
await d.dir(appPath, [
d.appPubspec({'foo': '1.2.3'}),
d.dir('lib')
]).create();
await pubCommand(command,
- args: ['--offline'], error: equalsIgnoringWhitespace("""
+ args: ['--offline', '--legacy-packages-file'],
+ error: equalsIgnoringWhitespace("""
Because myapp depends on foo any which doesn't exist (could not find
package foo in cache), version solving failed.
- """), exitCode: exit_codes.UNAVAILABLE);
+
+ Try again without --offline!
+ """),
+ exitCode: exit_codes.UNAVAILABLE);
await d.dir(appPath, [d.nothing('.packages')]).validate();
});
- test('.packages file has relative path to path dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3',
- deps: {'baz': 'any'}, contents: [d.dir('lib', [])]);
- builder.serve('baz', '9.9.9', deps: {}, contents: [d.dir('lib', [])]);
- });
+ test('.packages file has relative path to path dependency with flag',
+ () async {
+ await servePackages()
+ ..serve('foo', '1.2.3',
+ deps: {'baz': 'any'}, contents: [d.dir('lib', [])])
+ ..serve('baz', '9.9.9', deps: {}, contents: [d.dir('lib', [])]);
await d.dir('local_baz', [
d.libDir('baz', 'baz 3.2.1'),
@@ -103,7 +104,7 @@
d.dir('lib')
]).create();
- await pubCommand(command);
+ await pubCommand(command, args: ['--legacy-packages-file']);
await d.dir(appPath, [
d.packagesFile({'myapp': '.', 'baz': '../local_baz', 'foo': '1.2.3'}),
diff --git a/test/pub_get_and_upgrade_test.dart b/test/pub_get_and_upgrade_test.dart
index b93d10f..f64f93b 100644
--- a/test/pub_get_and_upgrade_test.dart
+++ b/test/pub_get_and_upgrade_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -47,7 +45,8 @@
await pubCommand(command);
await d.dir('myapp', [
- d.packagesFile({'myapp_name': '.'})
+ d.packageConfigFile(
+ [d.packageConfigEntry(name: 'myapp_name', path: '.')]),
]).validate();
});
diff --git a/test/pub_uploader_test.dart b/test/pub_uploader_test.dart
index 98bd2fe..47d50d3 100644
--- a/test/pub_uploader_test.dart
+++ b/test/pub_uploader_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:convert';
@@ -15,19 +13,6 @@
import 'descriptor.dart' as d;
import 'test_pub.dart';
-const _usageString = '''
-Manage uploaders for a package on pub.dartlang.org.
-
-Usage: pub uploader [options] {add/remove} <email>
--h, --help Print this usage information.
- --package The package whose uploaders will be modified.
- (defaults to the current package)
--C, --directory=<dir> Run this in the directory<dir>.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-uploader for detailed documentation.
-''';
-
Future<TestProcess> startPubUploader(PackageServer server, List<String> args) {
var tokenEndpoint = Uri.parse(server.url).resolve('/token').toString();
var allArgs = ['uploader', ...args];
@@ -40,33 +25,26 @@
void main() {
group('displays usage', () {
test('when run with no arguments', () {
- return runPub(
- args: ['uploader'], output: _usageString, exitCode: exit_codes.USAGE);
+ return runPub(args: ['uploader'], exitCode: exit_codes.USAGE);
});
test('when run with only a command', () {
- return runPub(
- args: ['uploader', 'add'],
- output: _usageString,
- exitCode: exit_codes.USAGE);
+ return runPub(args: ['uploader', 'add'], exitCode: exit_codes.USAGE);
});
test('when run with an invalid command', () {
return runPub(
- args: ['uploader', 'foo', 'email'],
- output: _usageString,
- exitCode: exit_codes.USAGE);
+ args: ['uploader', 'foo', 'email'], exitCode: exit_codes.USAGE);
});
});
test('adds an uploader', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
+ await d.credentialsFile(globalServer, 'access token').create();
var pub = await startPubUploader(
- globalPackageServer, ['--package', 'pkg', 'add', 'email']);
+ globalServer, ['--package', 'pkg', 'add', 'email']);
- globalPackageServer.expect('POST', '/api/packages/pkg/uploaders',
- (request) {
+ globalServer.expect('POST', '/api/packages/pkg/uploaders', (request) {
return request.readAsString().then((body) {
expect(body, equals('email=email'));
@@ -84,11 +62,11 @@
test('removes an uploader', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
+ await d.credentialsFile(globalServer, 'access token').create();
var pub = await startPubUploader(
- globalPackageServer, ['--package', 'pkg', 'remove', 'email']);
+ globalServer, ['--package', 'pkg', 'remove', 'email']);
- globalPackageServer.expect('DELETE', '/api/packages/pkg/uploaders/email',
+ globalServer.expect('DELETE', '/api/packages/pkg/uploaders/email',
(request) {
return shelf.Response.ok(
jsonEncode({
@@ -105,11 +83,10 @@
await d.validPackage.create();
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
- var pub = await startPubUploader(globalPackageServer, ['add', 'email']);
+ await d.credentialsFile(globalServer, 'access token').create();
+ var pub = await startPubUploader(globalServer, ['add', 'email']);
- globalPackageServer.expect('POST', '/api/packages/test_pkg/uploaders',
- (request) {
+ globalServer.expect('POST', '/api/packages/test_pkg/uploaders', (request) {
return shelf.Response.ok(
jsonEncode({
'success': {'message': 'Good job!'}
@@ -123,12 +100,11 @@
test('add provides an error', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
+ await d.credentialsFile(globalServer, 'access token').create();
var pub = await startPubUploader(
- globalPackageServer, ['--package', 'pkg', 'add', 'email']);
+ globalServer, ['--package', 'pkg', 'add', 'email']);
- globalPackageServer.expect('POST', '/api/packages/pkg/uploaders',
- (request) {
+ globalServer.expect('POST', '/api/packages/pkg/uploaders', (request) {
return shelf.Response(400,
body: jsonEncode({
'error': {'message': 'Bad job!'}
@@ -142,11 +118,11 @@
test('remove provides an error', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
+ await d.credentialsFile(globalServer, 'access token').create();
var pub = await startPubUploader(
- globalPackageServer, ['--package', 'pkg', 'remove', 'e/mail']);
+ globalServer, ['--package', 'pkg', 'remove', 'e/mail']);
- globalPackageServer.expect('DELETE', '/api/packages/pkg/uploaders/e%2Fmail',
+ globalServer.expect('DELETE', '/api/packages/pkg/uploaders/e%2Fmail',
(request) {
return shelf.Response(400,
body: jsonEncode({
@@ -161,11 +137,11 @@
test('add provides invalid JSON', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
+ await d.credentialsFile(globalServer, 'access token').create();
var pub = await startPubUploader(
- globalPackageServer, ['--package', 'pkg', 'add', 'email']);
+ globalServer, ['--package', 'pkg', 'add', 'email']);
- globalPackageServer.expect('POST', '/api/packages/pkg/uploaders',
+ globalServer.expect('POST', '/api/packages/pkg/uploaders',
(request) => shelf.Response.ok('{not json'));
expect(
@@ -177,11 +153,11 @@
test('remove provides invalid JSON', () async {
await servePackages();
- await d.credentialsFile(globalPackageServer, 'access token').create();
+ await d.credentialsFile(globalServer, 'access token').create();
var pub = await startPubUploader(
- globalPackageServer, ['--package', 'pkg', 'remove', 'email']);
+ globalServer, ['--package', 'pkg', 'remove', 'email']);
- globalPackageServer.expect('DELETE', '/api/packages/pkg/uploaders/email',
+ globalServer.expect('DELETE', '/api/packages/pkg/uploaders/email',
(request) => shelf.Response.ok('{not json'));
expect(
diff --git a/test/pubspec_test.dart b/test/pubspec_test.dart
index 5785b16..62f77c4 100644
--- a/test/pubspec_test.dart
+++ b/test/pubspec_test.dart
@@ -2,8 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
+import 'package:pub/src/language_version.dart';
import 'package:pub/src/package_name.dart';
import 'package:pub/src/pubspec.dart';
import 'package:pub/src/sdk.dart';
@@ -22,14 +21,15 @@
throw UnsupportedError('Cannot download fake packages.');
@override
- PackageRef parseRef(String name, description, {String containingPath}) {
+ PackageRef parseRef(String name, description,
+ {String? containingPath, LanguageVersion? languageVersion}) {
if (description != 'ok') throw FormatException('Bad');
return PackageRef(name, this, description);
}
@override
PackageId parseId(String name, Version version, description,
- {String containingPath}) =>
+ {String? containingPath}) =>
PackageId(name, this, version, description);
@override
@@ -50,7 +50,7 @@
var throwsPubspecException = throwsA(const TypeMatcher<PubspecException>());
void expectPubspecException(String contents, void Function(Pubspec) fn,
- [String expectedContains]) {
+ [String? expectedContains]) {
var expectation = const TypeMatcher<PubspecException>();
if (expectedContains != null) {
expectation = expectation.having(
@@ -88,7 +88,7 @@
version: ">=1.2.3 <3.4.5"
''', sources);
- var foo = pubspec.dependencies['foo'];
+ var foo = pubspec.dependencies['foo']!;
expect(foo.name, equals('foo'));
expect(foo.constraint.allows(Version(1, 2, 3)), isTrue);
expect(foo.constraint.allows(Version(1, 2, 5)), isTrue);
@@ -103,7 +103,7 @@
version: ">=1.2.3 <0.0.0"
''', sources);
- var foo = pubspec.dependencies['foo'];
+ var foo = pubspec.dependencies['foo']!;
expect(foo.name, equals('foo'));
expect(foo.constraint.isEmpty, isTrue);
});
@@ -124,7 +124,7 @@
version: ">=1.2.3 <3.4.5"
''', sources);
- var foo = pubspec.devDependencies['foo'];
+ var foo = pubspec.devDependencies['foo']!;
expect(foo.name, equals('foo'));
expect(foo.constraint.allows(Version(1, 2, 3)), isTrue);
expect(foo.constraint.allows(Version(1, 2, 5)), isTrue);
@@ -147,7 +147,7 @@
version: ">=1.2.3 <3.4.5"
''', sources);
- var foo = pubspec.dependencyOverrides['foo'];
+ var foo = pubspec.dependencyOverrides['foo']!;
expect(foo.name, equals('foo'));
expect(foo.constraint.allows(Version(1, 2, 3)), isTrue);
expect(foo.constraint.allows(Version(1, 2, 5)), isTrue);
@@ -169,7 +169,7 @@
unknown: blah
''', sources);
- var foo = pubspec.dependencies['foo'];
+ var foo = pubspec.dependencies['foo']!;
expect(foo.name, equals('foo'));
expect(foo.source, equals(sources['unknown']));
});
@@ -181,7 +181,7 @@
version: 1.2.3
''', sources);
- var foo = pubspec.dependencies['foo'];
+ var foo = pubspec.dependencies['foo']!;
expect(foo.name, equals('foo'));
expect(foo.source, equals(sources['hosted']));
});
@@ -294,6 +294,170 @@
'local pubspec.');
});
+ group('source dependencies', () {
+ test('with url and name', () {
+ var pubspec = Pubspec.parse(
+ '''
+name: pkg
+dependencies:
+ foo:
+ hosted:
+ url: https://example.org/pub/
+ name: bar
+''',
+ sources,
+ );
+
+ var foo = pubspec.dependencies['foo']!;
+ expect(foo.name, equals('foo'));
+ expect(foo.source!.name, 'hosted');
+ expect(foo.source!.serializeDescription('', foo.description), {
+ 'url': 'https://example.org/pub/',
+ 'name': 'bar',
+ });
+ });
+
+ test('with url only', () {
+ var pubspec = Pubspec.parse(
+ '''
+name: pkg
+environment:
+ sdk: ^2.15.0
+dependencies:
+ foo:
+ hosted:
+ url: https://example.org/pub/
+''',
+ sources,
+ );
+
+ var foo = pubspec.dependencies['foo']!;
+ expect(foo.name, equals('foo'));
+ expect(foo.source!.name, 'hosted');
+ expect(foo.source!.serializeDescription('', foo.description), {
+ 'url': 'https://example.org/pub/',
+ 'name': 'foo',
+ });
+ });
+
+ test('with url as string', () {
+ var pubspec = Pubspec.parse(
+ '''
+name: pkg
+environment:
+ sdk: ^2.15.0
+dependencies:
+ foo:
+ hosted: https://example.org/pub/
+''',
+ sources,
+ );
+
+ var foo = pubspec.dependencies['foo']!;
+ expect(foo.name, equals('foo'));
+ expect(foo.source!.name, 'hosted');
+ expect(foo.source!.serializeDescription('', foo.description), {
+ 'url': 'https://example.org/pub/',
+ 'name': 'foo',
+ });
+ });
+
+ test('interprets string description as name for older versions', () {
+ var pubspec = Pubspec.parse(
+ '''
+name: pkg
+environment:
+ sdk: ^2.14.0
+dependencies:
+ foo:
+ hosted: bar
+''',
+ sources,
+ );
+
+ var foo = pubspec.dependencies['foo']!;
+ expect(foo.name, equals('foo'));
+ expect(foo.source!.name, 'hosted');
+ expect(foo.source!.serializeDescription('', foo.description), {
+ 'url': 'https://pub.dartlang.org',
+ 'name': 'bar',
+ });
+ });
+
+ test(
+ 'reports helpful span when using new syntax with invalid environment',
+ () {
+ var pubspec = Pubspec.parse('''
+name: pkg
+environment:
+ sdk: invalid value
+dependencies:
+ foo:
+ hosted: https://example.org/pub/
+''', sources);
+
+ expect(
+ () => pubspec.dependencies,
+ throwsA(
+ isA<PubspecException>()
+ .having((e) => e.span!.text, 'span.text', 'invalid value'),
+ ),
+ );
+ },
+ );
+
+ test('without a description', () {
+ var pubspec = Pubspec.parse(
+ '''
+name: pkg
+dependencies:
+ foo:
+''',
+ sources,
+ );
+
+ var foo = pubspec.dependencies['foo']!;
+ expect(foo.name, equals('foo'));
+ expect(foo.source!.name, 'hosted');
+ expect(foo.source!.serializeDescription('', foo.description), {
+ 'url': 'https://pub.dartlang.org',
+ 'name': 'foo',
+ });
+ });
+
+ group('throws without a min SDK constraint', () {
+ test('and without a name', () {
+ expectPubspecException(
+ '''
+name: pkg
+dependencies:
+ foo:
+ hosted:
+ url: https://example.org/pub/
+''',
+ (pubspec) => pubspec.dependencies,
+ "The 'name' key must have a string value without a minimum Dart "
+ 'SDK constraint of 2.15.');
+ });
+
+ test(
+ 'and a hosted: <value> syntax that looks like an URI was meant',
+ () {
+ expectPubspecException(
+ '''
+name: pkg
+dependencies:
+ foo:
+ hosted: http://pub.example.org
+''',
+ (pubspec) => pubspec.dependencies,
+ 'Using `hosted: <url>` is only supported with a minimum SDK constraint of 2.15.',
+ );
+ },
+ );
+ });
+ });
+
group('git dependencies', () {
test('path must be a string', () {
expectPubspecException('''
@@ -548,7 +712,7 @@
''', sources);
expect(pubspec.features, contains('foobar'));
- var feature = pubspec.features['foobar'];
+ var feature = pubspec.features['foobar']!;
expect(feature.name, equals('foobar'));
expect(feature.onByDefault, isTrue);
expect(feature.dependencies, isEmpty);
@@ -585,7 +749,7 @@
expect(pubspec.features, contains('foobar'));
- var feature = pubspec.features['foobar'];
+ var feature = pubspec.features['foobar']!;
expect(feature.sdkConstraints,
containsPair('dart', VersionConstraint.parse('^1.0.0')));
expect(feature.sdkConstraints,
@@ -604,7 +768,7 @@
Pubspec.parse('features: {foobar: {default: false}}', sources);
expect(pubspec.features, contains('foobar'));
- expect(pubspec.features['foobar'].onByDefault, isFalse);
+ expect(pubspec.features['foobar']!.onByDefault, isFalse);
});
test('parses valid dependency specifications', () {
@@ -618,7 +782,7 @@
expect(pubspec.features, contains('foobar'));
- var feature = pubspec.features['foobar'];
+ var feature = pubspec.features['foobar']!;
expect(feature.name, equals('foobar'));
expect(feature.onByDefault, isTrue);
expect(feature.dependencies, hasLength(2));
@@ -634,7 +798,7 @@
test('can be null', () {
var pubspec =
Pubspec.parse('features: {foobar: {requires: null}}', sources);
- expect(pubspec.features['foobar'].requires, isEmpty);
+ expect(pubspec.features['foobar']!.requires, isEmpty);
});
test('must be a list', () {
diff --git a/test/pubspec_utils_test.dart b/test/pubspec_utils_test.dart
index 60863f4..6622c1c 100644
--- a/test/pubspec_utils_test.dart
+++ b/test/pubspec_utils_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/pubspec_utils.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:test/test.dart';
@@ -47,8 +45,10 @@
});
test('works on compatible version union', () {
- final constraint1 = VersionConstraint.parse('>=1.2.3 <2.0.0');
- final constraint2 = VersionConstraint.parse('>2.2.3 <=4.0.0');
+ final constraint1 =
+ VersionConstraint.parse('>=1.2.3 <2.0.0') as VersionRange;
+ final constraint2 =
+ VersionConstraint.parse('>2.2.3 <=4.0.0') as VersionRange;
final constraint = VersionUnion.fromRanges([constraint1, constraint2]);
final removedUpperBound = stripUpperBound(constraint) as VersionRange;
diff --git a/test/rate_limited_scheduler_test.dart b/test/rate_limited_scheduler_test.dart
index 632efbf..8562b07 100644
--- a/test/rate_limited_scheduler_test.dart
+++ b/test/rate_limited_scheduler_test.dart
@@ -2,11 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
-import 'package:pedantic/pedantic.dart';
import 'package:pub/src/rate_limited_scheduler.dart';
import 'package:test/test.dart';
@@ -19,8 +16,8 @@
final isBeingProcessed = threeCompleters();
Future<String> f(String i) async {
- isBeingProcessed[i].complete();
- await completers[i].future;
+ isBeingProcessed[i]!.complete();
+ await completers[i]!.future;
return i.toUpperCase();
}
@@ -30,11 +27,11 @@
preschedule('b');
preschedule('c');
await Future.wait(
- [isBeingProcessed['a'].future, isBeingProcessed['b'].future]);
- expect(isBeingProcessed['c'].isCompleted, isFalse);
- completers['a'].complete();
- await isBeingProcessed['c'].future;
- completers['c'].complete();
+ [isBeingProcessed['a']!.future, isBeingProcessed['b']!.future]);
+ expect(isBeingProcessed['c']!.isCompleted, isFalse);
+ completers['a']!.complete();
+ await isBeingProcessed['c']!.future;
+ completers['c']!.complete();
expect(await scheduler.schedule('c'), 'C');
});
});
@@ -45,8 +42,8 @@
final isBeingProcessed = threeCompleters();
Future<String> f(String i) async {
- isBeingProcessed[i].complete();
- await completers[i].future;
+ isBeingProcessed[i]!.complete();
+ await completers[i]!.future;
return i.toUpperCase();
}
@@ -57,18 +54,18 @@
preschedule1('a');
preschedule2('b');
preschedule1('c');
- await isBeingProcessed['a'].future;
+ await isBeingProcessed['a']!.future;
// b, c should not start processing due to rate-limiting.
- expect(isBeingProcessed['b'].isCompleted, isFalse);
- expect(isBeingProcessed['c'].isCompleted, isFalse);
+ expect(isBeingProcessed['b']!.isCompleted, isFalse);
+ expect(isBeingProcessed['c']!.isCompleted, isFalse);
});
- completers['a'].complete();
+ completers['a']!.complete();
// b is removed from the queue, now c should start processing.
- await isBeingProcessed['c'].future;
- completers['c'].complete();
+ await isBeingProcessed['c']!.future;
+ completers['c']!.complete();
expect(await scheduler.schedule('c'), 'C');
// b is not on the queue anymore.
- expect(isBeingProcessed['b'].isCompleted, isFalse);
+ expect(isBeingProcessed['b']!.isCompleted, isFalse);
});
});
@@ -78,27 +75,27 @@
final isBeingProcessed = threeCompleters();
Future<String> f(String i) async {
- isBeingProcessed[i].complete();
- await completers[i].future;
+ isBeingProcessed[i]!.complete();
+ await completers[i]!.future;
return i.toUpperCase();
}
final scheduler = RateLimitedScheduler(f, maxConcurrentOperations: 1);
- Future b;
+ Future? b;
await scheduler.withPrescheduling((preschedule) async {
preschedule('a');
preschedule('b');
- await isBeingProcessed['a'].future;
+ await isBeingProcessed['a']!.future;
// b should not start processing due to rate-limiting.
- expect(isBeingProcessed['b'].isCompleted, isFalse);
+ expect(isBeingProcessed['b']!.isCompleted, isFalse);
b = scheduler.schedule('b');
});
- completers['a'].complete();
+ completers['a']!.complete();
expect(await scheduler.schedule('a'), 'A');
// b was scheduled, so it should get processed now
- await isBeingProcessed['b'].future;
- completers['b'].complete();
+ await isBeingProcessed['b']!.future;
+ completers['b']!.complete();
expect(await b, 'B');
});
@@ -107,14 +104,14 @@
final isBeingProcessed = threeCompleters();
Future<String> f(String i) async {
- isBeingProcessed[i].complete();
- await completers[i].future;
+ isBeingProcessed[i]!.complete();
+ await completers[i]!.future;
return i.toUpperCase();
}
final scheduler = RateLimitedScheduler(f, maxConcurrentOperations: 2);
- completers['a'].complete();
+ completers['a']!.complete();
expect(await scheduler.schedule('a'), 'A');
// Would fail if isBeingProcessed['a'] was completed twice
expect(await scheduler.schedule('a'), 'A');
@@ -125,8 +122,8 @@
final isBeingProcessed = threeCompleters();
Future<String> f(String i) async {
- isBeingProcessed[i].complete();
- await completers[i].future;
+ isBeingProcessed[i]!.complete();
+ await completers[i]!.future;
return i.toUpperCase();
}
@@ -134,12 +131,12 @@
await scheduler.withPrescheduling((preschedule) async {
preschedule('a');
preschedule('b');
- await isBeingProcessed['a'].future;
+ await isBeingProcessed['a']!.future;
final cResult = scheduler.schedule('c');
- expect(isBeingProcessed['b'].isCompleted, isFalse);
- completers['a'].complete();
- completers['c'].complete();
- await isBeingProcessed['c'].future;
+ expect(isBeingProcessed['b']!.isCompleted, isFalse);
+ completers['a']!.complete();
+ completers['c']!.complete();
+ await isBeingProcessed['c']!.future;
// 'c' is done before we allow 'b' to finish processing
expect(await cResult, 'C');
});
@@ -150,8 +147,8 @@
final isBeingProcessed = threeCompleters();
Future<String> f(String i) async {
- isBeingProcessed[i].complete();
- await completers[i].future;
+ isBeingProcessed[i]!.complete();
+ await completers[i]!.future;
return i.toUpperCase();
}
@@ -161,14 +158,15 @@
preschedule('a');
preschedule('b');
preschedule('c');
- await isBeingProcessed['a'].future;
- await isBeingProcessed['b'].future;
- expect(isBeingProcessed['c'].isCompleted, isFalse);
- unawaited(completers['c'].future.catchError((_) {}));
- completers['c'].completeError('errorC');
- completers['a'].completeError('errorA');
- await isBeingProcessed['c'].future;
- completers['b'].completeError('errorB');
+
+ await isBeingProcessed['a']!.future;
+ await isBeingProcessed['b']!.future;
+ expect(isBeingProcessed['c']!.isCompleted, isFalse);
+ unawaited(completers['c']!.future.catchError((_) {}));
+ completers['c']!.completeError('errorC');
+ completers['a']!.completeError('errorA');
+ await isBeingProcessed['c']!.future;
+ completers['b']!.completeError('errorB');
expect(() async => await scheduler.schedule('a'), throwsA('errorA'));
expect(() async => await scheduler.schedule('b'), throwsA('errorB'));
expect(() async => await scheduler.schedule('c'), throwsA('errorC'));
@@ -179,9 +177,9 @@
final completers = threeCompleters();
final isBeingProcessed = threeCompleters();
- Future<String> f(String i) async {
- isBeingProcessed[i].complete();
- await completers[i].future;
+ Future<String?> f(String i) async {
+ isBeingProcessed[i]!.complete();
+ await completers[i]!.future;
return Zone.current['zoneValue'];
}
@@ -198,16 +196,16 @@
}, zoneValues: {'zoneValue': 'C'});
await runZoned(() async {
- await isBeingProcessed['a'].future;
- await isBeingProcessed['b'].future;
+ await isBeingProcessed['a']!.future;
+ await isBeingProcessed['b']!.future;
// This will put 'c' in front of the queue, but in a zone with zoneValue
// bound to S.
final f = expectLater(scheduler.schedule('c'), completion('S'));
- completers['a'].complete();
- completers['b'].complete();
+ completers['a']!.complete();
+ completers['b']!.complete();
expect(await scheduler.schedule('a'), 'A');
expect(await scheduler.schedule('b'), 'B');
- completers['c'].complete();
+ completers['c']!.complete();
await f;
}, zoneValues: {'zoneValue': 'S'});
});
diff --git a/test/real_version_test.dart b/test/real_version_test.dart
index 484a7f6..80afab7 100644
--- a/test/real_version_test.dart
+++ b/test/real_version_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io';
import 'package:path/path.dart' as path;
diff --git a/test/reformat_ranges_test.dart b/test/reformat_ranges_test.dart
new file mode 100644
index 0000000..35b085f
--- /dev/null
+++ b/test/reformat_ranges_test.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:pub/src/package_name.dart';
+import 'package:pub/src/solver/reformat_ranges.dart';
+import 'package:pub/src/utils.dart';
+import 'package:pub_semver/pub_semver.dart';
+import 'package:test/test.dart';
+
+void main() {
+ test('reformatMax when max has a build identifier', () {
+ expect(
+ reformatMax(
+ [PackageId('abc', null, Version.parse('1.2.3'), null)],
+ VersionRange(
+ min: Version.parse('0.2.4'),
+ max: Version.parse('1.2.4'),
+ alwaysIncludeMaxPreRelease: true,
+ ),
+ ),
+ equals(
+ Pair(
+ Version.parse('1.2.4-0'),
+ false,
+ ),
+ ),
+ );
+ expect(
+ reformatMax(
+ [PackageId('abc', null, Version.parse('1.2.4-3'), null)],
+ VersionRange(
+ min: Version.parse('0.2.4'),
+ max: Version.parse('1.2.4'),
+ alwaysIncludeMaxPreRelease: true,
+ ),
+ ),
+ equals(
+ Pair(
+ Version.parse('1.2.4-3'),
+ true,
+ ),
+ ),
+ );
+ expect(
+ reformatMax(
+ [],
+ VersionRange(
+ max: Version.parse('1.2.4+1'),
+ alwaysIncludeMaxPreRelease: true,
+ ),
+ ),
+ equals(null));
+ });
+}
diff --git a/test/remove/remove_test.dart b/test/remove/remove_test.dart
index 777d41b..8c82527 100644
--- a/test/remove/remove_test.dart
+++ b/test/remove/remove_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:io' show File;
import 'package:path/path.dart' as p;
@@ -14,7 +12,8 @@
void main() {
test('removes a package from dependencies', () async {
- await servePackages((builder) => builder.serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.appDir({'foo': '1.2.3'}).create();
await pubGet();
@@ -22,17 +21,16 @@
await pubRemove(args: ['foo']);
await d.cacheDir({}).validate();
- await d.appPackagesFile({}).validate();
+ await d.appPackageConfigFile([]).validate();
await d.appDir().validate();
});
test('removing a package from dependencies does not affect dev_dependencies',
() async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('foo', '1.2.2');
- builder.serve('bar', '2.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('foo', '1.2.2')
+ ..serve('bar', '2.0.0');
await d.dir(appPath, [
d.file('pubspec.yaml', '''
@@ -51,7 +49,9 @@
await pubRemove(args: ['foo']);
await d.cacheDir({'bar': '2.0.0'}).validate();
- await d.appPackagesFile({'bar': '2.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'bar', version: '2.0.0'),
+ ]).validate();
await d.dir(appPath, [
d.pubspec({
@@ -62,7 +62,8 @@
});
test('dry-run does not actually remove dependency', () async {
- await servePackages((builder) => builder.serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.appDir({'foo': '1.2.3'}).create();
await pubGet();
@@ -100,7 +101,8 @@
});
test('removes a package from dev_dependencies', () async {
- await servePackages((builder) => builder.serve('foo', '1.2.3'));
+ final server = await servePackages();
+ server.serve('foo', '1.2.3');
await d.dir(appPath, [
d.pubspec({
@@ -113,7 +115,7 @@
await pubRemove(args: ['foo']);
await d.cacheDir({}).validate();
- await d.appPackagesFile({}).validate();
+ await d.appPackageConfigFile([]).validate();
await d.dir(appPath, [
d.pubspec({'name': 'myapp'})
@@ -122,12 +124,11 @@
test('removes multiple packages from dependencies and dev_dependencies',
() async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3');
- builder.serve('bar', '2.3.4');
- builder.serve('baz', '3.2.1');
- builder.serve('jfj', '0.2.1');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3')
+ ..serve('bar', '2.3.4')
+ ..serve('baz', '3.2.1')
+ ..serve('jfj', '0.2.1');
await d.dir(appPath, [
d.pubspec({
@@ -141,7 +142,10 @@
await pubRemove(args: ['foo', 'bar', 'baz']);
await d.cacheDir({'jfj': '0.2.1'}).validate();
- await d.appPackagesFile({'jfj': '0.2.1'}).validate();
+
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'jfj', version: '0.2.1'),
+ ]).validate();
await d.dir(appPath, [
d.pubspec({
@@ -152,7 +156,8 @@
});
test('removes git dependencies', () async {
- await servePackages((builder) => builder.serve('bar', '1.2.3'));
+ final server = await servePackages();
+ server.serve('bar', '1.2.3');
ensureGit();
final repo = d.git('foo.git', [
@@ -170,12 +175,16 @@
await pubGet();
await pubRemove(args: ['foo']);
- await d.appPackagesFile({'bar': '1.2.3'}).validate();
+
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'bar', version: '1.2.3'),
+ ]).validate();
await d.appDir({'bar': '1.2.3'}).validate();
});
test('removes path dependencies', () async {
- await servePackages((builder) => builder.serve('bar', '1.2.3'));
+ final server = await servePackages();
+ server.serve('bar', '1.2.3');
await d
.dir('foo', [d.libDir('foo'), d.libPubspec('foo', '0.0.1')]).create();
@@ -187,21 +196,23 @@
await pubGet();
await pubRemove(args: ['foo']);
- await d.appPackagesFile({'bar': '1.2.3'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'bar', version: '1.2.3'),
+ ]).validate();
await d.appDir({'bar': '1.2.3'}).validate();
});
test('removes hosted dependencies', () async {
- await servePackages((builder) => builder.serve('bar', '2.0.1'));
+ final server = await servePackages();
+ server.serve('bar', '2.0.1');
- var server = await PackageServer.start((builder) {
- builder.serve('foo', '1.2.3');
- });
+ var custom = await startPackageServer();
+ custom.serve('foo', '1.2.3');
await d.appDir({
'foo': {
'version': '1.2.3',
- 'hosted': {'name': 'foo', 'url': 'http://localhost:${server.port}'}
+ 'hosted': {'name': 'foo', 'url': 'http://localhost:${custom.port}'}
},
'bar': '2.0.1'
}).create();
@@ -209,15 +220,16 @@
await pubGet();
await pubRemove(args: ['foo']);
- await d.appPackagesFile({'bar': '2.0.1'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'bar', version: '2.0.1'),
+ ]).validate();
await d.appDir({'bar': '2.0.1'}).validate();
});
test('preserves comments', () async {
- await servePackages((builder) {
- builder.serve('bar', '1.0.0');
- builder.serve('foo', '1.0.0');
- });
+ await servePackages()
+ ..serve('bar', '1.0.0')
+ ..serve('foo', '1.0.0');
await d.dir(appPath, [
d.file('pubspec.yaml', '''
diff --git a/test/run/allows_dart_extension_test.dart b/test/run/allows_dart_extension_test.dart
index f88e9bd..962270f 100644
--- a/test/run/allows_dart_extension_test.dart
+++ b/test/run/allows_dart_extension_test.dart
@@ -2,14 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
import '../test_pub.dart';
-const SCRIPT = """
+const _script = """
import 'dart:io';
main() {
@@ -23,7 +21,7 @@
test('allows a ".dart" extension on the argument', () async {
await d.dir(appPath, [
d.appPubspec(),
- d.dir('bin', [d.file('script.dart', SCRIPT)])
+ d.dir('bin', [d.file('script.dart', _script)])
]).create();
await pubGet();
diff --git a/test/run/app_can_read_from_stdin_test.dart b/test/run/app_can_read_from_stdin_test.dart
index a0c3983..20f9b32 100644
--- a/test/run/app_can_read_from_stdin_test.dart
+++ b/test/run/app_can_read_from_stdin_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
diff --git a/test/run/dartdev/app_can_read_from_stdin_test.dart b/test/run/dartdev/app_can_read_from_stdin_test.dart
deleted file mode 100644
index 933b3ad..0000000
--- a/test/run/dartdev/app_can_read_from_stdin_test.dart
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-void main() {
- test('the spawned application can read line-by-line from stdin', () async {
- await d.dir(appPath, [
- d.appPubspec(),
- d.dir('bin', [
- d.file('script.dart', """
- import 'dart:io';
-
- main() {
- print("started");
- var line1 = stdin.readLineSync();
- print("between");
- var line2 = stdin.readLineSync();
- print(line1);
- print(line2);
- }
- """)
- ])
- ]).create();
-
- await pubGet();
- var pub = await pubRunFromDartDev(args: ['myapp:script']);
-
- await expectLater(pub.stdout, emitsThrough('started'));
- pub.stdin.writeln('first');
- await expectLater(pub.stdout, emits('between'));
- pub.stdin.writeln('second');
- expect(pub.stdout, emits('first'));
- expect(pub.stdout, emits('second'));
- await pub.shouldExit(0);
- });
-
- test('the spawned application can read streamed from stdin', () async {
- await d.dir(appPath, [
- d.appPubspec(),
- d.dir('bin', [
- d.file('script.dart', """
- import 'dart:io';
-
- main() {
- print("started");
- stdin.listen(stdout.add);
- }
- """)
- ])
- ]).create();
-
- await pubGet();
- var pub = await pubRunFromDartDev(args: ['myapp:script']);
-
- await expectLater(pub.stdout, emitsThrough('started'));
- pub.stdin.writeln('first');
- await expectLater(pub.stdout, emits('first'));
- pub.stdin.writeln('second');
- await expectLater(pub.stdout, emits('second'));
- pub.stdin.writeln('third');
- await expectLater(pub.stdout, emits('third'));
- await pub.stdin.close();
- await pub.shouldExit(0);
- });
-}
diff --git a/test/run/dartdev/errors_if_only_transitive_dependency_test.dart b/test/run/dartdev/errors_if_only_transitive_dependency_test.dart
deleted file mode 100644
index 529eeb2..0000000
--- a/test/run/dartdev/errors_if_only_transitive_dependency_test.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:pub/src/exit_codes.dart' as exit_codes;
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-void main() {
- test('Errors if the script is in a non-immediate dependency.', () async {
- await d.dir('foo', [
- d.libPubspec('foo', '1.0.0'),
- d.dir('bin', [d.file('bar.dart', "main() => print('foobar');")])
- ]).create();
-
- await d.dir('bar', [
- d.libPubspec('bar', '1.0.0', deps: {
- 'foo': {'path': '../foo'}
- })
- ]).create();
-
- await d.dir(appPath, [
- d.appPubspec({
- 'bar': {'path': '../bar'}
- })
- ]).create();
-
- await pubGet();
-
- var pub = await pubRunFromDartDev(args: ['foo:script']);
- expect(pub.stderr, emits('Package "foo" is not an immediate dependency.'));
- expect(pub.stderr,
- emits('Cannot run executables in transitive dependencies.'));
- await pub.shouldExit(exit_codes.DATA);
- });
-}
diff --git a/test/run/dartdev/errors_if_path_in_dependency_test.dart b/test/run/dartdev/errors_if_path_in_dependency_test.dart
deleted file mode 100644
index ddf553a..0000000
--- a/test/run/dartdev/errors_if_path_in_dependency_test.dart
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:pub/src/exit_codes.dart' as exit_codes;
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-void main() {
- test(
- 'Errors if the executable is in a subdirectory in a '
- 'dependency.', () async {
- await d.dir('foo', [d.libPubspec('foo', '1.0.0')]).create();
-
- await d.dir(appPath, [
- d.appPubspec({
- 'foo': {'path': '../foo'}
- })
- ]).create();
-
- await runPub(args: ['run', 'foo:sub/dir'], error: '''
-Cannot run an executable in a subdirectory of a dependency.
-
-Usage: pub run <executable> [arguments...]
--h, --help Print this usage information.
- --[no-]enable-asserts Enable assert statements.
- --enable-experiment=<experiment> Runs the executable in a VM with the
- given experiments enabled.
- (Will disable snapshotting, resulting in
- slower startup).
- --[no-]sound-null-safety Override the default null safety
- execution mode.
--C, --directory=<dir> Run this in the directory<dir>.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-run for detailed documentation.
-''', exitCode: exit_codes.USAGE);
- });
-}
diff --git a/test/run/dartdev/forwards_signal_posix_test.dart b/test/run/dartdev/forwards_signal_posix_test.dart
deleted file mode 100644
index 6044de6..0000000
--- a/test/run/dartdev/forwards_signal_posix_test.dart
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-// Windows doesn't support sending signals.
-@TestOn('!windows')
-import 'dart:io';
-
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-const _catchableSignals = [
- ProcessSignal.sighup,
- ProcessSignal.sigterm,
- ProcessSignal.sigusr1,
- ProcessSignal.sigusr2,
- ProcessSignal.sigwinch,
-];
-
-const SCRIPT = """
-import 'dart:io';
-
-main() {
- ProcessSignal.SIGHUP.watch().first.then(print);
- ProcessSignal.SIGTERM.watch().first.then(print);
- ProcessSignal.SIGUSR1.watch().first.then(print);
- ProcessSignal.SIGUSR2.watch().first.then(print);
- ProcessSignal.SIGWINCH.watch().first.then(print);
-
- print("ready");
-}
-""";
-
-void main() {
- test('forwards signals to the inner script', () async {
- await d.dir(appPath, [
- d.appPubspec(),
- d.dir('bin', [d.file('script.dart', SCRIPT)])
- ]).create();
-
- await pubGet();
- var pub = await pubRunFromDartDev(args: ['myapp:script']);
-
- await expectLater(pub.stdout, emitsThrough('ready'));
- for (var signal in _catchableSignals) {
- pub.signal(signal);
- await expectLater(pub.stdout, emits(signal.toString()));
- }
-
- await pub.kill();
- });
-}
diff --git a/test/run/dartdev/loads_package_imports_in_a_dependency_test.dart b/test/run/dartdev/loads_package_imports_in_a_dependency_test.dart
deleted file mode 100644
index f6d84c1..0000000
--- a/test/run/dartdev/loads_package_imports_in_a_dependency_test.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-void main() {
- test('loads package imports in a dependency', () async {
- await d.dir('foo', [
- d.libPubspec('foo', '1.0.0'),
- d.dir('lib', [d.file('foo.dart', "final value = 'foobar';")]),
- d.dir('bin', [
- d.file('bar.dart', '''
-import "package:foo/foo.dart";
-
-main() => print(value);
-''')
- ])
- ]).create();
-
- await d.dir(appPath, [
- d.appPubspec({
- 'foo': {'path': '../foo'}
- })
- ]).create();
-
- await pubGet();
- var pub = await pubRunFromDartDev(args: ['foo:bar']);
- expect(pub.stdout, emitsThrough('foobar'));
- await pub.shouldExit();
- });
-}
diff --git a/test/run/dartdev/nonexistent_dependency_test.dart b/test/run/dartdev/nonexistent_dependency_test.dart
deleted file mode 100644
index 695d147..0000000
--- a/test/run/dartdev/nonexistent_dependency_test.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:pub/src/exit_codes.dart' as exit_codes;
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-void main() {
- test('Errors if the script is in an unknown package.', () async {
- await d.dir(appPath, [d.appPubspec()]).create();
-
- await pubGet();
- var pub = await pubRunFromDartDev(args: ['foo:script']);
- expect(
- pub.stderr,
- emits('Could not find package "foo". Did you forget to add a '
- 'dependency?'));
- await pub.shouldExit(exit_codes.DATA);
- });
-}
diff --git a/test/run/dartdev/nonexistent_script_in_dependency_test.dart b/test/run/dartdev/nonexistent_script_in_dependency_test.dart
deleted file mode 100644
index 5cf982f..0000000
--- a/test/run/dartdev/nonexistent_script_in_dependency_test.dart
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:path/path.dart' as p;
-import 'package:pub/src/exit_codes.dart' as exit_codes;
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-void main() {
- test('Errors if the script in a dependency does not exist.', () async {
- await d.dir('foo', [d.libPubspec('foo', '1.0.0')]).create();
-
- await d.dir(appPath, [
- d.appPubspec({
- 'foo': {'path': '../foo'}
- })
- ]).create();
-
- await pubGet();
-
- var pub = await pubRunFromDartDev(args: ['foo:script']);
- expect(
- pub.stderr,
- emits(
- "Could not find ${p.join("bin", "script.dart")} in package foo."));
- await pub.shouldExit(exit_codes.NO_INPUT);
- });
-}
diff --git a/test/run/dartdev/package_api_test.dart b/test/run/dartdev/package_api_test.dart
deleted file mode 100644
index b4c4f80..0000000
--- a/test/run/dartdev/package_api_test.dart
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:path/path.dart' as p;
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-const _script = """
- import 'dart:isolate';
-
- main() async {
- print(await Isolate.packageRoot);
- print(await Isolate.packageConfig);
- print(await Isolate.resolvePackageUri(
- Uri.parse('package:myapp/resource.txt')));
- print(await Isolate.resolvePackageUri(
- Uri.parse('package:foo/resource.txt')));
- }
-""";
-
-void main() {
- test('an untransformed application sees a file: package config', () async {
- await d.dir('foo', [d.libPubspec('foo', '1.0.0')]).create();
-
- await d.dir(appPath, [
- d.appPubspec({
- 'foo': {'path': '../foo'}
- }),
- d.dir('bin', [d.file('script.dart', _script)])
- ]).create();
-
- await pubGet();
- var pub = await pubRunFromDartDev(args: ['myapp:script']);
-
- expect(pub.stdout, emitsThrough('null'));
- expect(
- pub.stdout,
- emits(p
- .toUri(p.join(d.sandbox, 'myapp/.dart_tool/package_config.json'))
- .toString()));
- expect(pub.stdout,
- emits(p.toUri(p.join(d.sandbox, 'myapp/lib/resource.txt')).toString()));
- expect(pub.stdout,
- emits(p.toUri(p.join(d.sandbox, 'foo/lib/resource.txt')).toString()));
- await pub.shouldExit(0);
- });
-
- test('a snapshotted application sees a file: package root', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('script.dart', _script)])
- ]);
- });
-
- await d.dir(appPath, [
- d.appPubspec({'foo': 'any'})
- ]).create();
-
- await pubGet();
-
- var pub = await pubRunFromDartDev(args: ['foo:script']);
-
- expect(pub.stdout, emits('Building package executable...'));
- expect(pub.stdout, emits('Built foo:script.'));
- expect(pub.stdout, emits('null'));
- expect(
- pub.stdout,
- emits(p
- .toUri(p.join(d.sandbox, 'myapp/.dart_tool/package_config.json'))
- .toString()));
- expect(pub.stdout,
- emits(p.toUri(p.join(d.sandbox, 'myapp/lib/resource.txt')).toString()));
- var fooResourcePath = p.join(
- globalPackageServer.pathInCache('foo', '1.0.0'), 'lib/resource.txt');
- expect(pub.stdout, emits(p.toUri(fooResourcePath).toString()));
- await pub.shouldExit(0);
- });
-}
diff --git a/test/run/dartdev/passes_along_arguments_test.dart b/test/run/dartdev/passes_along_arguments_test.dart
deleted file mode 100644
index 00d05fc..0000000
--- a/test/run/dartdev/passes_along_arguments_test.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-const SCRIPT = '''
-main(List<String> args) {
- print(args.join(" "));
-}
-''';
-
-void main() {
- test('passes arguments to the spawned script', () async {
- await d.dir(appPath, [
- d.appPubspec(),
- d.dir('bin', [d.file('args.dart', SCRIPT)])
- ]).create();
-
- await pubGet();
-
- // Use some args that would trip up pub's arg parser to ensure that it
- // isn't trying to look at them.
- var pub = await pubRunFromDartDev(
- args: ['myapp:args', '--verbose', '-m', '--', 'help']);
-
- expect(pub.stdout, emitsThrough('--verbose -m -- help'));
- await pub.shouldExit();
- });
-}
diff --git a/test/run/dartdev/runs_default_app_without_arguments.dart b/test/run/dartdev/runs_default_app_without_arguments.dart
deleted file mode 100644
index 3b9e119..0000000
--- a/test/run/dartdev/runs_default_app_without_arguments.dart
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-void main() {
- test('runs default Dart application without arguments', () async {
- await d.dir(appPath, [
- d.appPubspec(),
- d.dir('bin', [d.file('myapp.dart', "main() => print('foobar');")])
- ]).create();
-
- await pubGet();
- var pub = await pubRunFromDartDev(args: []);
- expect(pub.stdout, emits('foobar'));
- await pub.shouldExit();
- });
-
- test('runs main.dart Dart application without arguments', () async {
- await d.dir(appPath, [
- d.appPubspec(),
- d.dir('bin', [d.file('main.dart', "main() => print('foobar');")])
- ]).create();
-
- await pubGet();
- var pub = await pubRunFromDartDev(args: []);
- expect(pub.stdout, emits('foobar'));
- await pub.shouldExit();
- });
-
- test('prefers default Dart application without arguments', () async {
- await d.dir(appPath, [
- d.appPubspec(),
- d.dir('bin', [
- d.file('myapp.dart', "main() => print('foobar');"),
- d.file('main.dart', "main() => print('-');"),
- ])
- ]).create();
-
- await pubGet();
- var pub = await pubRunFromDartDev(args: []);
- expect(pub.stdout, emits('foobar'));
- await pub.shouldExit();
- });
-}
diff --git a/test/run/dartdev/runs_from_a_dependency_override_after_dependency_test.dart b/test/run/dartdev/runs_from_a_dependency_override_after_dependency_test.dart
deleted file mode 100644
index 9bb84d5..0000000
--- a/test/run/dartdev/runs_from_a_dependency_override_after_dependency_test.dart
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-void main() {
- // Regression test for issue 23113
- test('runs a named Dart application in a dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'name': 'foo',
- 'version': '1.0.0'
- }, contents: [
- d.dir('bin', [d.file('bar.dart', "main() => print('foobar');")])
- ]);
- });
-
- await d.dir(appPath, [
- d.appPubspec({'foo': null})
- ]).create();
-
- await pubGet(args: ['--precompile']);
-
- var pub = await pubRunFromDartDev(args: ['foo:bar']);
- expect(pub.stdout, emitsThrough('foobar'));
- await pub.shouldExit();
-
- await d.dir('foo', [
- d.libPubspec('foo', '2.0.0'),
- d.dir('bin', [d.file('bar.dart', "main() => print('different');")])
- ]).create();
-
- await d.dir(appPath, [
- d.pubspec({
- 'name': 'myapp',
- 'dependencies': {
- 'foo': {'path': '../foo'}
- }
- })
- ]).create();
-
- await pubGet();
-
- pub = await pubRunFromDartDev(args: ['foo:bar']);
- expect(pub.stdout, emitsThrough('different'));
- await pub.shouldExit();
- });
-}
diff --git a/test/run/dartdev/runs_named_app_in_dependency_test.dart b/test/run/dartdev/runs_named_app_in_dependency_test.dart
deleted file mode 100644
index b7e3124..0000000
--- a/test/run/dartdev/runs_named_app_in_dependency_test.dart
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-void main() {
- test('runs a named Dart application in a dependency', () async {
- await d.dir('foo', [
- d.libPubspec('foo', '1.0.0'),
- d.dir('bin', [d.file('bar.dart', "main() => print('foobar');")])
- ]).create();
-
- await d.dir(appPath, [
- d.appPubspec({
- 'foo': {'path': '../foo'}
- })
- ]).create();
-
- await pubGet();
- var pub = await pubRunFromDartDev(args: ['foo:bar']);
- expect(pub.stdout, emitsThrough('foobar'));
- await pub.shouldExit();
- });
-}
diff --git a/test/run/dartdev/runs_named_app_in_dev_dependency_test.dart b/test/run/dartdev/runs_named_app_in_dev_dependency_test.dart
deleted file mode 100644
index 990d360..0000000
--- a/test/run/dartdev/runs_named_app_in_dev_dependency_test.dart
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-void main() {
- test('runs a named Dart application in a dev dependency', () async {
- await d.dir('foo', [
- d.libPubspec('foo', '1.0.0'),
- d.dir('bin', [d.file('bar.dart', "main() => print('foobar');")])
- ]).create();
-
- await d.dir(appPath, [
- d.pubspec({
- 'name': 'myapp',
- 'dev_dependencies': {
- 'foo': {'path': '../foo'}
- }
- })
- ]).create();
-
- await pubGet();
- var pub = await pubRunFromDartDev(args: ['foo:bar']);
- expect(pub.stdout, emitsThrough('foobar'));
- await pub.shouldExit();
- });
-}
diff --git a/test/run/dartdev/runs_shorthand_app_in_dependency_test.dart b/test/run/dartdev/runs_shorthand_app_in_dependency_test.dart
deleted file mode 100644
index 5cf7865..0000000
--- a/test/run/dartdev/runs_shorthand_app_in_dependency_test.dart
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-void main() {
- test('runs a shorthand Dart application in a dependency', () async {
- await d.dir('foo', [
- d.libPubspec('foo', '1.0.0'),
- d.dir('bin', [d.file('foo.dart', "main() => print('foo');")])
- ]).create();
-
- await d.dir(appPath, [
- d.pubspec({
- 'name': 'myapp',
- 'dependencies': {
- 'foo': {'path': '../foo'}
- }
- })
- ]).create();
-
- await pubGet();
- var pub = await pubRunFromDartDev(args: ['foo']);
- expect(pub.stdout, emitsThrough('foo'));
- await pub.shouldExit();
- });
-}
diff --git a/test/run/dartdev/runs_the_script_in_checked_mode_test.dart b/test/run/dartdev/runs_the_script_in_checked_mode_test.dart
deleted file mode 100644
index 002406f..0000000
--- a/test/run/dartdev/runs_the_script_in_checked_mode_test.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-void main() {
- test('runs the script with assertions enabled', () async {
- await d.dir(appPath, [
- d.appPubspec(),
- d.dir('bin', [d.file('script.dart', 'main() { assert(false); }')])
- ]).create();
-
- await pubGet();
- await runPub(
- args: ['run', '--enable-asserts', 'myapp:script'],
- error: contains('Failed assertion'),
- exitCode: 255);
- });
-}
diff --git a/test/run/dartdev/runs_the_script_in_unchecked_mode_test.dart b/test/run/dartdev/runs_the_script_in_unchecked_mode_test.dart
deleted file mode 100644
index bc85e54..0000000
--- a/test/run/dartdev/runs_the_script_in_unchecked_mode_test.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// @dart=2.10
-
-import 'package:test/test.dart';
-
-import '../../descriptor.dart' as d;
-import '../../test_pub.dart';
-
-const SCRIPT = '''
-main() {
- assert(false);
- print("no checks");
-}
-''';
-
-void main() {
- test('runs the script without assertions by default', () async {
- await d.dir(appPath, [
- d.appPubspec(),
- d.dir('bin', [d.file('script.dart', SCRIPT)])
- ]).create();
-
- await pubGet();
- await runPub(args: ['run', 'myapp:script'], output: contains('no checks'));
- });
-}
diff --git a/test/run/enable_experiments_test.dart b/test/run/enable_experiments_test.dart
index 95468f0..dd6512b 100644
--- a/test/run/enable_experiments_test.dart
+++ b/test/run/enable_experiments_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
diff --git a/test/run/errors_if_no_executable_is_given_test.dart b/test/run/errors_if_no_executable_is_given_test.dart
index 2bec1a3..3e5abd6 100644
--- a/test/run/errors_if_no_executable_is_given_test.dart
+++ b/test/run/errors_if_no_executable_is_given_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -14,22 +12,10 @@
test('Errors if the executable does not exist.', () async {
await d.dir(appPath, [d.appPubspec()]).create();
- await runPub(args: ['run'], error: '''
-Must specify an executable to run.
-
-Usage: pub run <executable> [arguments...]
--h, --help Print this usage information.
- --[no-]enable-asserts Enable assert statements.
- --enable-experiment=<experiment> Runs the executable in a VM with the
- given experiments enabled.
- (Will disable snapshotting, resulting in
- slower startup).
- --[no-]sound-null-safety Override the default null safety
- execution mode.
--C, --directory=<dir> Run this in the directory<dir>.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-run for detailed documentation.
-''', exitCode: exit_codes.USAGE);
+ await runPub(
+ args: ['run'],
+ error: contains('Must specify an executable to run.'),
+ exitCode: exit_codes.USAGE,
+ );
});
}
diff --git a/test/run/errors_if_only_transitive_dependency_test.dart b/test/run/errors_if_only_transitive_dependency_test.dart
index d5d1601..71fcd3d 100644
--- a/test/run/errors_if_only_transitive_dependency_test.dart
+++ b/test/run/errors_if_only_transitive_dependency_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/run/errors_if_path_in_dependency_test.dart b/test/run/errors_if_path_in_dependency_test.dart
index 5625c4e..329650b 100644
--- a/test/run/errors_if_path_in_dependency_test.dart
+++ b/test/run/errors_if_path_in_dependency_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -22,22 +20,12 @@
})
]).create();
- await runPub(args: ['run', 'foo:sub/dir'], error: '''
-Cannot run an executable in a subdirectory of a dependency.
-
-Usage: pub run <executable> [arguments...]
--h, --help Print this usage information.
- --[no-]enable-asserts Enable assert statements.
- --enable-experiment=<experiment> Runs the executable in a VM with the
- given experiments enabled.
- (Will disable snapshotting, resulting in
- slower startup).
- --[no-]sound-null-safety Override the default null safety
- execution mode.
--C, --directory=<dir> Run this in the directory<dir>.
-
-Run "pub help" to see global options.
-See https://dart.dev/tools/pub/cmd/pub-run for detailed documentation.
-''', exitCode: exit_codes.USAGE);
+ await runPub(
+ args: ['run', 'foo:sub/dir'],
+ error: contains(
+ 'Cannot run an executable in a subdirectory of a dependency.',
+ ),
+ exitCode: exit_codes.USAGE,
+ );
});
}
diff --git a/test/run/forwards_signal_posix_test.dart b/test/run/forwards_signal_posix_test.dart
index 17fb0ea..5205145 100644
--- a/test/run/forwards_signal_posix_test.dart
+++ b/test/run/forwards_signal_posix_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
// Windows doesn't support sending signals.
// TODO(sigurdm): Test this when vm-args are provided.
// This test doesn't work when we subprocess instead of an isolate
@@ -25,7 +23,7 @@
ProcessSignal.sigwinch,
];
-const SCRIPT = """
+const _script = """
import 'dart:io';
main() {
@@ -43,7 +41,7 @@
test('forwards signals to the inner script', () async {
await d.dir(appPath, [
d.appPubspec(),
- d.dir('bin', [d.file('script.dart', SCRIPT)])
+ d.dir('bin', [d.file('script.dart', _script)])
]).create();
await pubGet();
diff --git a/test/run/includes_parent_directories_of_entrypoint_test.dart b/test/run/includes_parent_directories_of_entrypoint_test.dart
index f17b548..6bc4e27 100644
--- a/test/run/includes_parent_directories_of_entrypoint_test.dart
+++ b/test/run/includes_parent_directories_of_entrypoint_test.dart
@@ -2,15 +2,13 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import '../descriptor.dart' as d;
import '../test_pub.dart';
-const SCRIPT = r"""
+const _script = r"""
import '../../a.dart';
import '../b.dart';
main() {
@@ -28,7 +26,7 @@
d.file('a.dart', "var a = 'a';"),
d.dir('a', [
d.file('b.dart', "var b = 'b';"),
- d.dir('b', [d.file('app.dart', SCRIPT)])
+ d.dir('b', [d.file('app.dart', _script)])
])
])
]).create();
diff --git a/test/run/loads_package_imports_in_a_dependency_test.dart b/test/run/loads_package_imports_in_a_dependency_test.dart
index 66c261d..7bfb047 100644
--- a/test/run/loads_package_imports_in_a_dependency_test.dart
+++ b/test/run/loads_package_imports_in_a_dependency_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
diff --git a/test/run/nonexistent_dependency_test.dart b/test/run/nonexistent_dependency_test.dart
index 5b0f941..2051149 100644
--- a/test/run/nonexistent_dependency_test.dart
+++ b/test/run/nonexistent_dependency_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/run/nonexistent_script_in_dependency_test.dart b/test/run/nonexistent_script_in_dependency_test.dart
index 5153c25..62816df 100644
--- a/test/run/nonexistent_script_in_dependency_test.dart
+++ b/test/run/nonexistent_script_in_dependency_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/run/nonexistent_script_test.dart b/test/run/nonexistent_script_test.dart
index 9930430..0e12ee1 100644
--- a/test/run/nonexistent_script_test.dart
+++ b/test/run/nonexistent_script_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/run/package_api_test.dart b/test/run/package_api_test.dart
index e7b814f..4d05408 100644
--- a/test/run/package_api_test.dart
+++ b/test/run/package_api_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
@@ -51,11 +49,10 @@
});
test('a snapshotted application sees a file: package root', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', contents: [
- d.dir('bin', [d.file('script.dart', _script)])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', contents: [
+ d.dir('bin', [d.file('script.dart', _script)])
+ ]);
await d.dir(appPath, [
d.appPubspec({'foo': 'any'})
@@ -75,8 +72,8 @@
.toString()));
expect(pub.stdout,
emits(p.toUri(p.join(d.sandbox, 'myapp/lib/resource.txt')).toString()));
- var fooResourcePath = p.join(
- globalPackageServer.pathInCache('foo', '1.0.0'), 'lib/resource.txt');
+ var fooResourcePath =
+ p.join(globalServer.pathInCache('foo', '1.0.0'), 'lib/resource.txt');
expect(pub.stdout, emits(p.toUri(fooResourcePath).toString()));
await pub.shouldExit(0);
});
diff --git a/test/run/passes_along_arguments_test.dart b/test/run/passes_along_arguments_test.dart
index d2beebf..624d9f2 100644
--- a/test/run/passes_along_arguments_test.dart
+++ b/test/run/passes_along_arguments_test.dart
@@ -2,14 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
import '../test_pub.dart';
-const SCRIPT = '''
+const _script = '''
main(List<String> args) {
print(args.join(" "));
}
@@ -19,7 +17,7 @@
test('passes arguments to the spawned script', () async {
await d.dir(appPath, [
d.appPubspec(),
- d.dir('bin', [d.file('args.dart', SCRIPT)])
+ d.dir('bin', [d.file('args.dart', _script)])
]).create();
await pubGet();
diff --git a/test/run/precompile_test.dart b/test/run/precompile_test.dart
index ac663d5..2d70b4c 100644
--- a/test/run/precompile_test.dart
+++ b/test/run/precompile_test.dart
@@ -2,14 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
import '../test_pub.dart';
-const SCRIPT = r'''
+const _script = r'''
import 'dart:io';
main(List<String> args) {
@@ -23,11 +21,11 @@
d.appPubspec({'test': '1.0.0'}),
]).create();
- await servePackages((server) => server
- ..serve('test', '1.0.0', contents: [
- d.dir('bin',
- [d.file('test.dart', 'main(List<String> args) => print("hello");')])
- ]));
+ final server = await servePackages();
+ server.serve('test', '1.0.0', contents: [
+ d.dir('bin',
+ [d.file('test.dart', 'main(List<String> args) => print("hello");')])
+ ]);
await pubGet(args: ['--no-precompile']);
}
@@ -59,10 +57,10 @@
d.appPubspec({'test': '1.0.0'}),
]).create();
- await servePackages((server) => server
- ..serve('test', '1.0.0', contents: [
- d.dir('bin', [d.file('test.dart', SCRIPT)])
- ]));
+ final server = await servePackages();
+ server.serve('test', '1.0.0', contents: [
+ d.dir('bin', [d.file('test.dart', _script)])
+ ]);
await pubGet(
args: ['--no-precompile'], environment: {'PUB_CACHE': '.pub_cache'});
@@ -82,10 +80,10 @@
d.appPubspec({'test': '1.0.0'}),
]).create();
- await servePackages((server) => server
- ..serve('test', '1.0.0', contents: [
- d.dir('bin', [d.file('test.dart', SCRIPT)])
- ]));
+ final server = await servePackages();
+ server.serve('test', '1.0.0', contents: [
+ d.dir('bin', [d.file('test.dart', _script)])
+ ]);
await pubGet(
args: ['--precompile'],
@@ -106,10 +104,10 @@
d.appPubspec({'test': '1.0.0'}),
]).create();
- await servePackages((server) => server
- ..serve('test', '1.0.0', contents: [
- d.dir('bin', [d.file('test.dart', SCRIPT)])
- ]));
+ final server = await servePackages();
+ server.serve('test', '1.0.0', contents: [
+ d.dir('bin', [d.file('test.dart', _script)])
+ ]);
await pubGet(
args: ['--precompile'],
diff --git a/test/run/runs_app_in_directory_in_entrypoint_test.dart b/test/run/runs_app_in_directory_in_entrypoint_test.dart
index ef720c5..ac8af0d 100644
--- a/test/run/runs_app_in_directory_in_entrypoint_test.dart
+++ b/test/run/runs_app_in_directory_in_entrypoint_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
diff --git a/test/run/runs_app_in_entrypoint_test.dart b/test/run/runs_app_in_entrypoint_test.dart
index 3f3ed38..6cb932a 100644
--- a/test/run/runs_app_in_entrypoint_test.dart
+++ b/test/run/runs_app_in_entrypoint_test.dart
@@ -2,14 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
import '../test_pub.dart';
-const SCRIPT = """
+const _script = """
import 'dart:io';
main() {
@@ -23,7 +21,7 @@
test('runs a Dart application in the entrypoint package', () async {
await d.dir(appPath, [
d.appPubspec(),
- d.dir('bin', [d.file('script.dart', SCRIPT)])
+ d.dir('bin', [d.file('script.dart', _script)])
]).create();
await pubGet();
diff --git a/test/run/runs_from_a_dependency_override_after_dependency_test.dart b/test/run/runs_from_a_dependency_override_after_dependency_test.dart
index c3cde77..c11bacb 100644
--- a/test/run/runs_from_a_dependency_override_after_dependency_test.dart
+++ b/test/run/runs_from_a_dependency_override_after_dependency_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
@@ -12,14 +10,13 @@
void main() {
// Regression test for issue 23113
test('runs a named Dart application in a dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'name': 'foo',
- 'version': '1.0.0'
- }, contents: [
- d.dir('bin', [d.file('bar.dart', "main() => print('foobar');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'name': 'foo',
+ 'version': '1.0.0'
+ }, contents: [
+ d.dir('bin', [d.file('bar.dart', "main() => print('foobar');")])
+ ]);
await d.dir(appPath, [
d.appPubspec({'foo': null})
diff --git a/test/run/runs_named_app_in_dependency_test.dart b/test/run/runs_named_app_in_dependency_test.dart
index d554eb4..8f3d73d 100644
--- a/test/run/runs_named_app_in_dependency_test.dart
+++ b/test/run/runs_named_app_in_dependency_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
diff --git a/test/run/runs_named_app_in_dev_dependency_test.dart b/test/run/runs_named_app_in_dev_dependency_test.dart
index f1493d4..287f05b 100644
--- a/test/run/runs_named_app_in_dev_dependency_test.dart
+++ b/test/run/runs_named_app_in_dev_dependency_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
diff --git a/test/run/runs_shorthand_app_in_dependency_test.dart b/test/run/runs_shorthand_app_in_dependency_test.dart
index cd3c66a..455e049 100644
--- a/test/run/runs_shorthand_app_in_dependency_test.dart
+++ b/test/run/runs_shorthand_app_in_dependency_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
diff --git a/test/run/runs_the_script_in_checked_mode_test.dart b/test/run/runs_the_script_in_checked_mode_test.dart
index 8b8e214..8b4010a 100644
--- a/test/run/runs_the_script_in_checked_mode_test.dart
+++ b/test/run/runs_the_script_in_checked_mode_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
diff --git a/test/run/runs_the_script_in_unchecked_mode_test.dart b/test/run/runs_the_script_in_unchecked_mode_test.dart
index da86989..026a748 100644
--- a/test/run/runs_the_script_in_unchecked_mode_test.dart
+++ b/test/run/runs_the_script_in_unchecked_mode_test.dart
@@ -2,14 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
import '../test_pub.dart';
-const SCRIPT = '''
+const _script = '''
main() {
assert(false);
print("no checks");
@@ -20,7 +18,7 @@
test('runs the script without assertions by default', () async {
await d.dir(appPath, [
d.appPubspec(),
- d.dir('bin', [d.file('script.dart', SCRIPT)])
+ d.dir('bin', [d.file('script.dart', _script)])
]).create();
await pubGet();
diff --git a/test/sdk_test.dart b/test/sdk_test.dart
index 93ebdac..6165cd5 100644
--- a/test/sdk_test.dart
+++ b/test/sdk_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/io.dart';
@@ -15,9 +13,8 @@
void main() {
forBothPubGetAndUpgrade((command) {
setUp(() async {
- await servePackages((builder) {
- builder.serve('bar', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('bar', '1.0.0');
await d.dir('flutter', [
d.dir('packages', [
@@ -40,13 +37,10 @@
}).create();
await pubCommand(command,
environment: {'FLUTTER_ROOT': p.join(d.sandbox, 'flutter')});
-
- await d.dir(appPath, [
- d.packagesFile({
- 'myapp': '.',
- 'foo': p.join(d.sandbox, 'flutter', 'packages', 'foo'),
- 'bar': '1.0.0'
- })
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(
+ name: 'foo', path: p.join(d.sandbox, 'flutter', 'packages', 'foo')),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
]).validate();
});
@@ -57,11 +51,10 @@
await pubCommand(command,
environment: {'FLUTTER_ROOT': p.join(d.sandbox, 'flutter')});
- await d.dir(appPath, [
- d.packagesFile({
- 'myapp': '.',
- 'baz': p.join(d.sandbox, 'flutter', 'bin', 'cache', 'pkg', 'baz')
- })
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(
+ name: 'baz',
+ path: p.join(d.sandbox, 'flutter', 'bin', 'cache', 'pkg', 'baz')),
]).validate();
});
@@ -96,10 +89,7 @@
deleteEntry(p.join(d.sandbox, 'flutter', 'version'));
await pubCommand(command,
environment: {'FLUTTER_ROOT': p.join(d.sandbox, 'flutter')});
-
- await d.dir(appPath, [
- d.packagesFile({'myapp': '.'})
- ]).validate();
+ await d.appPackageConfigFile([]).validate();
});
group('fails if', () {
@@ -120,7 +110,7 @@
'foo': {'sdk': 'unknown'}
}).create();
await pubCommand(command, error: equalsIgnoringWhitespace("""
- Because myapp depends on foo any from sdk which doesn't exist
+ Because myapp depends on foo from sdk which doesn't exist
(unknown SDK "unknown"), version solving failed.
"""), exitCode: exit_codes.UNAVAILABLE);
});
@@ -130,7 +120,7 @@
'foo': {'sdk': 'flutter'}
}).create();
await pubCommand(command, error: equalsIgnoringWhitespace("""
- Because myapp depends on foo any from sdk which doesn't exist (the
+ Because myapp depends on foo from sdk which doesn't exist (the
Flutter SDK is not available), version solving failed.
Flutter users should run `flutter pub get` instead of `dart pub
@@ -145,7 +135,7 @@
await pubCommand(command,
environment: {'FLUTTER_ROOT': p.join(d.sandbox, 'flutter')},
error: equalsIgnoringWhitespace("""
- Because myapp depends on bar any from sdk which doesn't exist
+ Because myapp depends on bar from sdk which doesn't exist
(could not find package bar in the Flutter SDK), version solving
failed.
"""),
@@ -157,7 +147,7 @@
'bar': {'sdk': 'dart'}
}).create();
await pubCommand(command, error: equalsIgnoringWhitespace("""
- Because myapp depends on bar any from sdk which doesn't exist
+ Because myapp depends on bar from sdk which doesn't exist
(could not find package bar in the Dart SDK), version solving
failed.
"""), exitCode: exit_codes.UNAVAILABLE);
@@ -172,13 +162,10 @@
}).create();
await pubCommand(command,
environment: {'FUCHSIA_DART_SDK_ROOT': p.join(d.sandbox, 'fuchsia')});
-
- await d.dir(appPath, [
- d.packagesFile({
- 'myapp': '.',
- 'foo': p.join(d.sandbox, 'fuchsia', 'packages', 'foo'),
- 'bar': '1.0.0'
- })
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(
+ name: 'foo', path: p.join(d.sandbox, 'fuchsia', 'packages', 'foo')),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
]).validate();
});
});
diff --git a/test/snapshot_test.dart b/test/snapshot_test.dart
index 6ad44f6..8143f7e 100644
--- a/test/snapshot_test.dart
+++ b/test/snapshot_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
@@ -13,17 +11,15 @@
void main() {
group('creates a snapshot', () {
test('for an immediate dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3', contents: [
- d.dir('bin', [
- d.file('hello.dart', "void main() => print('hello!');"),
- d.file('goodbye.dart', "void main() => print('goodbye!');"),
- d.file('shell.sh', 'echo shell'),
- d.dir(
- 'subdir', [d.file('sub.dart', "void main() => print('sub!');")])
- ])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.3', contents: [
+ d.dir('bin', [
+ d.file('hello.dart', "void main() => print('hello!');"),
+ d.file('goodbye.dart', "void main() => print('goodbye!');"),
+ d.file('shell.sh', 'echo shell'),
+ d.dir('subdir', [d.file('sub.dart', "void main() => print('sub!');")])
+ ])
+ ]);
await d.appDir({'foo': '1.2.3'}).create();
@@ -51,8 +47,8 @@
});
test("for an immediate dependency that's also transitive", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3', contents: [
+ await servePackages()
+ ..serve('foo', '1.2.3', contents: [
d.dir('bin', [
d.file('hello.dart', "void main() => print('hello!');"),
d.file('goodbye.dart', "void main() => print('goodbye!');"),
@@ -60,9 +56,8 @@
d.dir(
'subdir', [d.file('sub.dart', "void main() => print('sub!');")])
])
- ]);
- builder.serve('bar', '1.2.3', deps: {'foo': '1.2.3'});
- });
+ ])
+ ..serve('bar', '1.2.3', deps: {'foo': '1.2.3'});
await d.appDir({'foo': '1.2.3'}).create();
@@ -91,12 +86,11 @@
group('again if', () {
test('its package is updated', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3', contents: [
- d.dir('bin',
- [d.file('hello.dart', "void main() => print('hello!');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '1.2.3', contents: [
+ d.dir(
+ 'bin', [d.file('hello.dart', "void main() => print('hello!');")])
+ ]);
await d.appDir({'foo': 'any'}).create();
@@ -107,12 +101,10 @@
d.file('hello.dart-$versionSuffix.snapshot', contains('hello!'))
]).validate();
- globalPackageServer.add((builder) {
- builder.serve('foo', '1.2.4', contents: [
- d.dir('bin',
- [d.file('hello.dart', "void main() => print('hello 2!');")])
- ]);
- });
+ server.serve('foo', '1.2.4', contents: [
+ d.dir('bin',
+ [d.file('hello.dart', "void main() => print('hello 2!');")])
+ ]);
await pubUpgrade(
args: ['--precompile'], output: contains('Built foo:hello.'));
@@ -127,22 +119,22 @@
});
test('a dependency of its package is updated', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3', pubspec: {
- 'dependencies': {'bar': 'any'}
- }, contents: [
- d.dir('bin', [
- d.file('hello.dart', """
+ final server = await servePackages();
+
+ server.serve('foo', '1.2.3', pubspec: {
+ 'dependencies': {'bar': 'any'}
+ }, contents: [
+ d.dir('bin', [
+ d.file('hello.dart', """
import 'package:bar/bar.dart';
void main() => print(message);
""")
- ])
- ]);
- builder.serve('bar', '1.2.3', contents: [
- d.dir('lib', [d.file('bar.dart', "final message = 'hello!';")])
- ]);
- });
+ ])
+ ]);
+ server.serve('bar', '1.2.3', contents: [
+ d.dir('lib', [d.file('bar.dart', "final message = 'hello!';")])
+ ]);
await d.appDir({'foo': 'any'}).create();
@@ -153,11 +145,9 @@
d.file('hello.dart-$versionSuffix.snapshot', contains('hello!'))
]).validate();
- globalPackageServer.add((builder) {
- builder.serve('bar', '1.2.4', contents: [
- d.dir('lib', [d.file('bar.dart', "final message = 'hello 2!';")]),
- ]);
- });
+ server.serve('bar', '1.2.4', contents: [
+ d.dir('lib', [d.file('bar.dart', "final message = 'hello 2!';")]),
+ ]);
await pubUpgrade(
args: ['--precompile'], output: contains('Built foo:hello.'));
@@ -209,12 +199,11 @@
});
test('the SDK is out of date', () async {
- await servePackages((builder) {
- builder.serve('foo', '5.6.7', contents: [
- d.dir('bin',
- [d.file('hello.dart', "void main() => print('hello!');")])
- ]);
- });
+ final server = await servePackages();
+ server.serve('foo', '5.6.7', contents: [
+ d.dir(
+ 'bin', [d.file('hello.dart', "void main() => print('hello!');")])
+ ]);
await d.appDir({'foo': '5.6.7'}).create();
diff --git a/test/test_pub.dart b/test/test_pub.dart
index 1351914..be2825e 100644
--- a/test/test_pub.dart
+++ b/test/test_pub.dart
@@ -2,15 +2,13 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
/// Test infrastructure for testing pub.
///
/// Unlike typical unit tests, most pub tests are integration tests that stage
/// some stuff on the file system, run pub, and then validate the results. This
/// library provides an API to build tests like that.
-import 'dart:async';
import 'dart:convert';
+import 'dart:core';
import 'dart:io';
import 'dart:isolate';
import 'dart:math';
@@ -28,7 +26,6 @@
import 'package:pub/src/io.dart';
import 'package:pub/src/lock_file.dart';
import 'package:pub/src/log.dart' as log;
-import 'package:pub/src/sdk.dart';
import 'package:pub/src/source_registry.dart';
import 'package:pub/src/system_cache.dart';
import 'package:pub/src/utils.dart';
@@ -39,11 +36,9 @@
import 'package:test_process/test_process.dart';
import 'descriptor.dart' as d;
-import 'descriptor_server.dart';
import 'package_server.dart';
-export 'descriptor_server.dart';
-export 'package_server.dart';
+export 'package_server.dart' show PackageServer;
/// A [Matcher] that matches JavaScript generated by dart2js with minification
/// enabled.
@@ -82,7 +77,7 @@
orElse: () => null) as Map<String, dynamic>;
/// The suffix appended to a built snapshot.
-final versionSuffix = testVersion ?? sdk.version;
+final versionSuffix = testVersion;
/// Enum identifying a pub command that can be run with a well-defined success
/// output.
@@ -130,14 +125,15 @@
// TODO(rnystrom): Clean up other tests to call this when possible.
Future<void> pubCommand(
RunCommand command, {
- Iterable<String> args,
- output,
- error,
- silent,
- warning,
- int exitCode,
- Map<String, String> environment,
- String workingDirectory,
+ Iterable<String>? args,
+ Object? output,
+ Object? error,
+ Object? silent,
+ Object? warning,
+ int? exitCode,
+ Map<String, String?>? environment,
+ String? workingDirectory,
+ includeParentEnvironment = true,
}) async {
if (error != null && warning != null) {
throw ArgumentError("Cannot pass both 'error' and 'warning'.");
@@ -161,17 +157,18 @@
silent: silent,
exitCode: exitCode,
environment: environment,
- workingDirectory: workingDirectory);
+ workingDirectory: workingDirectory,
+ includeParentEnvironment: includeParentEnvironment);
}
Future<void> pubAdd({
- Iterable<String> args,
- output,
- error,
- warning,
- int exitCode,
- Map<String, String> environment,
- String workingDirectory,
+ Iterable<String>? args,
+ Object? output,
+ Object? error,
+ Object? warning,
+ int? exitCode,
+ Map<String, String>? environment,
+ String? workingDirectory,
}) async =>
await pubCommand(
RunCommand.add,
@@ -185,13 +182,14 @@
);
Future<void> pubGet({
- Iterable<String> args,
- output,
- error,
- warning,
- int exitCode,
- Map<String, String> environment,
- String workingDirectory,
+ Iterable<String>? args,
+ Object? output,
+ Object? error,
+ Object? warning,
+ int? exitCode,
+ Map<String, String?>? environment,
+ String? workingDirectory,
+ bool includeParentEnvironment = true,
}) async =>
await pubCommand(
RunCommand.get,
@@ -202,16 +200,17 @@
exitCode: exitCode,
environment: environment,
workingDirectory: workingDirectory,
+ includeParentEnvironment: includeParentEnvironment,
);
Future<void> pubUpgrade(
- {Iterable<String> args,
- output,
- error,
- warning,
- int exitCode,
- Map<String, String> environment,
- String workingDirectory}) async =>
+ {Iterable<String>? args,
+ Object? output,
+ Object? error,
+ Object? warning,
+ int? exitCode,
+ Map<String, String>? environment,
+ String? workingDirectory}) async =>
await pubCommand(
RunCommand.upgrade,
args: args,
@@ -224,13 +223,13 @@
);
Future<void> pubDowngrade({
- Iterable<String> args,
- output,
- error,
- warning,
- int exitCode,
- Map<String, String> environment,
- String workingDirectory,
+ Iterable<String>? args,
+ Object? output,
+ Object? error,
+ Object? warning,
+ int? exitCode,
+ Map<String, String>? environment,
+ String? workingDirectory,
}) async =>
await pubCommand(
RunCommand.downgrade,
@@ -244,13 +243,13 @@
);
Future<void> pubRemove({
- Iterable<String> args,
- output,
- error,
- warning,
- int exitCode,
- Map<String, String> environment,
- String workingDirectory,
+ Iterable<String>? args,
+ Object? output,
+ Object? error,
+ Object? warning,
+ int? exitCode,
+ Map<String, String>? environment,
+ String? workingDirectory,
}) async =>
await pubCommand(
RunCommand.remove,
@@ -272,8 +271,8 @@
/// Returns the `pub run` process.
Future<PubProcess> pubRun(
{bool global = false,
- Iterable<String> args,
- Map<String, String> environment,
+ required Iterable<String> args,
+ Map<String, String>? environment,
bool verbose = true}) async {
var pubArgs = global ? ['global', 'run'] : ['run'];
pubArgs.addAll(args);
@@ -290,20 +289,6 @@
return pub;
}
-/// Schedules starting the "pub run --v2" process and validates the
-/// expected startup output.
-///
-/// Returns the `pub run` process.
-Future<PubProcess> pubRunFromDartDev({Iterable<String> args}) async {
- final pub = await startPub(args: ['run', '--dart-dev-run', ...args]);
-
- // Loading sources and transformers isn't normally printed, but the pub test
- // infrastructure runs pub in verbose mode, which enables this.
- expect(pub.stdout, mayEmitMultiple(startsWith('Loading')));
-
- return pub;
-}
-
/// Schedules renaming (moving) the directory at [from] to [to], both of which
/// are assumed to be relative to [d.sandbox].
void renameInSandbox(String from, String to) {
@@ -330,23 +315,27 @@
///
/// If [environment] is given, any keys in it will override the environment
/// variables passed to the spawned process.
-Future<void> runPub({
- List<String> args,
- output,
- error,
- outputJson,
- silent,
- int exitCode,
- String workingDirectory,
- Map<String, String> environment,
- List<String> input,
-}) async {
+Future<void> runPub(
+ {List<String>? args,
+ Object? output,
+ Object? error,
+ Object? outputJson,
+ Object? silent,
+ int? exitCode,
+ String? workingDirectory,
+ Map<String, String?>? environment,
+ List<String>? input,
+ includeParentEnvironment = true}) async {
exitCode ??= exit_codes.SUCCESS;
// Cannot pass both output and outputJson.
assert(output == null || outputJson == null);
var pub = await startPub(
- args: args, workingDirectory: workingDirectory, environment: environment);
+ args: args,
+ workingDirectory: workingDirectory,
+ environment: environment,
+ includeParentEnvironment: includeParentEnvironment,
+ );
if (input != null) {
input.forEach(pub.stdin.writeln);
@@ -379,14 +368,20 @@
/// package server.
///
/// Any futures in [args] will be resolved before the process is started.
-Future<PubProcess> startPublish(PackageServer server,
- {List<String> args}) async {
+Future<PubProcess> startPublish(
+ PackageServer server, {
+ List<String>? args,
+ String authMethod = 'oauth2',
+ Map<String, String>? environment,
+ String path = '',
+}) async {
var tokenEndpoint = Uri.parse(server.url).resolve('/token').toString();
args = ['lish', ...?args];
- return await startPub(
- args: args,
- tokenEndpoint: tokenEndpoint,
- environment: {'PUB_HOSTED_URL': server.url});
+ return await startPub(args: args, tokenEndpoint: tokenEndpoint, environment: {
+ 'PUB_HOSTED_URL': server.url + path,
+ '_PUB_TEST_AUTH_METHOD': authMethod,
+ if (environment != null) ...environment,
+ });
}
/// Handles the beginning confirmation process for uploading a packages.
@@ -416,28 +411,19 @@
String testVersion = '0.1.2+3';
/// Gets the environment variables used to run pub in a test context.
-Map<String, String> getPubTestEnvironment([String tokenEndpoint]) {
- var environment = {
- 'CI': 'false', // unless explicitly given tests don't run pub in CI mode
- '_PUB_TESTING': 'true',
- '_PUB_TEST_CONFIG_DIR': _pathInSandbox(configPath),
- 'PUB_CACHE': _pathInSandbox(cachePath),
- 'PUB_ENVIRONMENT': 'test-environment',
+Map<String, String> getPubTestEnvironment([String? tokenEndpoint]) => {
+ 'CI': 'false', // unless explicitly given tests don't run pub in CI mode
+ '_PUB_TESTING': 'true',
+ '_PUB_TEST_CONFIG_DIR': _pathInSandbox(configPath),
+ 'PUB_CACHE': _pathInSandbox(cachePath),
+ 'PUB_ENVIRONMENT': 'test-environment',
- // Ensure a known SDK version is set for the tests that rely on that.
- '_PUB_TEST_SDK_VERSION': testVersion
- };
-
- if (tokenEndpoint != null) {
- environment['_PUB_TEST_TOKEN_ENDPOINT'] = tokenEndpoint;
- }
-
- if (globalServer != null) {
- environment['PUB_HOSTED_URL'] = 'http://localhost:${globalServer.port}';
- }
-
- return environment;
-}
+ // Ensure a known SDK version is set for the tests that rely on that.
+ '_PUB_TEST_SDK_VERSION': testVersion,
+ if (tokenEndpoint != null) '_PUB_TEST_TOKEN_ENDPOINT': tokenEndpoint,
+ if (_globalServer?.port != null)
+ 'PUB_HOSTED_URL': 'http://localhost:${_globalServer?.port}'
+ };
/// The path to the root of pub's sources in the pub repo.
final String _pubRoot = (() {
@@ -456,25 +442,16 @@
/// If [environment] is given, any keys in it will override the environment
/// variables passed to the spawned process.
Future<PubProcess> startPub(
- {Iterable<String> args,
- String tokenEndpoint,
- String workingDirectory,
- Map<String, String> environment,
- bool verbose = true}) async {
+ {Iterable<String>? args,
+ String? tokenEndpoint,
+ String? workingDirectory,
+ Map<String, String?>? environment,
+ bool verbose = true,
+ includeParentEnvironment = true}) async {
args ??= [];
ensureDir(_pathInSandbox(appPath));
- // Find a Dart executable we can use to spawn. Use the same one that was
- // used to run this script itself.
- var dartBin = Platform.executable;
-
- // If the executable looks like a path, get its full path. That way we
- // can still find it when we spawn it with a different working directory.
- if (dartBin.contains(Platform.pathSeparator)) {
- dartBin = p.absolute(dartBin);
- }
-
// If there's a snapshot for "pub" available we use it. If the snapshot is
// out-of-date local source the tests will be useless, therefore it is
// recommended to use a temporary file with a unique name for each test run.
@@ -489,37 +466,47 @@
var dartArgs = ['--packages=$dotPackagesPath', '--enable-asserts'];
dartArgs
- ..addAll([pubPath, if (verbose) '--verbose'])
+ ..addAll([pubPath, if (!verbose) '--verbosity=normal'])
..addAll(args);
- return await PubProcess.start(dartBin, dartArgs,
- environment: getPubTestEnvironment(tokenEndpoint)
- ..addAll(environment ?? {}),
+ final mergedEnvironment = getPubTestEnvironment(tokenEndpoint);
+ for (final e in (environment ?? {}).entries) {
+ var value = e.value;
+ if (value == null) {
+ mergedEnvironment.remove(e.key);
+ } else {
+ mergedEnvironment[e.key] = value;
+ }
+ }
+
+ return await PubProcess.start(Platform.resolvedExecutable, dartArgs,
+ environment: mergedEnvironment,
workingDirectory: workingDirectory ?? _pathInSandbox(appPath),
- description: args.isEmpty ? 'pub' : 'pub ${args.first}');
+ description: args.isEmpty ? 'pub' : 'pub ${args.first}',
+ includeParentEnvironment: includeParentEnvironment);
}
/// A subclass of [TestProcess] that parses pub's verbose logging output and
/// makes [stdout] and [stderr] work as though pub weren't running in verbose
/// mode.
class PubProcess extends TestProcess {
- StreamSplitter<Pair<log.Level, String>> get _logSplitter {
- __logSplitter ??= StreamSplitter(StreamGroup.merge([
- _outputToLog(super.stdoutStream(), log.Level.MESSAGE),
- _outputToLog(super.stderrStream(), log.Level.ERROR)
+ late final StreamSplitter<Pair<log.Level, String>> _logSplitter =
+ createLogSplitter();
+
+ StreamSplitter<Pair<log.Level, String>> createLogSplitter() {
+ return StreamSplitter(StreamGroup.merge([
+ _outputToLog(super.stdoutStream(), log.Level.message),
+ _outputToLog(super.stderrStream(), log.Level.error)
]));
- return __logSplitter;
}
- StreamSplitter<Pair<log.Level, String>> __logSplitter;
-
static Future<PubProcess> start(String executable, Iterable<String> arguments,
- {String workingDirectory,
- Map<String, String> environment,
+ {String? workingDirectory,
+ Map<String, String>? environment,
bool includeParentEnvironment = true,
bool runInShell = false,
- String description,
- Encoding encoding,
+ String? description,
+ Encoding encoding = utf8,
bool forwardStdio = false}) async {
var process = await Process.start(executable, arguments.toList(),
workingDirectory: workingDirectory,
@@ -534,25 +521,24 @@
description = '$humanExecutable ${arguments.join(' ')}';
}
- encoding ??= utf8;
return PubProcess(process, description,
encoding: encoding, forwardStdio: forwardStdio);
}
/// This is protected.
PubProcess(process, description,
- {Encoding encoding, bool forwardStdio = false})
+ {Encoding encoding = utf8, bool forwardStdio = false})
: super(process, description,
encoding: encoding, forwardStdio: forwardStdio);
final _logLineRegExp = RegExp(r'^([A-Z ]{4})[:|] (.*)$');
final Map<String, log.Level> _logLevels = [
- log.Level.ERROR,
- log.Level.WARNING,
- log.Level.MESSAGE,
- log.Level.IO,
- log.Level.SOLVER,
- log.Level.FINE
+ log.Level.error,
+ log.Level.warning,
+ log.Level.message,
+ log.Level.io,
+ log.Level.solver,
+ log.Level.fine
].fold({}, (levels, level) {
levels[level.name] = level;
return levels;
@@ -560,21 +546,21 @@
Stream<Pair<log.Level, String>> _outputToLog(
Stream<String> stream, log.Level defaultLevel) {
- log.Level lastLevel;
+ late log.Level lastLevel;
return stream.map((line) {
var match = _logLineRegExp.firstMatch(line);
if (match == null) return Pair<log.Level, String>(defaultLevel, line);
var level = _logLevels[match[1]] ?? lastLevel;
lastLevel = level;
- return Pair<log.Level, String>(level, match[2]);
+ return Pair<log.Level, String>(level, match[2]!);
});
}
@override
Stream<String> stdoutStream() {
return _logSplitter.split().expand((entry) {
- if (entry.first != log.Level.MESSAGE) return [];
+ if (entry.first != log.Level.message) return [];
return [entry.last];
});
}
@@ -582,7 +568,7 @@
@override
Stream<String> stderrStream() {
return _logSplitter.split().expand((entry) {
- if (entry.first != log.Level.ERROR && entry.first != log.Level.WARNING) {
+ if (entry.first != log.Level.error && entry.first != log.Level.warning) {
return [];
}
return [entry.last];
@@ -592,9 +578,9 @@
/// A stream of log messages that are silent by default.
Stream<String> silentStream() {
return _logSplitter.split().expand((entry) {
- if (entry.first == log.Level.MESSAGE) return [];
- if (entry.first == log.Level.ERROR) return [];
- if (entry.first == log.Level.WARNING) return [];
+ if (entry.first == log.Level.message) return [];
+ if (entry.first == log.Level.error) return [];
+ if (entry.first == log.Level.warning) return [];
return [entry.last];
});
}
@@ -617,15 +603,15 @@
/// [hosted] is a list of package names to version strings for dependencies on
/// hosted packages.
Future<void> createLockFile(String package,
- {Iterable<String> dependenciesInSandBox,
- Map<String, String> hosted}) async {
+ {Iterable<String>? dependenciesInSandBox,
+ Map<String, String>? hosted}) async {
var cache = SystemCache(rootDir: _pathInSandbox(cachePath));
var lockFile = _createLockFile(cache.sources,
sandbox: dependenciesInSandBox, hosted: hosted);
await d.dir(package, [
- d.file('pubspec.lock', lockFile.serialize(null)),
+ d.file('pubspec.lock', lockFile.serialize(p.join(d.sandbox, package))),
d.file(
'.packages',
lockFile.packagesFile(
@@ -640,8 +626,8 @@
/// Like [createLockFile], but creates only a `.packages` file without a
/// lockfile.
Future<void> createPackagesFile(String package,
- {Iterable<String> dependenciesInSandBox,
- Map<String, String> hosted}) async {
+ {Iterable<String>? dependenciesInSandBox,
+ Map<String, String>? hosted}) async {
var cache = SystemCache(rootDir: _pathInSandbox(cachePath));
var lockFile = _createLockFile(cache.sources,
sandbox: dependenciesInSandBox, hosted: hosted);
@@ -666,7 +652,7 @@
/// [hosted] is a list of package names to version strings for dependencies on
/// hosted packages.
LockFile _createLockFile(SourceRegistry sources,
- {Iterable<String> sandbox, Map<String, String> hosted}) {
+ {Iterable<String>? sandbox, Map<String, String>? hosted}) {
var dependencies = {};
if (sandbox != null) {
@@ -677,7 +663,9 @@
var packages = dependencies.keys.map((name) {
var dependencyPath = dependencies[name];
- return sources.path.idFor(name, Version(0, 0, 0), dependencyPath);
+ return sources.path.parseId(
+ name, Version(0, 0, 0), {'path': dependencyPath, 'relative': true},
+ containingPath: p.join(d.sandbox, appPath));
}).toList();
if (hosted != null) {
@@ -704,14 +692,14 @@
/// Describes a map representing a library package with the given [name],
/// [version], and [dependencies].
-Map packageMap(
+Map<String, Object> packageMap(
String name,
String version, [
- Map dependencies,
- Map devDependencies,
- Map environment,
+ Map? dependencies,
+ Map? devDependencies,
+ Map? environment,
]) {
- var package = <String, dynamic>{
+ var package = <String, Object>{
'name': name,
'version': version,
'homepage': 'http://pub.dartlang.org',
@@ -833,7 +821,7 @@
/// which may be a literal JSON object, or any other [Matcher].
void _validateOutputJson(
List<String> failures, String pipe, expected, String actualText) {
- Map actual;
+ late Map actual;
try {
actual = jsonDecode(actualText);
} on FormatException {
@@ -914,8 +902,9 @@
line = line
.replaceAll(d.sandbox, r'$SANDBOX')
.replaceAll(Platform.pathSeparator, '/');
- if (globalPackageServer != null) {
- line = line.replaceAll(globalPackageServer.port.toString(), '\$PORT');
+ var port = _globalServer?.port;
+ if (port != null) {
+ line = line.replaceAll(port.toString(), '\$PORT');
}
return line;
});
@@ -925,9 +914,9 @@
Future<void> runPubIntoBuffer(
List<String> args,
StringBuffer buffer, {
- Map<String, String> environment,
- String workingDirectory,
- String stdin,
+ Map<String, String>? environment,
+ String? workingDirectory,
+ String? stdin,
}) async {
final process = await startPub(
args: args,
@@ -941,15 +930,49 @@
}
final exitCode = await process.exitCode;
+ // TODO(jonasfj): Clean out temporary directory names from env vars...
+ // if (workingDirectory != null) {
+ // buffer.writeln('\$ cd $workingDirectory');
+ // }
+ // if (environment != null && environment.isNotEmpty) {
+ // buffer.writeln(environment.entries
+ // .map((e) => '\$ export ${e.key}=${e.value}')
+ // .join('\n'));
+ // }
buffer.writeln(_filter([
'\$ pub ${args.join(' ')}',
...await process.stdout.rest.toList(),
]).join('\n'));
for (final line in _filter(await process.stderr.rest.toList())) {
- buffer.writeln('[ERR] $line');
+ buffer.writeln('[STDERR] $line');
}
if (exitCode != 0) {
- buffer.writeln('[Exit code] $exitCode');
+ buffer.writeln('[EXIT CODE] $exitCode');
}
buffer.write('\n');
}
+
+/// The current global [PackageServer].
+PackageServer get globalServer => _globalServer!;
+PackageServer? _globalServer;
+
+/// Creates an HTTP server that replicates the structure of pub.dartlang.org and
+/// makes it the current [globalServer].
+Future<PackageServer> servePackages() async {
+ final server = await startPackageServer();
+ _globalServer = server;
+
+ addTearDown(() {
+ _globalServer = null;
+ });
+ return server;
+}
+
+Future<PackageServer> startPackageServer() async {
+ final server = await PackageServer.start();
+
+ addTearDown(() async {
+ await server.close();
+ });
+ return server;
+}
diff --git a/test/testdata/README.md b/test/testdata/README.md
new file mode 100644
index 0000000..ad4a817
--- /dev/null
+++ b/test/testdata/README.md
@@ -0,0 +1,25 @@
+# Test Data
+
+Data used in tests is called _test data_ and is located in this folder, or
+sub-folders thereof. This is not for test files, this folder should not contain
+test code, only data used in tests.
+
+## Golden Test
+
+The `test` wrapper `testWithGolden('<name>', (ctx) async {` will register a
+test case, and create a file:
+ `test/testdata/goldens/path/to/myfile_test/<name>.txt`
+, where `path/to/myfile_test.dart` is the name of the file containing the test
+case, and `<name>` is the name of the test case.
+
+Any calls to `ctx.run` will run `pub` and compare the output to a section in the
+golden file. If the file does not exist, it is created and the
+test is marked as skipped.
+Thus, it is safe to delete all files in `test/testdata/goldens` and recreate
+them -- just carefully review the changes before committing.
+
+**Maintaining goldens**:
+ 1. Delete `test/testdata/goldens/`.
+ 2. Re-run tests to re-create files in `test/testdata/goldens/`.
+ 3. Compare changes, using `git diff test/testdata/goldens/`.
+
diff --git a/test/dependency_services/goldens/dependency_report_adding_transitive.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Adding transitive.txt
similarity index 83%
rename from test/dependency_services/goldens/dependency_report_adding_transitive.txt
rename to test/testdata/goldens/dependency_services/dependency_services_test/Adding transitive.txt
index 2a7fe2a..659163c 100644
--- a/test/dependency_services/goldens/dependency_report_adding_transitive.txt
+++ b/test/testdata/goldens/dependency_services/dependency_services_test/Adding transitive.txt
@@ -1,4 +1,6 @@
-$ pub __experimental-dependency-services list
+# GENERATED BY: test/dependency_services/dependency_services_test.dart
+
+$ bin/dependency_services.dart list
{
"dependencies": [
{
@@ -10,7 +12,7 @@
]
}
-$ pub __experimental-dependency-services report
+$ bin/dependency_services.dart report
{
"dependencies": [
{
@@ -52,10 +54,8 @@
]
}
-$ pub __experimental-dependency-services apply
-Resolving dependencies...
-+ transitive 1.0.0
-Would change 1 dependency.
+$ bin/dependency_services.dart apply
+{"dependencies":[]}
myapp/pubspec.yaml:
{"name":"app","dependencies":{"foo":^2.2.3},"environment":{"sdk":">=0.1.2 <1.0.0"}}
@@ -67,7 +67,7 @@
dependency: "direct main"
description:
name: foo
- url: "http://localhost:34801"
+ url: "http://localhost:<port>"
source: hosted
version: 2.2.3
sdks:
diff --git a/test/dependency_services/goldens/dependency_report_removing_transitive.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Removing transitive.txt
similarity index 80%
rename from test/dependency_services/goldens/dependency_report_removing_transitive.txt
rename to test/testdata/goldens/dependency_services/dependency_services_test/Removing transitive.txt
index c9bdee8..8f8cd13 100644
--- a/test/dependency_services/goldens/dependency_report_removing_transitive.txt
+++ b/test/testdata/goldens/dependency_services/dependency_services_test/Removing transitive.txt
@@ -1,4 +1,6 @@
-$ pub __experimental-dependency-services list
+# GENERATED BY: test/dependency_services/dependency_services_test.dart
+
+$ bin/dependency_services.dart list
{
"dependencies": [
{
@@ -16,7 +18,7 @@
]
}
-$ pub __experimental-dependency-services report
+$ bin/dependency_services.dart report
{
"dependencies": [
{
@@ -36,7 +38,7 @@
{
"name": "transitive",
"version": null,
- "kind": null,
+ "kind": "transitive",
"constraint": null
}
],
@@ -50,7 +52,7 @@
{
"name": "transitive",
"version": null,
- "kind": null,
+ "kind": "transitive",
"constraint": null
}
]
@@ -67,11 +69,8 @@
]
}
-$ pub __experimental-dependency-services apply
-Resolving dependencies...
-These packages are no longer being depended on:
-- transitive 1.0.0
-Would change 1 dependency.
+$ bin/dependency_services.dart apply
+{"dependencies":[]}
myapp/pubspec.yaml:
{"name":"app","dependencies":{"foo":^2.2.3},"environment":{"sdk":">=0.1.2 <1.0.0"}}
@@ -83,14 +82,14 @@
dependency: "direct main"
description:
name: foo
- url: "http://localhost:39343"
+ url: "http://localhost:<port>"
source: hosted
version: 2.2.3
transitive:
dependency: transitive
description:
name: transitive
- url: "http://localhost:39343"
+ url: "http://localhost:<port>"
source: hosted
version: "1.0.0"
sdks:
diff --git a/test/deps/goldens/formatting.txt b/test/testdata/goldens/deps/executables_test/applies formatting before printing executables.txt
similarity index 71%
rename from test/deps/goldens/formatting.txt
rename to test/testdata/goldens/deps/executables_test/applies formatting before printing executables.txt
index ff5aec9..d8448df 100644
--- a/test/deps/goldens/formatting.txt
+++ b/test/testdata/goldens/deps/executables_test/applies formatting before printing executables.txt
@@ -1,3 +1,7 @@
+# GENERATED BY: test/deps/executables_test.dart
+
+## Section 0
+$ tree
|-- bar
| |-- bin
| | '-- qux.dart
@@ -10,18 +14,28 @@
'-- myapp
|-- bin
| '-- myapp.dart
+ |-- pubspec.lock
'-- pubspec.yaml
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub deps --executables
myapp
foo: foo, baz
bar:qux
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub deps --executables --dev
myapp
foo: foo, baz
bar:qux
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub deps --json
{
"root": "myapp",
diff --git a/test/deps/goldens/dev_dependencies.txt b/test/testdata/goldens/deps/executables_test/dev dependencies.txt
similarity index 62%
rename from test/deps/goldens/dev_dependencies.txt
rename to test/testdata/goldens/deps/executables_test/dev dependencies.txt
index 3fb677c..2d72b44 100644
--- a/test/deps/goldens/dev_dependencies.txt
+++ b/test/testdata/goldens/deps/executables_test/dev dependencies.txt
@@ -1,16 +1,30 @@
+# GENERATED BY: test/deps/executables_test.dart
+
+## Section 0
+$ tree
|-- foo
| |-- bin
| | '-- bar.dart
| '-- pubspec.yaml
'-- myapp
+ |-- pubspec.lock
'-- pubspec.yaml
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub deps --executables
foo:bar
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub deps --executables --dev
foo:bar
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub deps --json
{
"root": "myapp",
diff --git a/test/testdata/goldens/deps/executables_test/lists Dart executables, without entrypoints.txt b/test/testdata/goldens/deps/executables_test/lists Dart executables, without entrypoints.txt
new file mode 100644
index 0000000..a12d363
--- /dev/null
+++ b/test/testdata/goldens/deps/executables_test/lists Dart executables, without entrypoints.txt
@@ -0,0 +1,50 @@
+# GENERATED BY: test/deps/executables_test.dart
+
+## Section 0
+$ tree
+'-- myapp
+ |-- bin
+ | |-- bar.dart
+ | '-- foo.dart
+ |-- pubspec.lock
+ '-- pubspec.yaml
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
+$ pub deps --executables
+myapp: bar, foo
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
+$ pub deps --executables --dev
+myapp: bar, foo
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
+$ pub deps --json
+{
+ "root": "myapp",
+ "packages": [
+ {
+ "name": "myapp",
+ "version": "0.0.0",
+ "kind": "root",
+ "source": "root",
+ "dependencies": []
+ }
+ ],
+ "sdks": [
+ {
+ "name": "Dart",
+ "version": "0.1.2+3"
+ }
+ ],
+ "executables": [
+ ":bar",
+ ":foo"
+ ]
+}
+
diff --git a/test/deps/goldens/only_immediate.txt b/test/testdata/goldens/deps/executables_test/lists executables from a dependency.txt
similarity index 62%
copy from test/deps/goldens/only_immediate.txt
copy to test/testdata/goldens/deps/executables_test/lists executables from a dependency.txt
index 5e42925..75a1b33 100644
--- a/test/deps/goldens/only_immediate.txt
+++ b/test/testdata/goldens/deps/executables_test/lists executables from a dependency.txt
@@ -1,20 +1,30 @@
-|-- baz
-| |-- bin
-| | '-- qux.dart
-| '-- pubspec.yaml
+# GENERATED BY: test/deps/executables_test.dart
+
+## Section 0
+$ tree
|-- foo
| |-- bin
| | '-- bar.dart
| '-- pubspec.yaml
'-- myapp
+ |-- pubspec.lock
'-- pubspec.yaml
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub deps --executables
foo:bar
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub deps --executables --dev
foo:bar
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub deps --json
{
"root": "myapp",
@@ -33,15 +43,6 @@
"version": "1.0.0",
"kind": "direct",
"source": "path",
- "dependencies": [
- "baz"
- ]
- },
- {
- "name": "baz",
- "version": "1.0.0",
- "kind": "transitive",
- "source": "path",
"dependencies": []
}
],
diff --git a/test/deps/goldens/only_immediate.txt b/test/testdata/goldens/deps/executables_test/lists executables only from immediate dependencies.txt
similarity index 68%
rename from test/deps/goldens/only_immediate.txt
rename to test/testdata/goldens/deps/executables_test/lists executables only from immediate dependencies.txt
index 5e42925..de70643 100644
--- a/test/deps/goldens/only_immediate.txt
+++ b/test/testdata/goldens/deps/executables_test/lists executables only from immediate dependencies.txt
@@ -1,3 +1,7 @@
+# GENERATED BY: test/deps/executables_test.dart
+
+## Section 0
+$ tree
|-- baz
| |-- bin
| | '-- qux.dart
@@ -7,14 +11,24 @@
| | '-- bar.dart
| '-- pubspec.yaml
'-- myapp
+ |-- pubspec.lock
'-- pubspec.yaml
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub deps --executables
foo:bar
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub deps --executables --dev
foo:bar
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub deps --json
{
"root": "myapp",
diff --git a/test/deps/goldens/overrides.txt b/test/testdata/goldens/deps/executables_test/overriden dependencies executables.txt
similarity index 66%
rename from test/deps/goldens/overrides.txt
rename to test/testdata/goldens/deps/executables_test/overriden dependencies executables.txt
index ab76e79..910210e 100644
--- a/test/deps/goldens/overrides.txt
+++ b/test/testdata/goldens/deps/executables_test/overriden dependencies executables.txt
@@ -1,3 +1,7 @@
+# GENERATED BY: test/deps/executables_test.dart
+
+## Section 0
+$ tree
|-- foo-1.0
| |-- bin
| | '-- bar.dart
@@ -8,14 +12,24 @@
| | '-- baz.dart
| '-- pubspec.yaml
'-- myapp
+ |-- pubspec.lock
'-- pubspec.yaml
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub deps --executables
foo: bar, baz
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub deps --executables --dev
foo: bar, baz
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub deps --json
{
"root": "myapp",
diff --git a/test/testdata/goldens/deps/executables_test/skips executables in sub directories.txt b/test/testdata/goldens/deps/executables_test/skips executables in sub directories.txt
new file mode 100644
index 0000000..289f7c8
--- /dev/null
+++ b/test/testdata/goldens/deps/executables_test/skips executables in sub directories.txt
@@ -0,0 +1,50 @@
+# GENERATED BY: test/deps/executables_test.dart
+
+## Section 0
+$ tree
+'-- myapp
+ |-- bin
+ | |-- foo.dart
+ | '-- sub
+ | '-- bar.dart
+ |-- pubspec.lock
+ '-- pubspec.yaml
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
+$ pub deps --executables
+myapp:foo
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
+$ pub deps --executables --dev
+myapp:foo
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
+$ pub deps --json
+{
+ "root": "myapp",
+ "packages": [
+ {
+ "name": "myapp",
+ "version": "0.0.0",
+ "kind": "root",
+ "source": "root",
+ "dependencies": []
+ }
+ ],
+ "sdks": [
+ {
+ "name": "Dart",
+ "version": "0.1.2+3"
+ }
+ ],
+ "executables": [
+ ":foo"
+ ]
+}
+
diff --git a/test/testdata/goldens/deps/executables_test/skips non-Dart executables.txt b/test/testdata/goldens/deps/executables_test/skips non-Dart executables.txt
new file mode 100644
index 0000000..d4a2db3
--- /dev/null
+++ b/test/testdata/goldens/deps/executables_test/skips non-Dart executables.txt
@@ -0,0 +1,45 @@
+# GENERATED BY: test/deps/executables_test.dart
+
+## Section 0
+$ tree
+'-- myapp
+ |-- bin
+ | |-- bar.sh
+ | '-- foo.py
+ |-- pubspec.lock
+ '-- pubspec.yaml
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
+$ pub deps --executables
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
+$ pub deps --executables --dev
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
+$ pub deps --json
+{
+ "root": "myapp",
+ "packages": [
+ {
+ "name": "myapp",
+ "version": "0.0.0",
+ "kind": "root",
+ "source": "root",
+ "dependencies": []
+ }
+ ],
+ "sdks": [
+ {
+ "name": "Dart",
+ "version": "0.1.2+3"
+ }
+ ],
+ "executables": []
+}
+
diff --git a/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt b/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt
new file mode 100644
index 0000000..237b3b5
--- /dev/null
+++ b/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt
@@ -0,0 +1,126 @@
+# GENERATED BY: test/directory_option_test.dart
+
+## Section 0
+$ pub add --directory=myapp foo
+Resolving dependencies in myapp...
++ foo 1.0.0
+Changed 1 dependency in myapp!
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
+$ pub -C myapp add bar
+Resolving dependencies in myapp...
++ bar 1.2.3
+Changed 1 dependency in myapp!
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
+$ pub -C myapp/example get --directory=myapp bar
+Resolving dependencies in myapp...
+Got dependencies in myapp!
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
+$ pub remove bar -C myapp
+Resolving dependencies in myapp...
+These packages are no longer being depended on:
+- bar 1.2.3
+Changed 1 dependency in myapp!
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 4
+$ pub get bar -C myapp
+Resolving dependencies in myapp...
+Got dependencies in myapp!
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 5
+$ pub get bar -C myapp/example
+Resolving dependencies in myapp/example...
++ foo 1.0.0
++ test_pkg 1.0.0 from path myapp
+Changed 2 dependencies in myapp/example!
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 6
+$ pub get bar -C myapp/example2
+Resolving dependencies in myapp/example2...
+[STDERR] Error on line 1, column 9 of myapp/pubspec.yaml: "name" field doesn't match expected name "myapp".
+[STDERR] â•·
+[STDERR] 1 │ {"name":"test_pkg","version":"1.0.0","homepage":"http://pub.dartlang.org","description":"A package, I guess.","environment":{"sdk":">=1.8.0 <=2.0.0"}, dependencies: { foo: ^1.0.0}}
+[STDERR] │ ^^^^^^^^^^
+[STDERR] ╵
+[EXIT CODE] 65
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 7
+$ pub get bar -C myapp/broken_dir
+[STDERR] Could not find a file named "pubspec.yaml" in "$SANDBOX/myapp/broken_dir".
+[EXIT CODE] 66
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 8
+$ pub downgrade -C myapp
+Resolving dependencies in myapp...
+ foo 1.0.0
+No dependencies changed in myapp.
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 9
+$ pub upgrade bar -C myapp
+Resolving dependencies in myapp...
+ foo 1.0.0
+No dependencies changed in myapp.
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 10
+$ pub run -C myapp bin/app.dart
+Building package executable...
+Built test_pkg:app.
+Hi
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 11
+$ pub publish -C myapp --dry-run
+Publishing test_pkg 1.0.0 to http://localhost:$PORT:
+|-- CHANGELOG.md
+|-- LICENSE
+|-- README.md
+|-- bin
+| '-- app.dart
+|-- example
+| '-- pubspec.yaml
+|-- example2
+| '-- pubspec.yaml
+|-- lib
+| '-- test_pkg.dart
+'-- pubspec.yaml
+The server may enforce additional checks.
+[STDERR]
+[STDERR] Package has 0 warnings.
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 12
+$ pub uploader -C myapp add sigurdm@google.com
+Good job!
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 13
+$ pub deps -C myapp
+Dart SDK 1.12.0
+test_pkg 1.0.0
+'-- foo 1.0.0
+
diff --git a/test/testdata/goldens/embedding/embedding_test/logfile is written with --verbose and on unexpected exceptions.txt b/test/testdata/goldens/embedding/embedding_test/logfile is written with --verbose and on unexpected exceptions.txt
new file mode 100644
index 0000000..fc69b03
--- /dev/null
+++ b/test/testdata/goldens/embedding/embedding_test/logfile is written with --verbose and on unexpected exceptions.txt
@@ -0,0 +1,308 @@
+# GENERATED BY: test/embedding/embedding_test.dart
+
+$ tool/test-bin/pub_command_runner.dart pub --verbose get
+MSG : Resolving dependencies...
+MSG : + foo 1.0.0
+MSG : Downloading foo 1.0.0...
+MSG : Changed 1 dependency!
+MSG : Logs written to $SANDBOX/cache/log/pub_log.txt.
+[E] FINE: Pub 0.1.2+3
+[E] SLVR: fact: myapp is 0.0.0
+[E] SLVR: derived: myapp
+[E] SLVR: fact: myapp depends on foo any
+[E] SLVR: selecting myapp
+[E] SLVR: derived: foo any
+[E] IO : Get versions from http://localhost:$PORT/api/packages/foo.
+[E] IO : HTTP GET http://localhost:$PORT/api/packages/foo
+[E] | Accept: application/vnd.pub.v2+json
+[E] | X-Pub-OS: $OS
+[E] | X-Pub-Command: get
+[E] | X-Pub-Session-ID: $ID
+[E] | X-Pub-Environment: test-environment
+[E] | X-Pub-Reason: direct
+[E] | user-agent: Dart pub 0.1.2+3
+[E] IO : HTTP response 200 OK for GET http://localhost:$PORT/api/packages/foo
+[E] | took: $TIME
+[E] | date: $TIME
+[E] | content-length: 197
+[E] | x-frame-options: SAMEORIGIN
+[E] | content-type: text/plain; charset=utf-8
+[E] | x-xss-protection: 1; mode=block
+[E] | x-content-type-options: nosniff
+[E] | server: dart:io with Shelf
+[E] IO : Writing $N characters to text file $SANDBOX/cache/hosted/localhost%58$PORT/.cache/foo-versions.json.
+[E] FINE: Contents:
+[E] | {"name":"foo","uploaders":["nweiz@google.com"],"versions":[{"pubspec":{"name":"foo","version":"1.0.0"},"version":"1.0.0","archive_url":"http://localhost:$PORT/packages/foo/versions/1.0.0.tar.gz"}],"_fetchedAt": "$TIME"}
+[E] SLVR: selecting foo 1.0.0
+[E] SLVR: Version solving took: $TIME
+[E] | Tried 1 solutions.
+[E] FINE: Resolving dependencies finished ($TIME)
+[E] IO : Get package from http://localhost:$PORT/packages/foo/versions/1.0.0.tar.gz.
+[E] IO : Created temp directory $DIR
+[E] IO : HTTP GET http://localhost:$PORT/packages/foo/versions/1.0.0.tar.gz
+[E] | X-Pub-OS: $OS
+[E] | X-Pub-Command: get
+[E] | X-Pub-Session-ID: $ID
+[E] | X-Pub-Environment: test-environment
+[E] | X-Pub-Reason: direct
+[E] | user-agent: Dart pub 0.1.2+3
+[E] IO : HTTP response 200 OK for GET http://localhost:$PORT/packages/foo/versions/1.0.0.tar.gz
+[E] | took: $TIME
+[E] | transfer-encoding: chunked
+[E] | date: $TIME
+[E] | x-frame-options: SAMEORIGIN
+[E] | content-type: text/plain; charset=utf-8
+[E] | x-xss-protection: 1; mode=block
+[E] | x-content-type-options: nosniff
+[E] | server: dart:io with Shelf
+[E] IO : Creating $FILE from stream
+[E] FINE: Created $FILE from stream
+[E] IO : Created temp directory $DIR
+[E] IO : Reading binary file $FILE.
+[E] FINE: Extracting .tar.gz stream to $DIR
+[E] IO : Creating $FILE from stream
+[E] FINE: Created $FILE from stream
+[E] IO : Creating $FILE from stream
+[E] FINE: Created $FILE from stream
+[E] FINE: Extracted .tar.gz to $DIR
+[E] IO : Renaming directory $A to $B
+[E] IO : Deleting directory $DIR
+[E] IO : Writing $N characters to text file pubspec.lock.
+[E] FINE: Contents:
+[E] | # Generated by pub
+[E] | # See https://dart.dev/tools/pub/glossary#lockfile
+[E] | packages:
+[E] | foo:
+[E] | dependency: "direct main"
+[E] | description:
+[E] | name: foo
+[E] | url: "http://localhost:$PORT"
+[E] | source: hosted
+[E] | version: "1.0.0"
+[E] | sdks:
+[E] | dart: ">=0.1.2 <1.0.0"
+[E] IO : Writing $N characters to text file .dart_tool/package_config.json.
+[E] FINE: Contents:
+[E] | {
+[E] | "configVersion": 2,
+[E] | "packages": [
+[E] | {
+[E] | "name": "foo",
+[E] | "rootUri": "file://$SANDBOX/cache/hosted/localhost%2558$PORT/foo-1.0.0",
+[E] | "packageUri": "lib/",
+[E] | "languageVersion": "2.7"
+[E] | },
+[E] | {
+[E] | "name": "myapp",
+[E] | "rootUri": "../",
+[E] | "packageUri": "lib/",
+[E] | "languageVersion": "0.1"
+[E] | }
+[E] | ],
+[E] | "generated": "$TIME",
+[E] | "generator": "pub",
+[E] | "generatorVersion": "0.1.2+3"
+[E] | }
+[E] IO : Writing $N characters to text file $SANDBOX/cache/log/pub_log.txt.
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+Information about the latest pub run.
+
+If you believe something is not working right, you can go to
+https://github.com/dart-lang/pub/issues/new to post a new issue and attach this file.
+
+Before making this file public, make sure to remove any sensitive information!
+
+Pub version: 0.1.2+3
+Created: $TIME
+FLUTTER_ROOT: <not set>
+PUB_HOSTED_URL: http://localhost:$PORT
+PUB_CACHE: "$SANDBOX/cache"
+Command: dart pub --verbose get
+Platform: $OS
+
+---- $SANDBOX/myapp/pubspec.yaml ----
+{"name":"myapp","environment":{"sdk":">=0.1.2 <1.0.0"},"dependencies":{"foo":"any"}}
+---- End pubspec.yaml ----
+---- $SANDBOX/myapp/pubspec.lock ----
+# Generated by pub
+# See https://dart.dev/tools/pub/glossary#lockfile
+packages:
+ foo:
+ dependency: "direct main"
+ description:
+ name: foo
+ url: "http://localhost:$PORT"
+ source: hosted
+ version: "1.0.0"
+sdks:
+ dart: ">=0.1.2 <1.0.0"
+
+---- End pubspec.lock ----
+---- Log transcript ----
+FINE: Pub 0.1.2+3
+MSG : Resolving dependencies...
+SLVR: fact: myapp is 0.0.0
+SLVR: derived: myapp
+SLVR: fact: myapp depends on foo any
+SLVR: selecting myapp
+SLVR: derived: foo any
+IO : Get versions from http://localhost:$PORT/api/packages/foo.
+IO : HTTP GET http://localhost:$PORT/api/packages/foo
+ | Accept: application/vnd.pub.v2+json
+ | X-Pub-OS: $OS
+ | X-Pub-Command: get
+ | X-Pub-Session-ID: $ID
+ | X-Pub-Environment: test-environment
+ | X-Pub-Reason: direct
+ | user-agent: Dart pub 0.1.2+3
+IO : HTTP response 200 OK for GET http://localhost:$PORT/api/packages/foo
+ | took: $TIME
+ | date: $TIME
+ | content-length: 197
+ | x-frame-options: SAMEORIGIN
+ | content-type: text/plain; charset=utf-8
+ | x-xss-protection: 1; mode=block
+ | x-content-type-options: nosniff
+ | server: dart:io with Shelf
+IO : Writing $N characters to text file $SANDBOX/cache/hosted/localhost%58$PORT/.cache/foo-versions.json.
+FINE: Contents:
+ | {"name":"foo","uploaders":["nweiz@google.com"],"versions":[{"pubspec":{"name":"foo","version":"1.0.0"},"version":"1.0.0","archive_url":"http://localhost:$PORT/packages/foo/versions/1.0.0.tar.gz"}],"_fetchedAt": "$TIME"}
+SLVR: selecting foo 1.0.0
+SLVR: Version solving took: $TIME
+ | Tried 1 solutions.
+FINE: Resolving dependencies finished ($TIME)
+MSG : + foo 1.0.0
+IO : Get package from http://localhost:$PORT/packages/foo/versions/1.0.0.tar.gz.
+MSG : Downloading foo 1.0.0...
+IO : Created temp directory $DIR
+IO : HTTP GET http://localhost:$PORT/packages/foo/versions/1.0.0.tar.gz
+ | X-Pub-OS: $OS
+ | X-Pub-Command: get
+ | X-Pub-Session-ID: $ID
+ | X-Pub-Environment: test-environment
+ | X-Pub-Reason: direct
+ | user-agent: Dart pub 0.1.2+3
+IO : HTTP response 200 OK for GET http://localhost:$PORT/packages/foo/versions/1.0.0.tar.gz
+ | took: $TIME
+ | transfer-encoding: chunked
+ | date: $TIME
+ | x-frame-options: SAMEORIGIN
+ | content-type: text/plain; charset=utf-8
+ | x-xss-protection: 1; mode=block
+ | x-content-type-options: nosniff
+ | server: dart:io with Shelf
+IO : Creating $FILE from stream
+FINE: Created $FILE from stream
+IO : Created temp directory $DIR
+IO : Reading binary file $FILE.
+FINE: Extracting .tar.gz stream to $DIR
+IO : Creating $FILE from stream
+FINE: Created $FILE from stream
+IO : Creating $FILE from stream
+FINE: Created $FILE from stream
+FINE: Extracted .tar.gz to $DIR
+IO : Renaming directory $A to $B
+IO : Deleting directory $DIR
+IO : Writing $N characters to text file pubspec.lock.
+FINE: Contents:
+ | # Generated by pub
+ | # See https://dart.dev/tools/pub/glossary#lockfile
+ | packages:
+ | foo:
+ | dependency: "direct main"
+ | description:
+ | name: foo
+ | url: "http://localhost:$PORT"
+ | source: hosted
+ | version: "1.0.0"
+ | sdks:
+ | dart: ">=0.1.2 <1.0.0"
+MSG : Changed 1 dependency!
+IO : Writing $N characters to text file .dart_tool/package_config.json.
+FINE: Contents:
+ | {
+ | "configVersion": 2,
+ | "packages": [
+ | {
+ | "name": "foo",
+ | "rootUri": "file://$SANDBOX/cache/hosted/localhost%2558$PORT/foo-1.0.0",
+ | "packageUri": "lib/",
+ | "languageVersion": "2.7"
+ | },
+ | {
+ | "name": "myapp",
+ | "rootUri": "../",
+ | "packageUri": "lib/",
+ | "languageVersion": "0.1"
+ | }
+ | ],
+ | "generated": "$TIME",
+ | "generator": "pub",
+ | "generatorVersion": "0.1.2+3"
+ | }
+---- End log transcript ----
+-------------------------------- END OF OUTPUT ---------------------------------
+
+$ tool/test-bin/pub_command_runner.dart pub fail
+[E] Bad state: Pub has crashed
+[E] tool/test-bin/pub_command_runner.dart $LINE:$COL ThrowingCommand.runProtected
+[E] package:pub/src/command.dart $LINE:$COL PubCommand.run.<fn>
+[E] package:pub/src/command.dart $LINE:$COL PubCommand.run.<fn>
+[E] dart:async new Future.sync
+[E] package:pub/src/utils.dart $LINE:$COL captureErrors.wrappedCallback
+[E] dart:async runZonedGuarded
+[E] package:pub/src/utils.dart $LINE:$COL captureErrors
+[E] package:pub/src/command.dart $LINE:$COL PubCommand.run
+[E] package:args/command_runner.dart $LINE:$COL CommandRunner.runCommand
+[E] tool/test-bin/pub_command_runner.dart $LINE:$COL Runner.runCommand
+[E] tool/test-bin/pub_command_runner.dart $LINE:$COL Runner.run
+[E] tool/test-bin/pub_command_runner.dart $LINE:$COL main
+[E] This is an unexpected error. The full log and other details are collected in:
+[E]
+[E] $SANDBOX/cache/log/pub_log.txt
+[E]
+[E] Consider creating an issue on https://github.com/dart-lang/pub/issues/new
+[E] and attaching the relevant parts of that log file.
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+Information about the latest pub run.
+
+If you believe something is not working right, you can go to
+https://github.com/dart-lang/pub/issues/new to post a new issue and attach this file.
+
+Before making this file public, make sure to remove any sensitive information!
+
+Pub version: 0.1.2+3
+Created: $TIME
+FLUTTER_ROOT: <not set>
+PUB_HOSTED_URL: http://localhost:$PORT
+PUB_CACHE: "$SANDBOX/cache"
+Command: dart pub fail
+Platform: $OS
+
+---- Log transcript ----
+FINE: Pub 0.1.2+3
+ERR : Bad state: Pub has crashed
+FINE: Exception type: StateError
+ERR : tool/test-bin/pub_command_runner.dart $LINE:$COL ThrowingCommand.runProtected
+ | package:pub/src/command.dart $LINE:$COL PubCommand.run.<fn>
+ | package:pub/src/command.dart $LINE:$COL PubCommand.run.<fn>
+ | dart:async new Future.sync
+ | package:pub/src/utils.dart $LINE:$COL captureErrors.wrappedCallback
+ | dart:async runZonedGuarded
+ | package:pub/src/utils.dart $LINE:$COL captureErrors
+ | package:pub/src/command.dart $LINE:$COL PubCommand.run
+ | package:args/command_runner.dart $LINE:$COL CommandRunner.runCommand
+ | tool/test-bin/pub_command_runner.dart $LINE:$COL Runner.runCommand
+ | tool/test-bin/pub_command_runner.dart $LINE:$COL Runner.run
+ | tool/test-bin/pub_command_runner.dart $LINE:$COL main
+ERR : This is an unexpected error. The full log and other details are collected in:
+ |
+ | $SANDBOX/cache/log/pub_log.txt
+ |
+ | Consider creating an issue on https://github.com/dart-lang/pub/issues/new
+ | and attaching the relevant parts of that log file.
+---- End log transcript ----
diff --git a/test/testdata/goldens/embedding/embedding_test/run works, though hidden.txt b/test/testdata/goldens/embedding/embedding_test/run works, though hidden.txt
new file mode 100644
index 0000000..214712a
--- /dev/null
+++ b/test/testdata/goldens/embedding/embedding_test/run works, though hidden.txt
@@ -0,0 +1,11 @@
+# GENERATED BY: test/embedding/embedding_test.dart
+
+$ tool/test-bin/pub_command_runner.dart pub get
+Resolving dependencies...
+Got dependencies!
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+$ tool/test-bin/pub_command_runner.dart pub run bin/main.dart
+Hi
+
diff --git a/test/testdata/goldens/help_test/pub add --help.txt b/test/testdata/goldens/help_test/pub add --help.txt
new file mode 100644
index 0000000..3d1f429
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub add --help.txt
@@ -0,0 +1,27 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub add --help
+Add dependencies to pubspec.yaml.
+
+Usage: pub add <package>[:<constraint>] [<package2>[:<constraint2>]...] [options]
+-h, --help Print this usage information.
+-d, --dev Adds to the development dependencies instead.
+ --git-url Git URL of the package
+ --git-ref Git branch or commit to be retrieved
+ --git-path Path of git package in repository
+ --hosted-url URL of package host server
+ --path Add package from local path
+ --sdk=<[flutter]> add package from SDK source
+ [flutter]
+ --[no-]offline Use cached packages instead of accessing the
+ network.
+-n, --dry-run Report what dependencies would change but don't
+ change any.
+ --[no-]precompile Build executables in immediate dependencies.
+-C, --directory=<dir> Run this in the directory <dir>.
+ --legacy-packages-file Generate the legacy ".packages" file
+
+Run "pub help" to see global options.
+See https://dart.dev/tools/pub/cmd/pub-add for detailed documentation.
+
diff --git a/test/testdata/goldens/help_test/pub cache --help.txt b/test/testdata/goldens/help_test/pub cache --help.txt
new file mode 100644
index 0000000..fdb0b2c
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub cache --help.txt
@@ -0,0 +1,17 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub cache --help
+Work with the system cache.
+
+Usage: pub cache [arguments...]
+-h, --help Print this usage information.
+
+Available subcommands:
+ add Install a package.
+ clean Clears the global PUB_CACHE.
+ repair Reinstall cached packages.
+
+Run "pub help" to see global options.
+See https://dart.dev/tools/pub/cmd/pub-cache for detailed documentation.
+
diff --git a/test/testdata/goldens/help_test/pub cache add --help.txt b/test/testdata/goldens/help_test/pub cache add --help.txt
new file mode 100644
index 0000000..05068f0
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub cache add --help.txt
@@ -0,0 +1,14 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub cache add --help
+Install a package.
+
+Usage: pub cache add <package> [--version <constraint>] [--all]
+-h, --help Print this usage information.
+ --all Install all matching versions.
+-v, --version Version constraint.
+
+Run "pub help" to see global options.
+See https://dart.dev/tools/pub/cmd/pub-cache for detailed documentation.
+
diff --git a/test/testdata/goldens/help_test/pub cache clean --help.txt b/test/testdata/goldens/help_test/pub cache clean --help.txt
new file mode 100644
index 0000000..71dd1d6
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub cache clean --help.txt
@@ -0,0 +1,12 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub cache clean --help
+Clears the global PUB_CACHE.
+
+Usage: pub cache clean <subcommand> [arguments...]
+-h, --help Print this usage information.
+-f, --force Don't ask for confirmation.
+
+Run "pub help" to see global options.
+
diff --git a/test/testdata/goldens/help_test/pub cache repair --help.txt b/test/testdata/goldens/help_test/pub cache repair --help.txt
new file mode 100644
index 0000000..ac09115
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub cache repair --help.txt
@@ -0,0 +1,12 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub cache repair --help
+Reinstall cached packages.
+
+Usage: pub cache repair <subcommand> [arguments...]
+-h, --help Print this usage information.
+
+Run "pub help" to see global options.
+See https://dart.dev/tools/pub/cmd/pub-cache for detailed documentation.
+
diff --git a/test/testdata/goldens/help_test/pub deps --help.txt b/test/testdata/goldens/help_test/pub deps --help.txt
new file mode 100644
index 0000000..475353f
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub deps --help.txt
@@ -0,0 +1,19 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub deps --help
+Print package dependencies.
+
+Usage: pub deps [arguments...]
+-h, --help Print this usage information.
+-s, --style How output should be displayed.
+ [compact, tree (default), list]
+ --[no-]dev Whether to include dev dependencies.
+ (defaults to on)
+ --executables List all available executables.
+ --json Output dependency information in a json format.
+-C, --directory=<dir> Run this in the directory<dir>.
+
+Run "pub help" to see global options.
+See https://dart.dev/tools/pub/cmd/pub-deps for detailed documentation.
+
diff --git a/test/testdata/goldens/help_test/pub downgrade --help.txt b/test/testdata/goldens/help_test/pub downgrade --help.txt
new file mode 100644
index 0000000..ddf71e7
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub downgrade --help.txt
@@ -0,0 +1,20 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub downgrade --help
+Downgrade the current package's dependencies to oldest versions.
+
+
+
+Usage: pub downgrade [dependencies...]
+-h, --help Print this usage information.
+ --[no-]offline Use cached packages instead of accessing the
+ network.
+-n, --dry-run Report what dependencies would change but don't
+ change any.
+-C, --directory=<dir> Run this in the directory<dir>.
+ --legacy-packages-file Generate the legacy ".packages" file
+
+Run "pub help" to see global options.
+See https://dart.dev/tools/pub/cmd/pub-downgrade for detailed documentation.
+
diff --git a/test/testdata/goldens/help_test/pub get --help.txt b/test/testdata/goldens/help_test/pub get --help.txt
new file mode 100644
index 0000000..104f69c
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub get --help.txt
@@ -0,0 +1,19 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub get --help
+Get the current package's dependencies.
+
+Usage: pub get <subcommand> [arguments...]
+-h, --help Print this usage information.
+ --[no-]offline Use cached packages instead of accessing the
+ network.
+-n, --dry-run Report what dependencies would change but don't
+ change any.
+ --[no-]precompile Build executables in immediate dependencies.
+ --legacy-packages-file Generate the legacy ".packages" file
+-C, --directory=<dir> Run this in the directory<dir>.
+
+Run "pub help" to see global options.
+See https://dart.dev/tools/pub/cmd/pub-get for detailed documentation.
+
diff --git a/test/testdata/goldens/help_test/pub global --help.txt b/test/testdata/goldens/help_test/pub global --help.txt
new file mode 100644
index 0000000..6aa723c
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub global --help.txt
@@ -0,0 +1,18 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub global --help
+Work with global packages.
+
+Usage: pub global [arguments...]
+-h, --help Print this usage information.
+
+Available subcommands:
+ activate Make a package's executables globally available.
+ deactivate Remove a previously activated package.
+ list List globally activated packages.
+ run Run an executable from a globally activated package.
+
+Run "pub help" to see global options.
+See https://dart.dev/tools/pub/cmd/pub-global for detailed documentation.
+
diff --git a/test/testdata/goldens/help_test/pub global activate --help.txt b/test/testdata/goldens/help_test/pub global activate --help.txt
new file mode 100644
index 0000000..5341266
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub global activate --help.txt
@@ -0,0 +1,19 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub global activate --help
+Make a package's executables globally available.
+
+Usage: pub global activate <package> [version-constraint]
+-h, --help Print this usage information.
+-s, --source The source used to find the package.
+ [git, hosted (default), path]
+ --no-executables Do not put executables on PATH.
+-x, --executable Executable(s) to place on PATH.
+ --overwrite Overwrite executables from other packages with the same
+ name.
+-u, --hosted-url A custom pub server URL for the package. Only applies
+ when using the `hosted` source.
+
+Run "pub help" to see global options.
+
diff --git a/test/testdata/goldens/help_test/pub global deactivate --help.txt b/test/testdata/goldens/help_test/pub global deactivate --help.txt
new file mode 100644
index 0000000..8b8178b
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub global deactivate --help.txt
@@ -0,0 +1,11 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub global deactivate --help
+Remove a previously activated package.
+
+Usage: pub global deactivate <package>
+-h, --help Print this usage information.
+
+Run "pub help" to see global options.
+
diff --git a/test/testdata/goldens/help_test/pub global list --help.txt b/test/testdata/goldens/help_test/pub global list --help.txt
new file mode 100644
index 0000000..12244be
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub global list --help.txt
@@ -0,0 +1,11 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub global list --help
+List globally activated packages.
+
+Usage: pub global list <subcommand> [arguments...]
+-h, --help Print this usage information.
+
+Run "pub help" to see global options.
+
diff --git a/test/testdata/goldens/help_test/pub global run --help.txt b/test/testdata/goldens/help_test/pub global run --help.txt
new file mode 100644
index 0000000..f829064
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub global run --help.txt
@@ -0,0 +1,18 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub global run --help
+Run an executable from a globally activated package.
+
+Usage: pub global run <package>:<executable> [args...]
+-h, --help Print this usage information.
+ --[no-]enable-asserts Enable assert statements.
+ --enable-experiment=<experiment> Runs the executable in a VM with the
+ given experiments enabled. (Will disable
+ snapshotting, resulting in slower
+ startup).
+ --[no-]sound-null-safety Override the default null safety
+ execution mode.
+
+Run "pub help" to see global options.
+
diff --git a/test/testdata/goldens/help_test/pub login --help.txt b/test/testdata/goldens/help_test/pub login --help.txt
new file mode 100644
index 0000000..ce7233b
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub login --help.txt
@@ -0,0 +1,11 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub login --help
+Log into pub.dev.
+
+Usage: pub login
+-h, --help Print this usage information.
+
+Run "pub help" to see global options.
+
diff --git a/test/testdata/goldens/help_test/pub logout --help.txt b/test/testdata/goldens/help_test/pub logout --help.txt
new file mode 100644
index 0000000..3937ef7
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub logout --help.txt
@@ -0,0 +1,11 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub logout --help
+Log out of pub.dev.
+
+Usage: pub logout <subcommand> [arguments...]
+-h, --help Print this usage information.
+
+Run "pub help" to see global options.
+
diff --git a/test/outdated/goldens/helptext.txt b/test/testdata/goldens/help_test/pub outdated --help.txt
similarity index 96%
rename from test/outdated/goldens/helptext.txt
rename to test/testdata/goldens/help_test/pub outdated --help.txt
index 20a4ecc..9a7b1bc 100644
--- a/test/outdated/goldens/helptext.txt
+++ b/test/testdata/goldens/help_test/pub outdated --help.txt
@@ -1,3 +1,6 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
$ pub outdated --help
Analyze your dependencies to find which ones can be upgraded.
diff --git a/test/testdata/goldens/help_test/pub publish --help.txt b/test/testdata/goldens/help_test/pub publish --help.txt
new file mode 100644
index 0000000..2977db0
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub publish --help.txt
@@ -0,0 +1,15 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub publish --help
+Publish the current package to pub.dartlang.org.
+
+Usage: pub publish [options]
+-h, --help Print this usage information.
+-n, --dry-run Validate but do not publish the package.
+-f, --force Publish without confirmation if there are no errors.
+-C, --directory=<dir> Run this in the directory<dir>.
+
+Run "pub help" to see global options.
+See https://dart.dev/tools/pub/cmd/pub-lish for detailed documentation.
+
diff --git a/test/testdata/goldens/help_test/pub remove --help.txt b/test/testdata/goldens/help_test/pub remove --help.txt
new file mode 100644
index 0000000..b82f9b6
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub remove --help.txt
@@ -0,0 +1,19 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub remove --help
+Removes a dependency from the current package.
+
+Usage: pub remove <package>
+-h, --help Print this usage information.
+ --[no-]offline Use cached packages instead of accessing the
+ network.
+-n, --dry-run Report what dependencies would change but don't
+ change any.
+ --[no-]precompile Precompile executables in immediate dependencies.
+-C, --directory=<dir> Run this in the directory<dir>.
+ --legacy-packages-file Generate the legacy ".packages" file
+
+Run "pub help" to see global options.
+See https://dart.dev/tools/pub/cmd/pub-remove for detailed documentation.
+
diff --git a/test/testdata/goldens/help_test/pub run --help.txt b/test/testdata/goldens/help_test/pub run --help.txt
new file mode 100644
index 0000000..f2844f3
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub run --help.txt
@@ -0,0 +1,20 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub run --help
+Run an executable from a package.
+
+Usage: pub run <executable> [arguments...]
+-h, --help Print this usage information.
+ --[no-]enable-asserts Enable assert statements.
+ --enable-experiment=<experiment> Runs the executable in a VM with the
+ given experiments enabled.
+ (Will disable snapshotting, resulting in
+ slower startup).
+ --[no-]sound-null-safety Override the default null safety
+ execution mode.
+-C, --directory=<dir> Run this in the directory<dir>.
+
+Run "pub help" to see global options.
+See https://dart.dev/tools/pub/cmd/pub-run for detailed documentation.
+
diff --git a/test/testdata/goldens/help_test/pub token --help.txt b/test/testdata/goldens/help_test/pub token --help.txt
new file mode 100644
index 0000000..fa164c5
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub token --help.txt
@@ -0,0 +1,16 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub token --help
+Manage authentication tokens for hosted pub repositories.
+
+Usage: pub token [arguments...]
+-h, --help Print this usage information.
+
+Available subcommands:
+ add Add authentication tokens for a package repository.
+ list List servers for which a token exists.
+ remove Remove secret token for package repository.
+
+Run "pub help" to see global options.
+
diff --git a/test/testdata/goldens/help_test/pub token add --help.txt b/test/testdata/goldens/help_test/pub token add --help.txt
new file mode 100644
index 0000000..7068a5c
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub token add --help.txt
@@ -0,0 +1,13 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub token add --help
+Add authentication tokens for a package repository.
+
+Usage: pub token add
+-h, --help Print this usage information.
+ --env-var Read the secret token from this environment variable when
+ making requests.
+
+Run "pub help" to see global options.
+
diff --git a/test/testdata/goldens/help_test/pub token list --help.txt b/test/testdata/goldens/help_test/pub token list --help.txt
new file mode 100644
index 0000000..5c333b5
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub token list --help.txt
@@ -0,0 +1,11 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub token list --help
+List servers for which a token exists.
+
+Usage: pub token list
+-h, --help Print this usage information.
+
+Run "pub help" to see global options.
+
diff --git a/test/testdata/goldens/help_test/pub token remove --help.txt b/test/testdata/goldens/help_test/pub token remove --help.txt
new file mode 100644
index 0000000..1f79f81
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub token remove --help.txt
@@ -0,0 +1,12 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub token remove --help
+Remove secret token for package repository.
+
+Usage: pub token remove
+-h, --help Print this usage information.
+ --all Remove all secret tokens.
+
+Run "pub help" to see global options.
+
diff --git a/test/testdata/goldens/help_test/pub upgrade --help.txt b/test/testdata/goldens/help_test/pub upgrade --help.txt
new file mode 100644
index 0000000..c787951
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub upgrade --help.txt
@@ -0,0 +1,23 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub upgrade --help
+Upgrade the current package's dependencies to latest versions.
+
+Usage: pub upgrade [dependencies...]
+-h, --help Print this usage information.
+ --[no-]offline Use cached packages instead of accessing the
+ network.
+-n, --dry-run Report what dependencies would change but don't
+ change any.
+ --[no-]precompile Precompile executables in immediate dependencies.
+ --null-safety Upgrade constraints in pubspec.yaml to null-safety
+ versions
+ --legacy-packages-file Generate the legacy ".packages" file
+ --major-versions Upgrades packages to their latest resolvable
+ versions, and updates pubspec.yaml.
+-C, --directory=<dir> Run this in the directory<dir>.
+
+Run "pub help" to see global options.
+See https://dart.dev/tools/pub/cmd/pub-upgrade for detailed documentation.
+
diff --git a/test/testdata/goldens/help_test/pub uploader --help.txt b/test/testdata/goldens/help_test/pub uploader --help.txt
new file mode 100644
index 0000000..10c9d9d
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub uploader --help.txt
@@ -0,0 +1,15 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub uploader --help
+Manage uploaders for a package on pub.dartlang.org.
+
+Usage: pub uploader [options] {add/remove} <email>
+-h, --help Print this usage information.
+ --package The package whose uploaders will be modified.
+ (defaults to the current package)
+-C, --directory=<dir> Run this in the directory<dir>.
+
+Run "pub help" to see global options.
+See https://dart.dev/tools/pub/cmd/pub-uploader for detailed documentation.
+
diff --git a/test/testdata/goldens/help_test/pub version --help.txt b/test/testdata/goldens/help_test/pub version --help.txt
new file mode 100644
index 0000000..82e9f9f
--- /dev/null
+++ b/test/testdata/goldens/help_test/pub version --help.txt
@@ -0,0 +1,11 @@
+# GENERATED BY: test/help_test.dart
+
+## Section 0
+$ pub version --help
+Print pub version.
+
+Usage: pub version
+-h, --help Print this usage information.
+
+Run "pub help" to see global options.
+
diff --git a/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/401-with-message.txt b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/401-with-message.txt
new file mode 100644
index 0000000..8dcaaf5
--- /dev/null
+++ b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/401-with-message.txt
@@ -0,0 +1,13 @@
+# GENERATED BY: test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
+
+## Section 0
+$ pub get
+Resolving dependencies...
+[STDERR] Because myapp depends on foo any which doesn't exist (authentication failed), version solving failed.
+[STDERR]
+[STDERR] http://localhost:$PORT package repository requested authentication!
+[STDERR] You can provide credentials using:
+[STDERR] pub token add http://localhost:$PORT
+[STDERR] <message>
+[EXIT CODE] 69
+
diff --git a/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/401.txt b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/401.txt
new file mode 100644
index 0000000..68d5bd0
--- /dev/null
+++ b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/401.txt
@@ -0,0 +1,12 @@
+# GENERATED BY: test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
+
+## Section 0
+$ pub get
+Resolving dependencies...
+[STDERR] Because myapp depends on foo any which doesn't exist (authentication failed), version solving failed.
+[STDERR]
+[STDERR] http://localhost:$PORT package repository requested authentication!
+[STDERR] You can provide credentials using:
+[STDERR] pub token add http://localhost:$PORT
+[EXIT CODE] 69
+
diff --git a/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/403-with-message.txt b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/403-with-message.txt
new file mode 100644
index 0000000..882660c
--- /dev/null
+++ b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/403-with-message.txt
@@ -0,0 +1,13 @@
+# GENERATED BY: test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
+
+## Section 0
+$ pub get
+Resolving dependencies...
+[STDERR] Because myapp depends on foo any which doesn't exist (authorization failed), version solving failed.
+[STDERR]
+[STDERR] Insufficient permissions to the resource at the http://localhost:$PORT package repository.
+[STDERR] You can modify credentials using:
+[STDERR] pub token add http://localhost:$PORT
+[STDERR] <message>
+[EXIT CODE] 69
+
diff --git a/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/403.txt b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/403.txt
new file mode 100644
index 0000000..f8a5af9
--- /dev/null
+++ b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/403.txt
@@ -0,0 +1,12 @@
+# GENERATED BY: test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
+
+## Section 0
+$ pub get
+Resolving dependencies...
+[STDERR] Because myapp depends on foo any which doesn't exist (authorization failed), version solving failed.
+[STDERR]
+[STDERR] Insufficient permissions to the resource at the http://localhost:$PORT package repository.
+[STDERR] You can modify credentials using:
+[STDERR] pub token add http://localhost:$PORT
+[EXIT CODE] 69
+
diff --git a/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/bad_json.txt b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/bad_json.txt
new file mode 100644
index 0000000..8e446c2
--- /dev/null
+++ b/test/testdata/goldens/hosted/fail_gracefully_on_bad_version_listing_response_test/bad_json.txt
@@ -0,0 +1,10 @@
+# GENERATED BY: test/hosted/fail_gracefully_on_bad_version_listing_response_test.dart
+
+## Section 0
+$ pub get
+Resolving dependencies...
+[STDERR] Because myapp depends on foo any which doesn't exist (Got badly formatted response trying to find package foo at http://localhost:$PORT), version solving failed.
+[STDERR]
+[STDERR] Check that "http://localhost:$PORT" is a valid package repository.
+[EXIT CODE] 65
+
diff --git a/test/testdata/goldens/hosted/fail_gracefully_with_hint_test/supports two hints.txt b/test/testdata/goldens/hosted/fail_gracefully_with_hint_test/supports two hints.txt
new file mode 100644
index 0000000..a45b0f0
--- /dev/null
+++ b/test/testdata/goldens/hosted/fail_gracefully_with_hint_test/supports two hints.txt
@@ -0,0 +1,13 @@
+# GENERATED BY: test/hosted/fail_gracefully_with_hint_test.dart
+
+## Section 0
+$ pub get --offline
+Resolving dependencies...
+[STDERR] Because foo <1.2.4 requires the Flutter SDK and foo >=1.2.4 depends on bar any, every version of foo requires bar any.
+[STDERR] So, because bar doesn't exist (could not find package bar in cache) and myapp depends on foo any, version solving failed.
+[STDERR]
+[STDERR] Flutter users should run `flutter pub get` instead of `dart pub get`.
+[STDERR]
+[STDERR] Try again without --offline!
+[EXIT CODE] 69
+
diff --git a/test/outdated/goldens/handles_sdk_dependencies.txt b/test/testdata/goldens/outdated/outdated_test/Handles SDK dependencies.txt
similarity index 84%
rename from test/outdated/goldens/handles_sdk_dependencies.txt
rename to test/testdata/goldens/outdated/outdated_test/Handles SDK dependencies.txt
index aba2f87..c9bc73f 100644
--- a/test/outdated/goldens/handles_sdk_dependencies.txt
+++ b/test/testdata/goldens/outdated/outdated_test/Handles SDK dependencies.txt
@@ -1,3 +1,6 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
$ pub outdated --json
{
"packages": [
@@ -19,6 +22,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub outdated --no-color
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -33,6 +39,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `flutter pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub outdated --no-color --no-transitive
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -47,6 +56,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `flutter pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub outdated --no-color --up-to-date
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -63,6 +75,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `flutter pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 4
$ pub outdated --no-color --prereleases
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -77,6 +92,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `flutter pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 5
$ pub outdated --no-color --no-dev-dependencies
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -89,6 +107,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `flutter pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 6
$ pub outdated --no-color --no-dependency-overrides
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -103,6 +124,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `flutter pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 7
$ pub outdated --no-color --mode=null-safety
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -119,6 +143,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `flutter pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 8
$ pub outdated --no-color --mode=null-safety --transitive
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -135,6 +162,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `flutter pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 9
$ pub outdated --no-color --mode=null-safety --no-prereleases
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -151,6 +181,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `flutter pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 10
$ pub outdated --json --mode=null-safety
{
"packages": [
@@ -195,6 +228,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 11
$ pub outdated --json --no-dev-dependencies
{
"packages": [
diff --git a/test/outdated/goldens/circular_dependencies.txt b/test/testdata/goldens/outdated/outdated_test/circular dependency on root.txt
similarity index 80%
rename from test/outdated/goldens/circular_dependencies.txt
rename to test/testdata/goldens/outdated/outdated_test/circular dependency on root.txt
index 27b6202..b9ab0a5 100644
--- a/test/outdated/goldens/circular_dependencies.txt
+++ b/test/testdata/goldens/outdated/outdated_test/circular dependency on root.txt
@@ -1,3 +1,6 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
$ pub outdated --json
{
"packages": [
@@ -19,6 +22,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub outdated --no-color
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -31,6 +37,9 @@
1 upgradable dependency is locked (in pubspec.lock) to an older version.
To update it, use `dart pub upgrade`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub outdated --no-color --no-transitive
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -43,6 +52,9 @@
1 upgradable dependency is locked (in pubspec.lock) to an older version.
To update it, use `dart pub upgrade`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub outdated --no-color --up-to-date
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -55,6 +67,9 @@
1 upgradable dependency is locked (in pubspec.lock) to an older version.
To update it, use `dart pub upgrade`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 4
$ pub outdated --no-color --prereleases
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -67,6 +82,9 @@
1 upgradable dependency is locked (in pubspec.lock) to an older version.
To update it, use `dart pub upgrade`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 5
$ pub outdated --no-color --no-dev-dependencies
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -79,6 +97,9 @@
1 upgradable dependency is locked (in pubspec.lock) to an older version.
To update it, use `dart pub upgrade`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 6
$ pub outdated --no-color --no-dependency-overrides
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -91,6 +112,9 @@
1 upgradable dependency is locked (in pubspec.lock) to an older version.
To update it, use `dart pub upgrade`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 7
$ pub outdated --no-color --mode=null-safety
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -104,6 +128,9 @@
1 upgradable dependency is locked (in pubspec.lock) to an older version.
To update it, use `dart pub upgrade`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 8
$ pub outdated --no-color --mode=null-safety --transitive
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -117,6 +144,9 @@
1 upgradable dependency is locked (in pubspec.lock) to an older version.
To update it, use `dart pub upgrade`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 9
$ pub outdated --no-color --mode=null-safety --no-prereleases
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -130,6 +160,9 @@
1 upgradable dependency is locked (in pubspec.lock) to an older version.
To update it, use `dart pub upgrade`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 10
$ pub outdated --json --mode=null-safety
{
"packages": [
@@ -155,6 +188,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 11
$ pub outdated --json --no-dev-dependencies
{
"packages": [
diff --git a/test/testdata/goldens/outdated/outdated_test/does not allow arguments - handles bad flags.txt b/test/testdata/goldens/outdated/outdated_test/does not allow arguments - handles bad flags.txt
new file mode 100644
index 0000000..6ab6163
--- /dev/null
+++ b/test/testdata/goldens/outdated/outdated_test/does not allow arguments - handles bad flags.txt
@@ -0,0 +1,64 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
+$ pub outdated random_argument
+[STDERR] Command "outdated" does not take any arguments.
+[STDERR]
+[STDERR] Usage: pub outdated [options]
+[STDERR] -h, --help Print this usage information.
+[STDERR] --[no-]color Whether to color the output.
+[STDERR] Defaults to color when connected to a
+[STDERR] terminal, and no-color otherwise.
+[STDERR] --[no-]dependency-overrides Show resolutions with `dependency_overrides`.
+[STDERR] (defaults to on)
+[STDERR] --[no-]dev-dependencies Take dev dependencies into account.
+[STDERR] (defaults to on)
+[STDERR] --json Output the results using a json format.
+[STDERR] --mode=<PROPERTY> Highlight versions with PROPERTY.
+[STDERR] Only packages currently missing that PROPERTY
+[STDERR] will be included unless --show-all.
+[STDERR] [outdated (default), null-safety]
+[STDERR] --[no-]prereleases Include prereleases in latest version.
+[STDERR] (defaults to on in --mode=null-safety).
+[STDERR] --[no-]show-all Include dependencies that are already
+[STDERR] fullfilling --mode.
+[STDERR] --[no-]transitive Show transitive dependencies.
+[STDERR] (defaults to off in --mode=null-safety).
+[STDERR] -C, --directory=<dir> Run this in the directory<dir>.
+[STDERR]
+[STDERR] Run "pub help" to see global options.
+[STDERR] See https://dart.dev/tools/pub/cmd/pub-outdated for detailed documentation.
+[EXIT CODE] 64
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
+$ pub outdated --bad_flag
+[STDERR] Could not find an option named "bad_flag".
+[STDERR]
+[STDERR] Usage: pub outdated [options]
+[STDERR] -h, --help Print this usage information.
+[STDERR] --[no-]color Whether to color the output.
+[STDERR] Defaults to color when connected to a
+[STDERR] terminal, and no-color otherwise.
+[STDERR] --[no-]dependency-overrides Show resolutions with `dependency_overrides`.
+[STDERR] (defaults to on)
+[STDERR] --[no-]dev-dependencies Take dev dependencies into account.
+[STDERR] (defaults to on)
+[STDERR] --json Output the results using a json format.
+[STDERR] --mode=<PROPERTY> Highlight versions with PROPERTY.
+[STDERR] Only packages currently missing that PROPERTY
+[STDERR] will be included unless --show-all.
+[STDERR] [outdated (default), null-safety]
+[STDERR] --[no-]prereleases Include prereleases in latest version.
+[STDERR] (defaults to on in --mode=null-safety).
+[STDERR] --[no-]show-all Include dependencies that are already
+[STDERR] fullfilling --mode.
+[STDERR] --[no-]transitive Show transitive dependencies.
+[STDERR] (defaults to off in --mode=null-safety).
+[STDERR] -C, --directory=<dir> Run this in the directory<dir>.
+[STDERR]
+[STDERR] Run "pub help" to see global options.
+[STDERR] See https://dart.dev/tools/pub/cmd/pub-outdated for detailed documentation.
+[EXIT CODE] 64
+
diff --git a/test/outdated/goldens/prereleases.txt b/test/testdata/goldens/outdated/outdated_test/latest version reported while locked on a prerelease can be a prerelease.txt
similarity index 87%
rename from test/outdated/goldens/prereleases.txt
rename to test/testdata/goldens/outdated/outdated_test/latest version reported while locked on a prerelease can be a prerelease.txt
index 8b91475..12c2ee3 100644
--- a/test/outdated/goldens/prereleases.txt
+++ b/test/testdata/goldens/outdated/outdated_test/latest version reported while locked on a prerelease can be a prerelease.txt
@@ -1,3 +1,6 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
$ pub outdated --json
{
"packages": [
@@ -34,6 +37,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub outdated --no-color
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -47,6 +53,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub outdated --no-color --no-transitive
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -60,6 +69,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub outdated --no-color --up-to-date
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -74,6 +86,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 4
$ pub outdated --no-color --prereleases
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -88,6 +103,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 5
$ pub outdated --no-color --no-dev-dependencies
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -101,6 +119,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 6
$ pub outdated --no-color --no-dependency-overrides
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -114,6 +135,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 7
$ pub outdated --no-color --mode=null-safety
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -129,6 +153,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 8
$ pub outdated --no-color --mode=null-safety --transitive
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -144,6 +171,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 9
$ pub outdated --no-color --mode=null-safety --no-prereleases
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -159,6 +189,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 10
$ pub outdated --json --mode=null-safety
{
"packages": [
@@ -222,6 +255,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 11
$ pub outdated --json --no-dev-dependencies
{
"packages": [
diff --git a/test/outdated/goldens/mutually_incompatible.txt b/test/testdata/goldens/outdated/outdated_test/mutually incompatible newer versions.txt
similarity index 84%
rename from test/outdated/goldens/mutually_incompatible.txt
rename to test/testdata/goldens/outdated/outdated_test/mutually incompatible newer versions.txt
index ae40331..18baa88 100644
--- a/test/outdated/goldens/mutually_incompatible.txt
+++ b/test/testdata/goldens/outdated/outdated_test/mutually incompatible newer versions.txt
@@ -1,3 +1,6 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
$ pub outdated --json
{
"packages": [
@@ -34,6 +37,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub outdated --no-color
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -46,6 +52,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub outdated --no-color --no-transitive
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -58,6 +67,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub outdated --no-color --up-to-date
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -70,6 +82,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 4
$ pub outdated --no-color --prereleases
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -82,6 +97,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 5
$ pub outdated --no-color --no-dev-dependencies
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -94,6 +112,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 6
$ pub outdated --no-color --no-dependency-overrides
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -106,6 +127,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 7
$ pub outdated --no-color --mode=null-safety
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -119,6 +143,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 8
$ pub outdated --no-color --mode=null-safety --transitive
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -132,6 +159,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 9
$ pub outdated --no-color --mode=null-safety --no-prereleases
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -145,6 +175,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 10
$ pub outdated --json --mode=null-safety
{
"packages": [
@@ -189,6 +222,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 11
$ pub outdated --json --no-dev-dependencies
{
"packages": [
diff --git a/test/outdated/goldens/newer_versions.txt b/test/testdata/goldens/outdated/outdated_test/newer versions available.txt
similarity index 91%
rename from test/outdated/goldens/newer_versions.txt
rename to test/testdata/goldens/outdated/outdated_test/newer versions available.txt
index 6e74a3e..d6c0ff9 100644
--- a/test/outdated/goldens/newer_versions.txt
+++ b/test/testdata/goldens/outdated/outdated_test/newer versions available.txt
@@ -1,3 +1,6 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
$ pub outdated --json
{
"packages": [
@@ -84,6 +87,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub outdated --no-color
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -110,6 +116,9 @@
3 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub outdated --no-color --no-transitive
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -128,6 +137,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub outdated --no-color --up-to-date
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -156,6 +168,9 @@
3 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 4
$ pub outdated --no-color --prereleases
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -182,6 +197,9 @@
3 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 5
$ pub outdated --no-color --no-dev-dependencies
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -200,6 +218,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 6
$ pub outdated --no-color --no-dependency-overrides
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -226,6 +247,9 @@
3 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 7
$ pub outdated --no-color --mode=null-safety
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -247,6 +271,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 8
$ pub outdated --no-color --mode=null-safety --transitive
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -276,6 +303,9 @@
3 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 9
$ pub outdated --no-color --mode=null-safety --no-prereleases
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -297,6 +327,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 10
$ pub outdated --json --mode=null-safety
{
"packages": [
@@ -440,6 +473,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 11
$ pub outdated --json --no-dev-dependencies
{
"packages": [
diff --git a/test/outdated/goldens/no_dependencies.txt b/test/testdata/goldens/outdated/outdated_test/no dependencies.txt
similarity index 63%
rename from test/outdated/goldens/no_dependencies.txt
rename to test/testdata/goldens/outdated/outdated_test/no dependencies.txt
index 672c124..d256d7f 100644
--- a/test/outdated/goldens/no_dependencies.txt
+++ b/test/testdata/goldens/outdated/outdated_test/no dependencies.txt
@@ -1,44 +1,68 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
$ pub outdated --json
{
"packages": []
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub outdated --no-color
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub outdated --no-color --no-transitive
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub outdated --no-color --up-to-date
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 4
$ pub outdated --no-color --prereleases
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 5
$ pub outdated --no-color --no-dev-dependencies
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 6
$ pub outdated --no-color --no-dependency-overrides
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 7
$ pub outdated --no-color --mode=null-safety
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -46,6 +70,9 @@
All your dependencies declare support for null-safety.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 8
$ pub outdated --no-color --mode=null-safety --transitive
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -53,6 +80,9 @@
All your dependencies declare support for null-safety.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 9
$ pub outdated --no-color --mode=null-safety --no-prereleases
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -60,11 +90,17 @@
All your dependencies declare support for null-safety.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 10
$ pub outdated --json --mode=null-safety
{
"packages": []
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 11
$ pub outdated --json --no-dev-dependencies
{
"packages": []
diff --git a/test/outdated/goldens/no_lockfile.txt b/test/testdata/goldens/outdated/outdated_test/no lockfile.txt
similarity index 86%
rename from test/outdated/goldens/no_lockfile.txt
rename to test/testdata/goldens/outdated/outdated_test/no lockfile.txt
index bca5ab7..7f670db 100644
--- a/test/outdated/goldens/no_lockfile.txt
+++ b/test/testdata/goldens/outdated/outdated_test/no lockfile.txt
@@ -1,3 +1,6 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
$ pub outdated --json
{
"packages": [
@@ -30,6 +33,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub outdated --no-color
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -46,6 +52,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub outdated --no-color --no-transitive
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -62,6 +71,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub outdated --no-color --up-to-date
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -78,6 +90,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 4
$ pub outdated --no-color --prereleases
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -94,6 +109,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 5
$ pub outdated --no-color --no-dev-dependencies
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -110,6 +128,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 6
$ pub outdated --no-color --no-dependency-overrides
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -126,6 +147,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 7
$ pub outdated --no-color --mode=null-safety
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -143,6 +167,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 8
$ pub outdated --no-color --mode=null-safety --transitive
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -160,6 +187,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 9
$ pub outdated --no-color --mode=null-safety --no-prereleases
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -177,6 +207,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 10
$ pub outdated --json --mode=null-safety
{
"packages": [
@@ -215,6 +248,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 11
$ pub outdated --json --no-dev-dependencies
{
"packages": [
diff --git a/test/testdata/goldens/outdated/outdated_test/no pubspec.txt b/test/testdata/goldens/outdated/outdated_test/no pubspec.txt
new file mode 100644
index 0000000..ba8858a
--- /dev/null
+++ b/test/testdata/goldens/outdated/outdated_test/no pubspec.txt
@@ -0,0 +1,7 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
+$ pub outdated
+[STDERR] Could not find a file named "pubspec.yaml" in "$SANDBOX/myapp".
+[EXIT CODE] 66
+
diff --git a/test/outdated/goldens/null_safety.txt b/test/testdata/goldens/outdated/outdated_test/null safety compliance.txt
similarity index 90%
rename from test/outdated/goldens/null_safety.txt
rename to test/testdata/goldens/outdated/outdated_test/null safety compliance.txt
index 9a9ce9c..d345f55 100644
--- a/test/outdated/goldens/null_safety.txt
+++ b/test/testdata/goldens/outdated/outdated_test/null safety compliance.txt
@@ -1,3 +1,6 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
$ pub outdated --json
{
"packages": [
@@ -94,6 +97,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub outdated --no-color
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -111,6 +117,9 @@
6 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub outdated --no-color --no-transitive
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -128,6 +137,9 @@
6 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub outdated --no-color --up-to-date
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -145,6 +157,9 @@
6 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 4
$ pub outdated --no-color --prereleases
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -162,6 +177,9 @@
6 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 5
$ pub outdated --no-color --no-dev-dependencies
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -179,6 +197,9 @@
6 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 6
$ pub outdated --no-color --no-dependency-overrides
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -196,6 +217,9 @@
6 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 7
$ pub outdated --no-color --mode=null-safety
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -210,6 +234,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 8
$ pub outdated --no-color --mode=null-safety --transitive
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -224,6 +251,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 9
$ pub outdated --no-color --mode=null-safety --no-prereleases
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -238,6 +268,9 @@
2 dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 10
$ pub outdated --json --mode=null-safety
{
"packages": [
@@ -282,6 +315,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 11
$ pub outdated --json --no-dev-dependencies
{
"packages": [
diff --git a/test/outdated/goldens/null_safety_already_migrated.txt b/test/testdata/goldens/outdated/outdated_test/null-safety already migrated.txt
similarity index 74%
rename from test/outdated/goldens/null_safety_already_migrated.txt
rename to test/testdata/goldens/outdated/outdated_test/null-safety already migrated.txt
index b7ad48e..3d227ec 100644
--- a/test/outdated/goldens/null_safety_already_migrated.txt
+++ b/test/testdata/goldens/outdated/outdated_test/null-safety already migrated.txt
@@ -1,20 +1,32 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
$ pub outdated --json
{
"packages": []
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub outdated --no-color
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub outdated --no-color --no-transitive
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub outdated --no-color --up-to-date
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -32,24 +44,36 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 4
$ pub outdated --no-color --prereleases
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 5
$ pub outdated --no-color --no-dev-dependencies
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 6
$ pub outdated --no-color --no-dependency-overrides
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 7
$ pub outdated --no-color --mode=null-safety
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -62,6 +86,9 @@
dev_dependencies: all support null safety.
All dependencies opt in to null-safety.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 8
$ pub outdated --no-color --mode=null-safety --transitive
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -77,6 +104,9 @@
devTransitive ✗1.0.0 ✗1.0.0 ✗1.0.0 ✗1.0.0
All dependencies opt in to null-safety.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 9
$ pub outdated --no-color --mode=null-safety --no-prereleases
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -89,6 +119,9 @@
dev_dependencies: all support null safety.
All dependencies opt in to null-safety.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 10
$ pub outdated --json --mode=null-safety
{
"packages": [
@@ -114,6 +147,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 11
$ pub outdated --json --no-dev-dependencies
{
"packages": []
diff --git a/test/outdated/goldens/null_safety_no_resolution.txt b/test/testdata/goldens/outdated/outdated_test/null-safety no resolution.txt
similarity index 78%
rename from test/outdated/goldens/null_safety_no_resolution.txt
rename to test/testdata/goldens/outdated/outdated_test/null-safety no resolution.txt
index 89fb0e2..1ab20ad 100644
--- a/test/outdated/goldens/null_safety_no_resolution.txt
+++ b/test/testdata/goldens/outdated/outdated_test/null-safety no resolution.txt
@@ -1,20 +1,32 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
$ pub outdated --json
{
"packages": []
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub outdated --no-color
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub outdated --no-color --no-transitive
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub outdated --no-color --up-to-date
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -27,6 +39,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 4
$ pub outdated --no-color --prereleases
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -39,18 +54,27 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 5
$ pub outdated --no-color --no-dev-dependencies
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 6
$ pub outdated --no-color --no-dependency-overrides
Showing outdated packages.
[*] indicates versions that are not the latest available.
Found no outdated packages
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 7
$ pub outdated --no-color --mode=null-safety
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -63,6 +87,9 @@
foo ✗1.0.0 ✗1.0.0 - ✓2.0.0-nullsafety.0
No resolution was found. Try running `dart pub upgrade --null-safety --dry-run` to explore why.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 8
$ pub outdated --no-color --mode=null-safety --transitive
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -75,6 +102,9 @@
foo ✗1.0.0 ✗1.0.0 - ✓2.0.0-nullsafety.0
No resolution was found. Try running `dart pub upgrade --null-safety --dry-run` to explore why.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 9
$ pub outdated --no-color --mode=null-safety --no-prereleases
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -87,6 +117,9 @@
foo ✗1.0.0 ✗1.0.0 - ✗1.0.0
No resolution was found. Try running `dart pub upgrade --null-safety --dry-run` to explore why.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 10
$ pub outdated --json --mode=null-safety
{
"packages": [
@@ -125,6 +158,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 11
$ pub outdated --json --no-dev-dependencies
{
"packages": []
diff --git a/test/outdated/goldens/dependency_overrides_no_solution.txt b/test/testdata/goldens/outdated/outdated_test/overridden dependencies - no resolution.txt
similarity index 86%
rename from test/outdated/goldens/dependency_overrides_no_solution.txt
rename to test/testdata/goldens/outdated/outdated_test/overridden dependencies - no resolution.txt
index 9efeb58..909ee0a 100644
--- a/test/outdated/goldens/dependency_overrides_no_solution.txt
+++ b/test/testdata/goldens/outdated/outdated_test/overridden dependencies - no resolution.txt
@@ -1,3 +1,6 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
$ pub outdated --json
{
"packages": [
@@ -40,6 +43,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub outdated --no-color
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -52,6 +58,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub outdated --no-color --no-transitive
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -64,6 +73,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub outdated --no-color --up-to-date
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -76,6 +88,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 4
$ pub outdated --no-color --prereleases
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -88,6 +103,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 5
$ pub outdated --no-color --no-dev-dependencies
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -100,6 +118,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 6
$ pub outdated --no-color --no-dependency-overrides
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -111,6 +132,9 @@
foo *1.0.0 (overridden) - - 2.0.0
No resolution was found. Try running `dart pub upgrade --dry-run` to explore why.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 7
$ pub outdated --no-color --mode=null-safety
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -124,6 +148,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 8
$ pub outdated --no-color --mode=null-safety --transitive
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -137,6 +164,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 9
$ pub outdated --no-color --mode=null-safety --no-prereleases
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -150,6 +180,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 10
$ pub outdated --json --mode=null-safety
{
"packages": [
@@ -200,6 +233,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 11
$ pub outdated --json --no-dev-dependencies
{
"packages": [
diff --git a/test/outdated/goldens/dependency_overrides.txt b/test/testdata/goldens/outdated/outdated_test/overridden dependencies.txt
similarity index 89%
rename from test/outdated/goldens/dependency_overrides.txt
rename to test/testdata/goldens/outdated/outdated_test/overridden dependencies.txt
index eb0c881..49abe1b 100644
--- a/test/outdated/goldens/dependency_overrides.txt
+++ b/test/testdata/goldens/outdated/outdated_test/overridden dependencies.txt
@@ -1,3 +1,6 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
$ pub outdated --json
{
"packages": [
@@ -58,6 +61,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub outdated --no-color
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -71,6 +77,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
$ pub outdated --no-color --no-transitive
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -84,6 +93,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
$ pub outdated --no-color --up-to-date
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -97,6 +109,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 4
$ pub outdated --no-color --prereleases
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -110,6 +125,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 5
$ pub outdated --no-color --no-dev-dependencies
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -123,6 +141,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 6
$ pub outdated --no-color --no-dependency-overrides
Showing outdated packages.
[*] indicates versions that are not the latest available.
@@ -140,6 +161,9 @@
1 dependency is constrained to a version that is older than a resolvable version.
To update it, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 7
$ pub outdated --no-color --mode=null-safety
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -154,6 +178,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 8
$ pub outdated --no-color --mode=null-safety --transitive
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -168,6 +195,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 9
$ pub outdated --no-color --mode=null-safety --no-prereleases
Showing dependencies that are currently not opted in to null-safety.
[✗] indicates versions without null safety support.
@@ -182,6 +212,9 @@
You are already using the newest resolvable versions listed in the 'Resolvable' column.
Newer versions, listed in 'Latest', may not be mutually compatible.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 10
$ pub outdated --json --mode=null-safety
{
"packages": [
@@ -254,6 +287,9 @@
]
}
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 11
$ pub outdated --json --no-dev-dependencies
{
"packages": [
diff --git a/test/testdata/goldens/upgrade/example_warns_about_major_versions_test/pub upgrade --major-versions does not update major versions in example~.txt b/test/testdata/goldens/upgrade/example_warns_about_major_versions_test/pub upgrade --major-versions does not update major versions in example~.txt
new file mode 100644
index 0000000..ae304ea
--- /dev/null
+++ b/test/testdata/goldens/upgrade/example_warns_about_major_versions_test/pub upgrade --major-versions does not update major versions in example~.txt
@@ -0,0 +1,25 @@
+# GENERATED BY: test/upgrade/example_warns_about_major_versions_test.dart
+
+## Section 0
+$ pub upgrade --major-versions --example
+Resolving dependencies...
++ bar 2.0.0
+Changed 1 dependency!
+
+Changed 1 constraint in pubspec.yaml:
+ bar: ^1.0.0 -> ^2.0.0
+Resolving dependencies in ./example...
+Got dependencies in ./example.
+[STDERR] Running `upgrade --major-versions` only in `.`. Run `dart pub upgrade --major-versions --directory example/` separately.
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
+$ pub upgrade --major-versions --directory example
+Resolving dependencies in example...
+> foo 2.0.0 (was 1.0.0)
+Changed 1 dependency in example!
+
+Changed 1 constraint in pubspec.yaml:
+ foo: ^1.0.0 -> ^2.0.0
+
diff --git a/test/goldens/upgrade_null_safety_example.txt b/test/testdata/goldens/upgrade/example_warns_about_major_versions_test/pub upgrade --null-safety does not update null-safety of dependencies in example~.txt
similarity index 62%
rename from test/goldens/upgrade_null_safety_example.txt
rename to test/testdata/goldens/upgrade/example_warns_about_major_versions_test/pub upgrade --null-safety does not update null-safety of dependencies in example~.txt
index 5c5b31c..cabc0be 100644
--- a/test/goldens/upgrade_null_safety_example.txt
+++ b/test/testdata/goldens/upgrade/example_warns_about_major_versions_test/pub upgrade --null-safety does not update null-safety of dependencies in example~.txt
@@ -1,3 +1,6 @@
+# GENERATED BY: test/upgrade/example_warns_about_major_versions_test.dart
+
+## Section 0
$ pub upgrade --null-safety --example
Resolving dependencies...
+ bar 2.0.0
@@ -7,8 +10,11 @@
bar: ^1.0.0 -> ^2.0.0
Resolving dependencies in ./example...
Got dependencies in ./example.
-[ERR] Running `upgrade --null-safety` only in `.`. Run `dart pub upgrade --null-safety --directory example/` separately.
+[STDERR] Running `upgrade --null-safety` only in `.`. Run `dart pub upgrade --null-safety --directory example/` separately.
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
$ pub upgrade --null-safety --directory example
Resolving dependencies in example...
> bar 2.0.0 (was 1.0.0)
diff --git a/test/token/add_token_test.dart b/test/token/add_token_test.dart
index 8105ce5..ca68c41 100644
--- a/test/token/add_token_test.dart
+++ b/test/token/add_token_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -46,7 +44,7 @@
await runPub(
args: ['token', 'add', 'https://example.com/', '--env-var', 'TOKEN'],
- error: 'Environment variable `TOKEN` is not defined.',
+ error: 'Environment variable "TOKEN" is not defined.',
);
await d.tokensFile({
@@ -68,7 +66,7 @@
await runPub(
args: ['token', 'add', 'https://example.com/', '--env-var', 'TOKEN'],
environment: {'TOKEN': 'secret'},
- error: isNot(contains('Environment variable TOKEN is not defined.')),
+ error: isNot(contains('is not defined.')),
);
await d.tokensFile({
@@ -135,10 +133,21 @@
await d.dir(configPath).create();
await runPub(
args: ['token', 'add', 'http://mypub.com'],
- error: contains('Insecure package repository could not be added.'),
- exitCode: exit_codes.DATA,
+ error: contains('insecure repositories cannot use authentication'),
+ exitCode: exit_codes.USAGE,
);
await d.dir(configPath, [d.nothing('pub-tokens.json')]).validate();
});
+
+ test('with empty environment gives error message', () async {
+ await runPub(
+ args: ['token', 'add', 'https://mypub.com'],
+ input: ['auth-token'],
+ error: contains('No config dir found.'),
+ exitCode: exit_codes.DATA,
+ environment: {'_PUB_TEST_CONFIG_DIR': null},
+ includeParentEnvironment: false,
+ );
+ });
}
diff --git a/test/token/error_message_test.dart b/test/token/error_message_test.dart
new file mode 100644
index 0000000..53431a5
--- /dev/null
+++ b/test/token/error_message_test.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:shelf/shelf.dart' as shelf;
+import 'package:test/test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+void respondWithWwwAuthenticate(String headerValue) {
+ globalServer.expect('GET', '/api/packages/versions/new', (request) {
+ return shelf.Response(403, headers: {'www-authenticate': headerValue});
+ });
+}
+
+Future<void> expectPubErrorMessage(dynamic matcher) {
+ return runPub(
+ args: ['lish'],
+ environment: {
+ 'PUB_HOSTED_URL': globalServer.url,
+ '_PUB_TEST_AUTH_METHOD': 'token',
+ },
+ exitCode: 65,
+ input: ['y'],
+ error: matcher,
+ );
+}
+
+void main() {
+ setUp(() async {
+ await d.validPackage.create();
+ await servePackages();
+ await d.tokensFile({
+ 'version': 1,
+ 'hosted': [
+ {'url': globalServer.url, 'token': 'access token'},
+ ]
+ }).create();
+ });
+
+ test('prints www-authenticate message', () async {
+ respondWithWwwAuthenticate('bearer realm="pub", message="custom message"');
+ await expectPubErrorMessage(contains('custom message'));
+ });
+
+ test('sanitizes and prints dirty www-authenticate message', () {
+ // Unable to test this case because shelf does not allow characters [1]
+ // that pub cli supposed to sanitize.
+ //
+ // [1] https://github.com/dart-lang/sdk/blob/main/sdk/lib/_http/http_headers.dart#L653-L662
+ });
+
+ test('trims and prints long www-authenticate message', () async {
+ var message = List.generate(2048, (_) => 'a').join();
+
+ respondWithWwwAuthenticate('bearer realm="pub", message="$message"');
+ await expectPubErrorMessage(allOf(
+ isNot(contains(message)),
+ contains(message.substring(0, 1024)),
+ ));
+ });
+
+ test('does not prints message if realm is not equals to pub', () async {
+ respondWithWwwAuthenticate('bearer realm="web", message="custom message"');
+ await expectPubErrorMessage(isNot(contains('custom message')));
+ });
+
+ test('does not prints message if challenge is not equals to bearer',
+ () async {
+ respondWithWwwAuthenticate('basic realm="pub", message="custom message"');
+ await expectPubErrorMessage(isNot(contains('custom message')));
+ });
+
+ test('prints message for bearer challenge for pub realm only', () async {
+ respondWithWwwAuthenticate(
+ 'basic realm="pub", message="enter username and password", '
+ 'newAuth message="use web portal to login", '
+ 'bearer realm="api", message="contact IT dept to enroll", '
+ 'bearer realm="pub", '
+ 'bearer realm="pub", message="pub realm message"',
+ );
+ await expectPubErrorMessage(contains('pub realm message'));
+ });
+}
diff --git a/test/token/remove_token_test.dart b/test/token/remove_token_test.dart
index f9ce67d..bfe2428 100644
--- a/test/token/remove_token_test.dart
+++ b/test/token/remove_token_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
@@ -61,4 +59,14 @@
await d.dir(configPath, [d.nothing('pub-tokens.json')]).validate();
});
+
+ test('with empty environment gives error message', () async {
+ await runPub(
+ args: ['token', 'remove', 'http://mypub.com'],
+ error: contains('No config dir found.'),
+ exitCode: exit_codes.DATA,
+ environment: {'_PUB_TEST_CONFIG_DIR': null},
+ includeParentEnvironment: false,
+ );
+ });
}
diff --git a/test/token/token_authentication_test.dart b/test/token/token_authentication_test.dart
new file mode 100644
index 0000000..c020ac0
--- /dev/null
+++ b/test/token/token_authentication_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+
+import '../descriptor.dart' as d;
+import '../lish/utils.dart';
+import '../test_pub.dart';
+
+void main() {
+ setUp(d.validPackage.create);
+
+ test('with a pre existing environment token authenticates', () async {
+ await servePackages();
+ await d.tokensFile({
+ 'version': 1,
+ 'hosted': [
+ {'url': globalServer.url, 'env': 'TOKEN'},
+ ]
+ }).create();
+ var pub = await startPublish(globalServer,
+ authMethod: 'token', environment: {'TOKEN': 'access token'});
+ await confirmPublish(pub);
+
+ handleUploadForm(globalServer);
+
+ await pub.shouldExit(1);
+ });
+
+ test('with a pre existing opaque token authenticates', () async {
+ await servePackages();
+ await d.tokensFile({
+ 'version': 1,
+ 'hosted': [
+ {'url': globalServer.url, 'token': 'access token'},
+ ]
+ }).create();
+ var pub = await startPublish(globalServer, authMethod: 'token');
+ await confirmPublish(pub);
+
+ handleUploadForm(globalServer);
+
+ await pub.shouldExit(1);
+ });
+}
diff --git a/test/token/when_receives_401_removes_token_test.dart b/test/token/when_receives_401_removes_token_test.dart
new file mode 100644
index 0000000..86c0559
--- /dev/null
+++ b/test/token/when_receives_401_removes_token_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:shelf/shelf.dart' as shelf;
+import 'package:test/test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+void main() {
+ setUp(d.validPackage.create);
+
+ test('when receives 401 response removes saved token', () async {
+ final server = await servePackages();
+ await d.tokensFile({
+ 'version': 1,
+ 'hosted': [
+ {'url': server.url, 'token': 'access token'},
+ ]
+ }).create();
+ var pub = await startPublish(server, authMethod: 'token');
+ await confirmPublish(pub);
+
+ server.expect('GET', '/api/packages/versions/new', (request) {
+ return shelf.Response(401);
+ });
+
+ await pub.shouldExit(65);
+
+ await d.tokensFile({'version': 1, 'hosted': []}).validate();
+ });
+}
diff --git a/test/token/when_receives_403_persists_saved_token_test.dart b/test/token/when_receives_403_persists_saved_token_test.dart
new file mode 100644
index 0000000..45fc7a4
--- /dev/null
+++ b/test/token/when_receives_403_persists_saved_token_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:shelf/shelf.dart' as shelf;
+import 'package:test/test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+void main() {
+ setUp(d.validPackage.create);
+
+ test('when receives 403 response persists saved token', () async {
+ final server = await servePackages();
+ await d.tokensFile({
+ 'version': 1,
+ 'hosted': [
+ {'url': server.url, 'token': 'access token'},
+ ]
+ }).create();
+ var pub = await startPublish(server, authMethod: 'token');
+ await confirmPublish(pub);
+
+ server.expect('GET', '/api/packages/versions/new', (request) {
+ return shelf.Response(403);
+ });
+
+ await pub.shouldExit(65);
+
+ await d.tokensFile({
+ 'version': 1,
+ 'hosted': [
+ {'url': server.url, 'token': 'access token'},
+ ]
+ }).validate();
+ });
+}
diff --git a/test/unknown_source_test.dart b/test/unknown_source_test.dart
index 241f9c7..37591d0 100644
--- a/test/unknown_source_test.dart
+++ b/test/unknown_source_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:convert';
import 'package:test/test.dart';
@@ -74,7 +72,9 @@
await pubCommand(command);
// Should upgrade to the new one.
- await d.appPackagesFile({'foo': '../foo'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', path: '../foo'),
+ ]).validate();
});
});
}
diff --git a/test/upgrade/dry_run_does_not_apply_changes_test.dart b/test/upgrade/dry_run_does_not_apply_changes_test.dart
index e77d3b8..8c942ca 100644
--- a/test/upgrade/dry_run_does_not_apply_changes_test.dart
+++ b/test/upgrade/dry_run_does_not_apply_changes_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/io.dart';
import 'package:test/test.dart';
@@ -13,10 +11,9 @@
void main() {
test('--dry-run: shows report, changes nothing', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0');
// Create the first lockfile.
await d.appDir({'foo': '1.0.0'}).create();
@@ -52,10 +49,9 @@
});
test('--dry-run --major-versions: shows report, changes nothing', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0');
await d.appDir({'foo': '^1.0.0'}).create();
diff --git a/test/upgrade/example_warns_about_major_versions_test.dart b/test/upgrade/example_warns_about_major_versions_test.dart
index 0813ed2..b5c9a67 100644
--- a/test/upgrade/example_warns_about_major_versions_test.dart
+++ b/test/upgrade/example_warns_about_major_versions_test.dart
@@ -2,23 +2,19 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart = 2.11
-
-import 'package:test/test.dart';
-
import '../descriptor.dart' as d;
import '../golden_file.dart';
import '../test_pub.dart';
void main() {
- test(
+ testWithGolden(
'pub upgrade --major-versions does not update major versions in example/',
- () async {
- await servePackages((b) => b
+ (ctx) async {
+ await servePackages()
..serve('foo', '1.0.0')
..serve('foo', '2.0.0')
..serve('bar', '1.0.0')
- ..serve('bar', '2.0.0'));
+ ..serve('bar', '2.0.0');
await d.dir(appPath, [
d.pubspec({
'name': 'myapp',
@@ -36,24 +32,14 @@
])
]).create();
- final buffer = StringBuffer();
- await runPubIntoBuffer(
- ['upgrade', '--major-versions', '--example'],
- buffer,
- );
- await runPubIntoBuffer(
- ['upgrade', '--major-versions', '--directory', 'example'],
- buffer,
- );
-
- expectMatchesGoldenFile(
- buffer.toString(), 'test/goldens/upgrade_major_versions_example.txt');
+ await ctx.run(['upgrade', '--major-versions', '--example']);
+ await ctx.run(['upgrade', '--major-versions', '--directory', 'example']);
});
- test(
+ testWithGolden(
'pub upgrade --null-safety does not update null-safety of dependencies in example/',
- () async {
- await servePackages((b) => b
+ (ctx) async {
+ await servePackages()
..serve('foo', '1.0.0', pubspec: {
'environment': {'sdk': '>=2.7.0 <3.0.0'},
})
@@ -65,7 +51,7 @@
})
..serve('bar', '2.0.0', pubspec: {
'environment': {'sdk': '>=2.12.0 <3.0.0'},
- }));
+ });
await d.dir(appPath, [
d.pubspec({
'name': 'myapp',
@@ -86,20 +72,14 @@
])
]).create();
- final buffer = StringBuffer();
- await runPubIntoBuffer(
+ await ctx.run(
['upgrade', '--null-safety', '--example'],
- buffer,
environment: {'_PUB_TEST_SDK_VERSION': '2.13.0'},
);
- await runPubIntoBuffer(
+ await ctx.run(
['upgrade', '--null-safety', '--directory', 'example'],
- buffer,
environment: {'_PUB_TEST_SDK_VERSION': '2.13.0'},
);
-
- expectMatchesGoldenFile(
- buffer.toString(), 'test/goldens/upgrade_null_safety_example.txt');
});
}
diff --git a/test/upgrade/git/do_not_upgrade_if_unneeded_test.dart b/test/upgrade/git/do_not_upgrade_if_unneeded_test.dart
index dffb433..5638fb9 100644
--- a/test/upgrade/git/do_not_upgrade_if_unneeded_test.dart
+++ b/test/upgrade/git/do_not_upgrade_if_unneeded_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
diff --git a/test/upgrade/git/upgrade_locked_test.dart b/test/upgrade/git/upgrade_locked_test.dart
index 55938de..a8e744f 100644
--- a/test/upgrade/git/upgrade_locked_test.dart
+++ b/test/upgrade/git/upgrade_locked_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/upgrade/git/upgrade_one_locked_test.dart b/test/upgrade/git/upgrade_one_locked_test.dart
index 14fa010..5c41fa6 100644
--- a/test/upgrade/git/upgrade_one_locked_test.dart
+++ b/test/upgrade/git/upgrade_one_locked_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/upgrade/git/upgrade_to_incompatible_pubspec_test.dart b/test/upgrade/git/upgrade_to_incompatible_pubspec_test.dart
index 33f584c..e74a11e 100644
--- a/test/upgrade/git/upgrade_to_incompatible_pubspec_test.dart
+++ b/test/upgrade/git/upgrade_to_incompatible_pubspec_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
diff --git a/test/upgrade/git/upgrade_to_nonexistent_pubspec_test.dart b/test/upgrade/git/upgrade_to_nonexistent_pubspec_test.dart
index e1e160f..ae865eb 100644
--- a/test/upgrade/git/upgrade_to_nonexistent_pubspec_test.dart
+++ b/test/upgrade/git/upgrade_to_nonexistent_pubspec_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
diff --git a/test/upgrade/hosted/unlock_if_necessary_test.dart b/test/upgrade/hosted/unlock_if_necessary_test.dart
index 9bd78fb..2707100 100644
--- a/test/upgrade/hosted/unlock_if_necessary_test.dart
+++ b/test/upgrade/hosted/unlock_if_necessary_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -13,24 +11,28 @@
test(
"upgrades one locked pub server package's dependencies if it's "
'necessary', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'foo_dep': 'any'});
- builder.serve('foo_dep', '1.0.0');
- });
+ final server = await servePackages();
+
+ server.serve('foo', '1.0.0', deps: {'foo_dep': 'any'});
+ server.serve('foo_dep', '1.0.0');
await d.appDir({'foo': 'any'}).create();
await pubGet();
- await d.appPackagesFile({'foo': '1.0.0', 'foo_dep': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'foo_dep', version: '1.0.0'),
+ ]).validate();
- globalPackageServer.add((builder) {
- builder.serve('foo', '2.0.0', deps: {'foo_dep': '>1.0.0'});
- builder.serve('foo_dep', '2.0.0');
- });
+ server.serve('foo', '2.0.0', deps: {'foo_dep': '>1.0.0'});
+ server.serve('foo_dep', '2.0.0');
await pubUpgrade(args: ['foo']);
- await d.appPackagesFile({'foo': '2.0.0', 'foo_dep': '2.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.0.0'),
+ d.packageConfigEntry(name: 'foo_dep', version: '2.0.0'),
+ ]).validate();
});
}
diff --git a/test/upgrade/hosted/unlock_single_package_test.dart b/test/upgrade/hosted/unlock_single_package_test.dart
index ba3d80f..e443a6a 100644
--- a/test/upgrade/hosted/unlock_single_package_test.dart
+++ b/test/upgrade/hosted/unlock_single_package_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,37 +9,43 @@
void main() {
test('can unlock a single package only in upgrade', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': '<2.0.0'});
- builder.serve('bar', '1.0.0');
- });
+ final server = await servePackages();
+
+ server.serve('foo', '1.0.0', deps: {'bar': '<2.0.0'});
+ server.serve('bar', '1.0.0');
await d.appDir({'foo': 'any', 'bar': 'any'}).create();
await pubGet();
- await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ ]).validate();
- globalPackageServer.add((builder) {
- builder.serve('foo', '2.0.0', deps: {'bar': '<3.0.0'});
- builder.serve('bar', '2.0.0');
- });
+ server.serve('foo', '2.0.0', deps: {'bar': '<3.0.0'});
+ server.serve('bar', '2.0.0');
// This can't upgrade 'bar'
await pubUpgrade(args: ['bar']);
- await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.0.0'}).validate();
-
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ ]).validate();
// Introducing foo and bar 1.1.0, to show that only 'bar' will be upgraded
- globalPackageServer.add((builder) {
- builder.serve('foo', '1.1.0', deps: {'bar': '<2.0.0'});
- builder.serve('bar', '1.1.0');
- });
+ server.serve('foo', '1.1.0', deps: {'bar': '<2.0.0'});
+ server.serve('bar', '1.1.0');
await pubUpgrade(args: ['bar']);
- await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.1.0'}).validate();
-
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.1.0'),
+ ]).validate();
await pubUpgrade();
- await d.appPackagesFile({'foo': '2.0.0', 'bar': '2.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '2.0.0'),
+ ]).validate();
});
}
diff --git a/test/upgrade/hosted/upgrade_removed_constraints_test.dart b/test/upgrade/hosted/upgrade_removed_constraints_test.dart
index bb73ddc..cf72c07 100644
--- a/test/upgrade/hosted/upgrade_removed_constraints_test.dart
+++ b/test/upgrade/hosted/upgrade_removed_constraints_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,24 +9,29 @@
void main() {
test('upgrades dependencies whose constraints have been removed', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'shared_dep': 'any'});
- builder.serve('bar', '1.0.0', deps: {'shared_dep': '<2.0.0'});
- builder.serve('shared_dep', '1.0.0');
- builder.serve('shared_dep', '2.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'shared_dep': 'any'})
+ ..serve('bar', '1.0.0', deps: {'shared_dep': '<2.0.0'})
+ ..serve('shared_dep', '1.0.0')
+ ..serve('shared_dep', '2.0.0');
await d.appDir({'foo': 'any', 'bar': 'any'}).create();
await pubUpgrade();
- await d.appPackagesFile(
- {'foo': '1.0.0', 'bar': '1.0.0', 'shared_dep': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ d.packageConfigEntry(name: 'shared_dep', version: '1.0.0'),
+ ]).validate();
await d.appDir({'foo': 'any'}).create();
await pubUpgrade();
- await d.appPackagesFile({'foo': '1.0.0', 'shared_dep': '2.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'shared_dep', version: '2.0.0'),
+ ]).validate();
});
}
diff --git a/test/upgrade/hosted/warn_about_discontinued_test.dart b/test/upgrade/hosted/warn_about_discontinued_test.dart
new file mode 100644
index 0000000..ba7fc57
--- /dev/null
+++ b/test/upgrade/hosted/warn_about_discontinued_test.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+void main() {
+ test('Warns about discontinued dependencies', () async {
+ final server = await servePackages()
+ ..serve('foo', '1.2.3', deps: {'transitive': 'any'})
+ ..serve('transitive', '1.0.0');
+ await d.appDir({'foo': '1.2.3'}).create();
+ await pubGet();
+
+ server
+ ..discontinue('foo')
+ ..discontinue('transitive');
+ // We warn only about the direct dependency here:
+ await pubUpgrade(output: '''
+Resolving dependencies...
+ foo 1.2.3 (discontinued)
+ transitive 1.0.0
+ No dependencies changed.
+ 1 package is discontinued.
+''');
+ server.discontinue('foo', replacementText: 'bar');
+ // We warn only about the direct dependency here:
+ await pubUpgrade(output: '''
+Resolving dependencies...
+ foo 1.2.3 (discontinued replaced by bar)
+ transitive 1.0.0
+ No dependencies changed.
+ 1 package is discontinued.
+''');
+ });
+
+ test('Warns about discontinued dev_dependencies', () async {
+ final server = await servePackages()
+ ..serve('foo', '1.2.3', deps: {'transitive': 'any'})
+ ..serve('transitive', '1.0.0');
+
+ await d.dir(appPath, [
+ d.file('pubspec.yaml', '''
+name: myapp
+dependencies:
+
+dev_dependencies:
+ foo: 1.2.3
+environment:
+ sdk: '>=0.1.2 <1.0.0'
+''')
+ ]).create();
+ await pubGet();
+
+ server
+ ..discontinue('foo')
+ ..discontinue('transitive');
+
+ // We warn only about the direct dependency here:
+ await pubUpgrade(output: '''
+Resolving dependencies...
+ foo 1.2.3 (discontinued)
+ transitive 1.0.0
+ No dependencies changed.
+ 1 package is discontinued.
+''');
+ server.discontinue('foo', replacementText: 'bar');
+ // We warn only about the direct dependency here:
+ await pubUpgrade(output: '''
+Resolving dependencies...
+ foo 1.2.3 (discontinued replaced by bar)
+ transitive 1.0.0
+ No dependencies changed.
+ 1 package is discontinued.
+''');
+ });
+}
diff --git a/test/upgrade/renamed_package_circular_dependency.dart b/test/upgrade/renamed_package_circular_dependency.dart
index 84ce151..ec10b82 100644
--- a/test/upgrade/renamed_package_circular_dependency.dart
+++ b/test/upgrade/renamed_package_circular_dependency.dart
@@ -2,18 +2,15 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
import '../test_pub.dart';
void main() {
test('The upgrade report handles a package becoming root', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'myapp': 'any'});
- builder.serve('myapp', '1.0.0', deps: {'foo': 'any'});
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'myapp': 'any'})
+ ..serve('myapp', '1.0.0', deps: {'foo': 'any'});
await d.dir(appPath, [
d.pubspec({
diff --git a/test/upgrade/report/describes_change_test.dart b/test/upgrade/report/describes_change_test.dart
index 382deb0..96410cb 100644
--- a/test/upgrade/report/describes_change_test.dart
+++ b/test/upgrade/report/describes_change_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,11 +9,11 @@
void main() {
test('Shows count of discontinued packages', () async {
- await servePackages((builder) {
- builder.serve('foo', '2.0.0');
- });
+ final server = await servePackages();
- globalPackageServer.add((builder) => builder..discontinue('foo'));
+ server.serve('foo', '2.0.0');
+
+ server.discontinue('foo');
// Create the first lockfile.
await d.appDir({'foo': '2.0.0'}).create();
@@ -35,12 +33,11 @@
});
test('shows how package changed from previous lockfile', () async {
- await servePackages((builder) {
- builder.serve('unchanged', '1.0.0');
- builder.serve('version_changed', '1.0.0');
- builder.serve('version_changed', '2.0.0');
- builder.serve('source_changed', '1.0.0');
- });
+ await servePackages()
+ ..serve('unchanged', '1.0.0')
+ ..serve('version_changed', '1.0.0')
+ ..serve('version_changed', '2.0.0')
+ ..serve('source_changed', '1.0.0');
await d.dir('source_changed', [
d.libDir('source_changed'),
diff --git a/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart b/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart
index 41f90d0..ef987b9 100644
--- a/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart
+++ b/test/upgrade/report/does_not_show_newer_versions_for_locked_packages_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -13,14 +11,13 @@
test(
'Shows newer versions available for packages that are locked and not being upgraded',
() async {
- await servePackages((builder) {
- builder.serve('not_upgraded', '1.0.0');
- builder.serve('not_upgraded', '2.0.0');
- builder.serve('not_upgraded', '3.0.0-dev');
- builder.serve('upgraded', '1.0.0');
- builder.serve('upgraded', '2.0.0');
- builder.serve('upgraded', '3.0.0-dev');
- });
+ await servePackages()
+ ..serve('not_upgraded', '1.0.0')
+ ..serve('not_upgraded', '2.0.0')
+ ..serve('not_upgraded', '3.0.0-dev')
+ ..serve('upgraded', '1.0.0')
+ ..serve('upgraded', '2.0.0')
+ ..serve('upgraded', '3.0.0-dev');
// Constraint everything to the first version.
await d.appDir({'not_upgraded': '1.0.0', 'upgraded': '1.0.0'}).create();
diff --git a/test/upgrade/report/highlights_overrides_test.dart b/test/upgrade/report/highlights_overrides_test.dart
index 04ae0ba..93f9f3b 100644
--- a/test/upgrade/report/highlights_overrides_test.dart
+++ b/test/upgrade/report/highlights_overrides_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,7 +9,8 @@
void main() {
test('highlights overridden packages', () async {
- await servePackages((builder) => builder.serve('overridden', '1.0.0'));
+ final server = await servePackages();
+ server.serve('overridden', '1.0.0');
await d.dir(appPath, [
d.pubspec({
diff --git a/test/upgrade/report/leading_character_shows_change_test.dart b/test/upgrade/report/leading_character_shows_change_test.dart
index e7438d8..88f7ed2 100644
--- a/test/upgrade/report/leading_character_shows_change_test.dart
+++ b/test/upgrade/report/leading_character_shows_change_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,17 +9,16 @@
void main() {
test('the character before each package describes the change', () async {
- await servePackages((builder) {
- builder.serve('added', '1.0.0');
- builder.serve('downgraded', '1.0.0');
- builder.serve('downgraded', '2.0.0');
- builder.serve('overridden', '1.0.0');
- builder.serve('removed', '1.0.0');
- builder.serve('source_changed', '1.0.0');
- builder.serve('upgraded', '1.0.0');
- builder.serve('upgraded', '2.0.0');
- builder.serve('unchanged', '1.0.0');
- });
+ await servePackages()
+ ..serve('added', '1.0.0')
+ ..serve('downgraded', '1.0.0')
+ ..serve('downgraded', '2.0.0')
+ ..serve('overridden', '1.0.0')
+ ..serve('removed', '1.0.0')
+ ..serve('source_changed', '1.0.0')
+ ..serve('upgraded', '1.0.0')
+ ..serve('upgraded', '2.0.0')
+ ..serve('unchanged', '1.0.0');
await d.dir('description_changed_1', [
d.libDir('description_changed'),
diff --git a/test/upgrade/report/shows_newer_available_versions_test.dart b/test/upgrade/report/shows_newer_available_versions_test.dart
index 54c32ad..39d4e1a 100644
--- a/test/upgrade/report/shows_newer_available_versions_test.dart
+++ b/test/upgrade/report/shows_newer_available_versions_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,28 +9,26 @@
void main() {
test('shows how many newer versions are available', () async {
- await servePackages((builder) {
- builder.serve('multiple_newer', '1.0.0');
- builder.serve('multiple_newer', '1.0.1-unstable.1');
- builder.serve('multiple_newer', '1.0.1');
- builder.serve('multiple_newer', '1.0.2-unstable.1');
- builder.serve('multiple_newer_stable', '1.0.0');
- builder.serve('multiple_newer_stable', '1.0.1');
- builder.serve('multiple_newer_stable', '1.0.2');
- builder.serve('multiple_newer_unstable', '1.0.0');
- builder.serve('multiple_newer_unstable', '1.0.1-unstable.1');
- builder.serve('multiple_newer_unstable', '1.0.1-unstable.2');
- builder.serve('multiple_newer_unstable2', '1.0.1-unstable.1');
- builder.serve('multiple_newer_unstable2', '1.0.1-unstable.2');
- builder.serve('multiple_newer_unstable2', '1.0.1-unstable.2');
- builder.serve('no_newer', '1.0.0');
- builder.serve('one_newer_unstable', '1.0.0');
- builder.serve('one_newer_unstable', '1.0.1-unstable.1');
- builder.serve('one_newer_unstable2', '1.0.1-unstable.1');
- builder.serve('one_newer_unstable2', '1.0.1-unstable.2');
- builder.serve('one_newer_stable', '1.0.0');
- builder.serve('one_newer_stable', '1.0.1');
- });
+ await servePackages()
+ ..serve('multiple_newer', '1.0.0')
+ ..serve('multiple_newer', '1.0.1-unstable.1')
+ ..serve('multiple_newer', '1.0.1')
+ ..serve('multiple_newer', '1.0.2-unstable.1')
+ ..serve('multiple_newer_stable', '1.0.0')
+ ..serve('multiple_newer_stable', '1.0.1')
+ ..serve('multiple_newer_stable', '1.0.2')
+ ..serve('multiple_newer_unstable', '1.0.0')
+ ..serve('multiple_newer_unstable', '1.0.1-unstable.1')
+ ..serve('multiple_newer_unstable', '1.0.1-unstable.2')
+ ..serve('multiple_newer_unstable2', '1.0.1-unstable.1')
+ ..serve('multiple_newer_unstable2', '1.0.1-unstable.2')
+ ..serve('no_newer', '1.0.0')
+ ..serve('one_newer_unstable', '1.0.0')
+ ..serve('one_newer_unstable', '1.0.1-unstable.1')
+ ..serve('one_newer_unstable2', '1.0.1-unstable.1')
+ ..serve('one_newer_unstable2', '1.0.1-unstable.2')
+ ..serve('one_newer_stable', '1.0.0')
+ ..serve('one_newer_stable', '1.0.1');
// Constraint everything to the first version.
await d.appDir({
diff --git a/test/upgrade/report/shows_number_of_changed_dependencies_test.dart b/test/upgrade/report/shows_number_of_changed_dependencies_test.dart
index 1c79302..91ba5aa 100644
--- a/test/upgrade/report/shows_number_of_changed_dependencies_test.dart
+++ b/test/upgrade/report/shows_number_of_changed_dependencies_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -13,11 +11,10 @@
test(
'does not show how many newer versions are available for '
'packages that are locked and not being upgraded', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('b', '1.0.0');
- builder.serve('c', '2.0.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('b', '1.0.0')
+ ..serve('c', '2.0.0');
await d.appDir({'a': 'any'}).create();
diff --git a/test/upgrade/report/shows_pub_outdated_test.dart b/test/upgrade/report/shows_pub_outdated_test.dart
index 11d50da..0fdb322 100644
--- a/test/upgrade/report/shows_pub_outdated_test.dart
+++ b/test/upgrade/report/shows_pub_outdated_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../../descriptor.dart' as d;
@@ -11,24 +9,23 @@
void main() {
test('shows pub outdated', () async {
- await servePackages((builder) {
- builder.serve('multiple_newer', '1.0.0');
- builder.serve('multiple_newer', '1.0.1-unstable.1');
- builder.serve('multiple_newer', '1.0.1');
- builder.serve('multiple_newer', '1.0.2-unstable.1');
- builder.serve('multiple_newer', '1.0.2-unstable.2');
- builder.serve('multiple_newer_stable', '1.0.0');
- builder.serve('multiple_newer_stable', '1.0.1');
- builder.serve('multiple_newer_stable', '1.0.2');
- builder.serve('multiple_newer_unstable', '1.0.0');
- builder.serve('multiple_newer_unstable', '1.0.1-unstable.1');
- builder.serve('multiple_newer_unstable', '1.0.1-unstable.2');
- builder.serve('no_newer', '1.0.0');
- builder.serve('one_newer_unstable', '1.0.0');
- builder.serve('one_newer_unstable', '1.0.1-unstable.1');
- builder.serve('one_newer_stable', '1.0.0');
- builder.serve('one_newer_stable', '1.0.1');
- });
+ await servePackages()
+ ..serve('multiple_newer', '1.0.0')
+ ..serve('multiple_newer', '1.0.1-unstable.1')
+ ..serve('multiple_newer', '1.0.1')
+ ..serve('multiple_newer', '1.0.2-unstable.1')
+ ..serve('multiple_newer', '1.0.2-unstable.2')
+ ..serve('multiple_newer_stable', '1.0.0')
+ ..serve('multiple_newer_stable', '1.0.1')
+ ..serve('multiple_newer_stable', '1.0.2')
+ ..serve('multiple_newer_unstable', '1.0.0')
+ ..serve('multiple_newer_unstable', '1.0.1-unstable.1')
+ ..serve('multiple_newer_unstable', '1.0.1-unstable.2')
+ ..serve('no_newer', '1.0.0')
+ ..serve('one_newer_unstable', '1.0.0')
+ ..serve('one_newer_unstable', '1.0.1-unstable.1')
+ ..serve('one_newer_stable', '1.0.0')
+ ..serve('one_newer_stable', '1.0.1');
// Constraint everything to the first version.
await d.appDir({
diff --git a/test/upgrade/upgrade_major_versions_test.dart b/test/upgrade/upgrade_major_versions_test.dart
index 7ab389b..c5f0994 100644
--- a/test/upgrade/upgrade_major_versions_test.dart
+++ b/test/upgrade/upgrade_major_versions_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
@@ -12,14 +10,13 @@
void main() {
group('pub upgrade --major-versions', () {
test('bumps dependency constraints and shows summary report', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- builder.serve('bar', '0.1.0');
- builder.serve('bar', '0.2.0');
- builder.serve('baz', '1.0.0');
- builder.serve('baz', '1.0.1');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0')
+ ..serve('bar', '0.1.0')
+ ..serve('bar', '0.2.0')
+ ..serve('baz', '1.0.0')
+ ..serve('baz', '1.0.1');
await d.appDir({
'foo': '^1.0.0',
@@ -44,23 +41,21 @@
'bar': '^0.2.0',
'baz': '^1.0.0',
}).validate();
-
- await d.appPackagesFile({
- 'foo': '2.0.0',
- 'bar': '0.2.0',
- 'baz': '1.0.1',
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '0.2.0'),
+ d.packageConfigEntry(name: 'baz', version: '1.0.1'),
+ ]).validate();
});
test('bumps dev_dependency constraints and shows summary report', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- builder.serve('bar', '0.1.0');
- builder.serve('bar', '0.2.0');
- builder.serve('baz', '1.0.0');
- builder.serve('baz', '1.0.1');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0')
+ ..serve('bar', '0.1.0')
+ ..serve('bar', '0.2.0')
+ ..serve('baz', '1.0.0')
+ ..serve('baz', '1.0.1');
await d.dir(appPath, [
d.pubspec({
@@ -96,20 +91,18 @@
}),
]).validate();
- await d.appPackagesFile({
- 'foo': '2.0.0',
- 'bar': '0.2.0',
- 'baz': '1.0.1',
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '0.2.0'),
+ d.packageConfigEntry(name: 'baz', version: '1.0.1'),
+ ]).validate();
});
test('upgrades only the selected package', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- builder.serve('bar', '0.1.0');
- builder.serve('bar', '0.2.0');
- });
+ final server = await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0')
+ ..serve('bar', '0.1.0');
await d.appDir({
'foo': '^1.0.0',
@@ -118,6 +111,8 @@
await pubGet();
+ server.serve('bar', '0.1.1');
+
// 1 constraint should be updated
await pubUpgrade(
args: ['--major-versions', 'foo'],
@@ -132,15 +127,17 @@
'bar': '^0.1.0',
}).validate();
- await d.appPackagesFile({'foo': '2.0.0', 'bar': '0.1.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '2.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '0.1.0'),
+ ]).validate();
});
test('chooses the latest version where possible', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- builder.serve('foo', '3.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0')
+ ..serve('foo', '3.0.0');
await d.appDir({'foo': '^1.0.0'}).create();
@@ -164,17 +161,17 @@
d.file('pubspec.lock', contains('3.0.0'))
]).validate();
- await d.appPackagesFile({'foo': '3.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '3.0.0'),
+ ]).validate();
});
test('overridden dependencies - no resolution', () async {
- await servePackages(
- (builder) => builder
- ..serve('foo', '1.0.0', deps: {'bar': '^2.0.0'})
- ..serve('foo', '2.0.0', deps: {'bar': '^1.0.0'})
- ..serve('bar', '1.0.0', deps: {'foo': '^1.0.0'})
- ..serve('bar', '2.0.0', deps: {'foo': '^2.0.0'}),
- );
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': '^2.0.0'})
+ ..serve('foo', '2.0.0', deps: {'bar': '^1.0.0'})
+ ..serve('bar', '1.0.0', deps: {'foo': '^1.0.0'})
+ ..serve('bar', '2.0.0', deps: {'foo': '^2.0.0'});
await d.dir(appPath, [
d.pubspec({
@@ -218,23 +215,25 @@
})
]).validate();
- await d.appPackagesFile({'foo': '1.0.0', 'bar': '1.0.0'}).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '1.0.0'),
+ ]).validate();
});
test('upgrade should not downgrade any versions', () async {
/// The version solver solves the packages with the least number of
/// versions remaining, so we add more 'bar' packages to force 'foo' to be
/// resolved first
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0', pubspec: {
'dependencies': {'bar': '1.0.0'}
- });
- builder.serve('bar', '1.0.0');
- builder.serve('bar', '2.0.0');
- builder.serve('bar', '3.0.0');
- builder.serve('bar', '4.0.0');
- });
+ })
+ ..serve('bar', '1.0.0')
+ ..serve('bar', '2.0.0')
+ ..serve('bar', '3.0.0')
+ ..serve('bar', '4.0.0');
await d.appDir({
'foo': '^1.0.0',
@@ -257,10 +256,10 @@
'bar': '^4.0.0',
}).validate();
- await d.appPackagesFile({
- 'foo': '1.0.0',
- 'bar': '4.0.0',
- }).validate();
+ await d.appPackageConfigFile([
+ d.packageConfigEntry(name: 'foo', version: '1.0.0'),
+ d.packageConfigEntry(name: 'bar', version: '4.0.0'),
+ ]).validate();
});
});
}
diff --git a/test/upgrade/upgrade_null_safety_test.dart b/test/upgrade/upgrade_null_safety_test.dart
index 9c7dad0..557c589 100644
--- a/test/upgrade/upgrade_null_safety_test.dart
+++ b/test/upgrade/upgrade_null_safety_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
import '../test_pub.dart';
@@ -11,29 +9,28 @@
void main() {
group('pub upgrade --null-safety', () {
setUp(() async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'environment': {'sdk': '>=2.10.0<3.0.0'},
- });
- builder.serve('foo', '2.0.0', pubspec: {
+ })
+ ..serve('foo', '2.0.0', pubspec: {
'environment': {'sdk': '>=2.12.0<3.0.0'},
- });
- builder.serve('bar', '1.0.0', pubspec: {
+ })
+ ..serve('bar', '1.0.0', pubspec: {
'environment': {'sdk': '>=2.9.0<3.0.0'},
- });
- builder.serve('bar', '2.0.0-nullsafety.0', pubspec: {
+ })
+ ..serve('bar', '2.0.0-nullsafety.0', pubspec: {
'environment': {'sdk': '>=2.12.0<3.0.0'},
- });
- builder.serve('baz', '1.0.0', pubspec: {
+ })
+ ..serve('baz', '1.0.0', pubspec: {
'environment': {'sdk': '>=2.9.0<3.0.0'},
- });
- builder.serve('has_conflict', '1.0.0', pubspec: {
+ })
+ ..serve('has_conflict', '1.0.0', pubspec: {
'environment': {'sdk': '>=2.9.0<3.0.0'},
- });
- builder.serve('has_conflict', '2.0.0', pubspec: {
+ })
+ ..serve('has_conflict', '2.0.0', pubspec: {
'environment': {'sdk': '>=2.13.0<3.0.0'},
});
- });
});
test('upgrades to null-safety versions', () async {
diff --git a/test/validator/changelog_test.dart b/test/validator/changelog_test.dart
index be166c3..5bef662 100644
--- a/test/validator/changelog_test.dart
+++ b/test/validator/changelog_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/validator.dart';
import 'package:pub/src/validator/changelog.dart';
diff --git a/test/validator/compiled_dartdoc_test.dart b/test/validator/compiled_dartdoc_test.dart
index a656958..f1d3d6d 100644
--- a/test/validator/compiled_dartdoc_test.dart
+++ b/test/validator/compiled_dartdoc_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/validator.dart';
import 'package:pub/src/validator/compiled_dartdoc.dart';
diff --git a/test/validator/dependency_override_test.dart b/test/validator/dependency_override_test.dart
index f459119..21a437d 100644
--- a/test/validator/dependency_override_test.dart
+++ b/test/validator/dependency_override_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/validator.dart';
import 'package:pub/src/validator/dependency_override.dart';
diff --git a/test/validator/dependency_test.dart b/test/validator/dependency_test.dart
index 00ab0c3..db9db15 100644
--- a/test/validator/dependency_test.dart
+++ b/test/validator/dependency_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:convert';
@@ -29,7 +27,7 @@
/// Sets up a test package with dependency [dep] and mocks a server with
/// [hostedVersions] of the package available.
-Future setUpDependency(Map dep, {List<String> hostedVersions}) {
+Future setUpDependency(Map dep, {List<String>? hostedVersions}) {
useMockClient(MockClient((request) {
expect(request.method, equals('GET'));
expect(request.url.path, equals('/api/packages/foo'));
diff --git a/test/validator/deprecated_fields_test.dart b/test/validator/deprecated_fields_test.dart
index a13774b..ee4551d 100644
--- a/test/validator/deprecated_fields_test.dart
+++ b/test/validator/deprecated_fields_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/validator.dart';
import 'package:pub/src/validator/deprecated_fields.dart';
diff --git a/test/validator/directory_test.dart b/test/validator/directory_test.dart
index 5a5ec99..7cc53b6 100644
--- a/test/validator/directory_test.dart
+++ b/test/validator/directory_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/validator.dart';
import 'package:pub/src/validator/directory.dart';
diff --git a/test/validator/executable_test.dart b/test/validator/executable_test.dart
index 555f768..d9973e7 100644
--- a/test/validator/executable_test.dart
+++ b/test/validator/executable_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/validator.dart';
import 'package:pub/src/validator/executable.dart';
diff --git a/test/validator/flutter_constraint_test.dart b/test/validator/flutter_constraint_test.dart
index 685c59d..b7bdf7c 100644
--- a/test/validator/flutter_constraint_test.dart
+++ b/test/validator/flutter_constraint_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
@@ -20,7 +18,7 @@
}
Future<void> setup({
- String flutterConstraint,
+ String? flutterConstraint,
}) async {
final fakeFlutterRoot =
d.dir('fake_flutter_root', [d.file('version', '1.23.0')]);
diff --git a/test/validator/flutter_plugin_format_test.dart b/test/validator/flutter_plugin_format_test.dart
index cddeaf9..0c24bda 100644
--- a/test/validator/flutter_plugin_format_test.dart
+++ b/test/validator/flutter_plugin_format_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/validator.dart';
import 'package:pub/src/validator/flutter_plugin_format.dart';
diff --git a/test/validator/gitignore_test.dart b/test/validator/gitignore_test.dart
index d6140f5..f7b02fe 100644
--- a/test/validator/gitignore_test.dart
+++ b/test/validator/gitignore_test.dart
@@ -2,20 +2,25 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
+import 'dart:io';
+import 'package:path/path.dart' as p;
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:test/test.dart';
import '../descriptor.dart' as d;
import '../test_pub.dart';
-Future<void> expectValidation(error, int exitCode) async {
+Future<void> expectValidation(
+ error,
+ int exitCode, {
+ String? workingDirectory,
+}) async {
await runPub(
error: error,
args: ['publish', '--dry-run'],
environment: {'_PUB_TEST_SDK_VERSION': '2.12.0'},
- workingDirectory: d.path(appPath),
+ workingDirectory: workingDirectory ?? d.path(appPath),
exitCode: exitCode,
);
}
@@ -46,4 +51,55 @@
]),
exit_codes.DATA);
});
+
+ test('Should also consider gitignores from above the package root', () async {
+ await d.git('reporoot', [
+ d.dir(
+ 'myapp',
+ [
+ d.file('foo.txt'),
+ ...d.validPackage.contents,
+ ],
+ ),
+ ]).create();
+ final packageRoot = p.join(d.sandbox, 'reporoot', 'myapp');
+ await pubGet(
+ environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'},
+ workingDirectory: packageRoot);
+
+ await expectValidation(contains('Package has 0 warnings.'), 0,
+ workingDirectory: packageRoot);
+
+ await d.dir('reporoot', [
+ d.file('.gitignore', '*.txt'),
+ ]).create();
+
+ await expectValidation(
+ allOf([
+ contains('Package has 1 warning.'),
+ contains('foo.txt'),
+ contains(
+ 'Consider adjusting your `.gitignore` files to not ignore those files'),
+ ]),
+ exit_codes.DATA,
+ workingDirectory: packageRoot);
+ });
+
+ test('Should not follow symlinks', () async {
+ await d.git('myapp', [
+ ...d.validPackage.contents,
+ ]).create();
+ final packageRoot = p.join(d.sandbox, 'myapp');
+ await pubGet(
+ environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'},
+ workingDirectory: packageRoot);
+
+ Link(p.join(packageRoot, '.abc', 'itself')).createSync(
+ packageRoot,
+ recursive: true,
+ );
+
+ await expectValidation(contains('Package has 0 warnings.'), 0,
+ workingDirectory: packageRoot);
+ });
}
diff --git a/test/validator/language_version_test.dart b/test/validator/language_version_test.dart
index 37431d4..39c9465 100644
--- a/test/validator/language_version_test.dart
+++ b/test/validator/language_version_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/validator.dart';
import 'package:pub/src/validator/language_version.dart';
@@ -17,7 +15,7 @@
LanguageVersionValidator(entrypoint);
Future<void> setup(
- {String sdkConstraint, String libraryLanguageVersion}) async {
+ {required String sdkConstraint, String? libraryLanguageVersion}) async {
await d.validPackage.create();
await d.dir(appPath, [
d.pubspec({
diff --git a/test/validator/leak_detection_test.dart b/test/validator/leak_detection_test.dart
index ee7d5d3..c055e59 100644
--- a/test/validator/leak_detection_test.dart
+++ b/test/validator/leak_detection_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/validator.dart';
import 'package:pub/src/validator/leak_detection.dart';
diff --git a/test/validator/license_test.dart b/test/validator/license_test.dart
index 77225b5..8717c75 100644
--- a/test/validator/license_test.dart
+++ b/test/validator/license_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/io.dart';
diff --git a/test/validator/name_test.dart b/test/validator/name_test.dart
index 5639c09..7cbb51c 100644
--- a/test/validator/name_test.dart
+++ b/test/validator/name_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/io.dart';
diff --git a/test/validator/null_safety_mixed_mode_test.dart b/test/validator/null_safety_mixed_mode_test.dart
index 6ec4746..d62d051 100644
--- a/test/validator/null_safety_mixed_mode_test.dart
+++ b/test/validator/null_safety_mixed_mode_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
@@ -20,7 +18,7 @@
}
Future<void> setup({
- String sdkConstraint,
+ required String sdkConstraint,
Map dependencies = const {},
Map devDependencies = const {},
List<d.Descriptor> extraFiles = const [],
@@ -47,14 +45,13 @@
group('should consider a package valid if it', () {
test('is not opting in to null-safety, but depends on package that is',
() async {
- await servePackages(
- (server) => server.serve(
- 'foo',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- ),
+ final server = await servePackages();
+ server.serve(
+ 'foo',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ },
);
await setup(
@@ -63,14 +60,13 @@
});
test('is opting in to null-safety and depends on package that is',
() async {
- await servePackages(
- (server) => server.serve(
- 'foo',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- ),
+ final server = await servePackages();
+ server.serve(
+ 'foo',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ },
);
await setup(
@@ -80,14 +76,13 @@
test('is opting in to null-safety has dev_dependency that is not',
() async {
- await servePackages(
- (server) => server.serve(
- 'foo',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- ),
+ final server = await servePackages();
+ server.serve(
+ 'foo',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.9.0<3.0.0'}
+ },
);
await setup(sdkConstraint: '>=2.12.0 <3.0.0', devDependencies: {
@@ -100,14 +95,13 @@
group('should consider a package invalid if it', () {
test('is opting in to null-safety, but depends on package that is not',
() async {
- await servePackages(
- (server) => server.serve(
- 'foo',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- ),
+ final server = await servePackages();
+ server.serve(
+ 'foo',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.9.0<3.0.0'}
+ },
);
await setup(
@@ -136,17 +130,16 @@
test(
'is opting in to null-safety, but depends on package has file opting out',
() async {
- await servePackages(
- (server) => server.serve('foo', '0.0.1', pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- }, contents: [
- d.dir('lib', [
- d.file('foo.dart', '''
+ final server = await servePackages();
+ server.serve('foo', '0.0.1', pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ }, contents: [
+ d.dir('lib', [
+ d.file('foo.dart', '''
// @dart = 2.9
''')
- ])
- ]),
- );
+ ])
+ ]);
await setup(
sdkConstraint: '>=2.12.0 <3.0.0', dependencies: {'foo': '^0.0.1'});
diff --git a/test/validator/pubspec_field_test.dart b/test/validator/pubspec_field_test.dart
index 7d4dbd7..8e6fefc 100644
--- a/test/validator/pubspec_field_test.dart
+++ b/test/validator/pubspec_field_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/validator.dart';
import 'package:pub/src/validator/pubspec_field.dart';
@@ -57,7 +55,7 @@
test('has executables', () async {
var pkg = packageMap('test_pkg', '1.0.0');
- pkg['executables'] = <String, String>{
+ pkg['executables'] = <String, String?>{
'test_pkg': null,
'test_pkg_helper': 'helper',
};
diff --git a/test/validator/pubspec_test.dart b/test/validator/pubspec_test.dart
index 0d964ce..9942220 100644
--- a/test/validator/pubspec_test.dart
+++ b/test/validator/pubspec_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/validator/pubspec.dart';
import 'package:test/test.dart';
diff --git a/test/validator/pubspec_typo_test.dart b/test/validator/pubspec_typo_test.dart
index efc731b..ab2a547 100644
--- a/test/validator/pubspec_typo_test.dart
+++ b/test/validator/pubspec_typo_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/validator.dart';
import 'package:pub/src/validator/pubspec_typo.dart';
diff --git a/test/validator/readme_test.dart b/test/validator/readme_test.dart
index 132ff6c..6519c6f 100644
--- a/test/validator/readme_test.dart
+++ b/test/validator/readme_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as p;
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/io.dart';
diff --git a/test/validator/relative_version_numbering_test.dart b/test/validator/relative_version_numbering_test.dart
index 0a9a1f7..2f3da5c 100644
--- a/test/validator/relative_version_numbering_test.dart
+++ b/test/validator/relative_version_numbering_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/validator.dart';
import 'package:pub/src/validator/relative_version_numbering.dart';
@@ -15,10 +13,10 @@
Validator validator(Entrypoint entrypoint) => RelativeVersionNumberingValidator(
entrypoint,
- Uri.parse(globalPackageServer.url),
+ Uri.parse(globalServer.url),
);
-Future<void> setup({String sdkConstraint}) async {
+Future<void> setup({required String sdkConstraint}) async {
await d.validPackage.create();
await d.dir(appPath, [
d.pubspec({
@@ -35,14 +33,13 @@
group('should consider a package valid if it', () {
test('is not opting in to null-safety with previous non-null-safe version',
() async {
- await servePackages(
- (server) => server.serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- ),
+ final server = await servePackages();
+ server.serve(
+ 'test_pkg',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.9.0<3.0.0'}
+ },
);
await setup(sdkConstraint: '>=2.9.0 <3.0.0');
@@ -52,23 +49,21 @@
test(
'is not opting in to null-safety with previous non-null-safe version. '
'Even with a later null-safe version', () async {
- await servePackages(
- (server) => server
- ..serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- )
- ..serve(
- 'test_pkg',
- '2.0.0',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- ),
- );
+ await servePackages()
+ ..serve(
+ 'test_pkg',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.9.0<3.0.0'}
+ },
+ )
+ ..serve(
+ 'test_pkg',
+ '2.0.0',
+ pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ },
+ );
await setup(sdkConstraint: '>=2.9.0 <3.0.0');
await expectValidation(validator);
@@ -76,14 +71,13 @@
test('is opting in to null-safety with previous null-safe version',
() async {
- await servePackages(
- (server) => server.serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- ),
+ final server = await servePackages();
+ server.serve(
+ 'test_pkg',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ },
);
await setup(sdkConstraint: '>=2.12.0 <3.0.0');
@@ -93,14 +87,13 @@
test(
'is opting in to null-safety using a pre-release of 2.12.0 '
'with previous null-safe version', () async {
- await servePackages(
- (server) => server.serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- ),
+ final server = await servePackages();
+ server.serve(
+ 'test_pkg',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ },
);
await setup(sdkConstraint: '>=2.12.0-dev <3.0.0');
@@ -110,23 +103,21 @@
test(
'is opting in to null-safety with previous null-safe version. '
'Even with a later non-null-safe version', () async {
- await servePackages(
- (server) => server
- ..serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- )
- ..serve(
- 'test_pkg',
- '2.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- ),
- );
+ await servePackages()
+ ..serve(
+ 'test_pkg',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ },
+ )
+ ..serve(
+ 'test_pkg',
+ '2.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.9.0<3.0.0'}
+ },
+ );
await setup(sdkConstraint: '>=2.12.0 <3.0.0');
await expectValidation(validator);
@@ -134,13 +125,13 @@
test('is opting in to null-safety with no existing versions', () async {
await setup(sdkConstraint: '>=2.12.0 <3.0.0');
- await servePackages((x) => x);
+ await servePackages();
await expectValidation(validator);
});
test('is not opting in to null-safety with no existing versions', () async {
await setup(sdkConstraint: '>=2.9.0 <3.0.0');
- await servePackages((x) => x);
+ await servePackages();
await expectValidation(validator);
});
@@ -148,23 +139,21 @@
test(
'is not opting in to null-safety with previous null-safe stable version. '
'With an in-between not null-safe prerelease', () async {
- await servePackages(
- (server) => server
- ..serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- )
- ..serve(
- 'test_pkg',
- '0.0.2-dev',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- ),
- );
+ await servePackages()
+ ..serve(
+ 'test_pkg',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ },
+ )
+ ..serve(
+ 'test_pkg',
+ '0.0.2-dev',
+ pubspec: {
+ 'environment': {'sdk': '>=2.9.0<3.0.0'}
+ },
+ );
await setup(sdkConstraint: '>=2.9.0 <3.0.0');
await expectValidation(validator);
@@ -173,23 +162,21 @@
test(
'opts in to null-safety, with previous stable version not-null-safe. '
'With an in-between non-null-safe prerelease', () async {
- await servePackages(
- (server) => server
- ..serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- )
- ..serve(
- 'test_pkg',
- '0.0.2-dev',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- ),
- );
+ await servePackages()
+ ..serve(
+ 'test_pkg',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.9.0<3.0.0'}
+ },
+ )
+ ..serve(
+ 'test_pkg',
+ '0.0.2-dev',
+ pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ },
+ );
await setup(sdkConstraint: '>=2.12.0 <3.0.0');
await expectValidation(validator);
@@ -199,14 +186,13 @@
group('should warn if ', () {
test('opts in to null-safety, with previous version not-null-safe',
() async {
- await servePackages(
- (server) => server.serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- ),
+ final server = await servePackages();
+ server.serve(
+ 'test_pkg',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.9.0<3.0.0'}
+ },
);
await setup(sdkConstraint: '>=2.12.0 <3.0.0');
@@ -217,14 +203,13 @@
'is not opting in to null-safety with no existing stable versions. '
'With a previous in-between null-safe prerelease', () async {
await setup(sdkConstraint: '>=2.9.0 <3.0.0');
- await servePackages(
- (server) => server.serve(
- 'test_pkg',
- '0.0.2-dev',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- ),
+ final server = await servePackages();
+ server.serve(
+ 'test_pkg',
+ '0.0.2-dev',
+ pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ },
);
await expectValidation(validator, hints: isNotEmpty);
@@ -232,23 +217,21 @@
test(
'is not opting in to null-safety with previous non-null-safe stable version. '
'With an in-between null-safe prerelease', () async {
- await servePackages(
- (server) => server
- ..serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- )
- ..serve(
- 'test_pkg',
- '0.0.2-dev',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- ),
- );
+ await servePackages()
+ ..serve(
+ 'test_pkg',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.9.0<3.0.0'}
+ },
+ )
+ ..serve(
+ 'test_pkg',
+ '0.0.2-dev',
+ pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ },
+ );
await setup(sdkConstraint: '>=2.9.0 <3.0.0');
await expectValidation(validator, hints: isNotEmpty);
@@ -257,23 +240,21 @@
test(
'opts in to null-safety, with previous version not-null-safe. '
'Even with a later null-safe version', () async {
- await servePackages(
- (server) => server
- ..serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- )
- ..serve(
- 'test_pkg',
- '2.0.0',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- ),
- );
+ await servePackages()
+ ..serve(
+ 'test_pkg',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.9.0<3.0.0'}
+ },
+ )
+ ..serve(
+ 'test_pkg',
+ '2.0.0',
+ pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ },
+ );
await setup(sdkConstraint: '>=2.12.0 <3.0.0');
await expectValidation(validator, hints: isNotEmpty);
@@ -281,14 +262,13 @@
test('is not opting in to null-safety with previous null-safe version',
() async {
- await servePackages(
- (server) => server.serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- ),
+ final server = await servePackages();
+ server.serve(
+ 'test_pkg',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ },
);
await setup(sdkConstraint: '>=2.9.0 <3.0.0');
@@ -298,23 +278,21 @@
test(
'is not opting in to null-safety with previous null-safe version. '
'Even with a later non-null-safe version', () async {
- await servePackages(
- (server) => server
- ..serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- )
- ..serve(
- 'test_pkg',
- '2.0.0',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- ),
- );
+ await servePackages()
+ ..serve(
+ 'test_pkg',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ },
+ )
+ ..serve(
+ 'test_pkg',
+ '2.0.0',
+ pubspec: {
+ 'environment': {'sdk': '>=2.9.0<3.0.0'}
+ },
+ );
await setup(sdkConstraint: '>=2.9.0 <3.0.0');
await expectValidation(validator, hints: isNotEmpty);
@@ -323,23 +301,21 @@
test(
'is opting in to null-safety with previous null-safe stable version. '
'with an in-between non-null-safe prerelease', () async {
- await servePackages(
- (server) => server
- ..serve(
- 'test_pkg',
- '0.0.1',
- pubspec: {
- 'environment': {'sdk': '>=2.12.0<3.0.0'}
- },
- )
- ..serve(
- 'test_pkg',
- '0.0.2-dev',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- ),
- );
+ await servePackages()
+ ..serve(
+ 'test_pkg',
+ '0.0.1',
+ pubspec: {
+ 'environment': {'sdk': '>=2.12.0<3.0.0'}
+ },
+ )
+ ..serve(
+ 'test_pkg',
+ '0.0.2-dev',
+ pubspec: {
+ 'environment': {'sdk': '>=2.9.0<3.0.0'}
+ },
+ );
await setup(sdkConstraint: '>=2.12.0 <3.0.0');
await expectValidation(validator, hints: isNotEmpty);
@@ -349,14 +325,13 @@
'is opting in to null-safety with no existing stable versions. '
'With a previous non-null-safe prerelease', () async {
await setup(sdkConstraint: '>=2.12.0 <3.0.0');
- await servePackages(
- (server) => server.serve(
- 'test_pkg',
- '0.0.2-dev',
- pubspec: {
- 'environment': {'sdk': '>=2.9.0<3.0.0'}
- },
- ),
+ final server = await servePackages();
+ server.serve(
+ 'test_pkg',
+ '0.0.2-dev',
+ pubspec: {
+ 'environment': {'sdk': '>=2.9.0<3.0.0'}
+ },
);
await expectValidation(validator, hints: isNotEmpty);
});
diff --git a/test/validator/sdk_constraint_test.dart b/test/validator/sdk_constraint_test.dart
index 1310d17..c24adf2 100644
--- a/test/validator/sdk_constraint_test.dart
+++ b/test/validator/sdk_constraint_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/validator.dart';
import 'package:pub/src/validator/sdk_constraint.dart';
diff --git a/test/validator/size_test.dart b/test/validator/size_test.dart
index 37a746d..3a22e60 100644
--- a/test/validator/size_test.dart
+++ b/test/validator/size_test.dart
@@ -2,10 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
-import 'dart:math' as math;
import 'package:pub/src/validator/size.dart';
import 'package:test/test.dart';
@@ -20,7 +17,7 @@
Future<void> expectSizeValidationError(Matcher matcher) async {
await expectValidation(
- size(100 * math.pow(2, 20) + 1),
+ size(100 * 1048577 /*2^20 +1*/),
errors: contains(matcher),
);
}
@@ -30,7 +27,7 @@
await d.validPackage.create();
await expectValidation(size(100));
- await expectValidation(size(100 * math.pow(2, 20)));
+ await expectValidation(size(100 * 1048576 /*2^20*/));
});
group('considers a package invalid if it is more than 100 MB', () {
diff --git a/test/validator/strict_dependencies_test.dart b/test/validator/strict_dependencies_test.dart
index 0456413..7b7962a 100644
--- a/test/validator/strict_dependencies_test.dart
+++ b/test/validator/strict_dependencies_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:path/path.dart' as path;
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/validator.dart';
@@ -67,8 +65,8 @@
for (var port in ['import', 'export']) {
for (var isDev in [false, true]) {
- Map<String, String> deps;
- Map<String, String> devDeps;
+ Map<String, String>? deps;
+ Map<String, String>? devDeps;
if (isDev) {
devDeps = {'silly_monkey': '^1.2.3'};
diff --git a/test/validator/utils.dart b/test/validator/utils.dart
index 7eda0fd..5123683 100644
--- a/test/validator/utils.dart
+++ b/test/validator/utils.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'package:test/test.dart';
import '../test_pub.dart';
diff --git a/test/version_solver_test.dart b/test/version_solver_test.dart
index d9ea6a0..d36a16f 100644
--- a/test/version_solver_test.dart
+++ b/test/version_solver_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
import 'dart:async';
import 'dart:io';
@@ -31,6 +29,8 @@
group('override', override);
group('downgrade', downgrade);
group('features', features, skip: true);
+
+ group('regressions', regressions);
}
void basicGraph() {
@@ -40,14 +40,13 @@
});
test('simple dependency tree', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0', deps: {'aa': '1.0.0', 'ab': '1.0.0'});
- builder.serve('aa', '1.0.0');
- builder.serve('ab', '1.0.0');
- builder.serve('b', '1.0.0', deps: {'ba': '1.0.0', 'bb': '1.0.0'});
- builder.serve('ba', '1.0.0');
- builder.serve('bb', '1.0.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0', deps: {'aa': '1.0.0', 'ab': '1.0.0'})
+ ..serve('aa', '1.0.0')
+ ..serve('ab', '1.0.0')
+ ..serve('b', '1.0.0', deps: {'ba': '1.0.0', 'bb': '1.0.0'})
+ ..serve('ba', '1.0.0')
+ ..serve('bb', '1.0.0');
await d.appDir({'a': '1.0.0', 'b': '1.0.0'}).create();
await expectResolves(result: {
@@ -61,15 +60,14 @@
});
test('shared dependency with overlapping constraints', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0', deps: {'shared': '>=2.0.0 <4.0.0'});
- builder.serve('b', '1.0.0', deps: {'shared': '>=3.0.0 <5.0.0'});
- builder.serve('shared', '2.0.0');
- builder.serve('shared', '3.0.0');
- builder.serve('shared', '3.6.9');
- builder.serve('shared', '4.0.0');
- builder.serve('shared', '5.0.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0', deps: {'shared': '>=2.0.0 <4.0.0'})
+ ..serve('b', '1.0.0', deps: {'shared': '>=3.0.0 <5.0.0'})
+ ..serve('shared', '2.0.0')
+ ..serve('shared', '3.0.0')
+ ..serve('shared', '3.6.9')
+ ..serve('shared', '4.0.0')
+ ..serve('shared', '5.0.0');
await d.appDir({'a': '1.0.0', 'b': '1.0.0'}).create();
await expectResolves(
@@ -79,16 +77,15 @@
test(
'shared dependency where dependent version in turn affects other '
'dependencies', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '1.0.1', deps: {'bang': '1.0.0'});
- builder.serve('foo', '1.0.2', deps: {'whoop': '1.0.0'});
- builder.serve('foo', '1.0.3', deps: {'zoop': '1.0.0'});
- builder.serve('bar', '1.0.0', deps: {'foo': '<=1.0.1'});
- builder.serve('bang', '1.0.0');
- builder.serve('whoop', '1.0.0');
- builder.serve('zoop', '1.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '1.0.1', deps: {'bang': '1.0.0'})
+ ..serve('foo', '1.0.2', deps: {'whoop': '1.0.0'})
+ ..serve('foo', '1.0.3', deps: {'zoop': '1.0.0'})
+ ..serve('bar', '1.0.0', deps: {'foo': '<=1.0.1'})
+ ..serve('bang', '1.0.0')
+ ..serve('whoop', '1.0.0')
+ ..serve('zoop', '1.0.0');
await d.appDir({'foo': '<=1.0.2', 'bar': '1.0.0'}).create();
await expectResolves(
@@ -96,23 +93,21 @@
});
test('circular dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
- builder.serve('bar', '1.0.0', deps: {'foo': '1.0.0'});
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+ ..serve('bar', '1.0.0', deps: {'foo': '1.0.0'});
await d.appDir({'foo': '1.0.0'}).create();
await expectResolves(result: {'foo': '1.0.0', 'bar': '1.0.0'});
});
test('removed dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- builder.serve('bar', '1.0.0');
- builder.serve('bar', '2.0.0', deps: {'baz': '1.0.0'});
- builder.serve('baz', '1.0.0', deps: {'foo': '2.0.0'});
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0')
+ ..serve('bar', '1.0.0')
+ ..serve('bar', '2.0.0', deps: {'baz': '1.0.0'})
+ ..serve('baz', '1.0.0', deps: {'foo': '2.0.0'});
await d.appDir({'foo': '1.0.0', 'bar': 'any'}).create();
await expectResolves(result: {'foo': '1.0.0', 'bar': '1.0.0'}, tries: 2);
@@ -121,14 +116,13 @@
void withLockFile() {
test('with compatible locked dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
- builder.serve('foo', '1.0.1', deps: {'bar': '1.0.1'});
- builder.serve('foo', '1.0.2', deps: {'bar': '1.0.2'});
- builder.serve('bar', '1.0.0');
- builder.serve('bar', '1.0.1');
- builder.serve('bar', '1.0.2');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+ ..serve('foo', '1.0.1', deps: {'bar': '1.0.1'})
+ ..serve('foo', '1.0.2', deps: {'bar': '1.0.2'})
+ ..serve('bar', '1.0.0')
+ ..serve('bar', '1.0.1')
+ ..serve('bar', '1.0.2');
await d.appDir({'foo': '1.0.1'}).create();
await expectResolves(result: {'foo': '1.0.1', 'bar': '1.0.1'});
@@ -138,14 +132,13 @@
});
test('with incompatible locked dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
- builder.serve('foo', '1.0.1', deps: {'bar': '1.0.1'});
- builder.serve('foo', '1.0.2', deps: {'bar': '1.0.2'});
- builder.serve('bar', '1.0.0');
- builder.serve('bar', '1.0.1');
- builder.serve('bar', '1.0.2');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+ ..serve('foo', '1.0.1', deps: {'bar': '1.0.1'})
+ ..serve('foo', '1.0.2', deps: {'bar': '1.0.2'})
+ ..serve('bar', '1.0.0')
+ ..serve('bar', '1.0.1')
+ ..serve('bar', '1.0.2');
await d.appDir({'foo': '1.0.1'}).create();
await expectResolves(result: {'foo': '1.0.1', 'bar': '1.0.1'});
@@ -155,15 +148,14 @@
});
test('with unrelated locked dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
- builder.serve('foo', '1.0.1', deps: {'bar': '1.0.1'});
- builder.serve('foo', '1.0.2', deps: {'bar': '1.0.2'});
- builder.serve('bar', '1.0.0');
- builder.serve('bar', '1.0.1');
- builder.serve('bar', '1.0.2');
- builder.serve('baz', '1.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+ ..serve('foo', '1.0.1', deps: {'bar': '1.0.1'})
+ ..serve('foo', '1.0.2', deps: {'bar': '1.0.2'})
+ ..serve('bar', '1.0.0')
+ ..serve('bar', '1.0.1')
+ ..serve('bar', '1.0.2')
+ ..serve('baz', '1.0.0');
await d.appDir({'baz': '1.0.0'}).create();
await expectResolves(result: {'baz': '1.0.0'});
@@ -175,17 +167,16 @@
test(
'unlocks dependencies if necessary to ensure that a new '
'dependency is satisfied', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': '<2.0.0'});
- builder.serve('bar', '1.0.0', deps: {'baz': '<2.0.0'});
- builder.serve('baz', '1.0.0', deps: {'qux': '<2.0.0'});
- builder.serve('qux', '1.0.0');
- builder.serve('foo', '2.0.0', deps: {'bar': '<3.0.0'});
- builder.serve('bar', '2.0.0', deps: {'baz': '<3.0.0'});
- builder.serve('baz', '2.0.0', deps: {'qux': '<3.0.0'});
- builder.serve('qux', '2.0.0');
- builder.serve('newdep', '2.0.0', deps: {'baz': '>=1.5.0'});
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': '<2.0.0'})
+ ..serve('bar', '1.0.0', deps: {'baz': '<2.0.0'})
+ ..serve('baz', '1.0.0', deps: {'qux': '<2.0.0'})
+ ..serve('qux', '1.0.0')
+ ..serve('foo', '2.0.0', deps: {'bar': '<3.0.0'})
+ ..serve('bar', '2.0.0', deps: {'baz': '<3.0.0'})
+ ..serve('baz', '2.0.0', deps: {'qux': '<3.0.0'})
+ ..serve('qux', '2.0.0')
+ ..serve('newdep', '2.0.0', deps: {'baz': '>=1.5.0'});
await d.appDir({'foo': '1.0.0'}).create();
await expectResolves(result: {
@@ -209,11 +200,10 @@
test(
"produces a nice message for a locked dependency that's the only "
'version of its package', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': '>=2.0.0'});
- builder.serve('bar', '1.0.0');
- builder.serve('bar', '2.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': '>=2.0.0'})
+ ..serve('bar', '1.0.0')
+ ..serve('bar', '2.0.0');
await d.appDir({'foo': 'any'}).create();
await expectResolves(result: {'foo': '1.0.0', 'bar': '2.0.0'});
@@ -229,30 +219,27 @@
void rootDependency() {
test('with root source', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'myapp': 'any'});
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', deps: {'myapp': 'any'});
await d.appDir({'foo': '1.0.0'}).create();
await expectResolves(result: {'foo': '1.0.0'});
});
test('with mismatched sources', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'myapp': 'any'});
- builder.serve('bar', '1.0.0', deps: {
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'myapp': 'any'})
+ ..serve('bar', '1.0.0', deps: {
'myapp': {'git': 'http://nowhere.com/'}
});
- });
await d.appDir({'foo': '1.0.0', 'bar': '1.0.0'}).create();
await expectResolves(result: {'foo': '1.0.0', 'bar': '1.0.0'});
});
test('with wrong version', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'myapp': '>0.0.0'});
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', deps: {'myapp': '>0.0.0'});
await d.appDir({'foo': '1.0.0'}).create();
await expectResolves(error: equalsIgnoringWhitespace('''
@@ -265,10 +252,9 @@
void devDependency() {
test("includes root package's dev dependencies", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('bar', '1.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('bar', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -281,10 +267,9 @@
});
test("includes dev dependency's transitive dependencies", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
- builder.serve('bar', '1.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+ ..serve('bar', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -297,10 +282,9 @@
});
test("ignores transitive dependency's dev dependencies", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'dev_dependencies': {'bar': '1.0.0'}
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'dev_dependencies': {'bar': '1.0.0'}
});
await d.appDir({'foo': '1.0.0'}).create();
@@ -309,11 +293,10 @@
group('with both a dev and regular dependency', () {
test('succeeds when both are satisfied', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- builder.serve('foo', '3.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0')
+ ..serve('foo', '3.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -327,9 +310,8 @@
});
test("fails when main dependency isn't satisfied", () async {
- await servePackages((builder) {
- builder.serve('foo', '3.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '3.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -347,9 +329,8 @@
});
test("fails when dev dependency isn't satisfied", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -367,9 +348,8 @@
});
test('fails when dev and main constraints are incompatible', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -386,9 +366,8 @@
});
test('fails when dev and main sources are incompatible', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -407,9 +386,8 @@
});
test('fails when dev and main descriptions are incompatible', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -433,10 +411,9 @@
void unsolvable() {
test('no version that matches constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '2.0.0');
- builder.serve('foo', '2.1.3');
- });
+ await servePackages()
+ ..serve('foo', '2.0.0')
+ ..serve('foo', '2.1.3');
await d.appDir({'foo': '>=1.0.0 <2.0.0'}).create();
await expectResolves(error: equalsIgnoringWhitespace("""
@@ -446,12 +423,11 @@
});
test('no version that matches combined constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'shared': '>=2.0.0 <3.0.0'});
- builder.serve('bar', '1.0.0', deps: {'shared': '>=2.9.0 <4.0.0'});
- builder.serve('shared', '2.5.0');
- builder.serve('shared', '3.5.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'shared': '>=2.0.0 <3.0.0'})
+ ..serve('bar', '1.0.0', deps: {'shared': '>=2.9.0 <4.0.0'})
+ ..serve('shared', '2.5.0')
+ ..serve('shared', '3.5.0');
await d.appDir({'foo': '1.0.0', 'bar': '1.0.0'}).create();
await expectResolves(error: equalsIgnoringWhitespace('''
@@ -466,12 +442,11 @@
});
test('disjoint constraints', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'shared': '<=2.0.0'});
- builder.serve('bar', '1.0.0', deps: {'shared': '>3.0.0'});
- builder.serve('shared', '2.0.0');
- builder.serve('shared', '4.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'shared': '<=2.0.0'})
+ ..serve('bar', '1.0.0', deps: {'shared': '>3.0.0'})
+ ..serve('shared', '2.0.0')
+ ..serve('shared', '4.0.0');
await d.appDir({'foo': '1.0.0', 'bar': '1.0.0'}).create();
await expectResolves(error: equalsIgnoringWhitespace('''
@@ -483,20 +458,18 @@
});
test('mismatched descriptions', () async {
- var otherServer = await PackageServer.start((builder) {
- builder.serve('shared', '1.0.0');
- });
+ var otherServer = await startPackageServer();
+ otherServer.serve('shared', '1.0.0');
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'shared': '1.0.0'});
- builder.serve('bar', '1.0.0', deps: {
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'shared': '1.0.0'})
+ ..serve('bar', '1.0.0', deps: {
'shared': {
'hosted': {'name': 'shared', 'url': otherServer.url},
'version': '1.0.0'
}
- });
- builder.serve('shared', '1.0.0');
- });
+ })
+ ..serve('shared', '1.0.0');
await d.appDir({'foo': '1.0.0', 'bar': '1.0.0'}).create();
@@ -515,13 +488,12 @@
test('mismatched sources', () async {
await d.dir('shared', [d.libPubspec('shared', '1.0.0')]).create();
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'shared': '1.0.0'});
- builder.serve('bar', '1.0.0', deps: {
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'shared': '1.0.0'})
+ ..serve('bar', '1.0.0', deps: {
'shared': {'path': p.join(d.sandbox, 'shared')}
- });
- builder.serve('shared', '1.0.0');
- });
+ })
+ ..serve('shared', '1.0.0');
await d.appDir({'foo': '1.0.0', 'bar': '1.0.0'}).create();
await expectResolves(error: equalsIgnoringWhitespace('''
@@ -534,12 +506,11 @@
});
test('no valid solution', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0', deps: {'b': '1.0.0'});
- builder.serve('a', '2.0.0', deps: {'b': '2.0.0'});
- builder.serve('b', '1.0.0', deps: {'a': '2.0.0'});
- builder.serve('b', '2.0.0', deps: {'a': '1.0.0'});
- });
+ await servePackages()
+ ..serve('a', '1.0.0', deps: {'b': '1.0.0'})
+ ..serve('a', '2.0.0', deps: {'b': '2.0.0'})
+ ..serve('b', '1.0.0', deps: {'a': '2.0.0'})
+ ..serve('b', '2.0.0', deps: {'a': '1.0.0'});
await d.appDir({'a': 'any', 'b': 'any'}).create();
await expectResolves(error: equalsIgnoringWhitespace('''
@@ -554,10 +525,9 @@
// This is a regression test for #15550.
test('no version that matches while backtracking', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('b', '1.0.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('b', '1.0.0');
await d.appDir({'a': 'any', 'b': '>1.0.0'}).create();
await expectResolves(error: equalsIgnoringWhitespace("""
@@ -568,19 +538,18 @@
// This is a regression test for #18300.
test('issue 18300', () async {
- await servePackages((builder) {
- builder.serve('analyzer', '0.12.2');
- builder.serve('angular', '0.10.0',
- deps: {'di': '>=0.0.32 <0.1.0', 'collection': '>=0.9.1 <1.0.0'});
- builder.serve('angular', '0.9.11',
- deps: {'di': '>=0.0.32 <0.1.0', 'collection': '>=0.9.1 <1.0.0'});
- builder.serve('angular', '0.9.10',
- deps: {'di': '>=0.0.32 <0.1.0', 'collection': '>=0.9.1 <1.0.0'});
- builder.serve('collection', '0.9.0');
- builder.serve('collection', '0.9.1');
- builder.serve('di', '0.0.37', deps: {'analyzer': '>=0.13.0 <0.14.0'});
- builder.serve('di', '0.0.36', deps: {'analyzer': '>=0.13.0 <0.14.0'});
- });
+ await servePackages()
+ ..serve('analyzer', '0.12.2')
+ ..serve('angular', '0.10.0',
+ deps: {'di': '>=0.0.32 <0.1.0', 'collection': '>=0.9.1 <1.0.0'})
+ ..serve('angular', '0.9.11',
+ deps: {'di': '>=0.0.32 <0.1.0', 'collection': '>=0.9.1 <1.0.0'})
+ ..serve('angular', '0.9.10',
+ deps: {'di': '>=0.0.32 <0.1.0', 'collection': '>=0.9.1 <1.0.0'})
+ ..serve('collection', '0.9.0')
+ ..serve('collection', '0.9.1')
+ ..serve('di', '0.0.37', deps: {'analyzer': '>=0.13.0 <0.14.0'})
+ ..serve('di', '0.0.36', deps: {'analyzer': '>=0.13.0 <0.14.0'});
await d.appDir({'angular': 'any', 'collection': 'any'}).create();
await expectResolves(error: equalsIgnoringWhitespace('''
@@ -620,42 +589,40 @@
});
test('fail if all versions have bad source in dep', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {
'bar': {'bad': 'any'}
- });
- builder.serve('foo', '1.0.1', deps: {
+ })
+ ..serve('foo', '1.0.1', deps: {
'baz': {'bad': 'any'}
- });
- builder.serve('foo', '1.0.2', deps: {
+ })
+ ..serve('foo', '1.0.2', deps: {
'bang': {'bad': 'any'}
});
- });
await d.appDir({'foo': 'any'}).create();
await expectResolves(error: equalsIgnoringWhitespace('''
Because foo <1.0.1 depends on bar from unknown source "bad", foo <1.0.1 is
forbidden.
- And because foo >=1.0.1 <1.0.2 depends on baz any from bad, foo <1.0.2
- requires baz any from bad.
+ And because foo >=1.0.1 <1.0.2 depends on baz from bad, foo <1.0.2
+ requires baz from bad.
And because baz comes from unknown source "bad" and foo >=1.0.2 depends on
- bang any from bad, every version of foo requires bang any from bad.
- So, because bang comes from unknown source "bad" and myapp depends on foo
- any, version solving failed.
+ bang from bad, every version of foo requires bang from bad.
+ So, because bang comes from unknown source "bad" and myapp depends on foo any,
+ version solving failed.
'''), tries: 3);
});
test('ignore versions with bad source in dep', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': 'any'});
- builder.serve('foo', '1.0.1', deps: {
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': 'any'})
+ ..serve('foo', '1.0.1', deps: {
'bar': {'bad': 'any'}
- });
- builder.serve('foo', '1.0.2', deps: {
+ })
+ ..serve('foo', '1.0.2', deps: {
'bar': {'bad': 'any'}
- });
- builder.serve('bar', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0');
await d.appDir({'foo': 'any'}).create();
await expectResolves(result: {'foo': '1.0.0', 'bar': '1.0.0'}, tries: 2);
@@ -663,11 +630,10 @@
// Issue 1853
test('reports a nice error across a collapsed cause', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': 'any'});
- builder.serve('bar', '1.0.0', deps: {'baz': 'any'});
- builder.serve('baz', '1.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': 'any'})
+ ..serve('bar', '1.0.0', deps: {'baz': 'any'})
+ ..serve('baz', '1.0.0');
await d.dir('baz', [d.libPubspec('baz', '1.0.0')]).create();
await d.appDir({
@@ -685,28 +651,24 @@
void backtracking() {
test('circular dependency on older version', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('a', '2.0.0', deps: {'b': '1.0.0'});
- builder.serve('b', '1.0.0', deps: {'a': '1.0.0'});
- });
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('a', '2.0.0', deps: {'b': '1.0.0'})
+ ..serve('b', '1.0.0', deps: {'a': '1.0.0'});
await d.appDir({'a': '>=1.0.0'}).create();
await expectResolves(result: {'a': '1.0.0'}, tries: 2);
});
test('diamond dependency graph', () async {
- await servePackages((builder) {
- builder.serve('a', '2.0.0', deps: {'c': '^1.0.0'});
- builder.serve('a', '1.0.0');
-
- builder.serve('b', '2.0.0', deps: {'c': '^3.0.0'});
- builder.serve('b', '1.0.0', deps: {'c': '^2.0.0'});
-
- builder.serve('c', '3.0.0');
- builder.serve('c', '2.0.0');
- builder.serve('c', '1.0.0');
- });
+ await servePackages()
+ ..serve('a', '2.0.0', deps: {'c': '^1.0.0'})
+ ..serve('a', '1.0.0')
+ ..serve('b', '2.0.0', deps: {'c': '^3.0.0'})
+ ..serve('b', '1.0.0', deps: {'c': '^2.0.0'})
+ ..serve('c', '3.0.0')
+ ..serve('c', '2.0.0')
+ ..serve('c', '1.0.0');
await d.appDir({'a': 'any', 'b': 'any'}).create();
await expectResolves(result: {'a': '1.0.0', 'b': '2.0.0', 'c': '3.0.0'});
@@ -716,20 +678,16 @@
// requirement only exists because of both a and b. The solver should be able
// to deduce c 2.0.0's incompatibility and select c 1.0.0 instead.
test('backjumps after a partial satisfier', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0', deps: {'x': '>=1.0.0'});
- builder.serve('b', '1.0.0', deps: {'x': '<2.0.0'});
-
- builder.serve('c', '1.0.0');
- builder.serve('c', '2.0.0', deps: {'a': 'any', 'b': 'any'});
-
- builder.serve('x', '0.0.0');
- builder.serve('x', '1.0.0', deps: {'y': '1.0.0'});
- builder.serve('x', '2.0.0');
-
- builder.serve('y', '1.0.0');
- builder.serve('y', '2.0.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0', deps: {'x': '>=1.0.0'})
+ ..serve('b', '1.0.0', deps: {'x': '<2.0.0'})
+ ..serve('c', '1.0.0')
+ ..serve('c', '2.0.0', deps: {'a': 'any', 'b': 'any'})
+ ..serve('x', '0.0.0')
+ ..serve('x', '1.0.0', deps: {'y': '1.0.0'})
+ ..serve('x', '2.0.0')
+ ..serve('y', '1.0.0')
+ ..serve('y', '2.0.0');
await d.appDir({'c': 'any', 'y': '^2.0.0'}).create();
await expectResolves(result: {'c': '1.0.0', 'y': '2.0.0'}, tries: 2);
@@ -738,16 +696,15 @@
// This matches the Branching Error Reporting example in the version solver
// documentation, and tests that we display line numbers correctly.
test('branching error reporting', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'a': '^1.0.0', 'b': '^1.0.0'});
- builder.serve('foo', '1.1.0', deps: {'x': '^1.0.0', 'y': '^1.0.0'});
- builder.serve('a', '1.0.0', deps: {'b': '^2.0.0'});
- builder.serve('b', '1.0.0');
- builder.serve('b', '2.0.0');
- builder.serve('x', '1.0.0', deps: {'y': '^2.0.0'});
- builder.serve('y', '1.0.0');
- builder.serve('y', '2.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'a': '^1.0.0', 'b': '^1.0.0'})
+ ..serve('foo', '1.1.0', deps: {'x': '^1.0.0', 'y': '^1.0.0'})
+ ..serve('a', '1.0.0', deps: {'b': '^2.0.0'})
+ ..serve('b', '1.0.0')
+ ..serve('b', '2.0.0')
+ ..serve('x', '1.0.0', deps: {'y': '^2.0.0'})
+ ..serve('y', '1.0.0')
+ ..serve('y', '2.0.0');
await d.appDir({'foo': '^1.0.0'}).create();
await expectResolves(
@@ -772,14 +729,13 @@
// will resolve the problem. This test validates that b, which is farther
// in the dependency graph from myapp is downgraded first.
test('rolls back leaf versions first', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0', deps: {'b': 'any'});
- builder.serve('a', '2.0.0', deps: {'b': 'any', 'c': '2.0.0'});
- builder.serve('b', '1.0.0');
- builder.serve('b', '2.0.0', deps: {'c': '1.0.0'});
- builder.serve('c', '1.0.0');
- builder.serve('c', '2.0.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0', deps: {'b': 'any'})
+ ..serve('a', '2.0.0', deps: {'b': 'any', 'c': '2.0.0'})
+ ..serve('b', '1.0.0')
+ ..serve('b', '2.0.0', deps: {'c': '1.0.0'})
+ ..serve('c', '1.0.0')
+ ..serve('c', '2.0.0');
await d.appDir({'a': 'any'}).create();
await expectResolves(result: {'a': '2.0.0', 'b': '1.0.0', 'c': '2.0.0'});
@@ -788,15 +744,14 @@
// Only one version of baz, so foo and bar will have to downgrade until they
// reach it.
test('simple transitive', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
- builder.serve('foo', '2.0.0', deps: {'bar': '2.0.0'});
- builder.serve('foo', '3.0.0', deps: {'bar': '3.0.0'});
- builder.serve('bar', '1.0.0', deps: {'baz': 'any'});
- builder.serve('bar', '2.0.0', deps: {'baz': '2.0.0'});
- builder.serve('bar', '3.0.0', deps: {'baz': '3.0.0'});
- builder.serve('baz', '1.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+ ..serve('foo', '2.0.0', deps: {'bar': '2.0.0'})
+ ..serve('foo', '3.0.0', deps: {'bar': '3.0.0'})
+ ..serve('bar', '1.0.0', deps: {'baz': 'any'})
+ ..serve('bar', '2.0.0', deps: {'baz': '2.0.0'})
+ ..serve('bar', '3.0.0', deps: {'baz': '3.0.0'})
+ ..serve('baz', '1.0.0');
await d.appDir({'foo': 'any'}).create();
await expectResolves(
@@ -808,14 +763,13 @@
// make sure b has more versions than a so that the solver tries a first
// since it sorts sibling dependencies by number of versions.
test('backjump to nearer unsatisfied package', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0', deps: {'c': '1.0.0'});
- builder.serve('a', '2.0.0', deps: {'c': '2.0.0-nonexistent'});
- builder.serve('b', '1.0.0');
- builder.serve('b', '2.0.0');
- builder.serve('b', '3.0.0');
- builder.serve('c', '1.0.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0', deps: {'c': '1.0.0'})
+ ..serve('a', '2.0.0', deps: {'c': '2.0.0-nonexistent'})
+ ..serve('b', '1.0.0')
+ ..serve('b', '2.0.0')
+ ..serve('b', '3.0.0')
+ ..serve('c', '1.0.0');
await d.appDir({'a': 'any', 'b': 'any'}).create();
await expectResolves(
@@ -839,18 +793,17 @@
test('successful backjump to conflicting source', () async {
await d.dir('a', [d.libPubspec('a', '1.0.0')]).create();
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('b', '1.0.0', deps: {'a': 'any'});
- builder.serve('b', '2.0.0', deps: {
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('b', '1.0.0', deps: {'a': 'any'})
+ ..serve('b', '2.0.0', deps: {
'a': {'path': p.join(d.sandbox, 'a')}
- });
- builder.serve('c', '1.0.0');
- builder.serve('c', '2.0.0');
- builder.serve('c', '3.0.0');
- builder.serve('c', '4.0.0');
- builder.serve('c', '5.0.0');
- });
+ })
+ ..serve('c', '1.0.0')
+ ..serve('c', '2.0.0')
+ ..serve('c', '3.0.0')
+ ..serve('c', '4.0.0')
+ ..serve('c', '5.0.0');
await d.appDir({'a': 'any', 'b': 'any', 'c': 'any'}).create();
await expectResolves(result: {'a': '1.0.0', 'b': '1.0.0', 'c': '5.0.0'});
@@ -858,24 +811,22 @@
// Like the above test, but for a conflicting description.
test('successful backjump to conflicting description', () async {
- var otherServer = await PackageServer.start((builder) {
- builder.serve('a', '1.0.0');
- });
+ var otherServer = await startPackageServer();
+ otherServer.serve('a', '1.0.0');
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('b', '1.0.0', deps: {'a': 'any'});
- builder.serve('b', '2.0.0', deps: {
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('b', '1.0.0', deps: {'a': 'any'})
+ ..serve('b', '2.0.0', deps: {
'a': {
'hosted': {'name': 'a', 'url': otherServer.url}
}
- });
- builder.serve('c', '1.0.0');
- builder.serve('c', '2.0.0');
- builder.serve('c', '3.0.0');
- builder.serve('c', '4.0.0');
- builder.serve('c', '5.0.0');
- });
+ })
+ ..serve('c', '1.0.0')
+ ..serve('c', '2.0.0')
+ ..serve('c', '3.0.0')
+ ..serve('c', '4.0.0')
+ ..serve('c', '5.0.0');
await d.appDir({'a': 'any', 'b': 'any', 'c': 'any'}).create();
await expectResolves(result: {'a': '1.0.0', 'b': '1.0.0', 'c': '5.0.0'});
@@ -886,17 +837,16 @@
test('failing backjump to conflicting source', () async {
await d.dir('a', [d.libPubspec('a', '1.0.0')]).create();
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('b', '1.0.0', deps: {
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('b', '1.0.0', deps: {
'a': {'path': p.join(d.sandbox, 'shared')}
- });
- builder.serve('c', '1.0.0');
- builder.serve('c', '2.0.0');
- builder.serve('c', '3.0.0');
- builder.serve('c', '4.0.0');
- builder.serve('c', '5.0.0');
- });
+ })
+ ..serve('c', '1.0.0')
+ ..serve('c', '2.0.0')
+ ..serve('c', '3.0.0')
+ ..serve('c', '4.0.0')
+ ..serve('c', '5.0.0');
await d.appDir({'a': 'any', 'b': 'any', 'c': 'any'}).create();
await expectResolves(error: equalsIgnoringWhitespace('''
@@ -907,23 +857,21 @@
});
test('failing backjump to conflicting description', () async {
- var otherServer = await PackageServer.start((builder) {
- builder.serve('a', '1.0.0');
- });
+ var otherServer = await startPackageServer();
+ otherServer.serve('a', '1.0.0');
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('b', '1.0.0', deps: {
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('b', '1.0.0', deps: {
'a': {
'hosted': {'name': 'a', 'url': otherServer.url}
}
- });
- builder.serve('c', '1.0.0');
- builder.serve('c', '2.0.0');
- builder.serve('c', '3.0.0');
- builder.serve('c', '4.0.0');
- builder.serve('c', '5.0.0');
- });
+ })
+ ..serve('c', '1.0.0')
+ ..serve('c', '2.0.0')
+ ..serve('c', '3.0.0')
+ ..serve('c', '4.0.0')
+ ..serve('c', '5.0.0');
await d.appDir({'a': 'any', 'b': 'any', 'c': 'any'}).create();
await expectResolves(
@@ -942,39 +890,37 @@
// Since b has fewer versions, it will be traversed first, which means a will
// come later. Since later selections are revised first, a gets downgraded.
test('traverse into package with fewer versions first', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0', deps: {'c': 'any'});
- builder.serve('a', '2.0.0', deps: {'c': 'any'});
- builder.serve('a', '3.0.0', deps: {'c': 'any'});
- builder.serve('a', '4.0.0', deps: {'c': 'any'});
- builder.serve('a', '5.0.0', deps: {'c': '1.0.0'});
- builder.serve('b', '1.0.0', deps: {'c': 'any'});
- builder.serve('b', '2.0.0', deps: {'c': 'any'});
- builder.serve('b', '3.0.0', deps: {'c': 'any'});
- builder.serve('b', '4.0.0', deps: {'c': '2.0.0'});
- builder.serve('c', '1.0.0');
- builder.serve('c', '2.0.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0', deps: {'c': 'any'})
+ ..serve('a', '2.0.0', deps: {'c': 'any'})
+ ..serve('a', '3.0.0', deps: {'c': 'any'})
+ ..serve('a', '4.0.0', deps: {'c': 'any'})
+ ..serve('a', '5.0.0', deps: {'c': '1.0.0'})
+ ..serve('b', '1.0.0', deps: {'c': 'any'})
+ ..serve('b', '2.0.0', deps: {'c': 'any'})
+ ..serve('b', '3.0.0', deps: {'c': 'any'})
+ ..serve('b', '4.0.0', deps: {'c': '2.0.0'})
+ ..serve('c', '1.0.0')
+ ..serve('c', '2.0.0');
await d.appDir({'a': 'any', 'b': 'any'}).create();
await expectResolves(result: {'a': '4.0.0', 'b': '4.0.0', 'c': '2.0.0'});
});
test('complex backtrack', () async {
- await servePackages((builder) {
- // This sets up a hundred versions of foo and bar, 0.0.0 through 9.9.0. Each
- // version of foo depends on a baz with the same major version. Each version
- // of bar depends on a baz with the same minor version. There is only one
- // version of baz, 0.0.0, so only older versions of foo and bar will
- // satisfy it.
- builder.serve('baz', '0.0.0');
- for (var i = 0; i < 10; i++) {
- for (var j = 0; j < 10; j++) {
- builder.serve('foo', '$i.$j.0', deps: {'baz': '$i.0.0'});
- builder.serve('bar', '$i.$j.0', deps: {'baz': '0.$j.0'});
- }
+ final server = await servePackages();
+ // This sets up a hundred versions of foo and bar, 0.0.0 through 9.9.0. Each
+ // version of foo depends on a baz with the same major version. Each version
+ // of bar depends on a baz with the same minor version. There is only one
+ // version of baz, 0.0.0, so only older versions of foo and bar will
+ // satisfy it.
+ server.serve('baz', '0.0.0');
+ for (var i = 0; i < 10; i++) {
+ for (var j = 0; j < 10; j++) {
+ server.serve('foo', '$i.$j.0', deps: {'baz': '$i.0.0'});
+ server.serve('bar', '$i.$j.0', deps: {'baz': '0.$j.0'});
}
- });
+ }
await d.appDir({'foo': 'any', 'bar': 'any'}).create();
await expectResolves(
@@ -985,19 +931,18 @@
// versions of it is a waste of time: no possible versions can match. We need
// to jump past it to the most recent package that affected the constraint.
test('backjump past failed package on disjoint constraint', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0', deps: {
+ await servePackages()
+ ..serve('a', '1.0.0', deps: {
'foo': 'any' // ok
- });
- builder.serve('a', '2.0.0', deps: {
+ })
+ ..serve('a', '2.0.0', deps: {
'foo': '<1.0.0' // disjoint with myapp's constraint on foo
- });
- builder.serve('foo', '2.0.0');
- builder.serve('foo', '2.0.1');
- builder.serve('foo', '2.0.2');
- builder.serve('foo', '2.0.3');
- builder.serve('foo', '2.0.4');
- });
+ })
+ ..serve('foo', '2.0.0')
+ ..serve('foo', '2.0.1')
+ ..serve('foo', '2.0.2')
+ ..serve('foo', '2.0.3')
+ ..serve('foo', '2.0.4');
await d.appDir({'a': 'any', 'foo': '>2.0.0'}).create();
await expectResolves(result: {'a': '1.0.0', 'foo': '2.0.4'});
@@ -1008,14 +953,13 @@
// would backtrack over the failed package instead of trying different
// versions of it.
test('finds solution with less strict constraint', () async {
- await servePackages((builder) {
- builder.serve('a', '2.0.0');
- builder.serve('a', '1.0.0');
- builder.serve('b', '1.0.0', deps: {'a': '1.0.0'});
- builder.serve('c', '1.0.0', deps: {'b': 'any'});
- builder.serve('d', '2.0.0', deps: {'myapp': 'any'});
- builder.serve('d', '1.0.0', deps: {'myapp': '<1.0.0'});
- });
+ await servePackages()
+ ..serve('a', '2.0.0')
+ ..serve('a', '1.0.0')
+ ..serve('b', '1.0.0', deps: {'a': '1.0.0'})
+ ..serve('c', '1.0.0', deps: {'b': 'any'})
+ ..serve('d', '2.0.0', deps: {'myapp': 'any'})
+ ..serve('d', '1.0.0', deps: {'myapp': '<1.0.0'});
await d.appDir({'a': 'any', 'c': 'any', 'd': 'any'}).create();
await expectResolves(
@@ -1051,10 +995,9 @@
});
test('dependency does not match SDK', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'environment': {'sdk': '0.0.0'}
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'environment': {'sdk': '0.0.0'}
});
await d.appDir({'foo': 'any'}).create();
@@ -1067,12 +1010,11 @@
});
test('transitive dependency does not match SDK', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': 'any'});
- builder.serve('bar', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': 'any'})
+ ..serve('bar', '1.0.0', pubspec: {
'environment': {'sdk': '0.0.0'}
});
- });
await d.appDir({'foo': 'any'}).create();
await expectResolves(error: equalsIgnoringWhitespace('''
@@ -1085,41 +1027,39 @@
});
test('selects a dependency version that allows the SDK', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'environment': {'sdk': '0.1.2+3'}
- });
- builder.serve('foo', '2.0.0', pubspec: {
+ })
+ ..serve('foo', '2.0.0', pubspec: {
'environment': {'sdk': '0.1.2+3'}
- });
- builder.serve('foo', '3.0.0', pubspec: {
+ })
+ ..serve('foo', '3.0.0', pubspec: {
+ 'environment': {'sdk': '0.0.0'}
+ })
+ ..serve('foo', '4.0.0', pubspec: {
'environment': {'sdk': '0.0.0'}
});
- builder.serve('foo', '4.0.0', pubspec: {
- 'environment': {'sdk': '0.0.0'}
- });
- });
await d.appDir({'foo': 'any'}).create();
await expectResolves(result: {'foo': '2.0.0'});
});
test('selects a transitive dependency version that allows the SDK', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': 'any'});
- builder.serve('bar', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': 'any'})
+ ..serve('bar', '1.0.0', pubspec: {
'environment': {'sdk': '0.1.2+3'}
- });
- builder.serve('bar', '2.0.0', pubspec: {
+ })
+ ..serve('bar', '2.0.0', pubspec: {
'environment': {'sdk': '0.1.2+3'}
- });
- builder.serve('bar', '3.0.0', pubspec: {
+ })
+ ..serve('bar', '3.0.0', pubspec: {
+ 'environment': {'sdk': '0.0.0'}
+ })
+ ..serve('bar', '4.0.0', pubspec: {
'environment': {'sdk': '0.0.0'}
});
- builder.serve('bar', '4.0.0', pubspec: {
- 'environment': {'sdk': '0.0.0'}
- });
- });
await d.appDir({'foo': 'any'}).create();
await expectResolves(result: {'foo': '1.0.0', 'bar': '2.0.0'});
@@ -1128,24 +1068,23 @@
test(
'selects a dependency version that allows a transitive '
'dependency that allows the SDK', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
- builder.serve('foo', '2.0.0', deps: {'bar': '2.0.0'});
- builder.serve('foo', '3.0.0', deps: {'bar': '3.0.0'});
- builder.serve('foo', '4.0.0', deps: {'bar': '4.0.0'});
- builder.serve('bar', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+ ..serve('foo', '2.0.0', deps: {'bar': '2.0.0'})
+ ..serve('foo', '3.0.0', deps: {'bar': '3.0.0'})
+ ..serve('foo', '4.0.0', deps: {'bar': '4.0.0'})
+ ..serve('bar', '1.0.0', pubspec: {
'environment': {'sdk': '0.1.2+3'}
- });
- builder.serve('bar', '2.0.0', pubspec: {
+ })
+ ..serve('bar', '2.0.0', pubspec: {
'environment': {'sdk': '0.1.2+3'}
- });
- builder.serve('bar', '3.0.0', pubspec: {
+ })
+ ..serve('bar', '3.0.0', pubspec: {
+ 'environment': {'sdk': '0.0.0'}
+ })
+ ..serve('bar', '4.0.0', pubspec: {
'environment': {'sdk': '0.0.0'}
});
- builder.serve('bar', '4.0.0', pubspec: {
- 'environment': {'sdk': '0.0.0'}
- });
- });
await d.appDir({'foo': 'any'}).create();
await expectResolves(result: {'foo': '2.0.0', 'bar': '2.0.0'}, tries: 2);
@@ -1463,10 +1402,9 @@
});
test('fails for a dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'environment': {'flutter': '0.0.0'}
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'environment': {'flutter': '0.0.0'}
});
await d.appDir({'foo': 'any'}).create();
@@ -1479,13 +1417,12 @@
});
test("chooses a version that doesn't need Flutter", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0');
- builder.serve('foo', '3.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0')
+ ..serve('foo', '3.0.0', pubspec: {
'environment': {'flutter': '0.0.0'}
});
- });
await d.appDir({'foo': 'any'}).create();
await expectResolves(result: {'foo': '2.0.0'});
@@ -1612,17 +1549,16 @@
});
test('selects the latest dependency with a matching constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'environment': {'flutter': '^0.0.0'}
- });
- builder.serve('foo', '2.0.0', pubspec: {
+ })
+ ..serve('foo', '2.0.0', pubspec: {
'environment': {'flutter': '^1.0.0'}
- });
- builder.serve('foo', '3.0.0', pubspec: {
+ })
+ ..serve('foo', '3.0.0', pubspec: {
'environment': {'flutter': '^2.0.0'}
});
- });
await d.appDir({'foo': 'any'}).create();
await expectResolves(
@@ -1634,36 +1570,33 @@
void prerelease() {
test('prefer stable versions over unstable', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('a', '1.1.0-dev');
- builder.serve('a', '2.0.0-dev');
- builder.serve('a', '3.0.0-dev');
- });
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('a', '1.1.0-dev')
+ ..serve('a', '2.0.0-dev')
+ ..serve('a', '3.0.0-dev');
await d.appDir({'a': 'any'}).create();
await expectResolves(result: {'a': '1.0.0'});
});
test('use latest allowed prerelease if no stable versions match', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0-dev');
- builder.serve('a', '1.1.0-dev');
- builder.serve('a', '1.9.0-dev');
- builder.serve('a', '3.0.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0-dev')
+ ..serve('a', '1.1.0-dev')
+ ..serve('a', '1.9.0-dev')
+ ..serve('a', '3.0.0');
await d.appDir({'a': '<2.0.0'}).create();
await expectResolves(result: {'a': '1.9.0-dev'});
});
test('use an earlier stable version on a < constraint', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('a', '1.1.0');
- builder.serve('a', '2.0.0-dev');
- builder.serve('a', '2.0.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('a', '1.1.0')
+ ..serve('a', '2.0.0-dev')
+ ..serve('a', '2.0.0');
await d.appDir({'a': '<2.0.0'}).create();
await expectResolves(result: {'a': '1.1.0'});
@@ -1671,33 +1604,30 @@
test('prefer a stable version even if constraint mentions unstable',
() async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('a', '1.1.0');
- builder.serve('a', '2.0.0-dev');
- builder.serve('a', '2.0.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('a', '1.1.0')
+ ..serve('a', '2.0.0-dev')
+ ..serve('a', '2.0.0');
await d.appDir({'a': '<=2.0.0-dev'}).create();
await expectResolves(result: {'a': '1.1.0'});
});
test('use pre-release when desired', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('a', '1.1.0-dev');
- });
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('a', '1.1.0-dev');
await d.appDir({'a': '^1.1.0-dev'}).create();
await expectResolves(result: {'a': '1.1.0-dev'});
});
test('can upgrade from pre-release', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('a', '1.1.0-dev');
- builder.serve('a', '1.1.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('a', '1.1.0-dev')
+ ..serve('a', '1.1.0');
await d.appDir({'a': '^1.1.0-dev'}).create();
await expectResolves(result: {'a': '1.1.0'});
@@ -1706,12 +1636,11 @@
test('will use pre-release if depended on in stable release', () async {
// This behavior is desired because a stable package has dependency on a
// pre-release.
- await servePackages((builder) {
- builder.serve('a', '1.0.0', deps: {'b': '^1.0.0'});
- builder.serve('a', '1.1.0', deps: {'b': '^1.1.0-dev'});
- builder.serve('b', '1.0.0');
- builder.serve('b', '1.1.0-dev');
- });
+ await servePackages()
+ ..serve('a', '1.0.0', deps: {'b': '^1.0.0'})
+ ..serve('a', '1.1.0', deps: {'b': '^1.1.0-dev'})
+ ..serve('b', '1.0.0')
+ ..serve('b', '1.1.0-dev');
await d.appDir({'a': '^1.0.0'}).create();
await expectResolves(result: {
@@ -1721,12 +1650,11 @@
});
test('backtracks pre-release choice with direct dependency', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0', deps: {'b': '^1.0.0'});
- builder.serve('a', '1.1.0', deps: {'b': '^1.1.0-dev'});
- builder.serve('b', '1.0.0');
- builder.serve('b', '1.1.0-dev');
- });
+ await servePackages()
+ ..serve('a', '1.0.0', deps: {'b': '^1.0.0'})
+ ..serve('a', '1.1.0', deps: {'b': '^1.1.0-dev'})
+ ..serve('b', '1.0.0')
+ ..serve('b', '1.1.0-dev');
await d.appDir({
'a': '^1.0.0',
@@ -1741,13 +1669,12 @@
test('backtracking pre-release fails with indirect dependency', () async {
// NOTE: This behavior is not necessarily desired.
// If feasible it might worth changing this behavior in the future.
- await servePackages((builder) {
- builder.serve('a', '1.0.0', deps: {'b': '^1.0.0'});
- builder.serve('a', '1.1.0', deps: {'b': '^1.1.0-dev'});
- builder.serve('b', '1.0.0');
- builder.serve('b', '1.1.0-dev');
- builder.serve('c', '1.0.0', deps: {'b': '^1.0.0'});
- });
+ await servePackages()
+ ..serve('a', '1.0.0', deps: {'b': '^1.0.0'})
+ ..serve('a', '1.1.0', deps: {'b': '^1.1.0-dev'})
+ ..serve('b', '1.0.0')
+ ..serve('b', '1.1.0-dev')
+ ..serve('c', '1.0.0', deps: {'b': '^1.0.0'});
await d.appDir({
'a': '^1.0.0',
@@ -1762,14 +1689,13 @@
test('https://github.com/dart-lang/pub/issues/3057 regression', () async {
// This used to cause an infinite loop.
- await servePackages((builder) {
- builder.serve('a', '0.12.0', deps: {});
- builder.serve('b', '0.1.0', deps: {'c': '2.0.0'});
- builder.serve('b', '0.9.0-1', deps: {'c': '^1.6.0'});
- builder.serve('b', '0.10.0', deps: {'a': '1.0.0'});
- builder.serve('b', '0.17.0', deps: {'a': '1.0.0'});
- builder.serve('c', '2.0.1', deps: {});
- });
+ await servePackages()
+ ..serve('a', '0.12.0', deps: {})
+ ..serve('b', '0.1.0', deps: {'c': '2.0.0'})
+ ..serve('b', '0.9.0-1', deps: {'c': '^1.6.0'})
+ ..serve('b', '0.10.0', deps: {'a': '1.0.0'})
+ ..serve('b', '0.17.0', deps: {'a': '1.0.0'})
+ ..serve('c', '2.0.1', deps: {});
await d.appDir(
{
@@ -1784,13 +1710,12 @@
});
test('https://github.com/dart-lang/pub/pull/3038 regression', () async {
- await servePackages((builder) {
- builder.serve('a', '1.1.0', deps: {'b': '^1.0.0'});
- builder.serve('b', '1.0.0', deps: {'c': '^1.0.0'});
- builder.serve('c', '0.9.0');
- builder.serve('b', '1.1.0-alpha');
- builder.serve('a', '1.0.0', deps: {'b': '^1.1.0-alpha'});
- });
+ await servePackages()
+ ..serve('a', '1.1.0', deps: {'b': '^1.0.0'})
+ ..serve('b', '1.0.0', deps: {'c': '^1.0.0'})
+ ..serve('c', '0.9.0')
+ ..serve('b', '1.1.0-alpha')
+ ..serve('a', '1.0.0', deps: {'b': '^1.1.0-alpha'});
await d.appDir({
'a': '^1.0.0',
@@ -1801,11 +1726,10 @@
void override() {
test('chooses best version matching override constraint', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('a', '2.0.0');
- builder.serve('a', '3.0.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('a', '2.0.0')
+ ..serve('a', '3.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -1819,11 +1743,10 @@
});
test('uses override as dependency', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('a', '2.0.0');
- builder.serve('a', '3.0.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('a', '2.0.0')
+ ..serve('a', '3.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -1836,13 +1759,12 @@
});
test('ignores other constraints on overridden package', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('a', '2.0.0');
- builder.serve('a', '3.0.0');
- builder.serve('b', '1.0.0', deps: {'a': '1.0.0'});
- builder.serve('c', '1.0.0', deps: {'a': '3.0.0'});
- });
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('a', '2.0.0')
+ ..serve('a', '3.0.0')
+ ..serve('b', '1.0.0', deps: {'a': '1.0.0'})
+ ..serve('c', '1.0.0', deps: {'a': '3.0.0'});
await d.dir(appPath, [
d.pubspec({
@@ -1856,12 +1778,11 @@
});
test('backtracks on overidden package for its constraints', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0', deps: {'shared': 'any'});
- builder.serve('a', '2.0.0', deps: {'shared': '1.0.0'});
- builder.serve('shared', '1.0.0');
- builder.serve('shared', '2.0.0');
- });
+ await servePackages()
+ ..serve('a', '1.0.0', deps: {'shared': 'any'})
+ ..serve('a', '2.0.0', deps: {'shared': '1.0.0'})
+ ..serve('shared', '1.0.0')
+ ..serve('shared', '2.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -1875,14 +1796,13 @@
});
test('override compatible with locked dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
- builder.serve('foo', '1.0.1', deps: {'bar': '1.0.1'});
- builder.serve('foo', '1.0.2', deps: {'bar': '1.0.2'});
- builder.serve('bar', '1.0.0');
- builder.serve('bar', '1.0.1');
- builder.serve('bar', '1.0.2');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+ ..serve('foo', '1.0.1', deps: {'bar': '1.0.1'})
+ ..serve('foo', '1.0.2', deps: {'bar': '1.0.2'})
+ ..serve('bar', '1.0.0')
+ ..serve('bar', '1.0.1')
+ ..serve('bar', '1.0.2');
await d.appDir({'foo': '1.0.1'}).create();
await expectResolves(result: {'foo': '1.0.1', 'bar': '1.0.1'});
@@ -1898,14 +1818,13 @@
});
test('override incompatible with locked dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'bar': '1.0.0'});
- builder.serve('foo', '1.0.1', deps: {'bar': '1.0.1'});
- builder.serve('foo', '1.0.2', deps: {'bar': '1.0.2'});
- builder.serve('bar', '1.0.0');
- builder.serve('bar', '1.0.1');
- builder.serve('bar', '1.0.2');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'bar': '1.0.0'})
+ ..serve('foo', '1.0.1', deps: {'bar': '1.0.1'})
+ ..serve('foo', '1.0.2', deps: {'bar': '1.0.2'})
+ ..serve('bar', '1.0.0')
+ ..serve('bar', '1.0.1')
+ ..serve('bar', '1.0.2');
await d.appDir({'foo': '1.0.1'}).create();
await expectResolves(result: {'foo': '1.0.1', 'bar': '1.0.1'});
@@ -1921,10 +1840,9 @@
});
test('no version that matches override', () async {
- await servePackages((builder) {
- builder.serve('foo', '2.0.0');
- builder.serve('foo', '2.1.3');
- });
+ await servePackages()
+ ..serve('foo', '2.0.0')
+ ..serve('foo', '2.1.3');
await d.dir(appPath, [
d.pubspec({
@@ -1940,9 +1858,8 @@
});
test('overrides a bad source without error', () async {
- await servePackages((builder) {
- builder.serve('foo', '0.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '0.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -1958,10 +1875,9 @@
});
test('overrides an unmatched SDK constraint', () async {
- await servePackages((builder) {
- builder.serve('foo', '0.0.0', pubspec: {
- 'environment': {'sdk': '0.0.0'}
- });
+ final server = await servePackages();
+ server.serve('foo', '0.0.0', pubspec: {
+ 'environment': {'sdk': '0.0.0'}
});
await d.dir(appPath, [
@@ -1975,9 +1891,8 @@
});
test('overrides an unmatched root dependency', () async {
- await servePackages((builder) {
- builder.serve('foo', '0.0.0', deps: {'myapp': '1.0.0'});
- });
+ final server = await servePackages();
+ server.serve('foo', '0.0.0', deps: {'myapp': '1.0.0'});
await d.dir(appPath, [
d.pubspec({
@@ -1992,11 +1907,10 @@
// Regression test for #1853
test("overrides a locked package's dependency", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.2.3', deps: {'bar': '1.2.3'});
- builder.serve('bar', '1.2.3');
- builder.serve('bar', '0.0.1');
- });
+ await servePackages()
+ ..serve('foo', '1.2.3', deps: {'bar': '1.2.3'})
+ ..serve('bar', '1.2.3')
+ ..serve('bar', '0.0.1');
await d.appDir({'foo': 'any'}).create();
@@ -2016,12 +1930,11 @@
void downgrade() {
test('downgrades a dependency to the lowest matching version', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '2.0.0-dev');
- builder.serve('foo', '2.0.0');
- builder.serve('foo', '2.1.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '2.0.0-dev')
+ ..serve('foo', '2.0.0')
+ ..serve('foo', '2.1.0');
await d.appDir({'foo': '2.1.0'}).create();
await expectResolves(result: {'foo': '2.1.0'});
@@ -2033,12 +1946,11 @@
test(
'use earliest allowed prerelease if no stable versions match '
'while downgrading', () async {
- await servePackages((builder) {
- builder.serve('a', '1.0.0');
- builder.serve('a', '2.0.0-dev.1');
- builder.serve('a', '2.0.0-dev.2');
- builder.serve('a', '2.0.0-dev.3');
- });
+ await servePackages()
+ ..serve('a', '1.0.0')
+ ..serve('a', '2.0.0-dev.1')
+ ..serve('a', '2.0.0-dev.2')
+ ..serve('a', '2.0.0-dev.3');
await d.appDir({'a': '>=2.0.0-dev.1 <3.0.0'}).create();
await expectResolves(result: {'a': '2.0.0-dev.1'}, downgrade: true);
@@ -2047,67 +1959,63 @@
void features() {
test("doesn't enable an opt-in feature by default", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'default': false,
'dependencies': {'bar': '1.0.0'}
}
}
- });
- builder.serve('bar', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0');
await d.appDir({'foo': '1.0.0'}).create();
await expectResolves(result: {'foo': '1.0.0'});
});
test('enables an opt-out feature by default', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'default': true,
'dependencies': {'bar': '1.0.0'}
}
}
- });
- builder.serve('bar', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0');
await d.appDir({'foo': '1.0.0'}).create();
await expectResolves(result: {'foo': '1.0.0', 'bar': '1.0.0'});
});
test('features are opt-out by default', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'dependencies': {'bar': '1.0.0'}
}
}
- });
- builder.serve('bar', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0');
await d.appDir({'foo': '1.0.0'}).create();
await expectResolves(result: {'foo': '1.0.0', 'bar': '1.0.0'});
});
test("enables an opt-in feature if it's required", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'default': false,
'dependencies': {'bar': '1.0.0'}
}
}
- });
- builder.serve('bar', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0');
await d.appDir({
'foo': {
@@ -2119,16 +2027,15 @@
});
test("doesn't enable an opt-out feature if it's disabled", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'dependencies': {'bar': '1.0.0'}
}
}
- });
- builder.serve('bar', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0');
await d.appDir({
'foo': {
@@ -2140,22 +2047,21 @@
});
test('opting in takes precedence over opting out', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'dependencies': {'bar': '1.0.0'}
}
}
- });
- builder.serve('bar', '1.0.0');
- builder.serve('baz', '1.0.0', deps: {
+ })
+ ..serve('bar', '1.0.0')
+ ..serve('baz', '1.0.0', deps: {
'foo': {
'version': '1.0.0',
'features': {'stuff': true}
}
});
- });
await d.appDir({
'foo': {
@@ -2169,21 +2075,20 @@
});
test('implicitly opting in takes precedence over opting out', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'dependencies': {'bar': '1.0.0'}
}
}
- });
- builder.serve('bar', '1.0.0');
- builder.serve('baz', '1.0.0', deps: {
+ })
+ ..serve('bar', '1.0.0')
+ ..serve('baz', '1.0.0', deps: {
'foo': {
'version': '1.0.0',
}
});
- });
await d.appDir({
'foo': {
@@ -2197,18 +2102,17 @@
});
test("doesn't select a version with an unavailable feature", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'default': false,
'dependencies': {'bar': '1.0.0'}
}
}
- });
- builder.serve('foo', '1.1.0');
- builder.serve('bar', '1.0.0');
- });
+ })
+ ..serve('foo', '1.1.0')
+ ..serve('bar', '1.0.0');
await d.appDir({
'foo': {
@@ -2220,26 +2124,25 @@
});
test("doesn't select a version with an incompatible feature", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'default': false,
'dependencies': {'bar': '1.0.0'}
}
}
- });
- builder.serve('foo', '1.1.0', pubspec: {
+ })
+ ..serve('foo', '1.1.0', pubspec: {
'features': {
'stuff': {
'default': false,
'dependencies': {'bar': '2.0.0'}
}
}
- });
- builder.serve('bar', '1.0.0');
- builder.serve('bar', '2.0.0');
- });
+ })
+ ..serve('bar', '1.0.0')
+ ..serve('bar', '2.0.0');
await d.appDir({
'foo': {
@@ -2254,8 +2157,8 @@
test(
'backtracks if a feature is transitively incompatible with another '
'feature', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'default': false,
@@ -2267,27 +2170,24 @@
}
}
}
- });
- builder.serve('foo', '1.1.0', pubspec: {
+ })
+ ..serve('foo', '1.1.0', pubspec: {
'features': {
'stuff': {
'default': false,
'dependencies': {'bar': '1.0.0'}
}
}
- });
-
- builder.serve('bar', '1.0.0', pubspec: {
+ })
+ ..serve('bar', '1.0.0', pubspec: {
'features': {
'stuff': {
'dependencies': {'baz': '1.0.0'}
}
}
- });
-
- builder.serve('baz', '1.0.0');
- builder.serve('baz', '2.0.0');
- });
+ })
+ ..serve('baz', '1.0.0')
+ ..serve('baz', '2.0.0');
await d.appDir({
'foo': {
@@ -2302,30 +2202,27 @@
test("backtracks if a feature's dependencies are transitively incompatible",
() async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'default': false,
'dependencies': {'bar': '1.0.0'}
}
}
- });
- builder.serve('foo', '1.1.0', pubspec: {
+ })
+ ..serve('foo', '1.1.0', pubspec: {
'features': {
'stuff': {
'default': false,
'dependencies': {'bar': '2.0.0'}
}
}
- });
-
- builder.serve('bar', '1.0.0', deps: {'baz': '1.0.0'});
- builder.serve('bar', '2.0.0', deps: {'baz': '2.0.0'});
-
- builder.serve('baz', '1.0.0');
- builder.serve('baz', '2.0.0');
- });
+ })
+ ..serve('bar', '1.0.0', deps: {'baz': '1.0.0'})
+ ..serve('bar', '2.0.0', deps: {'baz': '2.0.0'})
+ ..serve('baz', '1.0.0')
+ ..serve('baz', '2.0.0');
await d.appDir({
'foo': {
@@ -2339,9 +2236,9 @@
});
test('disables a feature when it backtracks', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {'myapp': '0.0.0'});
- builder.serve('foo', '1.1.0', deps: {
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {'myapp': '0.0.0'})
+ ..serve('foo', '1.1.0', deps: {
// This is a transitively incompatible dependency with myapp, which will
// force the solver to backtrack and unselect foo 1.1.0.
'bar': '1.0.0',
@@ -2349,15 +2246,11 @@
'version': '0.0.0',
'features': {'stuff': true}
}
- });
-
- builder.serve('bar', '1.0.0', deps: {'baz': '2.0.0'});
-
- builder.serve('baz', '1.0.0');
- builder.serve('baz', '2.0.0');
-
- builder.serve('qux', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0', deps: {'baz': '2.0.0'})
+ ..serve('baz', '1.0.0')
+ ..serve('baz', '2.0.0')
+ ..serve('qux', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -2375,10 +2268,9 @@
});
test("the root package's features are opt-out by default", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('bar', '1.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('bar', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -2395,10 +2287,9 @@
});
test("the root package's features can be made opt-in", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('bar', '1.0.0');
- });
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('bar', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -2421,14 +2312,13 @@
// increases the total number of dependencies.
test("the root package's features can't be disabled by dependencies",
() async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {
'myapp': {
'features': {'stuff': false}
}
- });
- builder.serve('bar', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -2445,14 +2335,13 @@
});
test("the root package's features can be enabled by dependencies", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', deps: {
+ await servePackages()
+ ..serve('foo', '1.0.0', deps: {
'myapp': {
'features': {'stuff': true}
}
- });
- builder.serve('bar', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -2470,9 +2359,8 @@
});
test("resolution fails because a feature doesn't exist", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.dir(appPath, [
d.pubspec({
@@ -2492,17 +2380,16 @@
group('an "if available" dependency', () {
test('enables an opt-in feature', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'stuff': {
'default': false,
'dependencies': {'bar': '1.0.0'}
}
}
- });
- builder.serve('bar', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0');
await d.appDir({
'foo': {
@@ -2514,9 +2401,8 @@
});
test("is compatible with a feature that doesn't exist", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- });
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
await d.appDir({
'foo': {
@@ -2535,14 +2421,13 @@
group('succeeds when', () {
test('a Dart SDK constraint is matched', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'features': {
- 'stuff': {
- 'environment': {'sdk': '^0.1.0'}
- }
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'features': {
+ 'stuff': {
+ 'environment': {'sdk': '^0.1.0'}
}
- });
+ }
});
await d.dir(appPath, [
@@ -2556,14 +2441,13 @@
});
test('a Flutter SDK constraint is matched', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'features': {
- 'stuff': {
- 'environment': {'flutter': '^1.0.0'}
- }
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'features': {
+ 'stuff': {
+ 'environment': {'flutter': '^1.0.0'}
}
- });
+ }
});
await d.dir(appPath, [
@@ -2581,16 +2465,15 @@
group("doesn't choose a version because", () {
test("a Dart SDK constraint isn't matched", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '1.1.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '1.1.0', pubspec: {
'features': {
'stuff': {
'environment': {'sdk': '0.0.1'}
}
}
});
- });
await d.dir(appPath, [
d.pubspec({
@@ -2603,16 +2486,15 @@
});
test("Flutter isn't available", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '1.1.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '1.1.0', pubspec: {
'features': {
'stuff': {
'environment': {'flutter': '1.0.0'}
}
}
});
- });
await d.dir(appPath, [
d.pubspec({
@@ -2625,16 +2507,15 @@
});
test("a Flutter SDK constraint isn't matched", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0');
- builder.serve('foo', '1.1.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0')
+ ..serve('foo', '1.1.0', pubspec: {
'features': {
'stuff': {
'environment': {'flutter': '^2.0.0'}
}
}
});
- });
await d.dir(appPath, [
d.pubspec({
@@ -2651,14 +2532,13 @@
group('resolution fails because', () {
test("a Dart SDK constraint isn't matched", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'features': {
- 'stuff': {
- 'environment': {'sdk': '0.0.1'}
- }
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'features': {
+ 'stuff': {
+ 'environment': {'sdk': '0.0.1'}
}
- });
+ }
});
await d.dir(appPath, [
@@ -2675,14 +2555,13 @@
});
test("Flutter isn't available", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'features': {
- 'stuff': {
- 'environment': {'flutter': '1.0.0'}
- }
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'features': {
+ 'stuff': {
+ 'environment': {'flutter': '1.0.0'}
}
- });
+ }
});
await d.dir(appPath, [
@@ -2698,14 +2577,13 @@
});
test("a Flutter SDK constraint isn't matched", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
- 'features': {
- 'stuff': {
- 'environment': {'flutter': '^2.0.0'}
- }
+ final server = await servePackages();
+ server.serve('foo', '1.0.0', pubspec: {
+ 'features': {
+ 'stuff': {
+ 'environment': {'flutter': '^2.0.0'}
}
- });
+ }
});
await d.dir(appPath, [
@@ -2725,8 +2603,8 @@
group('with overlapping dependencies', () {
test('can enable extra features', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'dependencies': {'bar': '1.0.0'},
'features': {
'stuff': {
@@ -2738,19 +2616,16 @@
}
}
}
- });
-
- builder.serve('bar', '1.0.0', pubspec: {
+ })
+ ..serve('bar', '1.0.0', pubspec: {
'features': {
'stuff': {
'default': false,
'dependencies': {'baz': '1.0.0'}
}
}
- });
-
- builder.serve('baz', '1.0.0');
- });
+ })
+ ..serve('baz', '1.0.0');
await d.appDir({
'foo': {'version': '1.0.0'}
@@ -2768,8 +2643,8 @@
});
test("can't disable features", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'dependencies': {
'bar': {
'version': '1.0.0',
@@ -2786,19 +2661,16 @@
}
}
}
- });
-
- builder.serve('bar', '1.0.0', pubspec: {
+ })
+ ..serve('bar', '1.0.0', pubspec: {
'features': {
'stuff': {
'default': true,
'dependencies': {'baz': '1.0.0'}
}
}
- });
-
- builder.serve('baz', '1.0.0');
- });
+ })
+ ..serve('baz', '1.0.0');
await d.appDir({
'foo': {
@@ -2813,8 +2685,8 @@
group('with required features', () {
test('enables those features', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'main': {
'default': false,
@@ -2829,10 +2701,9 @@
'dependencies': {'baz': '1.0.0'}
}
}
- });
- builder.serve('bar', '1.0.0');
- builder.serve('baz', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0')
+ ..serve('baz', '1.0.0');
await d.appDir({
'foo': {
@@ -2845,8 +2716,8 @@
});
test('enables those features by default', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'main': {
'requires': ['required1', 'required2']
@@ -2860,10 +2731,9 @@
'dependencies': {'baz': '1.0.0'}
}
}
- });
- builder.serve('bar', '1.0.0');
- builder.serve('baz', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0')
+ ..serve('baz', '1.0.0');
await d.appDir({'foo': '1.0.0'}).create();
await expectResolves(
@@ -2871,8 +2741,8 @@
});
test("doesn't enable those features if it's disabled", () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'main': {
'requires': ['required']
@@ -2882,9 +2752,8 @@
'dependencies': {'bar': '1.0.0'}
}
}
- });
- builder.serve('bar', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0');
await d.appDir({
'foo': {
@@ -2897,8 +2766,8 @@
test("enables those features even if they'd otherwise be disabled",
() async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'main': {
'requires': ['required']
@@ -2908,9 +2777,8 @@
'dependencies': {'bar': '1.0.0'}
}
}
- });
- builder.serve('bar', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0');
await d.appDir({
'foo': {
@@ -2922,8 +2790,8 @@
});
test('enables features transitively', () async {
- await servePackages((builder) {
- builder.serve('foo', '1.0.0', pubspec: {
+ await servePackages()
+ ..serve('foo', '1.0.0', pubspec: {
'features': {
'main': {
'requires': ['required1']
@@ -2937,9 +2805,8 @@
'dependencies': {'bar': '1.0.0'}
}
}
- });
- builder.serve('bar', '1.0.0');
- });
+ })
+ ..serve('bar', '1.0.0');
await d.appDir({
'foo': {
@@ -2972,11 +2839,11 @@
///
/// If [downgrade] is `true`, this runs "pub downgrade" instead of "pub get".
Future expectResolves(
- {Map result,
+ {Map? result,
error,
output,
- int tries,
- Map<String, String> environment,
+ int? tries,
+ Map<String, String>? environment,
bool downgrade = false}) async {
await runPub(
args: [downgrade ? 'downgrade' : 'get'],
@@ -3001,12 +2868,13 @@
for (var dep in resultPubspec.dependencies.values) {
expect(ids, contains(dep.name));
var id = ids.remove(dep.name);
+ final source = dep.source;
- if (dep.source is HostedSource && dep.description is String) {
+ if (source is HostedSource && (dep.description.uri == source.defaultUrl)) {
// If the dep uses the default hosted source, grab it from the test
// package server rather than pub.dartlang.org.
dep = registry.hosted
- .refFor(dep.name, url: Uri.parse(globalPackageServer.url))
+ .refFor(dep.name, url: Uri.parse(globalServer.url))
.withConstraint(dep.constraint);
}
expect(dep.allows(id), isTrue, reason: 'Expected $id to match $dep.');
@@ -3014,3 +2882,20 @@
expect(ids, isEmpty, reason: 'Expected no additional packages.');
}
+
+void regressions() {
+ test('reformatRanges with a build', () async {
+ await servePackages()
+ ..serve('integration_test', '1.0.1',
+ deps: {'vm_service': '>= 4.2.0 <6.0.0'})
+ ..serve('integration_test', '1.0.2+2',
+ deps: {'vm_service': '>= 4.2.0 <7.0.0'})
+ ..serve('vm_service', '7.3.0');
+ await d.appDir({'integration_test': '^1.0.2'}).create();
+ await expectResolves(
+ error: contains(
+ 'Because no versions of integration_test match >=1.0.2 <1.0.2+2',
+ ),
+ );
+ });
+}
diff --git a/tool/extract_all_pub_dev.dart b/tool/extract_all_pub_dev.dart
index 8d7f049..f96dc5a 100644
--- a/tool/extract_all_pub_dev.dart
+++ b/tool/extract_all_pub_dev.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
/// This is a manual test that can be run to test the .tar.gz decoding.
/// It will save progress in [statusFileName] such that it doesn't have to be
/// finished in a single run.
@@ -33,7 +31,7 @@
Future<void> main() async {
var alreadyDonePackages = <String>{};
- var failures = <Map<String, dynamic>>[];
+ var failures = <Map<String, dynamic>?>[];
if (fileExists(statusFilename)) {
final json = jsonDecode(readTextFile(statusFilename));
for (final packageName in json['packages'] ?? []) {
diff --git a/tool/test-bin/pub_command_runner.dart b/tool/test-bin/pub_command_runner.dart
index 2470a91..e438aae 100644
--- a/tool/test-bin/pub_command_runner.dart
+++ b/tool/test-bin/pub_command_runner.dart
@@ -1,22 +1,50 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
+/// A trivial embedding of the pub command. Used from tests.
+import 'dart:convert';
import 'dart:io';
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
+import 'package:pub/pub.dart';
+import 'package:pub/src/command.dart';
import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/log.dart' as log;
-import 'package:pub/src/pub_embeddable_command.dart';
+import 'package:usage/usage.dart';
+
+final _LoggingAnalytics loggingAnalytics = _LoggingAnalytics();
+
+// A command for explicitly throwing an exception, to test the handling of
+// unexpected eceptions.
+class ThrowingCommand extends PubCommand {
+ @override
+ String get name => 'fail';
+
+ @override
+ String get description => 'Throws an exception';
+
+ bool get hide => true;
+
+ @override
+ Future<int> runProtected() async {
+ throw StateError('Pub has crashed');
+ }
+}
class Runner extends CommandRunner<int> {
- ArgResults _options;
+ late ArgResults _options;
Runner() : super('pub_command_runner', 'Tests the embeddable pub command.') {
- addCommand(PubEmbeddableCommand());
+ final analytics = Platform.environment['_PUB_LOG_ANALYTICS'] == 'true'
+ ? PubAnalytics(() => loggingAnalytics,
+ dependencyKindCustomDimensionName: 'cd1')
+ : null;
+ addCommand(
+ pubCommand(analytics: analytics, isVerbose: () => _options['verbose'])
+ ..addSubcommand(ThrowingCommand()));
+ argParser.addFlag('verbose');
}
@override
@@ -40,3 +68,51 @@
Future<void> main(List<String> arguments) async {
exitCode = await Runner().run(arguments);
}
+
+class _LoggingAnalytics extends AnalyticsMock {
+ _LoggingAnalytics() {
+ onSend.listen((event) {
+ stderr.writeln('[analytics]${json.encode(event)}');
+ });
+ }
+
+ @override
+ bool get firstRun => false;
+
+ @override
+ Future sendScreenView(String viewName, {Map<String, String>? parameters}) {
+ parameters ??= <String, String>{};
+ parameters['viewName'] = viewName;
+ return _log('screenView', parameters);
+ }
+
+ @override
+ Future sendEvent(String category, String action,
+ {String? label, int? value, Map<String, String>? parameters}) {
+ parameters ??= <String, String>{};
+ return _log(
+ 'event',
+ {'category': category, 'action': action, 'label': label, 'value': value}
+ ..addAll(parameters));
+ }
+
+ @override
+ Future sendSocial(String network, String action, String target) =>
+ _log('social', {'network': network, 'action': action, 'target': target});
+
+ @override
+ Future sendTiming(String variableName, int time,
+ {String? category, String? label}) {
+ return _log('timing', {
+ 'variableName': variableName,
+ 'time': time,
+ 'category': category,
+ 'label': label
+ });
+ }
+
+ Future<void> _log(String hitType, Map message) async {
+ final encoded = json.encode({'hitType': hitType, 'message': message});
+ stderr.writeln('[analytics]: $encoded');
+ }
+}
diff --git a/tool/test.dart b/tool/test.dart
index 2f4769d..7d98156 100755
--- a/tool/test.dart
+++ b/tool/test.dart
@@ -3,8 +3,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart=2.10
-
/// Test wrapper script.
/// Many of the integration tests runs the `pub` command, this is slow if every
/// invocation requires the dart compiler to load all the sources. This script
@@ -19,7 +17,7 @@
import 'package:pub/src/exceptions.dart';
Future<void> main(List<String> args) async {
- Process testProcess;
+ Process? testProcess;
final sub = ProcessSignal.sigint.watch().listen((signal) {
testProcess?.kill(signal);
});
@@ -31,7 +29,7 @@
await precompile(
executablePath: path.join('bin', 'pub.dart'),
outputPath: pubSnapshotFilename,
- incrementalDillOutputPath: pubSnapshotIncrementalFilename,
+ incrementalDillPath: pubSnapshotIncrementalFilename,
name: 'bin/pub.dart',
packageConfigPath: path.join('.dart_tool', 'package_config.json'));
testProcess = await Process.start(