| 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
 | 
| deleted file mode 100644
 | 
| index 47817a344c04ecfc1bc788affdc048991c671c56..0000000000000000000000000000000000000000
 | 
| --- a/sdk/lib/_internal/pub_generated/lib/src/global_packages.dart
 | 
| +++ /dev/null
 | 
| @@ -1,1109 +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.
 | 
| -
 | 
| -library pub.global_packages;
 | 
| -
 | 
| -import 'dart:async';
 | 
| -import 'dart:io';
 | 
| -
 | 
| -import 'package:path/path.dart' as p;
 | 
| -import 'package:barback/barback.dart';
 | 
| -import 'package:pub_semver/pub_semver.dart';
 | 
| -
 | 
| -import 'barback/asset_environment.dart';
 | 
| -import 'entrypoint.dart';
 | 
| -import 'exceptions.dart';
 | 
| -import 'executable.dart' as exe;
 | 
| -import 'io.dart';
 | 
| -import 'lock_file.dart';
 | 
| -import 'log.dart' as log;
 | 
| -import 'package.dart';
 | 
| -import 'pubspec.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';
 | 
| -
 | 
| -/// Maintains the set of packages that have been globally activated.
 | 
| -///
 | 
| -/// These have been hand-chosen by the user to make their executables in bin/
 | 
| -/// available to the entire system. This lets them access them even when the
 | 
| -/// current working directory is not inside another entrypoint package.
 | 
| -///
 | 
| -/// Only one version of a given package name can be globally activated at a
 | 
| -/// time. Activating a different version of a package will deactivate the
 | 
| -/// previous one.
 | 
| -///
 | 
| -/// This handles packages from uncached and cached sources a little differently.
 | 
| -/// For a cached source, the package is physically in the user's pub cache and
 | 
| -/// we don't want to mess with it by putting a lockfile in there. Instead, when
 | 
| -/// we activate the package, we create a full lockfile and put it in the
 | 
| -/// "global_packages" directory. It's named "<package>.lock". Unlike a normal
 | 
| -/// lockfile, it also contains an entry for the root package itself, so that we
 | 
| -/// know the version and description that was activated.
 | 
| -///
 | 
| -/// Uncached packages (i.e. "path" packages) are somewhere else on the user's
 | 
| -/// local file system and can have a lockfile directly in place. (And, in fact,
 | 
| -/// we want to ensure we honor the user's lockfile there.) To activate it, we
 | 
| -/// just need to know where that package directory is. For that, we create a
 | 
| -/// lockfile that *only* contains the root package's [PackageId] -- basically
 | 
| -/// just the path to the directory where the real lockfile lives.
 | 
| -class GlobalPackages {
 | 
| -  /// The [SystemCache] containing the global packages.
 | 
| -  final SystemCache cache;
 | 
| -
 | 
| -  /// The directory where the lockfiles for activated packages are stored.
 | 
| -  String get _directory => p.join(cache.rootDir, "global_packages");
 | 
| -
 | 
| -  /// The directory where binstubs for global package executables are stored.
 | 
| -  String get _binStubDir => p.join(cache.rootDir, "bin");
 | 
| -
 | 
| -  /// Creates a new global package registry backed by the given directory on
 | 
| -  /// the user's file system.
 | 
| -  ///
 | 
| -  /// The directory may not physically exist yet. If not, this will create it
 | 
| -  /// when needed.
 | 
| -  GlobalPackages(this.cache);
 | 
| -
 | 
| -  /// Caches the package located in the Git repository [repo] and makes it the
 | 
| -  /// active global version.
 | 
| -  ///
 | 
| -  /// [executables] is the names of the executables that should have binstubs.
 | 
| -  /// If `null`, all executables in the package will get binstubs. If empty, no
 | 
| -  /// binstubs will be created.
 | 
| -  ///
 | 
| -  /// 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 activateGit(String repo, List<String> executables,
 | 
| -      {bool overwriteBinStubs}) {
 | 
| -    final completer0 = new Completer();
 | 
| -    scheduleMicrotask(() {
 | 
| -      try {
 | 
| -        var source = cache.sources["git"] as GitSource;
 | 
| -        new Future.value(source.getPackageNameFromRepo(repo)).then((x0) {
 | 
| -          try {
 | 
| -            var name = x0;
 | 
| -            _describeActive(name);
 | 
| -            new Future.value(
 | 
| -                _installInCache(
 | 
| -                    new PackageDep(name, "git", VersionConstraint.any, repo),
 | 
| -                    executables,
 | 
| -                    overwriteBinStubs: overwriteBinStubs)).then((x1) {
 | 
| -              try {
 | 
| -                x1;
 | 
| -                completer0.complete();
 | 
| -              } catch (e0, s0) {
 | 
| -                completer0.completeError(e0, s0);
 | 
| -              }
 | 
| -            }, onError: completer0.completeError);
 | 
| -          } catch (e1, s1) {
 | 
| -            completer0.completeError(e1, s1);
 | 
| -          }
 | 
| -        }, onError: completer0.completeError);
 | 
| -      } catch (e, s) {
 | 
| -        completer0.completeError(e, s);
 | 
| -      }
 | 
| -    });
 | 
| -    return completer0.future;
 | 
| -  }
 | 
| -
 | 
| -  /// Finds the latest version of the hosted package with [name] that matches
 | 
| -  /// [constraint] and makes it the active global version.
 | 
| -  ///
 | 
| -  /// [executables] is the names of the executables that should have binstubs.
 | 
