Add --directory option (#2876)
To run a command in another directory from CWD
diff --git a/lib/src/command.dart b/lib/src/command.dart
index b6eaab1..313ea99 100644
--- a/lib/src/command.dart
+++ b/lib/src/command.dart
@@ -43,6 +43,8 @@
/// 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;
+
SystemCache get cache => _cache ??= SystemCache(isOffline: isOffline);
SystemCache _cache;
@@ -55,7 +57,7 @@
///
/// This will load the pubspec and fail with an error if the current directory
/// is not a package.
- Entrypoint get entrypoint => _entrypoint ??= Entrypoint.current(cache);
+ Entrypoint get entrypoint => _entrypoint ??= Entrypoint(directory, cache);
Entrypoint _entrypoint;
@@ -279,6 +281,7 @@
bool get captureStackChains;
log.Verbosity get verbosity;
bool get trace;
+ 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 9050273..fda2250 100644
--- a/lib/src/command/add.dart
+++ b/lib/src/command/add.dart
@@ -74,6 +74,8 @@
argParser.addFlag('precompile',
help: 'Precompile executables in immediate dependencies.');
+ argParser.addOption('directory',
+ abbr: 'C', help: 'Run this in the directory<dir>.', valueHelp: 'dir');
}
@override
@@ -96,6 +98,7 @@
/// in case [package] was already a transitive dependency. In the case
/// where the user specifies a version constraint, this serves to ensure
/// 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));
} on GitException {
@@ -149,7 +152,7 @@
/// Create a new [Entrypoint] since we have to reprocess the updated
/// pubspec file.
- await Entrypoint.current(cache).acquireDependencies(SolveType.GET,
+ await Entrypoint(directory, cache).acquireDependencies(SolveType.GET,
precompile: argResults['precompile']);
}
diff --git a/lib/src/command/deps.dart b/lib/src/command/deps.dart
index aea2e18..98e68a3 100644
--- a/lib/src/command/deps.dart
+++ b/lib/src/command/deps.dart
@@ -52,11 +52,14 @@
argParser.addFlag('executables',
negatable: false, help: 'List all available executables.');
+
+ argParser.addOption('directory',
+ abbr: 'C', help: 'Run this in the directory<dir>.', valueHelp: 'dir');
}
@override
Future<void> runProtected() async {
- // Explicitly run this in case we don't access `entrypoint.packageGraph`.
+ // Explicitly Run this in the directorycase we don't access `entrypoint.packageGraph`.
entrypoint.assertUpToDate();
_buffer = StringBuffer();
diff --git a/lib/src/command/downgrade.dart b/lib/src/command/downgrade.dart
index 3e75775..b46ce1d 100644
--- a/lib/src/command/downgrade.dart
+++ b/lib/src/command/downgrade.dart
@@ -33,6 +33,9 @@
help: "Report what dependencies would change but don't change any.");
argParser.addFlag('packages-dir', hide: true);
+
+ argParser.addOption('directory',
+ abbr: 'C', help: 'Run this in the directory<dir>.', valueHelp: 'dir');
}
@override
diff --git a/lib/src/command/get.dart b/lib/src/command/get.dart
index d6b0305..1f23806 100644
--- a/lib/src/command/get.dart
+++ b/lib/src/command/get.dart
@@ -32,6 +32,9 @@
help: 'Precompile executables in immediate dependencies.');
argParser.addFlag('packages-dir', hide: true);
+
+ argParser.addOption('directory',
+ abbr: 'C', help: 'Run this in the directory<dir>.', valueHelp: 'dir');
}
@override
diff --git a/lib/src/command/lish.dart b/lib/src/command/lish.dart
index abc0c65..bbb2373 100644
--- a/lib/src/command/lish.dart
+++ b/lib/src/command/lish.dart
@@ -63,6 +63,9 @@
argParser.addOption('server',
help: 'The package server to which to upload this package.',
hide: true);
+
+ argParser.addOption('directory',
+ abbr: 'C', help: 'Run this in the directory<dir>.', valueHelp: 'dir');
}
Future<void> _publish(List<int> packageBytes) async {
diff --git a/lib/src/command/list_package_dirs.dart b/lib/src/command/list_package_dirs.dart
index d0c5ed8..10fe5aa 100644
--- a/lib/src/command/list_package_dirs.dart
+++ b/lib/src/command/list_package_dirs.dart
@@ -26,6 +26,8 @@
ListPackageDirsCommand() {
argParser.addOption('format',
help: 'How output should be displayed.', allowed: ['json']);
+ argParser.addOption('directory',
+ abbr: 'C', help: 'Run this in the directory<dir>.', valueHelp: 'dir');
}
@override
diff --git a/lib/src/command/outdated.dart b/lib/src/command/outdated.dart
index 632ff6f..843b306 100644
--- a/lib/src/command/outdated.dart
+++ b/lib/src/command/outdated.dart
@@ -8,6 +8,7 @@
import 'dart:math';
import 'package:meta/meta.dart';
+import 'package:path/path.dart' as path;
import 'package:pub_semver/pub_semver.dart';
import '../command.dart';
@@ -107,6 +108,8 @@
help: 'Show transitive dependencies.\n'
'(defaults to off in --mode=null-safety).',
);
+ argParser.addOption('directory',
+ abbr: 'C', help: 'Run this in the directory<dir>.', valueHelp: 'dir');
}
@override
@@ -258,25 +261,23 @@
final useColors =
argResults.wasParsed('color') ? argResults['color'] : canUseAnsiCodes;
- await _outputHuman(
- rows,
- mode,
- useColors: useColors,
- showAll: showAll,
- includeDevDependencies: includeDevDependencies,
- lockFileExists: fileExists(entrypoint.lockFilePath),
- hasDirectDependencies: rootPubspec.dependencies.values.any(
- // Test if it contains non-SDK dependencies
- (c) => c.source is! SdkSource,
- ),
- hasDevDependencies: rootPubspec.devDependencies.values.any(
- // Test if it contains non-SDK dependencies
- (c) => c.source is! SdkSource,
- ),
- showTransitiveDependencies: showTransitiveDependencies,
- hasUpgradableResolution: hasUpgradableResolution,
- hasResolvableResolution: hasResolvableResolution,
- );
+ await _outputHuman(rows, mode,
+ useColors: useColors,
+ showAll: showAll,
+ includeDevDependencies: includeDevDependencies,
+ lockFileExists: fileExists(entrypoint.lockFilePath),
+ hasDirectDependencies: rootPubspec.dependencies.values.any(
+ // Test if it contains non-SDK dependencies
+ (c) => c.source is! SdkSource,
+ ),
+ hasDevDependencies: rootPubspec.devDependencies.values.any(
+ // Test if it contains non-SDK dependencies
+ (c) => c.source is! SdkSource,
+ ),
+ showTransitiveDependencies: showTransitiveDependencies,
+ hasUpgradableResolution: hasUpgradableResolution,
+ hasResolvableResolution: hasResolvableResolution,
+ directory: path.normalize(directory));
}
}
@@ -448,11 +449,10 @@
@required bool showTransitiveDependencies,
@required bool hasUpgradableResolution,
@required bool hasResolvableResolution,
+ @required String directory,
}) async {
- final explanation = mode.explanation;
- if (explanation != null) {
- log.message(explanation + '\n');
- }
+ final directoryDesc = directory == '.' ? '' : ' in $directory';
+ log.message(mode.explanation(directoryDesc) + '\n');
final markedRows =
Map.fromIterables(rows, await mode.markVersionDetails(rows));
@@ -603,7 +603,7 @@
Future<List<List<_MarkedVersionDetails>>> markVersionDetails(
List<_PackageDetails> packageDetails);
- String get explanation;
+ String explanation(String directoryDescription);
String get foundNoBadText;
String get allGood;
String get noResolutionText;
@@ -614,8 +614,8 @@
class _OutdatedMode implements Mode {
@override
- String get explanation => '''
-Showing outdated packages.
+ String explanation(String directoryDescription) => '''
+Showing outdated packages$directoryDescription.
[${log.red('*')}] indicates versions that are not the latest available.
''';
@@ -692,8 +692,8 @@
{@required this.shouldShowSpinner});
@override
- String get explanation => '''
-Showing dependencies that are currently not opted in to null-safety.
+ String explanation(String directoryDescription) => '''
+Showing dependencies$directoryDescription that are currently not opted in to null-safety.
[${log.red(_notCompliantEmoji)}] indicates versions without null safety support.
[${log.green(_compliantEmoji)}] indicates versions opting in to null safety.
''';
diff --git a/lib/src/command/remove.dart b/lib/src/command/remove.dart
index 9ed4ebe..b899988 100644
--- a/lib/src/command/remove.dart
+++ b/lib/src/command/remove.dart
@@ -41,6 +41,8 @@
argParser.addFlag('precompile',
help: 'Precompile executables in immediate dependencies.');
+ argParser.addOption('directory',
+ abbr: 'C', help: 'Run this in the directory<dir>.', valueHelp: 'dir');
}
@override
@@ -66,7 +68,7 @@
/// Update the pubspec.
_writeRemovalToPubspec(packages);
- await Entrypoint.current(cache).acquireDependencies(SolveType.GET,
+ await Entrypoint(directory, cache).acquireDependencies(SolveType.GET,
precompile: argResults['precompile']);
}
}
diff --git a/lib/src/command/run.dart b/lib/src/command/run.dart
index 7491d61..4d6e7c6 100644
--- a/lib/src/command/run.dart
+++ b/lib/src/command/run.dart
@@ -45,6 +45,8 @@
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');
}
@override
diff --git a/lib/src/command/upgrade.dart b/lib/src/command/upgrade.dart
index 81aa747..499379e 100644
--- a/lib/src/command/upgrade.dart
+++ b/lib/src/command/upgrade.dart
@@ -62,6 +62,8 @@
'and updates pubspec.yaml.',
negatable: false,
);
+ argParser.addOption('directory',
+ abbr: 'C', help: 'Run this in the directory<dir>.', valueHelp: 'dir');
}
/// Avoid showing spinning progress messages when not in a terminal.
@@ -218,7 +220,7 @@
// 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.current(cache).acquireDependencies(
+ await Entrypoint(directory, cache).acquireDependencies(
SolveType.UPGRADE,
precompile: _precompile,
);
@@ -311,7 +313,7 @@
// 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.current(cache).acquireDependencies(
+ await Entrypoint(directory, cache).acquireDependencies(
SolveType.UPGRADE,
precompile: _precompile,
);
diff --git a/lib/src/command/uploader.dart b/lib/src/command/uploader.dart
index 6fd09d2..99a6a57 100644
--- a/lib/src/command/uploader.dart
+++ b/lib/src/command/uploader.dart
@@ -35,6 +35,8 @@
argParser.addOption('package',
help: 'The package whose uploaders will be modified.\n'
'(defaults to the current package)');
+ argParser.addOption('directory',
+ abbr: 'C', help: 'Run this in the directory<dir>.', valueHelp: 'dir');
}
@override
diff --git a/lib/src/command_runner.dart b/lib/src/command_runner.dart
index f1ecb4d..8210f42 100644
--- a/lib/src/command_runner.dart
+++ b/lib/src/command_runner.dart
@@ -44,6 +44,9 @@
class PubCommandRunner extends CommandRunner<int> implements PubTopLevel {
@override
+ String get directory => _argResults['directory'];
+
+ @override
bool get captureStackChains {
return _argResults['trace'] ||
_argResults['verbose'] ||
@@ -109,6 +112,13 @@
});
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',
+ );
// When adding new commands be sure to also add them to
// `pub_embeddable_command.dart`.
diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index 55a56b3..127bc0a 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -169,11 +169,6 @@
/// The path to the directory containing dependency executable snapshots.
String get _snapshotPath => p.join(cachePath, 'bin');
- /// Loads the entrypoint for the package at the current directory.
- Entrypoint.current(this.cache)
- : root = Package.load(null, '.', cache.sources),
- isGlobal = false;
-
/// Loads the entrypoint from a package at [rootDir].
Entrypoint(String rootDir, this.cache)
: root = Package.load(null, rootDir, cache.sources),
diff --git a/lib/src/pub_embeddable_command.dart b/lib/src/pub_embeddable_command.dart
index 6b147fc..3a56d9a 100644
--- a/lib/src/pub_embeddable_command.dart
+++ b/lib/src/pub_embeddable_command.dart
@@ -32,11 +32,21 @@
@override
String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-global';
+ @override
+ String get directory => argResults['directory'];
+
PubEmbeddableCommand() : super() {
argParser.addFlag('trace',
help: 'Print debugging information when an error occurs.');
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',
+ );
// This list is intentionally shorter than the one in
// pub_command_runner.dart.
//
diff --git a/lib/src/solver/report.dart b/lib/src/solver/report.dart
index 39f005f..3fd18cf 100644
--- a/lib/src/solver/report.dart
+++ b/lib/src/solver/report.dart
@@ -2,6 +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.
+import 'package:path/path.dart' as path;
import 'package:pub_semver/pub_semver.dart';
import '../command_runner.dart';
@@ -70,25 +71,33 @@
return oldId != newId;
}).length;
+ var suffix = '';
+ if (_root.dir != null) {
+ final dir = path.normalize(_root.dir);
+ if (dir != '.') {
+ suffix = ' in $dir';
+ }
+ }
+
if (dryRun) {
if (numChanged == 0) {
- log.message('No dependencies would change.');
+ log.message('No dependencies would change$suffix.');
} else if (numChanged == 1) {
- log.message('Would change $numChanged dependency.');
+ log.message('Would change $numChanged dependency$suffix.');
} else {
- log.message('Would change $numChanged dependencies.');
+ log.message('Would change $numChanged dependencies$suffix.');
}
} else {
if (numChanged == 0) {
if (_type == SolveType.GET) {
- log.message('Got dependencies!');
+ log.message('Got dependencies$suffix!');
} else {
- log.message('No dependencies changed.');
+ log.message('No dependencies changed$suffix.');
}
} else if (numChanged == 1) {
- log.message('Changed $numChanged dependency!');
+ log.message('Changed $numChanged dependency$suffix!');
} else {
- log.message('Changed $numChanged dependencies!');
+ log.message('Changed $numChanged dependencies$suffix!');
}
}
}
diff --git a/test/directory_option_test.dart b/test/directory_option_test.dart
new file mode 100644
index 0000000..cb3398d
--- /dev/null
+++ b/test/directory_option_test.dart
@@ -0,0 +1,92 @@
+// 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:convert';
+
+import 'package:path/path.dart' as p;
+import 'package:test/test.dart';
+import 'package:shelf/shelf.dart' as shelf;
+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..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'});
+ };
+
+ await validPackage.create();
+ await dir(appPath, [
+ dir('bin', [
+ file('app.dart', '''
+main() => print('Hi');
+''')
+ ]),
+ dir('example', [
+ pubspec({
+ 'name': 'example',
+ 'environment': {'sdk': '>=1.2.0 <2.0.0'},
+ 'dependencies': {
+ 'test_pkg': {'path': '../'}
+ }
+ })
+ ]),
+ dir('example2', [
+ pubspec({
+ 'name': 'example',
+ 'environment': {'sdk': '>=1.2.0 <2.0.0'},
+ 'dependencies': {
+ 'myapp': {'path': '../'} // Wrong name of dependency
+ }
+ })
+ ]),
+ ]).create();
+ final buffer = StringBuffer();
+ Future<void> run(List<String> args) async {
+ await runPubIntoBuffer(
+ args,
+ buffer,
+ 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/embedding/goldens/helptext.txt b/test/embedding/goldens/helptext.txt
index 864e30f..c06b931 100644
--- a/test/embedding/goldens/helptext.txt
+++ b/test/embedding/goldens/helptext.txt
@@ -28,9 +28,11 @@
[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] -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.
@@ -54,9 +56,11 @@
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".
+-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.
@@ -85,6 +89,7 @@
-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>.
Run "pub_command_runner help" to see global options.
See https://dart.dev/tools/pub/cmd/pub-get for detailed documentation.
diff --git a/test/goldens/directory_option.txt b/test/goldens/directory_option.txt
new file mode 100644
index 0000000..0465b6b
--- /dev/null
+++ b/test/goldens/directory_option.txt
@@ -0,0 +1,81 @@
+$ pub add --directory=myapp foo
+Resolving dependencies...
++ foo 1.0.0
+Changed 1 dependency in myapp!
+
+$ pub -C myapp add bar
+Resolving dependencies...
++ bar 1.2.3
+Changed 1 dependency in myapp!
+
+$ pub -C myapp/example get --directory=myapp bar
+Resolving dependencies...
+Got dependencies in myapp!
+
+$ pub remove bar -C myapp
+Resolving dependencies...
+These packages are no longer being depended on:
+- bar 1.2.3
+Changed 1 dependency in myapp!
+
+$ pub get bar -C myapp
+Resolving dependencies...
+Got dependencies in myapp!
+
+$ pub get bar -C myapp/example
+Resolving dependencies...
++ 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...
+[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...
+ foo 1.0.0
+No dependencies changed in myapp.
+
+$ pub upgrade bar -C myapp
+Resolving dependencies...
+ foo 1.0.0
+No dependencies changed in myapp.
+
+$ pub run -C myapp bin/app.dart
+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
+[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/lish/force_cannot_be_combined_with_dry_run_test.dart b/test/lish/force_cannot_be_combined_with_dry_run_test.dart
index ea46ead..15456e0 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
@@ -16,9 +16,10 @@
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.
+-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/outdated/goldens/bad_arguments.txt b/test/outdated/goldens/bad_arguments.txt
index 1c0f1a7..b184530 100644
--- a/test/outdated/goldens/bad_arguments.txt
+++ b/test/outdated/goldens/bad_arguments.txt
@@ -21,6 +21,7 @@
[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.
@@ -49,6 +50,7 @@
[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.
diff --git a/test/outdated/goldens/helptext.txt b/test/outdated/goldens/helptext.txt
index 85e8836..20a4ecc 100644
--- a/test/outdated/goldens/helptext.txt
+++ b/test/outdated/goldens/helptext.txt
@@ -21,6 +21,7 @@
fullfilling --mode.
--[no-]transitive Show transitive dependencies.
(defaults to off in --mode=null-safety).
+-C, --directory=<dir> Run this in the directory<dir>.
Run "pub help" to see global options.
See https://dart.dev/tools/pub/cmd/pub-outdated for detailed documentation.
diff --git a/test/outdated/goldens/no_pubspec.txt b/test/outdated/goldens/no_pubspec.txt
index 85afd8b..ec3a40a 100644
--- a/test/outdated/goldens/no_pubspec.txt
+++ b/test/outdated/goldens/no_pubspec.txt
@@ -1,4 +1,4 @@
-$ pub outdated
+$ 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 a3210ff..1c0a28d 100644
--- a/test/outdated/outdated_test.dart
+++ b/test/outdated/outdated_test.dart
@@ -2,61 +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.
-import 'dart:io';
-
import 'package:test/test.dart';
import '../descriptor.dart' as d;
import '../golden_file.dart';
import '../test_pub.dart';
-/// Runs `pub outdated [args]` and appends the output to [buffer].
-Future<void> runPubOutdated(List<String> args, StringBuffer buffer,
- {Map<String, String> environment}) async {
- final process =
- await startPub(args: ['outdated', ...args], environment: environment);
- final exitCode = await process.exitCode;
-
- buffer.writeln([
- '\$ pub outdated ${args.join(' ')}',
- ...await process.stdout.rest.where((line) {
- // Downloading order is not deterministic, so to avoid flakiness we filter
- // out these lines.
- return !line.startsWith('Downloading ');
- }).toList(),
- ].join('\n'));
- final stderrLines = await process.stderr.rest.toList();
- for (final line in stderrLines) {
- final sanitized = line
- .replaceAll(d.sandbox, r'$SANDBOX')
- .replaceAll(Platform.pathSeparator, '/');
- buffer.writeln('[ERR] $sanitized');
- }
- if (exitCode != 0) {
- buffer.writeln('[Exit code] $exitCode');
- }
- buffer.write('\n');
-}
-
/// 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 [
- ['--json'],
- ['--no-color'],
- ['--no-color', '--no-transitive'],
- ['--no-color', '--up-to-date'],
- ['--no-color', '--prereleases'],
- ['--no-color', '--no-dev-dependencies'],
- ['--no-color', '--no-dependency-overrides'],
- ['--no-color', '--mode=null-safety'],
- ['--no-color', '--mode=null-safety', '--transitive'],
- ['--no-color', '--mode=null-safety', '--no-prereleases'],
- ['--json', '--mode=null-safety'],
- ['--json', '--no-dev-dependencies'],
+ ['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 runPubOutdated(args, buffer, environment: environment);
+ await runPubIntoBuffer(args, buffer, environment: environment);
}
// The easiest way to update the golden files is to delete them and rerun the
// test.
@@ -66,7 +36,10 @@
Future<void> main() async {
test('help text', () async {
final buffer = StringBuffer();
- await runPubOutdated(['--help'], buffer);
+ await runPubIntoBuffer(
+ ['outdated', '--help'],
+ buffer,
+ );
expectMatchesGoldenFile(
buffer.toString(), 'test/outdated/goldens/helptext.txt');
});
@@ -74,10 +47,7 @@
test('no pubspec', () async {
await d.dir(appPath, []).create();
final buffer = StringBuffer();
- await runPubOutdated(
- [],
- buffer,
- );
+ await runPubIntoBuffer(['outdated'], buffer);
expectMatchesGoldenFile(
buffer.toString(), 'test/outdated/goldens/no_pubspec.txt');
});
@@ -469,8 +439,8 @@
test("doesn't allow arguments. Handles bad flags", () async {
final sb = StringBuffer();
- await runPubOutdated(['random_argument'], sb);
- await runPubOutdated(['--bad_flag'], sb);
+ await runPubIntoBuffer(['outdated', 'random_argument'], sb);
+ await runPubIntoBuffer(['outdated', '--bad_flag'], sb);
expectMatchesGoldenFile(
sb.toString(), 'test/outdated/goldens/bad_arguments.txt');
});
diff --git a/test/pub_uploader_test.dart b/test/pub_uploader_test.dart
index f1967e0..92f5a06 100644
--- a/test/pub_uploader_test.dart
+++ b/test/pub_uploader_test.dart
@@ -17,9 +17,10 @@
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)
+-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/run/dartdev/errors_if_path_in_dependency_test.dart b/test/run/dartdev/errors_if_path_in_dependency_test.dart
index fcd8d0c..38b2e74 100644
--- a/test/run/dartdev/errors_if_path_in_dependency_test.dart
+++ b/test/run/dartdev/errors_if_path_in_dependency_test.dart
@@ -33,6 +33,7 @@
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/run/errors_if_no_executable_is_given_test.dart b/test/run/errors_if_no_executable_is_given_test.dart
index f3195fa..44fdf4b 100644
--- a/test/run/errors_if_no_executable_is_given_test.dart
+++ b/test/run/errors_if_no_executable_is_given_test.dart
@@ -25,6 +25,7 @@
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/run/errors_if_path_in_dependency_test.dart b/test/run/errors_if_path_in_dependency_test.dart
index 76cbf79..ff7edb8 100644
--- a/test/run/errors_if_path_in_dependency_test.dart
+++ b/test/run/errors_if_path_in_dependency_test.dart
@@ -33,6 +33,7 @@
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/test_pub.dart b/test/test_pub.dart
index 0e8bbd4..f780f3b 100644
--- a/test/test_pub.dart
+++ b/test/test_pub.dart
@@ -841,3 +841,48 @@
/// A [StreamMatcher] that matches multiple lines of output.
StreamMatcher emitsLines(String output) => emitsInOrder(output.split('\n'));
+
+Iterable<String> _filter(List<String> input) {
+ return input
+ // Downloading order is not deterministic, so to avoid flakiness we filter
+ // out these lines.
+ .where((line) => !line.startsWith('Downloading '))
+ // Any paths in output should be relative to the sandbox and with forward
+ // slashes to be stable across platforms.
+ .map((line) {
+ line = line
+ .replaceAll(d.sandbox, r'$SANDBOX')
+ .replaceAll(Platform.pathSeparator, '/');
+ if (globalPackageServer != null) {
+ line = line.replaceAll(globalPackageServer.port.toString(), '\$PORT');
+ }
+ return line;
+ });
+}
+
+/// Runs `pub outdated [args]` and appends the output to [buffer].
+Future<void> runPubIntoBuffer(
+ List<String> args,
+ StringBuffer buffer, {
+ Map<String, String> environment,
+ String workingDirectory,
+}) async {
+ final process = await startPub(
+ args: args,
+ environment: environment,
+ workingDirectory: workingDirectory,
+ );
+ final exitCode = await process.exitCode;
+
+ 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');
+ }
+ if (exitCode != 0) {
+ buffer.writeln('[Exit code] $exitCode');
+ }
+ buffer.write('\n');
+}