| Index: sdk/lib/_internal/pub_generated/lib/src/global_packages.dart
|
| diff --git a/sdk/lib/_internal/pub_generated/lib/src/global_packages.dart b/sdk/lib/_internal/pub_generated/lib/src/global_packages.dart
|
| index 85a1983f66e66f026736507a0325d3125e37b403..7035105649086102fafdaebc48d3a51b6b6737f7 100644
|
| --- a/sdk/lib/_internal/pub_generated/lib/src/global_packages.dart
|
| +++ b/sdk/lib/_internal/pub_generated/lib/src/global_packages.dart
|
| @@ -11,18 +11,22 @@ import 'lock_file.dart';
|
| import 'log.dart' as log;
|
| import 'package.dart';
|
| import 'pubspec.dart';
|
| -import 'system_cache.dart';
|
| +import 'sdk.dart' as sdk;
|
| import 'solver/version_solver.dart';
|
| import 'source/cached.dart';
|
| import 'source/git.dart';
|
| import 'source/path.dart';
|
| +import 'system_cache.dart';
|
| import 'utils.dart';
|
| import 'version.dart';
|
| +final _binStubPackagePattern = new RegExp(r"Package: ([a-zA-Z0-9_-]+)");
|
| class GlobalPackages {
|
| final SystemCache cache;
|
| String get _directory => p.join(cache.rootDir, "global_packages");
|
| + String get _binStubDir => p.join(cache.rootDir, "bin");
|
| GlobalPackages(this.cache);
|
| - Future activateGit(String repo) {
|
| + Future activateGit(String repo, List<String> executables,
|
| + {bool overwriteBinStubs}) {
|
| final completer0 = new Completer();
|
| scheduleMicrotask(() {
|
| try {
|
| @@ -34,7 +38,11 @@ class GlobalPackages {
|
| _installInCache(
|
| new PackageDep(name, "git", VersionConstraint.any, repo)).then((x1) {
|
| try {
|
| - x1;
|
| + var package = x1;
|
| + _updateBinStubs(
|
| + package,
|
| + executables,
|
| + overwriteBinStubs: overwriteBinStubs);
|
| completer0.complete(null);
|
| } catch (e1) {
|
| completer0.completeError(e1);
|
| @@ -54,11 +62,35 @@ class GlobalPackages {
|
| });
|
| return completer0.future;
|
| }
|
| - Future activateHosted(String name, VersionConstraint constraint) {
|
| - _describeActive(name);
|
| - return _installInCache(new PackageDep(name, "hosted", constraint, name));
|
| + Future activateHosted(String name, VersionConstraint constraint,
|
| + List<String> executables, {bool overwriteBinStubs}) {
|
| + final completer0 = new Completer();
|
| + scheduleMicrotask(() {
|
| + try {
|
| + _describeActive(name);
|
| + _installInCache(
|
| + new PackageDep(name, "hosted", constraint, name)).then((x0) {
|
| + try {
|
| + var package = x0;
|
| + _updateBinStubs(
|
| + package,
|
| + executables,
|
| + overwriteBinStubs: overwriteBinStubs);
|
| + completer0.complete(null);
|
| + } catch (e0) {
|
| + completer0.completeError(e0);
|
| + }
|
| + }, onError: (e1) {
|
| + completer0.completeError(e1);
|
| + });
|
| + } catch (e2) {
|
| + completer0.completeError(e2);
|
| + }
|
| + });
|
| + return completer0.future;
|
| }
|
| - Future activatePath(String path) {
|
| + Future activatePath(String path, List<String> executables,
|
| + {bool overwriteBinStubs}) {
|
| final completer0 = new Completer();
|
| scheduleMicrotask(() {
|
| try {
|
| @@ -77,6 +109,10 @@ class GlobalPackages {
|
| _writeLockFile(name, new LockFile([id]));
|
| var binDir = p.join(_directory, name, 'bin');
|
| join0() {
|
| + _updateBinStubs(
|
| + entrypoint.root,
|
| + executables,
|
| + overwriteBinStubs: overwriteBinStubs);
|
| completer0.complete(null);
|
| }
|
| if (dirExists(binDir)) {
|
| @@ -97,7 +133,7 @@ class GlobalPackages {
|
| });
|
| return completer0.future;
|
| }
|
| - Future _installInCache(PackageDep dep) {
|
| + Future<Package> _installInCache(PackageDep dep) {
|
| final completer0 = new Completer();
|
| scheduleMicrotask(() {
|
| try {
|
| @@ -128,7 +164,7 @@ class GlobalPackages {
|
| try {
|
| x3;
|
| _writeLockFile(dep.name, lockFile);
|
| - completer0.complete(null);
|
| + completer0.complete(graph.packages[dep.name]);
|
| } catch (e3) {
|
| completer0.completeError(e3);
|
| }
|
| @@ -255,14 +291,13 @@ class GlobalPackages {
|
| return null;
|
| }
|
| }
|
| - bool deactivate(String name, {bool logDeactivate: false}) {
|
| + bool deactivate(String name) {
|
| var dir = p.join(_directory, name);
|
| if (!dirExists(dir)) return false;
|
| - if (logDeactivate) {
|
| - var lockFile = new LockFile.load(_getLockFilePath(name), cache.sources);
|
| - var id = lockFile.packages[name];
|
| - log.message('Deactivated package ${_formatPackage(id)}.');
|
| - }
|
| + _deleteBinStubs(name);
|
| + var lockFile = new LockFile.load(_getLockFilePath(name), cache.sources);
|
| + var id = lockFile.packages[name];
|
| + log.message('Deactivated package ${_formatPackage(id)}.');
|
| deleteEntry(dir);
|
| return true;
|
| }
|
| @@ -357,4 +392,132 @@ class GlobalPackages {
|
| return '${log.bold(id.name)} ${id.version}';
|
| }
|
| }
|
| + void _updateBinStubs(Package package, List<String> executables,
|
| + {bool overwriteBinStubs}) {
|
| + _deleteBinStubs(package.name);
|
| + if ((executables != null && executables.isEmpty) ||
|
| + package.pubspec.executables.isEmpty) {
|
| + return;
|
| + }
|
| + ensureDir(_binStubDir);
|
| + var installed = [];
|
| + var collided = {};
|
| + var allExecutables = ordered(package.pubspec.executables.keys);
|
| + for (var executable in allExecutables) {
|
| + if (executables != null && !executables.contains(executable)) continue;
|
| + var script = package.pubspec.executables[executable];
|
| + var previousPackage =
|
| + _createBinStub(package, executable, script, overwrite: overwriteBinStubs);
|
| + if (previousPackage != null) {
|
| + collided[executable] = previousPackage;
|
| + if (!overwriteBinStubs) continue;
|
| + }
|
| + installed.add(executable);
|
| + }
|
| + if (installed.isNotEmpty) {
|
| + var names = namedSequence("executable", installed.map(log.bold));
|
| + log.message("Installed $names.");
|
| + }
|
| + if (collided.isNotEmpty) {
|
| + for (var command in ordered(collided.keys)) {
|
| + if (overwriteBinStubs) {
|
| + log.warning(
|
| + "Replaced ${log.bold(command)} previously installed from "
|
| + "${log.bold(collided[command])}.");
|
| + } else {
|
| + log.warning(
|
| + "Executable ${log.bold(command)} was already installed "
|
| + "from ${log.bold(collided[command])}.");
|
| + }
|
| + }
|
| + if (!overwriteBinStubs) {
|
| + log.warning(
|
| + "Deactivate the other package(s) or activate "
|
| + "${log.bold(package.name)} using --overwrite-executables.");
|
| + }
|
| + }
|
| + if (executables != null) {
|
| + var unknown = ordered(
|
| + executables.where((exe) => !package.pubspec.executables.keys.contains(exe)));
|
| + if (unknown.isNotEmpty) {
|
| + dataError("Unknown ${namedSequence('executable', unknown)}.");
|
| + }
|
| + }
|
| + var binFiles = package.listFiles(
|
| + beneath: "bin",
|
| + recursive: false).map((path) => p.relative(path, from: package.dir)).toList();
|
| + for (var executable in installed) {
|
| + var script = package.pubspec.executables[executable];
|
| + var scriptPath = p.join("bin", "$script.dart");
|
| + if (!binFiles.contains(scriptPath)) {
|
| + log.warning(
|
| + 'Warning: Executable "$executable" runs "$scriptPath", '
|
| + 'which was not found in ${log.bold(package.name)}.');
|
| + }
|
| + }
|
| + }
|
| + String _createBinStub(Package package, String executable, String script,
|
| + {bool overwrite}) {
|
| + var binStubPath = p.join(_binStubDir, executable);
|
| + var previousPackage;
|
| + if (fileExists(binStubPath)) {
|
| + var contents = readTextFile(binStubPath);
|
| + var match = _binStubPackagePattern.firstMatch(contents);
|
| + if (match != null) {
|
| + previousPackage = match[1];
|
| + if (!overwrite) return previousPackage;
|
| + } else {
|
| + log.fine("Could not parse binstub $binStubPath:\n$contents");
|
| + }
|
| + }
|
| + if (Platform.operatingSystem == "windows") {
|
| + var batch = """
|
| +@echo off
|
| +rem This file was created by pub v${sdk.version}.
|
| +rem Package: ${package.name}
|
| +rem Version: ${package.version}
|
| +rem Executable: ${executable}
|
| +rem Script: ${script}
|
| +pub global run ${package.name}:$script "%*"
|
| +""";
|
| + writeTextFile(binStubPath, batch);
|
| + } else {
|
| + var bash = """
|
| +# This file was created by pub v${sdk.version}.
|
| +# Package: ${package.name}
|
| +# Version: ${package.version}
|
| +# Executable: ${executable}
|
| +# Script: ${script}
|
| +pub global run ${package.name}:$script "\$@"
|
| +""";
|
| + writeTextFile(binStubPath, bash);
|
| + var result = Process.runSync('chmod', ['+x', binStubPath]);
|
| + if (result.exitCode != 0) {
|
| + try {
|
| + deleteEntry(binStubPath);
|
| + } on IOException catch (err) {
|
| + log.fine("Could not delete binstub:\n$err");
|
| + }
|
| + fail(
|
| + 'Could not make "$binStubPath" executable (exit code '
|
| + '${result.exitCode}):\n${result.stderr}');
|
| + }
|
| + }
|
| + return previousPackage;
|
| + }
|
| + void _deleteBinStubs(String package) {
|
| + if (!dirExists(_binStubDir)) return;
|
| + for (var file in listDir(_binStubDir, includeDirs: false)) {
|
| + var contents = readTextFile(file);
|
| + var match = _binStubPackagePattern.firstMatch(contents);
|
| + if (match == null) {
|
| + log.fine("Could not parse binstub $file:\n$contents");
|
| + continue;
|
| + }
|
| + if (match[1] == package) {
|
| + log.fine("Deleting old binstub $file");
|
| + deleteEntry(file);
|
| + }
|
| + }
|
| + }
|
| }
|
|
|