| -  /// If `null`, all executables in the package will get binstubs. If empty, no
 | 
| -  /// binstubs will be created.
 | 
| -  ///
 | 
| -  /// 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 activateHosted(String name, VersionConstraint constraint,
 | 
| -      List<String> executables, {bool overwriteBinStubs}) {
 | 
| -    final completer0 = new Completer();
 | 
| -    scheduleMicrotask(() {
 | 
| -      try {
 | 
| -        _describeActive(name);
 | 
| -        new Future.value(
 | 
| -            _installInCache(
 | 
| -                new PackageDep(name, "hosted", constraint, name),
 | 
| -                executables,
 | 
| -                overwriteBinStubs: overwriteBinStubs)).then((x0) {
 | 
| -          try {
 | 
| -            x0;
 | 
| -            completer0.complete();
 | 
| -          } catch (e0, s0) {
 | 
| -            completer0.completeError(e0, s0);
 | 
| -          }
 | 
| -        }, onError: completer0.completeError);
 | 
| -      } catch (e, s) {
 | 
| -        completer0.completeError(e, s);
 | 
| -      }
 | 
| -    });
 | 
| -    return completer0.future;
 | 
| -  }
 | 
| -
 | 
| -  /// Makes the local package at [path] globally active.
 | 
| -  ///
 | 
| -  /// [executables] is the names of the executables that should have binstubs.
 | 
| -  /// If `null`, all executables in the package will get binstubs. If empty, no
 | 
| -  /// binstubs will be created.
 | 
| -  ///
 | 
| -  /// 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 activatePath(String path, List<String> executables,
 | 
| -      {bool overwriteBinStubs}) {
 | 
| -    final completer0 = new Completer();
 | 
| -    scheduleMicrotask(() {
 | 
| -      try {
 | 
| -        var entrypoint = new Entrypoint(path, cache);
 | 
| -        new Future.value(entrypoint.ensureLockFileIsUpToDate()).then((x0) {
 | 
| -          try {
 | 
| -            x0;
 | 
| -            var name = entrypoint.root.name;
 | 
| -            _describeActive(name);
 | 
| -            var fullPath = canonicalize(entrypoint.root.dir);
 | 
| -            var id = new PackageId(
 | 
| -                name,
 | 
| -                "path",
 | 
| -                entrypoint.root.version,
 | 
| -                PathSource.describePath(fullPath));
 | 
| -            _writeLockFile(name, new LockFile([id]));
 | 
| -            var binDir = p.join(_directory, name, 'bin');
 | 
| -            join0() {
 | 
| -              _updateBinStubs(
 | 
| -                  entrypoint.root,
 | 
| -                  executables,
 | 
| -                  overwriteBinStubs: overwriteBinStubs);
 | 
| -              completer0.complete();
 | 
| -            }
 | 
| -            if (dirExists(binDir)) {
 | 
| -              deleteEntry(binDir);
 | 
| -              join0();
 | 
| -            } else {
 | 
| -              join0();
 | 
| -            }
 | 
| -          } catch (e0, s0) {
 | 
| -            completer0.completeError(e0, s0);
 | 
| -          }
 | 
| -        }, onError: completer0.completeError);
 | 
| -      } catch (e, s) {
 | 
| -        completer0.completeError(e, s);
 | 
| -      }
 | 
| -    });
 | 
| -    return completer0.future;
 | 
| -  }
 | 
| -
 | 
| -  /// Installs the package [dep] and its dependencies into the system cache.
 | 
| -  Future _installInCache(PackageDep dep, List<String> executables,
 | 
| -      {bool overwriteBinStubs}) {
 | 
| -    final completer0 = new Completer();
 | 
| -    scheduleMicrotask(() {
 | 
| -      try {
 | 
| -        var source = cache.sources[dep.source];
 | 
| -        var root = new Package.inMemory(
 | 
| -            new Pubspec(
 | 
| -                "pub global activate",
 | 
| -                dependencies: [dep],
 | 
| -                sources: cache.sources));
 | 
| -        new Future.value(
 | 
| -            resolveVersions(SolveType.GET, cache.sources, root)).then((x0) {
 | 
| -          try {
 | 
| -            var result = x0;
 | 
| -            join0() {
 | 
| -              result.showReport(SolveType.GET);
 | 
| -              new Future.value(
 | 
| -                  Future.wait(result.packages.map(_cacheDependency))).then((x1) {
 | 
| -                try {
 | 
| -                  var ids = x1;
 | 
| -                  var lockFile = new LockFile(ids);
 | 
| -                  new Future.value(
 | 
| -                      new Entrypoint.inMemory(
 | 
| -                          root,
 | 
| -                          lockFile,
 | 
| -                          cache).loadPackageGraph(result)).then((x2) {
 | 
| -                    try {
 | 
| -                      var graph = x2;
 | 
| -                      new Future.value(
 | 
| -                          _precompileExecutables(graph.entrypoint, dep.name)).then((x3) {
 | 
| -                        try {
 | 
| -                          var snapshots = x3;
 | 
| -                          _writeLockFile(dep.name, lockFile);
 | 
| -                          _updateBinStubs(
 | 
| -                              graph.packages[dep.name],
 | 
| -                              executables,
 | 
| -                              overwriteBinStubs: overwriteBinStubs,
 | 
| -                              snapshots: snapshots);
 | 
| -                          completer0.complete();
 | 
| -                        } catch (e0, s0) {
 | 
| -                          completer0.completeError(e0, s0);
 | 
| -                        }
 | 
| -                      }, onError: completer0.completeError);
 | 
| -                    } catch (e1, s1) {
 | 
| -                      completer0.completeError(e1, s1);
 | 
| -                    }
 | 
| -                  }, onError: completer0.completeError);
 | 
| -                } catch (e2, s2) {
 | 
| -                  completer0.completeError(e2, s2);
 | 
| -                }
 | 
| -              }, onError: completer0.completeError);
 | 
| -            }
 | 
| -            if (!result.succeeded) {
 | 
| -              join1() {
 | 
| -                join2() {
 | 
| -                  throw result.error;
 | 
| -                  join0();
 | 
| -                }
 | 
| -                if (result.error is NoVersionException) {
 | 
| -                  dataError(result.error.message);
 | 
| -                  join2();
 | 
| -                } else {
 | 
| -                  join2();
 | 
| -                }
 | 
| -              }
 | 
| -              if (result.error.package != dep.name) {
 | 
| -                throw result.error;
 | 
| -                join1();
 | 
| -              } else {
 | 
| -                join1();
 | 
| -              }
 | 
| -            } else {
 | 
| -              join0();
 | 
| -            }
 | 
| -          } catch (e3, s3) {
 | 
| -            completer0.completeError(e3, s3);
 | 
| -          }
 | 
| -        }, onError: completer0.completeError);
 | 
| -      } catch (e, s) {
 | 
| -        completer0.completeError(e, s);
 | 
| -      }
 | 
| -    });
 | 
| -    return completer0.future;
 | 
| -  }
 | 
