// 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 'dart:async';
import 'dart:io';

import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';

import 'dart.dart' as dart;
import 'entrypoint.dart';
import 'exceptions.dart';
import 'executable.dart' as exe;
import 'http.dart' as http;
import 'io.dart';
import 'lock_file.dart';
import 'log.dart' as log;
import 'package.dart';
import 'package_name.dart';
import 'pubspec.dart';
import 'sdk.dart';
import 'solver.dart';
import 'solver/incompatibility_cause.dart';
import 'source/cached.dart';
import 'source/git.dart';
import 'source/hosted.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.
  ///
  /// The [features] map controls which features of the package to activate.
  ///
  /// 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,
      {Map<String, FeatureDependency> features, bool overwriteBinStubs}) async {
    var name = await cache.git.getPackageNameFromRepo(repo);
    // Call this just to log what the current active package is, if any.
    _describeActive(name);

    // TODO(nweiz): Add some special handling for git repos that contain path
    // dependencies. Their executables shouldn't be cached, and there should
    // be a mechanism for redoing dependency resolution if a path pubspec has
    // changed (see also issue 20499).
    await _installInCache(
        cache.git.source
            .refFor(name, repo)
            .withConstraint(VersionConstraint.any)
            .withFeatures(features ?? const {}),
        executables,
        overwriteBinStubs: overwriteBinStubs);
  }

  /// Finds the latest version of the hosted package with [name] that matches
  /// [constraint] and makes it the active global version.
  ///
  /// The [features] map controls which features of the package to activate.
  ///
  /// [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,
      {Map<String, FeatureDependency> features, bool overwriteBinStubs}) async {
    _describeActive(name);
    await _installInCache(
        cache.hosted.source
            .refFor(name)
            .withConstraint(constraint)
            .withFeatures(features ?? const {}),
        executables,
        overwriteBinStubs: overwriteBinStubs);
  }

  /// 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}) async {
    var entrypoint = new Entrypoint(path, cache, isGlobal: true);

    // Get the package's dependencies.
    await entrypoint.acquireDependencies(SolveType.GET);
    var name = entrypoint.root.name;

    // Call this just to log what the current active package is, if any.
    _describeActive(name);

    // Write a lockfile that points to the local package.
    var fullPath = canonicalize(entrypoint.root.dir);
    var id = cache.path.source.idFor(name, entrypoint.root.version, fullPath);

    // TODO(rnystrom): Look in "bin" and display list of binaries that
    // user can run.
    _writeLockFile(name, new LockFile([id]));

    var binDir = p.join(_directory, name, 'bin');
    if (dirExists(binDir)) deleteEntry(binDir);

    _updateBinStubs(entrypoint.root, executables,
        overwriteBinStubs: overwriteBinStubs);
    log.message('Activated ${_formatPackage(id)}.');
  }

  /// Installs the package [dep] and its dependencies into the system cache.
  Future _installInCache(PackageRange dep, List<String> executables,
      {bool overwriteBinStubs}) async {
    // Create a dummy package with just [dep] so we can do resolution on it.
    var root = new Package.inMemory(new Pubspec("pub global activate",
        dependencies: [dep], sources: cache.sources));

    // Resolve it and download its dependencies.
    //
    // TODO(nweiz): If this produces a SolveFailure that's caused by [dep] not
    // being available, report that as a [dataError].
    SolveResult result;
    try {
      result = await resolveVersions(SolveType.GET, cache, root);
    } on SolveFailure catch (error) {
      for (var incompatibility
          in error.incompatibility.externalIncompatibilities) {
        if (incompatibility.cause != IncompatibilityCause.noVersions) continue;
        if (incompatibility.terms.single.package.name != dep.name) continue;
        dataError(error.toString());
      }
      rethrow;
    }

    result.showReport(SolveType.GET);

    // Make sure all of the dependencies are locally installed.
    await Future.wait(result.packages.map((id) {
      return http.withDependencyType(root.dependencyType(id.name), () async {
        if (id.isRoot) return;

        var source = cache.source(id.source);
        if (source is CachedSource) await source.downloadToSystemCache(id);
      });
    }));

    var lockFile = result.lockFile;
    _writeLockFile(dep.name, lockFile);
    writeTextFile(_getPackagesFilePath(dep.name), lockFile.packagesFile(cache));

    // Load the package graph from [result] so we don't need to re-parse all
    // the pubspecs.
    var entrypoint =
        new Entrypoint.fromSolveResult(root, cache, result, isGlobal: true);
    var snapshots = await _precompileExecutables(entrypoint, dep.name);

    _updateBinStubs(entrypoint.packageGraph.packages[dep.name], executables,
        overwriteBinStubs: overwriteBinStubs, snapshots: snapshots);

    var id = lockFile.packages[dep.name];
    log.message('Activated ${_formatPackage(id)}.');
  }

  /// Precompiles the executables for [packageName] 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 packageName) {
    return log.progress("Precompiling executables", () async {
      var binDir = p.join(_directory, packageName, 'bin');
      cleanDir(binDir);

      // Try to avoid starting up an asset server to precompile packages if
      // possible. This is faster and produces better error messages.
      var package = entrypoint.packageGraph.packages[packageName];
      var precompiled = {};
      await waitAndPrintErrors(package.executablePaths.map((path) async {
        var url = p.toUri(p.join(package.dir, path));
        var basename = p.basename(path);
        var snapshotPath = p.join(binDir, '$basename.snapshot');
        await dart.snapshot(url, snapshotPath,
            packagesFile: p.toUri(_getPackagesFilePath(package.name)),
            name: '${package.name}:${p.url.basenameWithoutExtension(path)}');
        precompiled[p.withoutExtension(basename)] = snapshotPath;
      }));
      return precompiled;
    });
  }

  /// 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));
  }

  /// 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];

      var source = id.source;
      if (source is GitSource) {
        var url = source.urlFromDescription(id.description);
        log.message('Package ${log.bold(name)} is currently active from Git '
            'repository "${url}".');
      } else if (source is PathSource) {
        var path = source.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 {
      // 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.
  Entrypoint find(String name) {
    var lockFilePath = _getLockFilePath(name);
    var lockFile;
    try {
      lockFile = new LockFile.load(lockFilePath, cache.sources);
    } on IOException {
      var oldLockFilePath = p.join(_directory, '$name.lock');
      try {
        // TODO(nweiz): This looks for Dart 1.6's old lockfile location.
        // Remove it when Dart 1.6 is old enough that we don't think anyone
        // will have these lockfiles anymore (issue 20703).
        lockFile = new LockFile.load(oldLockFilePath, cache.sources);
      } on IOException {
        // If we couldn't read the lock file, it's not activated.
        dataError("No active package ${log.bold(name)}.");
      }

      // Move the old lockfile to its new location.
      ensureDir(p.dirname(lockFilePath));
      new File(oldLockFilePath).renameSync(lockFilePath);
    }

    // Remove the package itself from the lockfile. We put it in there so we
    // could find and load the [Package] object, but normally an entrypoint
    // doesn't expect to be in its own lockfile.
    var id = lockFile.packages[name];
    lockFile = lockFile.removePackage(name);

    var source = cache.source(id.source);
    var entrypoint;
    if (source is CachedSource) {
      // For cached sources, the package itself is in the cache and the
      // lockfile is the one we just loaded.
      entrypoint = new Entrypoint.inMemory(cache.load(id), lockFile, cache,
          isGlobal: true);
    } else {
      // For uncached sources (i.e. path), the ID just points to the real
      // directory for the package.
      entrypoint = new Entrypoint(
          (id.source as PathSource).pathFromDescription(id.description), cache,
          isGlobal: true);
    }

    entrypoint.root.pubspec.sdkConstraints.forEach((sdkName, constraint) {
      var sdk = sdks[sdkName];
      if (sdk == null) {
        dataError('${log.bold(name)} ${entrypoint.root.version} requires '
            'unknown SDK "$name".');
      } else if (sdkName == "dart") {
        if (constraint.allows(sdk.version)) return;
        dataError("${log.bold(name)} ${entrypoint.root.version} doesn't "
            "support Dart ${sdk.version}.");
      } else {
        dataError("${log.bold(name)} ${entrypoint.root.version} requires the "
            "${sdk.name} SDK, which is unsupported for global executables.");
      }
    });

    return entrypoint;
  }

  /// 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 [checked] is true, the program is run in checked mode.
  ///
  /// Returns the exit code from the executable.
  Future<int> runExecutable(
      String package, String executable, Iterable<String> args,
      {bool checked: false}) {
    var binDir = p.join(_directory, package, 'bin');
    // Snapshots are compiled in Dart 1 mode, so in Dart 2 mode we always run
    // executables from source.
    if (isDart2 || !fileExists(p.join(binDir, '$executable.dart.snapshot'))) {
      return exe.runExecutable(find(package), package, executable, args,
          isGlobal: true, checked: checked, cache: cache);
    }

    // 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, checked: checked,
        recompile: () async {
      log.fine("$package:$executable is out of date and needs to be "
          "recompiled.");
      await _precompileExecutables(
          find(package).packageGraph.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");

  /// Gets the path to the .packages file for an activated cached package with
  /// [name].
  String _getPackagesFilePath(String name) =>
      p.join(_directory, name, ".packages");

  /// 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) {
    var source = id.source;
    if (source is GitSource) {
      var url = source.urlFromDescription(id.description);
      return '${log.bold(id.name)} ${id.version} from Git repository "$url"';
    } else if (source is PathSource) {
      var path = source.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 lists of strings. The first indicates which packages
  /// were successfully re-activated; the second indicates which failed.
  Future<Pair<List<String>, List<String>>> repairActivatedPackages() async {
    var executables = <String, List<String>>{};
    if (dirExists(_binStubDir)) {
      for (var entry in listDir(_binStubDir)) {
        try {
          var binstub = readTextFile(entry);
          var package = _binStubProperty(binstub, "Package");
          if (package == null) {
            throw new ApplicationException("No 'Package' property.");
          }

          var executable = _binStubProperty(binstub, "Executable");
          if (executable == null) {
            throw new ApplicationException("No 'Executable' property.");
          }

          executables.putIfAbsent(package, () => []).add(executable);
        } catch (error, stackTrace) {
          log.error(
              "Error reading binstub for "
              "\"${p.basenameWithoutExtension(entry)}\"",
              error,
              stackTrace);

          tryDeleteEntry(entry);
        }
      }
    }

    var successes = <String>[];
    var failures = <String>[];
    if (dirExists(_directory)) {
      for (var entry in listDir(_directory)) {
        var id;
        try {
          id = _loadPackageId(entry);
          log.message("Reactivating ${log.bold(id.name)} ${id.version}...");

          var entrypoint = find(id.name);
          var snapshots = await _precompileExecutables(entrypoint, id.name);
          var packageExecutables = executables.remove(id.name);
          if (packageExecutables == null) packageExecutables = [];
          _updateBinStubs(
              entrypoint.packageGraph.packages[id.name], packageExecutables,
              overwriteBinStubs: true,
              snapshots: snapshots,
              suggestIfNotOnPath: false);
          successes.add(id.name);
        } catch (error, stackTrace) {
          var message = "Failed to reactivate "
              "${log.bold(p.basenameWithoutExtension(entry))}";
          if (id != null) {
            message += " ${id.version}";
            if (id.source is! HostedSource) message += " from ${id.source}";
          }

          log.error(message, error, stackTrace);
          failures.add(p.basenameWithoutExtension(entry));

          tryDeleteEntry(entry);
        }
      }
    }

    if (executables.isNotEmpty) {
      var message = new StringBuffer("Binstubs exist for non-activated "
          "packages:\n");
      executables.forEach((package, executableNames) {
        // TODO(nweiz): Use a normal for loop here when
        // https://github.com/dart-lang/async_await/issues/68 is fixed.
        executableNames.forEach(
            (executable) => deleteEntry(p.join(_binStubDir, executable)));

        message.writeln("  From ${log.bold(package)}: "
            "${toSentence(executableNames)}");
      });
      log.error(message);
    }

    return new Pair(successes, failures);
  }

  /// 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 = <String>[];
    var collided = <String, String>{};
    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 "\$@"
""";
      }

      // Write this as the system encoding since the system is going to execute
      // it and it might contain non-ASCII caharacters in the pathnames.
      writeTextFile(binStubPath, bash, encoding: const SystemEncoding());

      // 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.
      //
      // The "command" builtin is more reliable than the "which" executable. See
      // http://unix.stackexchange.com/questions/85249/why-not-use-which-what-to-use-then
      var result =
          runProcessSync("command", ["-v", installed], runInShell: true);
      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];
  }
}
