mirror of
https://github.com/dart-lang/sdk
synced 2024-09-22 20:23:41 +00:00
Add a "pub global run" command.
BUG=https://code.google.com/p/dart/issues/detail?id=18538 R=nweiz@google.com Review URL: https://codereview.chromium.org//354763006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@37963 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
824f4d2ea9
commit
d0d175bf69
|
@ -25,7 +25,6 @@ import 'command/uploader.dart';
|
|||
import 'command/version.dart';
|
||||
import 'entrypoint.dart';
|
||||
import 'exceptions.dart';
|
||||
import 'exit_codes.dart' as exit_codes;
|
||||
import 'log.dart' as log;
|
||||
import 'global_packages.dart';
|
||||
import 'system_cache.dart';
|
||||
|
@ -68,7 +67,7 @@ abstract class PubCommand {
|
|||
/// [commands].
|
||||
static void usageErrorWithCommands(Map<String, PubCommand> commands,
|
||||
String message) {
|
||||
throw new UsageException(message, _listCommands(commands));
|
||||
throw new UsageException(message)..bindUsage(_listCommands(commands));
|
||||
}
|
||||
|
||||
/// Writes [commands] in a nicely formatted list to [buffer].
|
||||
|
@ -191,7 +190,10 @@ abstract class PubCommand {
|
|||
entrypoint = new Entrypoint(path.current, cache);
|
||||
}
|
||||
|
||||
return syncFuture(onRun);
|
||||
return syncFuture(onRun).catchError((error) {
|
||||
if (error is UsageException) error.bindUsage(_getUsage());
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
/// Override this to perform the specific command.
|
||||
|
@ -214,13 +216,6 @@ abstract class PubCommand {
|
|||
log.message('$description\n\n${_getUsage()}');
|
||||
}
|
||||
|
||||
// TODO(rnystrom): Use this in other places handle usage failures.
|
||||
/// Throw a [UsageException] for a usage error of this command with
|
||||
/// [message].
|
||||
void usageError(String message) {
|
||||
throw new UsageException(message, _getUsage());
|
||||
}
|
||||
|
||||
/// Parses a user-supplied integer [intString] named [name].
|
||||
///
|
||||
/// If the parsing fails, prints a usage message and exits.
|
||||
|
|
|
@ -7,6 +7,7 @@ library pub.command.global;
|
|||
import '../command.dart';
|
||||
import 'global_activate.dart';
|
||||
import 'global_deactivate.dart';
|
||||
import 'global_run.dart';
|
||||
|
||||
/// Handles the `global` pub command.
|
||||
class GlobalCommand extends PubCommand {
|
||||
|
@ -15,6 +16,7 @@ class GlobalCommand extends PubCommand {
|
|||
|
||||
final subcommands = {
|
||||
"activate": new GlobalActivateCommand(),
|
||||
"deactivate": new GlobalDeactivateCommand()
|
||||
"deactivate": new GlobalDeactivateCommand(),
|
||||
"run": new GlobalRunCommand()
|
||||
};
|
||||
}
|
||||
|
|
49
sdk/lib/_internal/pub/lib/src/command/global_run.dart
Normal file
49
sdk/lib/_internal/pub/lib/src/command/global_run.dart
Normal file
|
@ -0,0 +1,49 @@
|
|||
// 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.
|
||||
|
||||
library pub.command.global_run;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:barback/barback.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:stack_trace/stack_trace.dart';
|
||||
|
||||
import '../barback/asset_environment.dart';
|
||||
import '../command.dart';
|
||||
import '../entrypoint.dart';
|
||||
import '../executable.dart';
|
||||
import '../exit_codes.dart' as exit_codes;
|
||||
import '../io.dart';
|
||||
import '../log.dart' as log;
|
||||
import '../utils.dart';
|
||||
|
||||
/// Handles the `global run` pub command.
|
||||
class GlobalRunCommand extends PubCommand {
|
||||
bool get requiresEntrypoint => false;
|
||||
bool get takesArguments => true;
|
||||
bool get allowTrailingOptions => false;
|
||||
String get description =>
|
||||
"Run an executable from a globally activated package.";
|
||||
String get usage => "pub global run <package> <executable> [args...]";
|
||||
|
||||
Future onRun() {
|
||||
if (commandOptions.rest.isEmpty) {
|
||||
usageError("Must specify a package and executable to run.");
|
||||
}
|
||||
|
||||
if (commandOptions.rest.length == 1) {
|
||||
usageError("Must specify an executable to run.");
|
||||
}
|
||||
|
||||
var package = commandOptions.rest[0];
|
||||
var executable = commandOptions.rest[1];
|
||||
var args = commandOptions.rest.skip(2);
|
||||
|
||||
return globals.find(package).then((entrypoint) {
|
||||
return runExecutable(entrypoint, package, executable, args);
|
||||
}).then(flushThenExit);
|
||||
}
|
||||
}
|
|
@ -36,7 +36,7 @@ class ListPackageDirsCommand extends PubCommand {
|
|||
// Include the local paths to all locked packages.
|
||||
var packages = {};
|
||||
var futures = [];
|
||||
entrypoint.loadLockFile().packages.forEach((name, package) {
|
||||
entrypoint.lockFile.packages.forEach((name, package) {
|
||||
var source = entrypoint.cache.sources[package.source];
|
||||
futures.add(source.getDirectory(package).then((packageDir) {
|
||||
packages[name] = path.join(packageDir, "lib");
|
||||
|
|
|
@ -13,13 +13,12 @@ import 'package:stack_trace/stack_trace.dart';
|
|||
|
||||
import '../barback/asset_environment.dart';
|
||||
import '../command.dart';
|
||||
import '../executable.dart';
|
||||
import '../exit_codes.dart' as exit_codes;
|
||||
import '../io.dart';
|
||||
import '../log.dart' as log;
|
||||
import '../utils.dart';
|
||||
|
||||
final _arrow = getSpecial('\u2192', '=>');
|
||||
|
||||
/// Handles the `run` pub command.
|
||||
class RunCommand extends PubCommand {
|
||||
bool get takesArguments => true;
|
||||
|
@ -32,109 +31,20 @@ class RunCommand extends PubCommand {
|
|||
usageError("Must specify an executable to run.");
|
||||
}
|
||||
|
||||
// Unless the user overrides the verbosity, we want to filter out the
|
||||
// normal pub output shown while loading the environment.
|
||||
if (log.verbosity == log.Verbosity.NORMAL) {
|
||||
log.verbosity = log.Verbosity.WARNING;
|
||||
}
|
||||
|
||||
var environment;
|
||||
var package = entrypoint.root.name;
|
||||
var rootDir;
|
||||
var scriptPath;
|
||||
var args;
|
||||
return AssetEnvironment.create(entrypoint, BarbackMode.RELEASE,
|
||||
WatcherType.NONE, useDart2JS: false)
|
||||
.then((_environment) {
|
||||
environment = _environment;
|
||||
var executable = commandOptions.rest[0];
|
||||
var args = commandOptions.rest.skip(1).toList();
|
||||
|
||||
// Show in-progress errors, but not results. Those get handled
|
||||
// implicitly by getAllAssets().
|
||||
environment.barback.errors.listen((error) {
|
||||
log.error(log.red("Build error:\n$error"));
|
||||
});
|
||||
// A command like "foo:bar" runs the "bar" script from the "foo" package.
|
||||
// If there is no colon prefix, default to the root package.
|
||||
if (executable.contains(":")) {
|
||||
var components = split1(executable, ":");
|
||||
package = components[0];
|
||||
executable = components[1];
|
||||
}
|
||||
|
||||
var script = commandOptions.rest[0];
|
||||
args = commandOptions.rest.skip(1).toList();
|
||||
|
||||
// A command like "foo:bar" runs the "bar" script from the "foo" package.
|
||||
// If there is no colon prefix, default to the root package.
|
||||
if (script.contains(":")) {
|
||||
var components = split1(script, ":");
|
||||
package = components[0];
|
||||
script = components[1];
|
||||
|
||||
var dep = entrypoint.root.immediateDependencies.firstWhere(
|
||||
(dep) => dep.name == package, orElse: () => null);
|
||||
if (dep == null) {
|
||||
if (environment.graph.packages.containsKey(package)) {
|
||||
dataError('Package "$package" is not an immediate dependency.\n'
|
||||
'Cannot run executables in transitive dependencies.');
|
||||
} else {
|
||||
dataError('Could not find package "$package". Did you forget to '
|
||||
'add a dependency?');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the command has a path separator, then it's a path relative to the
|
||||
// root of the package. Otherwise, it's implicitly understood to be in
|
||||
// "bin".
|
||||
var parts = path.split(script);
|
||||
if (parts.length > 1) {
|
||||
if (package != entrypoint.root.name) {
|
||||
usageError("Can not run an executable in a subdirectory of a "
|
||||
"dependency.");
|
||||
}
|
||||
|
||||
scriptPath = "${path.url.joinAll(parts.skip(1))}.dart";
|
||||
rootDir = parts.first;
|
||||
} else {
|
||||
scriptPath = "$script.dart";
|
||||
rootDir = "bin";
|
||||
}
|
||||
|
||||
if (package == entrypoint.root.name) {
|
||||
// Serve the entire root-most directory containing the entrypoint. That
|
||||
// ensures that, for example, things like `import '../../utils.dart';`
|
||||
// will work from within some deeply nested script.
|
||||
return environment.serveDirectory(rootDir);
|
||||
} else {
|
||||
// For other packages, always use the "bin" directory.
|
||||
return environment.servePackageBinDirectory(package);
|
||||
}
|
||||
}).then((server) {
|
||||
// Try to make sure the entrypoint script exists (or is generated) before
|
||||
// we spawn the process to run it.
|
||||
return environment.barback.getAssetById(
|
||||
new AssetId(package, path.url.join(rootDir, scriptPath))).then((_) {
|
||||
|
||||
// Run in checked mode.
|
||||
// TODO(rnystrom): Make this configurable.
|
||||
var mode = "--checked";
|
||||
args = [mode, server.url.resolve(scriptPath).toString()]..addAll(args);
|
||||
|
||||
return Process.start(Platform.executable, args).then((process) {
|
||||
// Note: we're not using process.std___.pipe(std___) here because
|
||||
// that prevents pub from also writing to the output streams.
|
||||
process.stderr.listen(stderr.add);
|
||||
process.stdout.listen(stdout.add);
|
||||
stdin.listen(process.stdin.add);
|
||||
|
||||
return process.exitCode;
|
||||
}).then(flushThenExit);
|
||||
}).catchError((error, stackTrace) {
|
||||
if (error is! AssetNotFoundException) throw error;
|
||||
|
||||
var message = "Could not find ${path.join(rootDir, scriptPath)}";
|
||||
if (package != entrypoint.root.name) {
|
||||
message += " in package $package";
|
||||
}
|
||||
|
||||
log.error("$message.");
|
||||
log.fine(new Chain.forTrace(stackTrace));
|
||||
return flushThenExit(exit_codes.NO_INPUT);
|
||||
});
|
||||
});
|
||||
return runExecutable(entrypoint, package, executable, args)
|
||||
.then(flushThenExit);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,17 +43,36 @@ class Entrypoint {
|
|||
/// the network.
|
||||
final SystemCache cache;
|
||||
|
||||
/// The lockfile for the entrypoint.
|
||||
///
|
||||
/// If not provided to the entrypoint, it will be laoded lazily from disc.
|
||||
LockFile _lockFile;
|
||||
|
||||
/// Loads the entrypoint from a package at [rootDir].
|
||||
Entrypoint(String rootDir, SystemCache cache)
|
||||
: root = new Package.load(null, rootDir, cache.sources),
|
||||
cache = cache;
|
||||
|
||||
// TODO(rnystrom): Make this path configurable.
|
||||
/// Creates an entrypoint given package and lockfile objects.
|
||||
Entrypoint.inMemory(this.root, this._lockFile, this.cache);
|
||||
|
||||
/// The path to the entrypoint's "packages" directory.
|
||||
String get packagesDir => path.join(root.dir, 'packages');
|
||||
|
||||
/// `true` if the entrypoint package currently has a lock file.
|
||||
bool get lockFileExists => entryExists(lockFilePath);
|
||||
bool get lockFileExists => _lockFile != null || entryExists(lockFilePath);
|
||||
|
||||
LockFile get lockFile {
|
||||
if (_lockFile != null) return _lockFile;
|
||||
|
||||
if (!lockFileExists) {
|
||||
_lockFile = new LockFile.empty();
|
||||
} else {
|
||||
_lockFile = new LockFile.load(lockFilePath, cache.sources);
|
||||
}
|
||||
|
||||
return _lockFile;
|
||||
}
|
||||
|
||||
/// The path to the entrypoint package's lockfile.
|
||||
String get lockFilePath => path.join(root.dir, 'pubspec.lock');
|
||||
|
@ -73,7 +92,7 @@ class Entrypoint {
|
|||
Future acquireDependencies({List<String> useLatest, bool isUpgrade: false,
|
||||
bool dryRun: false}) {
|
||||
return syncFuture(() {
|
||||
return resolveVersions(cache.sources, root, lockFile: loadLockFile(),
|
||||
return resolveVersions(cache.sources, root, lockFile: lockFile,
|
||||
useLatest: useLatest, upgradeAll: isUpgrade && useLatest.isEmpty);
|
||||
}).then((result) {
|
||||
if (!result.succeeded) throw result.error;
|
||||
|
@ -111,15 +130,6 @@ class Entrypoint {
|
|||
return source.get(id, packageDir).then((_) => source.resolveId(id));
|
||||
}
|
||||
|
||||
/// Loads the list of concrete package versions from the `pubspec.lock`, if it
|
||||
/// exists.
|
||||
///
|
||||
/// If it doesn't, this completes to an empty [LockFile].
|
||||
LockFile loadLockFile() {
|
||||
if (!lockFileExists) return new LockFile.empty();
|
||||
return new LockFile.load(lockFilePath, cache.sources);
|
||||
}
|
||||
|
||||
/// Determines whether or not the lockfile is out of date with respect to the
|
||||
/// pubspec.
|
||||
///
|
||||
|
@ -174,8 +184,6 @@ class Entrypoint {
|
|||
/// pubspec.
|
||||
Future _ensureLockFileIsUpToDate() {
|
||||
return syncFuture(() {
|
||||
var lockFile = loadLockFile();
|
||||
|
||||
// If we don't have a current lock file, we definitely need to install.
|
||||
if (!_isLockFileUpToDate(lockFile)) {
|
||||
if (lockFileExists) {
|
||||
|
@ -214,7 +222,6 @@ class Entrypoint {
|
|||
/// and up to date.
|
||||
Future<PackageGraph> loadPackageGraph() {
|
||||
return _ensureLockFileIsUpToDate().then((_) {
|
||||
var lockFile = loadLockFile();
|
||||
return Future.wait(lockFile.packages.values.map((id) {
|
||||
var source = cache.sources[id.source];
|
||||
return source.getDirectory(id)
|
||||
|
|
|
@ -51,12 +51,23 @@ class SilentException extends WrappedException {
|
|||
/// A class for command usage exceptions.
|
||||
class UsageException extends ApplicationException {
|
||||
/// The command usage information.
|
||||
final String usage;
|
||||
String _usage;
|
||||
|
||||
UsageException(String message, this.usage)
|
||||
UsageException(String message)
|
||||
: super(message);
|
||||
|
||||
String toString() => "$message\n\n$usage";
|
||||
String toString() {
|
||||
if (_usage == null) return message;
|
||||
return "$message\n\n$_usage";
|
||||
}
|
||||
|
||||
/// Attach usage information to the exception.
|
||||
///
|
||||
/// This is done after the exception is created so that code outside of the
|
||||
/// command can still generate usage errors.
|
||||
void bindUsage(String usage) {
|
||||
_usage = usage;
|
||||
}
|
||||
}
|
||||
|
||||
/// A class for errors in a command's input data.
|
||||
|
|
125
sdk/lib/_internal/pub/lib/src/executable.dart
Normal file
125
sdk/lib/_internal/pub/lib/src/executable.dart
Normal file
|
@ -0,0 +1,125 @@
|
|||
// 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.
|
||||
|
||||
library pub.executable;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:barback/barback.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:stack_trace/stack_trace.dart';
|
||||
|
||||
import 'barback/asset_environment.dart';
|
||||
import 'barback/barback_server.dart';
|
||||
import 'entrypoint.dart';
|
||||
import 'exit_codes.dart' as exit_codes;
|
||||
import 'log.dart' as log;
|
||||
import 'utils.dart';
|
||||
|
||||
/// Runs [executable] from [package] reachable from [entrypoint].
|
||||
///
|
||||
/// The executable string is a relative Dart file path using native path
|
||||
/// separators without a trailing ".dart" extension. It is contained within
|
||||
/// [package], which should either be the entrypoint package or an immediate
|
||||
/// dependency of it.
|
||||
///
|
||||
/// Arguments from [args] will be passed to the spawned Dart application.
|
||||
///
|
||||
/// Returns the exit code of the spawned app.
|
||||
Future<int> runExecutable(Entrypoint entrypoint, String package,
|
||||
String executable, Iterable<String> args) {
|
||||
// If the command has a path separator, then it's a path relative to the
|
||||
// root of the package. Otherwise, it's implicitly understood to be in
|
||||
// "bin".
|
||||
var rootDir = "bin";
|
||||
var parts = p.split(executable);
|
||||
if (parts.length > 1) {
|
||||
if (package != entrypoint.root.name) {
|
||||
usageError("Cannot run an executable in a subdirectory of a dependency.");
|
||||
}
|
||||
|
||||
rootDir = parts.first;
|
||||
} else {
|
||||
executable = p.join("bin", executable);
|
||||
}
|
||||
|
||||
// Unless the user overrides the verbosity, we want to filter out the
|
||||
// normal pub output shown while loading the environment.
|
||||
if (log.verbosity == log.Verbosity.NORMAL) {
|
||||
log.verbosity = log.Verbosity.WARNING;
|
||||
}
|
||||
|
||||
var environment;
|
||||
return AssetEnvironment.create(entrypoint, BarbackMode.RELEASE,
|
||||
WatcherType.NONE, useDart2JS: false).then((_environment) {
|
||||
environment = _environment;
|
||||
|
||||
environment.barback.errors.listen((error) {
|
||||
log.error(log.red("Build error:\n$error"));
|
||||
});
|
||||
|
||||
if (package == entrypoint.root.name) {
|
||||
// Serve the entire root-most directory containing the entrypoint. That
|
||||
// ensures that, for example, things like `import '../../utils.dart';`
|
||||
// will work from within some deeply nested script.
|
||||
return environment.serveDirectory(rootDir);
|
||||
}
|
||||
|
||||
// Make sure the dependency exists.
|
||||
var dep = entrypoint.root.immediateDependencies.firstWhere(
|
||||
(dep) => dep.name == package, orElse: () => null);
|
||||
if (dep == null) {
|
||||
if (environment.graph.packages.containsKey(package)) {
|
||||
dataError('Package "$package" is not an immediate dependency.\n'
|
||||
'Cannot run executables in transitive dependencies.');
|
||||
} else {
|
||||
dataError('Could not find package "$package". Did you forget to '
|
||||
'add a dependency?');
|
||||
}
|
||||
}
|
||||
|
||||
// For other packages, always use the "bin" directory.
|
||||
return environment.servePackageBinDirectory(package);
|
||||
}).then((server) {
|
||||
// Try to make sure the entrypoint script exists (or is generated) before
|
||||
// we spawn the process to run it.
|
||||
var assetPath = "${p.url.joinAll(p.split(executable))}.dart";
|
||||
var id = new AssetId(server.package, assetPath);
|
||||
return environment.barback.getAssetById(id).then((_) {
|
||||
var vmArgs = [];
|
||||
|
||||
// Run in checked mode.
|
||||
// TODO(rnystrom): Make this configurable.
|
||||
vmArgs.add("--checked");
|
||||
|
||||
// Get the URL of the executable, relative to the server's root directory.
|
||||
var relativePath = p.url.relative(assetPath,
|
||||
from: p.url.joinAll(p.split(server.rootDirectory)));
|
||||
vmArgs.add(server.url.resolve(relativePath).toString());
|
||||
vmArgs.addAll(args);
|
||||
|
||||
return Process.start(Platform.executable, vmArgs).then((process) {
|
||||
// Note: we're not using process.std___.pipe(std___) here because
|
||||
// that prevents pub from also writing to the output streams.
|
||||
process.stderr.listen(stderr.add);
|
||||
process.stdout.listen(stdout.add);
|
||||
stdin.listen(process.stdin.add);
|
||||
|
||||
return process.exitCode;
|
||||
});
|
||||
}).catchError((error, stackTrace) {
|
||||
if (error is! AssetNotFoundException) throw error;
|
||||
|
||||
var message = "Could not find ${log.bold(executable + ".dart")}";
|
||||
if (package != entrypoint.root.name) {
|
||||
message += " in package ${log.bold(server.package)}";
|
||||
}
|
||||
|
||||
log.error("$message.");
|
||||
log.fine(new Chain.forTrace(stackTrace));
|
||||
return exit_codes.NO_INPUT;
|
||||
});
|
||||
});
|
||||
}
|
|
@ -10,6 +10,7 @@ import 'dart:io';
|
|||
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
import 'entrypoint.dart';
|
||||
import 'io.dart';
|
||||
import 'lock_file.dart';
|
||||
import 'log.dart' as log;
|
||||
|
@ -50,13 +51,11 @@ class GlobalPackages {
|
|||
/// Finds the latest version of the hosted package with [name] that matches
|
||||
/// [constraint] and makes it the active global version.
|
||||
Future activate(String name, VersionConstraint constraint) {
|
||||
var lockFilePath = p.join(_directory, name + ".lock");
|
||||
|
||||
// See if we already have it activated.
|
||||
var lockFile;
|
||||
var currentVersion;
|
||||
try {
|
||||
lockFile = new LockFile.load(lockFilePath, cache.sources);
|
||||
lockFile = new LockFile.load(_getLockFilePath(name), cache.sources);
|
||||
currentVersion = lockFile.packages[name].version;
|
||||
|
||||
// Pull the root package out of the lock file so the solver doesn't see
|
||||
|
@ -66,7 +65,7 @@ class GlobalPackages {
|
|||
log.message("Package ${log.bold(name)} is already active at "
|
||||
"version ${log.bold(currentVersion)}.");
|
||||
} on IOException catch (error) {
|
||||
// If we couldn't read the lock and version file, it's not activated.
|
||||
// If we couldn't read the lock file, it's not activated.
|
||||
lockFile = new LockFile.empty();
|
||||
}
|
||||
|
||||
|
@ -98,7 +97,7 @@ class GlobalPackages {
|
|||
lockFile.packages[name] = id;
|
||||
|
||||
ensureDir(_directory);
|
||||
writeTextFile(lockFilePath,
|
||||
writeTextFile(_getLockFilePath(name),
|
||||
lockFile.serialize(cache.rootDir, cache.sources));
|
||||
|
||||
log.message("Activated ${log.bold(package.name)} ${package.version}.");
|
||||
|
@ -123,6 +122,35 @@ class GlobalPackages {
|
|||
}
|
||||
}
|
||||
|
||||
/// Finds the active packge with [name].
|
||||
///
|
||||
/// Returns an [Entrypoint] loaded with the active package if found.
|
||||
Future<Entrypoint> find(String name) {
|
||||
var lockFile;
|
||||
var version;
|
||||
return syncFuture(() {
|
||||
try {
|
||||
lockFile = new LockFile.load(_getLockFilePath(name), cache.sources);
|
||||
version = lockFile.packages[name].version;
|
||||
} on IOException catch (error) {
|
||||
// If we couldn't read the lock file, it's not activated.
|
||||
dataError("No active package ${log.bold(name)}.");
|
||||
}
|
||||
}).then((_) {
|
||||
// Load the package from the cache.
|
||||
var id = new PackageId(name, _source.name, version, name);
|
||||
return _source.getDirectory(id);
|
||||
}).then((dir) {
|
||||
return new Package.load(name, dir, cache.sources);
|
||||
}).then((package) {
|
||||
// Pull the root package out of the lock file so the solver doesn't see
|
||||
// it.
|
||||
lockFile.packages.remove(name);
|
||||
|
||||
return new Entrypoint.inMemory(package, lockFile, cache);
|
||||
});
|
||||
}
|
||||
|
||||
/// Picks the best version of [package] to activate that meets [constraint].
|
||||
///
|
||||
/// If [version] is not `null`, this tries to maintain that version if
|
||||
|
@ -149,4 +177,7 @@ class GlobalPackages {
|
|||
return versions.last;
|
||||
});
|
||||
}
|
||||
|
||||
/// Gets the path to the lock file for an activated package with [name].
|
||||
String _getLockFilePath(name) => p.join(_directory, name + ".lock");
|
||||
}
|
||||
|
|
|
@ -845,6 +845,7 @@ void fail(String message, [innerError, StackTrace innerTrace]) {
|
|||
/// 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 new DataException(message);
|
||||
}
|
||||
void dataError(String message) => throw new DataException(message);
|
||||
|
||||
/// Throw a [UsageException] for a usage error of a command with [message].
|
||||
void usageError(String message) => throw new UsageException(message);
|
||||
|
|
|
@ -75,10 +75,9 @@ class DependencyValidator extends Validator {
|
|||
|
||||
/// Warn that dependencies should have version constraints.
|
||||
void _warnAboutNoConstraint(PackageDep dep) {
|
||||
var lockFile = entrypoint.loadLockFile();
|
||||
var message = 'Your dependency on "${dep.name}" should have a version '
|
||||
'constraint.';
|
||||
var locked = lockFile.packages[dep.name];
|
||||
var locked = entrypoint.lockFile.packages[dep.name];
|
||||
if (locked != null) {
|
||||
message = '$message For example:\n'
|
||||
'\n'
|
||||
|
@ -107,7 +106,7 @@ class DependencyValidator extends Validator {
|
|||
/// Warn that dependencies should have lower bounds on their constraints.
|
||||
void _warnAboutNoConstraintLowerBound(PackageDep dep) {
|
||||
var message = 'Your dependency on "${dep.name}" should have a lower bound.';
|
||||
var locked = entrypoint.loadLockFile().packages[dep.name];
|
||||
var locked = entrypoint.lockFile.packages[dep.name];
|
||||
if (locked != null) {
|
||||
var constraint;
|
||||
if (locked.version == (dep.constraint as VersionRange).max) {
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// 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.
|
||||
|
||||
import '../../../lib/src/exit_codes.dart' as exit_codes;
|
||||
import '../../test_pub.dart';
|
||||
|
||||
main() {
|
||||
initConfig();
|
||||
integration('fails if no executable was given', () {
|
||||
schedulePub(args: ["global", "run", "pkg"],
|
||||
error: """
|
||||
Must specify an executable to run.
|
||||
|
||||
Usage: pub global run <package> <executable> [args...]
|
||||
-h, --help Print usage information for this command.
|
||||
|
||||
Run "pub help" to see global options.
|
||||
""",
|
||||
exitCode: exit_codes.USAGE);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// 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.
|
||||
|
||||
import '../../../lib/src/exit_codes.dart' as exit_codes;
|
||||
import '../../test_pub.dart';
|
||||
|
||||
main() {
|
||||
initConfig();
|
||||
integration('fails if no package was given', () {
|
||||
schedulePub(args: ["global", "run"],
|
||||
error: """
|
||||
Must specify a package and executable to run.
|
||||
|
||||
Usage: pub global run <package> <executable> [args...]
|
||||
-h, --help Print usage information for this command.
|
||||
|
||||
Run "pub help" to see global options.
|
||||
""",
|
||||
exitCode: exit_codes.USAGE);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// 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.
|
||||
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
import '../../../lib/src/exit_codes.dart' as exit_codes;
|
||||
import '../../descriptor.dart' as d;
|
||||
import '../../test_pub.dart';
|
||||
|
||||
main() {
|
||||
initConfig();
|
||||
integration('errors if the script does not exist.', () {
|
||||
servePackages([packageMap("foo", "1.0.0")]);
|
||||
|
||||
schedulePub(args: ["global", "activate", "foo"]);
|
||||
|
||||
var pub = pubRun(global: true, args: ["foo", "script"]);
|
||||
pub.stderr.expect("Could not find ${p.join("bin", "script.dart")}.");
|
||||
pub.shouldExit(exit_codes.NO_INPUT);
|
||||
});
|
||||
}
|
26
sdk/lib/_internal/pub/test/global/run/runs_script_test.dart
Normal file
26
sdk/lib/_internal/pub/test/global/run/runs_script_test.dart
Normal file
|
@ -0,0 +1,26 @@
|
|||
// 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.
|
||||
|
||||
import '../../../lib/src/exit_codes.dart' as exit_codes;
|
||||
import '../../descriptor.dart' as d;
|
||||
import '../../test_pub.dart';
|
||||
|
||||
main() {
|
||||
initConfig();
|
||||
integration('runs a script in an activated package', () {
|
||||
servePackages([
|
||||
packageMap("foo", "1.0.0")
|
||||
], contents: [
|
||||
d.dir("bin", [
|
||||
d.file("script.dart", "main(args) => print('ok');")
|
||||
])
|
||||
]);
|
||||
|
||||
schedulePub(args: ["global", "activate", "foo"]);
|
||||
|
||||
var pub = pubRun(global: true, args: ["foo", "script"]);
|
||||
pub.stdout.expect("ok");
|
||||
pub.shouldExit();
|
||||
});
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// 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.
|
||||
|
||||
import '../../descriptor.dart' as d;
|
||||
import '../../test_pub.dart';
|
||||
|
||||
const TRANSFORMER = """
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:barback/barback.dart';
|
||||
|
||||
class DartTransformer extends Transformer {
|
||||
DartTransformer.asPlugin();
|
||||
|
||||
String get allowedExtensions => '.in';
|
||||
|
||||
void apply(Transform transform) {
|
||||
transform.addOutput(new Asset.fromString(
|
||||
new AssetId("foo", "bin/script.dart"),
|
||||
"void main() => print('generated');"));
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
main() {
|
||||
initConfig();
|
||||
withBarbackVersions("any", () {
|
||||
integration('runs a global script generated by a transformer', () {
|
||||
makeGlobalPackage("foo", "1.0.0", [
|
||||
d.pubspec({
|
||||
"name": "foo",
|
||||
"version": "1.0.0",
|
||||
"transformers": ["foo/src/transformer"]
|
||||
}),
|
||||
d.dir("lib", [d.dir("src", [
|
||||
d.file("transformer.dart", TRANSFORMER),
|
||||
d.file("primary.in", "")
|
||||
])])
|
||||
], pkg: ['barback']);
|
||||
|
||||
var pub = pubRun(global: true, args: ["foo", "script"]);
|
||||
|
||||
pub.stdout.expect("generated");
|
||||
pub.shouldExit();
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
// 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.
|
||||
|
||||
import 'package:scheduled_test/scheduled_test.dart';
|
||||
|
||||
import '../../../lib/src/exit_codes.dart' as exit_codes;
|
||||
import '../../descriptor.dart' as d;
|
||||
import '../../test_pub.dart';
|
||||
|
||||
main() {
|
||||
initConfig();
|
||||
integration('errors if the package is not activated', () {
|
||||
servePackages([]);
|
||||
|
||||
schedulePub(args: ["global", "run", "foo", "bar"],
|
||||
error: startsWith("No active package foo."),
|
||||
exitCode: exit_codes.DATA);
|
||||
});
|
||||
}
|
|
@ -4,12 +4,12 @@
|
|||
|
||||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
const SCRIPT = """
|
||||
import 'dart:io';
|
||||
|
||||
main() {
|
||||
print("started");
|
||||
var line1 = stdin.readLineSync();
|
||||
print("between");
|
||||
var line2 = stdin.readLineSync();
|
||||
|
@ -30,6 +30,7 @@ main() {
|
|||
|
||||
var pub = pubRun(args: ["script"]);
|
||||
|
||||
pub.stdout.expect("started");
|
||||
pub.writeLine("first");
|
||||
pub.stdout.expect("between");
|
||||
pub.writeLine("second");
|
||||
|
|
|
@ -6,7 +6,6 @@ import 'package:scheduled_test/scheduled_test.dart';
|
|||
|
||||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
const SCRIPT = """
|
||||
import "package:myapp/lib.dart";
|
||||
|
@ -69,8 +68,7 @@ main() {
|
|||
|
||||
createLockFile('myapp', pkg: ['barback']);
|
||||
|
||||
var pub = pubRun(args: ["script"],
|
||||
transformers: ["myapp/src/transformer"]);
|
||||
var pub = pubRun(args: ["script"]);
|
||||
|
||||
// Note that the info log is only displayed here because the test
|
||||
// harness runs pub in verbose mode. By default, only the warning would
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
const SCRIPT = """
|
||||
main() {
|
||||
|
@ -51,8 +50,7 @@ main() {
|
|||
|
||||
createLockFile('myapp', pkg: ['barback']);
|
||||
|
||||
var pub = pubRun(args: ["script"],
|
||||
transformers: ["myapp/src/transformer"]);
|
||||
var pub = pubRun(args: ["script"]);
|
||||
|
||||
pub.stderr.expect("[Error from Failing]:");
|
||||
pub.stderr.expect("myapp|bin/script.dart.");
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
import '../../lib/src/exit_codes.dart' as exit_codes;
|
||||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
main() {
|
||||
initConfig();
|
||||
|
|
|
@ -22,7 +22,7 @@ main() {
|
|||
|
||||
schedulePub(args: ["run", "foo:sub/dir"],
|
||||
error: """
|
||||
Can not run an executable in a subdirectory of a dependency.
|
||||
Cannot run an executable in a subdirectory of a dependency.
|
||||
|
||||
Usage: pub run <executable> [args...]
|
||||
-h, --help Print usage information for this command.
|
||||
|
|
|
@ -6,7 +6,6 @@ import 'package:path/path.dart' as path;
|
|||
|
||||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
const SCRIPT = r"""
|
||||
import '../../a.dart';
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
import '../../lib/src/exit_codes.dart' as exit_codes;
|
||||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
main() {
|
||||
initConfig();
|
||||
|
|
|
@ -7,7 +7,6 @@ import 'package:path/path.dart' as p;
|
|||
import '../../lib/src/exit_codes.dart' as exit_codes;
|
||||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
main() {
|
||||
initConfig();
|
||||
|
|
|
@ -7,7 +7,6 @@ import 'package:path/path.dart' as p;
|
|||
import '../../lib/src/exit_codes.dart' as exit_codes;
|
||||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
main() {
|
||||
initConfig();
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
const SCRIPT = """
|
||||
main(List<String> args) {
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
const TRANSFORMER = """
|
||||
import 'dart:async';
|
||||
|
@ -41,8 +40,7 @@ main() {
|
|||
|
||||
createLockFile('myapp', pkg: ['barback']);
|
||||
|
||||
var pub = pubRun(args: ["script"],
|
||||
transformers: ["myapp/src/transformer"]);
|
||||
var pub = pubRun(args: ["script"]);
|
||||
|
||||
pub.stdout.expect("generated");
|
||||
pub.shouldExit();
|
||||
|
|
|
@ -6,7 +6,6 @@ import 'package:path/path.dart' as path;
|
|||
|
||||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
main() {
|
||||
initConfig();
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
const SCRIPT = """
|
||||
import 'dart:io';
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
main() {
|
||||
initConfig();
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
main() {
|
||||
initConfig();
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
import '../descriptor.dart' as d;
|
||||
import '../test_pub.dart';
|
||||
import '../serve/utils.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
const SCRIPT = """
|
||||
const TOKEN = "hi";
|
||||
|
@ -33,8 +32,7 @@ main() {
|
|||
|
||||
createLockFile('myapp', pkg: ['barback']);
|
||||
|
||||
var pub = pubRun(args: ["hi"],
|
||||
transformers: ["myapp/src/transformer"]);
|
||||
var pub = pubRun(args: ["hi"]);
|
||||
|
||||
pub.stdout.expect("(hi, transformed)");
|
||||
pub.shouldExit();
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS d.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:scheduled_test/scheduled_process.dart';
|
||||
import 'package:scheduled_test/scheduled_test.dart';
|
||||
|
||||
import '../test_pub.dart';
|
||||
|
||||
/// Schedules starting the "pub run" process and validates the expected startup
|
||||
/// output.
|
||||
///
|
||||
/// if [transformers] is given, it should contain a list of transformer IDs
|
||||
/// (like "myapp/src/transformer") and this will validate that the output for
|
||||
/// loading those is shown.
|
||||
///
|
||||
/// Returns the `pub run` process.
|
||||
ScheduledProcess pubRun({Iterable<String> args,
|
||||
Iterable<String> transformers}) {
|
||||
var pub = startPub(args: ["run"]..addAll(args));
|
||||
|
||||
// This isn't normally printed, but the pub test infrastructure runs pub in
|
||||
// verbose mode, which enables this.
|
||||
pub.stdout.expect(startsWith("Loading source assets"));
|
||||
|
||||
if (transformers != null) {
|
||||
for (var transformer in transformers) {
|
||||
pub.stdout.expect(startsWith("Loading $transformer transformers"));
|
||||
}
|
||||
}
|
||||
return pub;
|
||||
}
|
|
@ -225,7 +225,11 @@ Map<String, List<Map>> _servedPackages;
|
|||
/// If [replace] is false, subsequent calls to [servePackages] will add to the
|
||||
/// set of packages that are being served. Previous packages will continue to be
|
||||
/// served. Otherwise, the previous packages will no longer be served.
|
||||
void servePackages(List<Map> pubspecs, {bool replace: false}) {
|
||||
///
|
||||
/// If [contents] is given, its contents are added to every served
|
||||
/// package.
|
||||
void servePackages(List<Map> pubspecs, {bool replace: false,
|
||||
Iterable<d.Descriptor> contents}) {
|
||||
if (_servedPackages == null || _servedPackageDir == null) {
|
||||
_servedPackages = <String, List<Map>>{};
|
||||
_servedApiPackageDir = d.dir('packages', []);
|
||||
|
@ -246,11 +250,11 @@ void servePackages(List<Map> pubspecs, {bool replace: false}) {
|
|||
return awaitObject(pubspecs).then((resolvedPubspecs) {
|
||||
if (replace) _servedPackages.clear();
|
||||
|
||||
for (var spec in resolvedPubspecs) {
|
||||
var name = spec['name'];
|
||||
var version = spec['version'];
|
||||
for (var pubspec in resolvedPubspecs) {
|
||||
var name = pubspec['name'];
|
||||
var version = pubspec['version'];
|
||||
var versions = _servedPackages.putIfAbsent(name, () => []);
|
||||
versions.add(spec);
|
||||
versions.add(pubspec);
|
||||
}
|
||||
|
||||
_servedApiPackageDir.contents.clear();
|
||||
|
@ -273,10 +277,17 @@ void servePackages(List<Map> pubspecs, {bool replace: false}) {
|
|||
_servedPackageDir.contents.add(d.dir(name, [
|
||||
d.dir('versions', _servedPackages[name].map((pubspec) {
|
||||
var version = pubspec['version'];
|
||||
return d.tar('$version.tar.gz', [
|
||||
d.file('pubspec.yaml', JSON.encode(pubspec)),
|
||||
d.libDir(name, '$name $version')
|
||||
]);
|
||||
|
||||
var archiveContents = [
|
||||
d.file('pubspec.yaml', JSON.encode(pubspec)),
|
||||
d.libDir(name, '$name $version')
|
||||
];
|
||||
|
||||
if (contents != null) {
|
||||
archiveContents.addAll(contents);
|
||||
}
|
||||
|
||||
return d.tar('$version.tar.gz', archiveContents);
|
||||
}))
|
||||
]));
|
||||
}
|
||||
|
@ -377,6 +388,25 @@ void pubUpgrade({Iterable<String> args, output, error, warning, int exitCode}) {
|
|||
warning: warning, exitCode: exitCode);
|
||||
}
|
||||
|
||||
/// Schedules starting the "pub [global] run" process and validates the
|
||||
/// expected startup output.
|
||||
///
|
||||
/// If [global] is `true`, this invokes "pub global run", otherwise it does
|
||||
/// "pub run".
|
||||
///
|
||||
/// Returns the `pub run` process.
|
||||
ScheduledProcess pubRun({bool global: false, Iterable<String> args}) {
|
||||
var pubArgs = global ? ["global", "run"] : ["run"];
|
||||
pubArgs.addAll(args);
|
||||
var pub = startPub(args: pubArgs);
|
||||
|
||||
// Loading sources and transformers isn't normally printed, but the pub test
|
||||
// infrastructure runs pub in verbose mode, which enables this.
|
||||
pub.stdout.expect(consumeWhile(startsWith("Loading")));
|
||||
|
||||
return pub;
|
||||
}
|
||||
|
||||
/// Defines an integration test.
|
||||
///
|
||||
/// The [body] should schedule a series of operations which will be run
|
||||
|
@ -670,6 +700,42 @@ void ensureGit() {
|
|||
}
|
||||
}
|
||||
|
||||
/// Schedules activating a global package [package] without running
|
||||
/// "pub global activate".
|
||||
///
|
||||
/// This is useful because global packages must be hosted, but the test hosted
|
||||
/// server doesn't serve barback. The other parameters here follow
|
||||
/// [createLockFile].
|
||||
void makeGlobalPackage(String package, String version,
|
||||
Iterable<d.Descriptor> contents, {Iterable<String> pkg,
|
||||
Map<String, String> hosted}) {
|
||||
// Start the server so we know what port to use in the cache directory name.
|
||||
servePackages([]);
|
||||
|
||||
// Create the package in the hosted cache.
|
||||
d.hostedCache([
|
||||
d.dir("$package-$version", contents)
|
||||
]).create();
|
||||
|
||||
var lockFile = _createLockFile(pkg: pkg, hosted: hosted);
|
||||
|
||||
// Add the root package to the lockfile.
|
||||
var id = new PackageId(package, "hosted", new Version.parse(version),
|
||||
package);
|
||||
lockFile.packages[package] = id;
|
||||
|
||||
// Write the lockfile to the global cache.
|
||||
var sources = new SourceRegistry();
|
||||
sources.register(new HostedSource());
|
||||
sources.register(new PathSource());
|
||||
|
||||
d.dir(cachePath, [
|
||||
d.dir("global_packages", [
|
||||
d.file("$package.lock", lockFile.serialize(null, sources))
|
||||
])
|
||||
]).create();
|
||||
}
|
||||
|
||||
/// Creates a lock file for [package] without running `pub get`.
|
||||
///
|
||||
/// [sandbox] is a list of path dependencies to be found in the sandbox
|
||||
|
@ -681,6 +747,27 @@ void ensureGit() {
|
|||
/// hosted packages.
|
||||
void createLockFile(String package, {Iterable<String> sandbox,
|
||||
Iterable<String> pkg, Map<String, String> hosted}) {
|
||||
var lockFile = _createLockFile(sandbox: sandbox, pkg: pkg, hosted: hosted);
|
||||
|
||||
var sources = new SourceRegistry();
|
||||
sources.register(new HostedSource());
|
||||
sources.register(new PathSource());
|
||||
|
||||
d.file(path.join(package, 'pubspec.lock'),
|
||||
lockFile.serialize(null, sources)).create();
|
||||
}
|
||||
|
||||
/// Creates a lock file for [package] without running `pub get`.
|
||||
///
|
||||
/// [sandbox] is a list of path dependencies to be found in the sandbox
|
||||
/// directory. [pkg] is a list of packages in the Dart repo's "pkg" directory;
|
||||
/// each package listed here and all its dependencies will be linked to the
|
||||
/// version in the Dart repo.
|
||||
///
|
||||
/// [hosted] is a list of package names to version strings for dependencies on
|
||||
/// hosted packages.
|
||||
LockFile _createLockFile({Iterable<String> sandbox,
|
||||
Iterable<String> pkg, Map<String, String> hosted}) {
|
||||
var dependencies = {};
|
||||
|
||||
if (sandbox != null) {
|
||||
|
@ -732,12 +819,7 @@ void createLockFile(String package, {Iterable<String> sandbox,
|
|||
});
|
||||
}
|
||||
|
||||
var sources = new SourceRegistry();
|
||||
sources.register(new HostedSource());
|
||||
sources.register(new PathSource());
|
||||
|
||||
d.file(path.join(package, 'pubspec.lock'),
|
||||
lockFile.serialize(null, sources)).create();
|
||||
return lockFile;
|
||||
}
|
||||
|
||||
/// Uses [client] as the mock HTTP client for this test.
|
||||
|
|
Loading…
Reference in a new issue