| -
 | 
| -  /// Precompiles the executables for [package] and saves them in the global
 | 
| -  /// cache.
 | 
| -  ///
 | 
| -  /// Returns a map from executable name to path for the snapshots that were
 | 
| -  /// successfully precompiled.
 | 
| -  Future<Map<String, String>> _precompileExecutables(Entrypoint entrypoint,
 | 
| -      String package) {
 | 
| -    return log.progress("Precompiling executables", () {
 | 
| -      final completer0 = new Completer();
 | 
| -      scheduleMicrotask(() {
 | 
| -        try {
 | 
| -          var binDir = p.join(_directory, package, 'bin');
 | 
| -          cleanDir(binDir);
 | 
| -          new Future.value(entrypoint.loadPackageGraph()).then((x0) {
 | 
| -            try {
 | 
| -              var graph = x0;
 | 
| -              new Future.value(
 | 
| -                  AssetEnvironment.create(
 | 
| -                      entrypoint,
 | 
| -                      BarbackMode.RELEASE,
 | 
| -                      entrypoints: graph.packages[package].executableIds,
 | 
| -                      useDart2JS: false)).then((x1) {
 | 
| -                try {
 | 
| -                  var environment = x1;
 | 
| -                  environment.barback.errors.listen(((error) {
 | 
| -                    log.error(log.red("Build error:\n$error"));
 | 
| -                  }));
 | 
| -                  completer0.complete(
 | 
| -                      environment.precompileExecutables(package, binDir));
 | 
| -                } catch (e0, s0) {
 | 
| -                  completer0.completeError(e0, s0);
 | 
| -                }
 | 
| -              }, onError: completer0.completeError);
 | 
| -            } catch (e1, s1) {
 | 
| -              completer0.completeError(e1, s1);
 | 
| -            }
 | 
| -          }, onError: completer0.completeError);
 | 
| -        } catch (e, s) {
 | 
| -          completer0.completeError(e, s);
 | 
| -        }
 | 
| -      });
 | 
| -      return completer0.future;
 | 
| -    });
 | 
| -  }
 | 
| -
 | 
| -  /// Downloads [id] into the system cache if it's a cached package.
 | 
| -  ///
 | 
| -  /// Returns the resolved [PackageId] for [id].
 | 
| -  Future<PackageId> _cacheDependency(PackageId id) {
 | 
| -    final completer0 = new Completer();
 | 
| -    scheduleMicrotask(() {
 | 
| -      try {
 | 
| -        var source = cache.sources[id.source];
 | 
| -        join0() {
 | 
| -          completer0.complete(source.resolveId(id));
 | 
| -        }
 | 
| -        if (!id.isRoot && source is CachedSource) {
 | 
| -          new Future.value(source.downloadToSystemCache(id)).then((x0) {
 | 
| -            try {
 | 
| -              x0;
 | 
| -              join0();
 | 
| -            } catch (e0, s0) {
 | 
| -              completer0.completeError(e0, s0);
 | 
| -            }
 | 
| -          }, onError: completer0.completeError);
 | 
| -        } else {
 | 
| -          join0();
 | 
| -        }
 | 
| -      } catch (e, s) {
 | 
| -        completer0.completeError(e, s);
 | 
| -      }
 | 
| -    });
 | 
| -    return completer0.future;
 | 
| -  }
 | 
| -
 | 
| -  /// 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(cache.rootDir, cache.sources));
 | 
| -
 | 
| -    var id = lockFile.packages[package];
 | 
| -    log.message('Activated ${_formatPackage(id)}.');
 | 
| -  }
 | 
| -
 | 
| -  /// Shows the user the currently active package with [name], if any.
 | 
| -  void _describeActive(String name) {
 | 
| -    try {
 | 
| -      var lockFile = new LockFile.load(_getLockFilePath(name), cache.sources);
 | 
| -      var id = lockFile.packages[name];
 | 
| -
 | 
| -      if (id.source == 'git') {
 | 
| -        var url = GitSource.urlFromDescription(id.description);
 | 
| -        log.message(
 | 
| -            'Package ${log.bold(name)} is currently active from Git '
 | 
| -                'repository "${url}".');
 | 
| -      } else if (id.source == 'path') {
 | 
| -        var path = PathSource.pathFromDescription(id.description);
 | 
| -        log.message(
 | 
| -            'Package ${log.bold(name)} is currently active at path ' '"$path".');
 | 
| -      } else {
 | 
| -        log.message(
 | 
| -            'Package ${log.bold(name)} is currently active at version '
 | 
| -                '${log.bold(id.version)}.');
 | 
| -      }
 | 
| -    } on IOException catch (error) {
 | 
| -      // If we couldn't read the lock file, it's not activated.
 | 
| -      return null;
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  /// Deactivates a previously-activated package named [name].
 | 
| -  ///
 | 
| -  /// Returns `false` if no package with [name] was currently active.
 | 
| -  bool deactivate(String name) {
 | 
| -    var dir = p.join(_directory, name);
 | 
| -    if (!dirExists(dir)) return false;
 | 
| -
 | 
| -    _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;
 | 
| -  }
 | 
| -
 | 
| -  /// Finds the active package with [name].
 | 
| -  ///
 | 
| -  /// Returns an [Entrypoint] loaded with the active package if found.
 | 
| -  Future<Entrypoint> find(String name) {
 | 
| -    final completer0 = new Completer();
 | 
| -    scheduleMicrotask(() {
 | 
| -      try {
 | 
| -        var lockFilePath = _getLockFilePath(name);
 | 
| -        var lockFile;
 | 
| -        join0() {
 | 
| -          var id = lockFile.packages[name];
 | 
| -          lockFile.packages.remove(name);
 | 
| -          var source = cache.sources[id.source];
 | 
| -          join1() {
 | 
| -            assert(id.source == "path");
 | 
| -            completer0.complete(
 | 
| -                new Entrypoint(PathSource.pathFromDescription(id.description), cache));
 | 
| -          }
 | 
| -          if (source is CachedSource) {
 | 
| -            new Future.value(
 | 
| -                cache.sources[id.source].getDirectory(id)).then((x0) {
 | 
| -              try {
 | 
| -                var dir = x0;
 | 
| -                var package = new Package.load(name, dir, cache.sources);
 | 
| -                completer0.complete(
 | 
| -                    new Entrypoint.inMemory(package, lockFile, cache));
 | 
| -              } catch (e0, s0) {
 | 
| -                completer0.completeError(e0, s0);
 | 
| -              }
 | 
| -            }, onError: completer0.completeError);
 | 
| -          } else {
 | 
| -            join1();
 | 
| -          }
 | 
| -        }
 | 
| -        catch0(error, s1) {
 | 
| -          try {
 | 
| -            if (error is IOException) {
 | 
| -              var oldLockFilePath = p.join(_directory, '${name}.lock');
 | 
| -              join2() {
 | 
| -                ensureDir(p.dirname(lockFilePath));
 | 
| -                new File(oldLockFilePath).renameSync(lockFilePath);
 | 
| -                join0();
 | 
| -              }
 | 
| -              catch1(error, s2) {
 | 
| -                try {
 | 
| -                  if (error is IOException) {
 | 
| -                    dataError("No active package ${log.bold(name)}.");
 | 
| -                    join2();
 | 
| -                  } else {
 | 
| -                    throw error;
 | 
| -                  }
 | 
| -                } catch (error, s2) {
 | 
| -                  completer0.completeError(error, s2);
 | 
| -                }
 | 
| -              }
 | 
| -              try {
 | 
| -                lockFile = new LockFile.load(oldLockFilePath, cache.sources);
 | 
| -                join2();
 | 
| -              } catch (e1, s3) {
 | 
| -                catch1(e1, s3);
 | 
| -              }
 | 
| -            } else {
 | 
| -              throw error;
 | 
| -            }
 | 
| -          } catch (error, s1) {
 | 
| -            completer0.completeError(error, s1);
 | 
| -          }
 | 
| -        }
 | 
| -        try {
 | 
| -          lockFile = new LockFile.load(lockFilePath, cache.sources);
 | 
| -          join0();
 | 
| -        } catch (e2, s4) {
 | 
| -          catch0(e2, s4);
 | 
| -        }
 | 
| -      } catch (e, s) {
 | 
| -        completer0.completeError(e, s);
 | 
| -      }
 | 
| -    });
 | 
| -    return completer0.future;
 | 
| -  }
 | 
| -
 | 
| -  /// Runs [package]'s [executable] with [args].
 | 
| -  ///
 | 
| -  /// If [executable] is available in its precompiled form, that will be
 | 
| -  /// recompiled if the SDK has been upgraded since it was first compiled and
 | 
| -  /// then run. Otherwise, it will be run from source.
 | 
| -  ///
 | 
| -  /// If [mode] is passed, it's used as the barback mode; it defaults to
 | 
| -  /// [BarbackMode.RELEASE].
 | 
| -  ///
 | 
| -  /// Returns the exit code from the executable.
 | 
| -  Future<int> runExecutable(String package, String executable,
 | 
| -      Iterable<String> args, {BarbackMode mode}) {
 | 
| -    if (mode == null) mode = BarbackMode.RELEASE;
 | 
| -
 | 
| -    var binDir = p.join(_directory, package, 'bin');
 | 
| -    if (mode != BarbackMode.RELEASE ||
 | 
| -        !fileExists(p.join(binDir, '$executable.dart.snapshot'))) {
 | 
| -      return find(package).then((entrypoint) {
 | 
| -        return exe.runExecutable(
 | 
| -            entrypoint,
 | 
| -            package,
 | 
| -            executable,
 | 
| -            args,
 | 
| -            mode: mode,
 | 
| -            isGlobal: true);
 | 
| -      });
 | 
| -    }
 | 
| -
 | 
| -    // 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 snapshotPath = p.join(binDir, '$executable.dart.snapshot');
 | 
| -    return exe.runSnapshot(snapshotPath, args, recompile: () {
 | 
| -      log.fine(
 | 
| -          "$package:$executable is out of date and needs to be " "recompiled.");
 | 
| -      return find(
 | 
| -          package).then(
 | 
| -              (entrypoint) =>
 | 
| -                  entrypoint.loadPackageGraph()).then(
 | 
| -                      (graph) => _precompileExecutables(graph.entrypoint, package));
 | 
| -    });
 | 
| -  }
 | 
| -
 | 
| -  /// Gets the path to the lock file for an activated cached package with
 | 
| -  /// [name].
 | 
| -  String _getLockFilePath(String name) =>
 | 
| -      p.join(_directory, name, "pubspec.lock");
 | 
| -
 | 
| -  /// Shows the user a formatted list of globally activated packages.
 | 
| -  void listActivePackages() {
 | 
| -    if (!dirExists(_directory)) return;
 | 
| -
 | 
| -    listDir(_directory).map(_loadPackageId).toList()
 | 
| -        ..sort((id1, id2) => id1.name.compareTo(id2.name))
 | 
| -        ..forEach((id) => log.message(_formatPackage(id)));
 | 
| -  }
 | 
| -
 | 
| -  /// Returns the [PackageId] for the globally-activated package at [path].
 | 
| -  ///
 | 
| -  /// [path] should be a path within [_directory]. It can either be an old-style
 | 
| -  /// path to a single lockfile or a new-style path to a directory containing a
 | 
| -  /// lockfile.
 | 
| -  PackageId _loadPackageId(String path) {
 | 
| -    var name = p.basenameWithoutExtension(path);
 | 
| -    if (!fileExists(path)) path = p.join(path, 'pubspec.lock');
 | 
| -
 | 
| -    var id =
 | 
| -        new LockFile.load(p.join(_directory, path), cache.sources).packages[name];
 | 
| -
 | 
| -    if (id == null) {
 | 
| -      throw new FormatException(
 | 
| -          "Pubspec for activated package $name didn't " "contain an entry for itself.");
 | 
| -    }
 | 
| -
 | 
| -    return id;
 | 
| -  }
 | 
| -
 | 
| -  /// Returns formatted string representing the package [id].
 | 
| -  String _formatPackage(PackageId id) {
 | 
| -    if (id.source == 'git') {
 | 
| -      var url = GitSource.urlFromDescription(id.description);
 | 
| -      return '${log.bold(id.name)} ${id.version} from Git repository "$url"';
 | 
| -    } else if (id.source == 'path') {
 | 
| -      var path = PathSource.pathFromDescription(id.description);
 | 
| -      return '${log.bold(id.name)} ${id.version} at path "$path"';
 | 
| -    } else {
 | 
| -      return '${log.bold(id.name)} ${id.version}';
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  /// Repairs any corrupted globally-activated packages and their binstubs.
 | 
| -  ///
 | 
| -  /// Returns a pair of two [int]s. The first indicates how many packages were
 | 
| -  /// successfully re-activated; the second indicates how many failed.
 | 
| -  Future<Pair<int, int>> repairActivatedPackages() {
 | 
| -    final completer0 = new Completer();
 | 
| -    scheduleMicrotask(() {
 | 
| -      try {
 | 
| -        var executables = {};
 | 
| -        join0() {
 | 
| -          var successes = 0;
 | 
| -          var failures = 0;
 | 
| -          join1() {
 | 
| -            join2() {
 | 
| -              completer0.complete(new Pair(successes, failures));
 | 
| -            }
 | 
| -            if (executables.isNotEmpty) {
 | 
| -              var packages = pluralize("package", executables.length);
 | 
| -              var message =
 | 
| -                  new StringBuffer("Binstubs exist for non-activated " "packages:\n");
 | 
| -              executables.forEach(((package, executableNames) {
 | 
| -                executableNames.forEach(
 | 
| -                    (executable) => deleteEntry(p.join(_binStubDir, executable)));
 | 
| -                message.writeln(
 | 
| -                    "  From ${log.bold(package)}: " "${toSentence(executableNames)}");
 | 
| -              }));
 | 
| -              log.error(message);
 | 
| -              join2();
 | 
| -            } else {
 | 
| -              join2();
 | 
| -            }
 | 
| -          }
 | 
| -          if (dirExists(_directory)) {
 | 
| -            var it0 = listDir(_directory).iterator;
 | 
| -            break0() {
 | 
| -              join1();
 | 
| -            }
 | 
| -            var trampoline0;
 | 
| -            continue0() {
 | 
| -              trampoline0 = null;
 | 
| -              if (it0.moveNext()) {
 | 
| -                var entry = it0.current;
 | 
| -                var id;
 | 
| -                join3() {
 | 
| -                  trampoline0 = continue0;
 | 
| -                  do trampoline0(); while (trampoline0 != null);
 | 
| -                }
 | 
| -                catch0(error, stackTrace) {
 | 
| -                  try {
 | 
| -                    var message =
 | 
| -                        "Failed to reactivate " "${log.bold(p.basenameWithoutExtension(entry))}";
 | 
| -                    join4() {
 | 
| -                      log.error(message, error, stackTrace);
 | 
| -                      failures++;
 | 
| -                      tryDeleteEntry(entry);
 | 
| -                      join3();
 | 
| -                    }
 | 
| -                    if (id != null) {
 | 
| -                      message += " ${id.version}";
 | 
| -                      join5() {
 | 
| -                        join4();
 | 
| -                      }
 | 
| -                      if (id.source != "hosted") {
 | 
| -                        message += " from ${id.source}";
 | 
| -                        join5();
 | 
| -                      } else {
 | 
| -                        join5();
 | 
| -                      }
 | 
| -                    } else {
 | 
| -                      join4();
 | 
| -                    }
 | 
| -                  } catch (error, stackTrace) {
 | 
| -                    completer0.completeError(error, stackTrace);
 | 
| -                  }
 | 
| -                }
 | 
| -                try {
 | 
| -                  id = _loadPackageId(entry);
 | 
| -                  log.message(
 | 
| -                      "Reactivating ${log.bold(id.name)} ${id.version}...");
 | 
| -                  new Future.value(find(id.name)).then((x0) {
 | 
| -                    trampoline0 = () {
 | 
| -                      trampoline0 = null;
 | 
| -                      try {
 | 
| -                        var entrypoint = x0;
 | 
| -                        new Future.value(
 | 
| -                            entrypoint.loadPackageGraph()).then((x1) {
 | 
| -                          trampoline0 = () {
 | 
| -                            trampoline0 = null;
 | 
| -                            try {
 | 
| -                              var graph = x1;
 | 
| -                              new Future.value(
 | 
| -                                  _precompileExecutables(entrypoint, id.name)).then((x2) {
 | 
| -                                trampoline0 = () {
 | 
| -                                  trampoline0 = null;
 | 
| -                                  try {
 | 
| -                                    var snapshots = x2;
 | 
| -                                    var packageExecutables =
 | 
| -                                        executables.remove(id.name);
 | 
| -                                    join6() {
 | 
| -                                      _updateBinStubs(
 | 
| -                                          graph.packages[id.name],
 | 
| -                                          packageExecutables,
 | 
| -                                          overwriteBinStubs: true,
 | 
| -                                          snapshots: snapshots,
 | 
| -                                          suggestIfNotOnPath: false);
 | 
| -                                      successes++;
 | 
| -                                      join3();
 | 
| -                                    }
 | 
| -                                    if (packageExecutables == null) {
 | 
| -                                      packageExecutables = [];
 | 
| -                                      join6();
 | 
| -                                    } else {
 | 
| -                                      join6();
 | 
| -                                    }
 | 
| -                                  } catch (e0, s0) {
 | 
| -                                    catch0(e0, s0);
 | 
| -                                  }
 | 
| -                                };
 | 
| -                                do trampoline0(); while (trampoline0 != null);
 | 
| -                              }, onError: catch0);
 | 
| -                            } catch (e1, s1) {
 | 
| -                              catch0(e1, s1);
 | 
| -                            }
 | 
| -                          };
 | 
| -                          do trampoline0(); while (trampoline0 != null);
 | 
| -                        }, onError: catch0);
 | 
| -                      } catch (e2, s2) {
 | 
| -                        catch0(e2, s2);
 | 
| -                      }
 | 
| -                    };
 | 
| -                    do trampoline0(); while (trampoline0 != null);
 | 
| -                  }, onError: catch0);
 | 
| -                } catch (e3, s3) {
 | 
| -                  catch0(e3, s3);
 | 
| -                }
 | 
| -              } else {
 | 
| -                break0();
 | 
| -              }
 | 
| -            }
 | 
| -            trampoline0 = continue0;
 | 
| -            do trampoline0(); while (trampoline0 != null);
 | 
| -          } else {
 | 
| -            join1();
 | 
| -          }
 | 
| -        }
 | 
| -        if (dirExists(_binStubDir)) {
 | 
| -          var it1 = listDir(_binStubDir).iterator;
 | 
| -          break1() {
 | 
| -            join0();
 | 
| -          }
 | 
| -          var trampoline1;
 | 
| -          continue1() {
 | 
| -            trampoline1 = null;
 | 
| -            if (it1.moveNext()) {
 | 
| -              var entry = it1.current;
 | 
| -              join7() {
 | 
| -                trampoline1 = continue1;
 | 
| -                do trampoline1(); while (trampoline1 != null);
 | 
| -              }
 | 
| -              catch1(error, stackTrace) {
 | 
| -                try {
 | 
| -                  log.error(
 | 
| -                      "Error reading binstub for " "\"${p.basenameWithoutExtension(entry)}\"",
 | 
| -                      error,
 | 
| -                      stackTrace);
 | 
| -                  tryDeleteEntry(entry);
 | 
| -                  join7();
 | 
| -                } catch (error, stackTrace) {
 | 
| -                  completer0.completeError(error, stackTrace);
 | 
| -                }
 | 
| -              }
 | 
| -              try {
 | 
| -                var binstub = readTextFile(entry);
 | 
| -                var package = _binStubProperty(binstub, "Package");
 | 
| -                join8() {
 | 
| -                  var executable = _binStubProperty(binstub, "Executable");
 | 
| -                  join9() {
 | 
| -                    executables.putIfAbsent(package, (() {
 | 
| -                      return [];
 | 
| -                    })).add(executable);
 | 
| -                    join7();
 | 
| -                  }
 | 
| -                  if (executable == null) {
 | 
| -                    throw new ApplicationException("No 'Executable' property.");
 | 
| -                    join9();
 | 
| -                  } else {
 | 
| -                    join9();
 | 
| -                  }
 | 
| -                }
 | 
| -                if (package == null) {
 | 
| -                  throw new ApplicationException("No 'Package' property.");
 | 
| -                  join8();
 | 
| -                } else {
 | 
| -                  join8();
 | 
| -                }
 | 
| -              } catch (e4, s4) {
 | 
| -                catch1(e4, s4);
 | 
| -              }
 | 
| -            } else {
 | 
| -              break1();
 | 
| -            }
 | 
| -          }
 | 
| -          trampoline1 = continue1;
 | 
| -          do trampoline1(); while (trampoline1 != null);
 | 
| -        } else {
 | 
| -          join0();
 | 
| -        }
 | 
| -      } catch (e, s) {
 | 
| -        completer0.completeError(e, s);
 | 
| -      }
 | 
| -    });
 | 
| -    return completer0.future;
 | 
| -  }
 | 
| -
 | 
| -  /// Updates the binstubs for [package].
 | 
| -  ///
 | 
| -  /// A binstub is a little shell script in `PUB_CACHE/bin` that runs an
 | 
| -  /// executable from a globally activated package. This removes any old
 | 
| -  /// binstubs from the previously activated version of the package and
 | 
| -  /// (optionally) creates new ones for the executables listed in the package's
 | 
| -  /// pubspec.
 | 
| -  ///
 | 
| -  /// [executables] is the names of the executables that should have binstubs.
 | 
| -  /// If `null`, all executables in the package will get binstubs. If empty, no
 | 
| -  /// binstubs will be created.
 | 
| -  ///
 | 
| -  /// 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.
 | 
| -  ///
 | 
| -  /// If [snapshots] is given, it is a map of the names of executables whose
 | 
| -  /// snapshots were precompiled to the paths of those snapshots. Binstubs for
 | 
| -  /// those will run the snapshot directly and skip pub entirely.
 | 
| -  ///
 | 
| -
 | 
| -      /// If [suggestIfNotOnPath] is `true` (the default), this will warn the user if
 | 
| -  /// the bin directory isn't on their path.
 | 
| -  void _updateBinStubs(Package package, List<String> executables,
 | 
| -      {bool overwriteBinStubs, Map<String, String> snapshots, bool suggestIfNotOnPath:
 | 
| -      true}) {
 | 
| -    if (snapshots == null) snapshots = const {};
 | 
| -
 | 
| -    // Remove any previously activated binstubs for this package, in case the
 | 
| -    // list of executables has changed.
 | 
| -    _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,
 | 
| -          snapshot: snapshots[script]);
 | 
| -      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.");
 | 
| -    }
 | 
| -
 | 
| -    // Show errors for any collisions.
 | 
| -    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.");
 | 
| -      }
 | 
| -    }
 | 
| -
 | 
| -    // Show errors for any unknown executables.
 | 
| -    if (executables != null) {
 | 
| -      var unknown = ordered(
 | 
| -          executables.where((exe) => !package.pubspec.executables.keys.contains(exe)));
 | 
| -      if (unknown.isNotEmpty) {
 | 
| -        dataError("Unknown ${namedSequence('executable', unknown)}.");
 | 
| -      }
 | 
| -    }
 | 
| -
 | 
| -    // 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((path) => package.relative(path)).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)}.');
 | 
| -      }
 | 
| -    }
 | 
| -
 | 
| -    if (suggestIfNotOnPath && installed.isNotEmpty) {
 | 
| -      _suggestIfNotOnPath(installed.first);
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  /// Creates a binstub named [executable] that runs [script] from [package].
 | 
| -  ///
 | 
| -  /// If [overwrite] is `true`, this will replace an existing binstub with that
 | 
| -  /// name for another package.
 | 
| -  ///
 | 
| -  /// If [snapshot] is non-null, it is a path to a snapshot file. The binstub
 | 
| -  /// will invoke that directly. Otherwise, it will run `pub global run`.
 | 
| -  ///
 | 
| -  /// If a collision occurs, returns the name of the package that owns the
 | 
| -  /// existing binstub. Otherwise returns `null`.
 | 
| -  String _createBinStub(Package package, String executable, String script,
 | 
| -      {bool overwrite, String snapshot}) {
 | 
| -    var binStubPath = p.join(_binStubDir, executable);
 | 
| -
 | 
| -    if (Platform.operatingSystem == "windows") 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.
 | 
| -    var previousPackage;
 | 
| -    if (fileExists(binStubPath)) {
 | 
| -      var contents = readTextFile(binStubPath);
 | 
| -      previousPackage = _binStubProperty(contents, "Package");
 | 
| -      if (previousPackage == null) {
 | 
| -        log.fine("Could not parse binstub $binStubPath:\n$contents");
 | 
| -      } else if (!overwrite) {
 | 
| -        return previousPackage;
 | 
| -      }
 | 
| -    }
 | 
| -
 | 
| -    // If the script was precompiled to a snapshot, just invoke that directly
 | 
| -    // and skip pub global run entirely.
 | 
| -    var invocation;
 | 
| -    if (snapshot != null) {
 | 
| -      // 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));
 | 
| -      invocation = 'dart "$snapshot"';
 | 
| -    } else {
 | 
| -      invocation = "pub global run ${package.name}:$script";
 | 
| -    }
 | 
| -
 | 
| -    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}
 | 
| -$invocation %*
 | 
| -""";
 | 
| -
 | 
| -      if (snapshot != null) {
 | 
| -        batch += """
 | 
| -
 | 
| -rem The VM exits with code 253 if the snapshot version is out-of-date.
 | 
| -rem If it is, we need to delete it and run "pub global" manually.
 | 
| -if not errorlevel 253 (
 | 
| -  exit /b %errorlevel%
 | 
| -)
 | 
| -
 | 
| -pub global run ${package.name}:$script %*
 | 
| -""";
 | 
| -      }
 | 
| -
 | 
| -      writeTextFile(binStubPath, batch);
 | 
| -    } else {
 | 
| -      var bash = """
 | 
| -#!/usr/bin/env sh
 | 
| -# This file was created by pub v${sdk.version}.
 | 
| -# Package: ${package.name}
 | 
| -# Version: ${package.version}
 | 
| -# Executable: ${executable}
 | 
| -# Script: ${script}
 | 
| -$invocation "\$@"
 | 
| -""";
 | 
| -
 | 
| -      if (snapshot != null) {
 | 
| -        bash += """
 | 
| -
 | 
| -# The VM exits with code 253 if the snapshot version is out-of-date.
 | 
| -# If it is, we need to delete it and run "pub global" manually.
 | 
| -exit_code=\$?
 | 
| -if [ \$exit_code != 253 ]; then
 | 
| -  exit \$exit_code
 | 
| -fi
 | 
| -
 | 
| -pub global run ${package.name}:$script "\$@"
 | 
| -""";
 | 
| -      }
 | 
| -
 | 
| -      writeTextFile(binStubPath, bash);
 | 
| -
 | 
| -      // 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");
 | 
| -        }
 | 
| -
 | 
| -        fail(
 | 
| -            'Could not make "$binStubPath" executable (exit code '
 | 
| -                '${result.exitCode}):\n${result.stderr}');
 | 
| -      }
 | 
| -    }
 | 
| -
 | 
| -    return previousPackage;
 | 
| -  }
 | 
| -
 | 
| -  /// Deletes all existing binstubs for [package].
 | 
| -  void _deleteBinStubs(String package) {
 | 
| -    if (!dirExists(_binStubDir)) return;
 | 
| -
 | 
| -    for (var file in listDir(_binStubDir, includeDirs: false)) {
 | 
| -      var contents = readTextFile(file);
 | 
| -      var binStubPackage = _binStubProperty(contents, "Package");
 | 
| -      if (binStubPackage == null) {
 | 
| -        log.fine("Could not parse binstub $file:\n$contents");
 | 
| -        continue;
 | 
| -      }
 | 
| -
 | 
| -      if (binStubPackage == package) {
 | 
| -        log.fine("Deleting old binstub $file");
 | 
| -        deleteEntry(file);
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  /// Checks to see if the binstubs are on the user's PATH and, if not, suggests
 | 
| -  /// that the user add the directory to their PATH.
 | 
| -  ///
 | 
| -  /// [installed] should be the name of an installed executable that can be used
 | 
| -  /// to test whether accessing it on the path works.
 | 
| -  void _suggestIfNotOnPath(String installed) {
 | 
| -    if (Platform.operatingSystem == "windows") {
 | 
| -      // See if the shell can find one of the binstubs.
 | 
| -      // "\q" means return exit code 0 if found or 1 if not.
 | 
| -      var result = runProcessSync("where", [r"\q", installed + ".bat"]);
 | 
| -      if (result.exitCode == 0) return;
 | 
| -
 | 
| -      log.warning(
 | 
| -          "${log.yellow('Warning:')} Pub installs executables into "
 | 
| -              "${log.bold(_binStubDir)}, which is not on your path.\n"
 | 
| -              "You can fix that by adding that directory to your system's "
 | 
| -              '"Path" environment variable.\n'
 | 
| -              'A web search for "configure windows path" will show you how.');
 | 
| -    } else {
 | 
| -      // See if the shell can find one of the binstubs.
 | 
| -      var result = runProcessSync("which", [installed]);
 | 
| -      if (result.exitCode == 0) return;
 | 
| -
 | 
| -      var binDir = _binStubDir;
 | 
| -      if (binDir.startsWith(Platform.environment['HOME'])) {
 | 
| -        binDir =
 | 
| -            p.join("~", p.relative(binDir, from: Platform.environment['HOME']));
 | 
| -      }
 | 
| -
 | 
| -      log.warning(
 | 
| -          "${log.yellow('Warning:')} Pub installs executables into "
 | 
| -              "${log.bold(binDir)}, which is not on your path.\n"
 | 
| -              "You can fix that by adding this to your shell's config file "
 | 
| -              "(.bashrc, .bash_profile, etc.):\n" "\n"
 | 
| -              "  ${log.bold('export PATH="\$PATH":"$binDir"')}\n" "\n");
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  /// Returns the value of the property named [name] in the bin stub script
 | 
| -  /// [source].
 | 
| -  String _binStubProperty(String source, String name) {
 | 
| -    var pattern = new RegExp(quoteRegExp(name) + r": ([a-zA-Z0-9_-]+)");
 | 
| -    var match = pattern.firstMatch(source);
 | 
| -    return match == null ? null : match[1];
 | 
| -  }
 | 
| -}
 | 
| 
 |