// 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 'command_runner.dart';
import 'entrypoint.dart';
import 'exceptions.dart';
import 'executable.dart' as exec;
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 'sdk/dart.dart';
import 'solver.dart';
import 'solver/incompatibility_cause.dart';
import 'solver/report.dart';
import 'source/cached.dart';
import 'source/git.dart';
import 'source/hosted.dart';
import 'source/path.dart';
import 'source/root.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');

  String _packageDir(String packageName) => p.join(_directory, packageName);

  /// 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<void> activateGit(
    String repo,
    List<String>? executables, {
    required bool overwriteBinStubs,
    String? path,
    String? ref,
  }) async {
    var name = await cache.git.getPackageNameFromRepo(
      repo,
      ref,
      path,
      cache,
      relativeTo: p.current,
    );

    // 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).
    PackageRef packageRef;
    try {
      packageRef = cache.git.parseRef(
        name,
        {
          'url': repo,
          if (path != null) 'path': path,
          if (ref != null) 'ref': ref,
        },
        containingDescription: RootDescription(p.current),
      );
    } on FormatException catch (e) {
      throw ApplicationException(e.message);
    }
    await _installInCache(
      packageRef.withConstraint(VersionConstraint.any),
      executables,
      overwriteBinStubs: overwriteBinStubs,
    );
  }

  Package packageForConstraint(PackageRange dep, String dir) {
    return Package(
      Pubspec(
        'pub global activate',
        dependencies: [dep],
        sources: cache.sources,
      ),
      dir,
      [],
    );
  }

  /// 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.
  ///
  /// [url] is an optional custom pub server URL. If not null, the package to be
  /// activated will be fetched from this URL instead of the default pub URL.
  Future<void> activateHosted(
    PackageRange range,
    List<String>? executables, {
    required bool overwriteBinStubs,
    String? url,
  }) async {
    await _installInCache(
      range,
      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<void> activatePath(
    String path,
    List<String>? executables, {
    required bool overwriteBinStubs,
  }) async {
    var entrypoint = Entrypoint(path, cache);

    // Get the package's dependencies.
    await entrypoint.acquireDependencies(SolveType.get);
    var name = entrypoint.workspaceRoot.name;
    _describeActive(name, cache);

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

    final tempDir = cache.createTempDir();
    // TODO(rnystrom): Look in "bin" and display list of binaries that
    // user can run.
    LockFile([id], mainDependencies: {id.name})
        .writeToFile(p.join(tempDir, 'pubspec.lock'), cache);

    tryDeleteEntry(_packageDir(name));
    tryRenameDir(tempDir, _packageDir(name));

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

  /// Installs the package [dep] and its dependencies into the system cache.
  ///
  /// If [silent] less logging will be printed.
  Future<void> _installInCache(
    PackageRange dep,
    List<String>? executables, {
    required bool overwriteBinStubs,
    bool silent = false,
  }) async {
    final name = dep.name;
    final originalLockFile = _describeActive(name, cache);

    final tempDir = cache.createTempDir();
    // Create a dummy package with just [dep] so we can do resolution on it.
    var root = packageForConstraint(dep, tempDir);

    // Resolve it and download its dependencies.
    SolveResult result;
    try {
      result = await log.spinner(
        'Resolving dependencies',
        () => resolveVersions(SolveType.get, cache, root),
        condition: !silent,
      );
    } on SolveFailure catch (error) {
      for (var incompatibility
          in error.incompatibility.externalIncompatibilities) {
        if (incompatibility.cause is! NoVersionsIncompatibilityCause) continue;
        if (incompatibility.terms.single.package.name != name) continue;
        // If the SolveFailure is caused by [dep] not
        // being available, report that as a [dataError].
        dataError(error.toString());
      }
      rethrow;
    }
    // We want the entrypoint to be rooted at 'dep' not the dummy-package.
    result.packages.removeWhere((id) => id.name == 'pub global activate');

    final lockFile = await result.downloadCachedPackages(cache);
    final sameVersions =
        originalLockFile != null && originalLockFile.samePackageIds(lockFile);

    final id = lockFile.packages[name]!;
    if (sameVersions) {
      log.message('''
The package $name is already activated at newest available version.
To recompile executables, first run `$topLevelProgram pub global deactivate $name`.
''');
    } else {
      // Only precompile binaries if we have a new resolution.
      if (!silent) {
        await SolveReport(
          SolveType.get,
          null,
          root.pubspec,
          originalLockFile ?? LockFile.empty(),
          lockFile,
          result.availableVersions,
          cache,
          dryRun: false,
          quiet: false,
          enforceLockfile: false,
        ).show(summary: false);
      }

      lockFile.writeToFile(p.join(tempDir, 'pubspec.lock'), cache);

      // Load the package graph from [result] so we don't need to re-parse all
      // the pubspecs.
      final entrypoint = Entrypoint.global(
        root,
        lockFile,
        cache,
        solveResult: result,
      );

      await entrypoint.writePackageConfigFile();

      await entrypoint.precompileExecutables();

      tryDeleteEntry(_packageDir(name));
      tryRenameDir(tempDir, _packageDir(name));
    }

    final entrypoint = Entrypoint.global(
      packageForConstraint(dep, _packageDir(dep.name)),
      lockFile,
      cache,
      solveResult: result,
    );
    _updateBinStubs(
      entrypoint,
      cache.load(entrypoint.lockFile.packages[dep.name]!),
      executables,
      overwriteBinStubs: overwriteBinStubs,
    );
    if (!silent) log.message('Activated ${_formatPackage(id)}.');
  }

  /// Shows the user the currently active package with [name], if any.
  LockFile? _describeActive(String name, SystemCache cache) {
    late final LockFile lockFile;
    try {
      lockFile = LockFile.load(_getLockFilePath(name), cache.sources);
    } on IOException {
      // Couldn't read the lock file. It probably doesn't exist.
      return null;
    }
    var id = lockFile.packages[name]!;
    final description = id.description.description;

    if (description is GitDescription) {
      log.message('Package ${log.bold(name)} is currently active from Git '
          'repository "${GitDescription.prettyUri(description.url)}".');
    } else if (description is PathDescription) {
      log.message('Package ${log.bold(name)} is currently active at path '
          '"${description.path}".');
    } else {
      log.message('Package ${log.bold(name)} is currently active at version '
          '${log.bold(id.version.toString())}.');
    }
    return lockFile;
  }

  /// 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(_directory)) {
      return false;
    }
    // By listing all files instead of using only `dirExists` this check will
    // work on case-preserving file-systems.
    final files = listDir(_directory);
    if (!files.contains(dir)) {
      return false;
    }
    if (!dirExists(dir)) {
      // This can happen if `dir` was really a file.
      return false;
    }

    _deleteBinStubs(name);

    var lockFile = 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) async {
    var lockFilePath = _getLockFilePath(name);
    late LockFile lockFile;
    try {
      lockFile = LockFile.load(lockFilePath, cache.sources);
    } on IOException {
      // If we couldn't read the lock file, it's not activated.
      dataError('No active package ${log.bold(name)}.');
    }

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

    Entrypoint entrypoint;
    if (id.source is CachedSource) {
      // For cached sources, the package itself is in the cache and the
      // lockfile is the one we just loaded.
      entrypoint = Entrypoint.global(
        packageForConstraint(id.toRange(), _packageDir(id.name)),
        lockFile,
        cache,
      );
    } else {
      // For uncached sources (i.e. path), the ID just points to the real
      // directory for the package.
      entrypoint = Entrypoint(
        (id.description.description as PathDescription).path,
        cache,
      );
    }

    // Check that the SDK constraints the lockFile says we have are honored.
    lockFile.sdkConstraints.forEach((sdkName, constraint) {
      var sdk = sdks[sdkName];
      if (sdk == null) {
        dataError('${log.bold(name)} as globally activated requires '
            'unknown SDK "$name".');
      } else if (sdkName == 'dart') {
        if (constraint.effectiveConstraint.allows((sdk as DartSdk).version)) {
          return;
        }
        dataError('''
${log.bold(name)} as globally activated doesn't support Dart ${sdk.version}.

try:
`$topLevelProgram pub global activate $name` to reactivate.
''');
      } else {
        dataError('${log.bold(name)} as globally activated 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 built 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 [enableAsserts] is true, the program is run with assertions enabled.
  ///
  /// Returns the exit code from the executable.
  Future<int> runExecutable(
    Entrypoint entrypoint,
    exec.Executable executable,
    List<String> args, {
    bool enableAsserts = false,
    required Future<void> Function(exec.Executable) recompile,
    List<String> vmArgs = const [],
    required bool alwaysUseSubprocess,
  }) async {
    return await exec.runExecutable(
      entrypoint,
      executable,
      args,
      enableAsserts: enableAsserts,
      recompile: (exectuable) async {
        await recompile(exectuable);
        _refreshBinStubs(entrypoint, executable);
      },
      vmArgs: vmArgs,
      alwaysUseSubprocess: alwaysUseSubprocess,
    );
  }

  /// 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 =
        LockFile.load(p.join(_directory, path), cache.sources).packages[name];

    if (id == null) {
      throw 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) {
    final description = id.description.description;
    if (description is GitDescription) {
      var url = GitDescription.prettyUri(description.url);
      return '${log.bold(id.name)} ${id.version} from Git repository "$url"';
    } else if (description is PathDescription) {
      var path = description.path;
      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<(List<String> successes, List<String> failures)>
      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 ApplicationException("No 'Package' property.");
          }

          var executable = _binStubProperty(binstub, 'Executable');
          if (executable == null) {
            throw 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)) {
        PackageId? id;
        try {
          id = _loadPackageId(entry);
          log.message('Reactivating ${log.bold(id.name)} ${id.version}...');

          var entrypoint = await find(id.name);
          final packageExecutables = executables.remove(id.name) ?? [];

          if (entrypoint.isCached) {
            deleteEntry(_packageDir(id.name));
            await _installInCache(
              id.toRange(),
              packageExecutables,
              overwriteBinStubs: true,
              silent: true,
            );
          } else {
            await activatePath(
              entrypoint.workspaceRoot.dir,
              packageExecutables,
              overwriteBinStubs: true,
            );
          }
          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 = StringBuffer('Binstubs exist for non-activated '
          'packages:\n');
      executables.forEach((package, executableNames) {
        for (var executable in executableNames) {
          deleteEntry(p.join(_binStubDir, executable));
        }

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

    return (successes, failures);
  }

  /// Rewrites all binstubs that refer to [executable] of [entrypoint].
  ///
  /// This is meant to be called after a recompile due to eg. outdated
  /// snapshots.
  void _refreshBinStubs(Entrypoint entrypoint, exec.Executable executable) {
    if (!dirExists(_binStubDir)) return;
    for (var file in listDir(_binStubDir, includeDirs: false)) {
      var contents = readTextFile(file);
      var binStubPackage = _binStubProperty(contents, 'Package');
      var binStubScript = _binStubProperty(contents, 'Script');
      if (binStubPackage == null || binStubScript == null) {
        log.fine('Could not parse binstub $file:\n$contents');
        continue;
      }
      if (binStubPackage == entrypoint.workspaceRoot.name &&
          binStubScript ==
              p.basenameWithoutExtension(executable.relativePath)) {
        log.fine('Replacing old binstub $file');
        deleteEntry(file);
        _createBinStub(
          entrypoint.workspaceRoot,
          p.basenameWithoutExtension(file),
          binStubScript,
          overwrite: true,
          snapshot:
              executable.pathOfGlobalSnapshot(entrypoint.workspaceRoot.dir),
        );
      }
    }
  }

  /// 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 [suggestIfNotOnPath] is `true` (the default), this will warn the user if
  /// the bin directory isn't on their path.
  void _updateBinStubs(
    Entrypoint entrypoint,
    Package package,
    List<String>? executables, {
    required bool overwriteBinStubs,
    bool suggestIfNotOnPath = true,
  }) {
    // 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: entrypoint.pathOfSnapshot(
          exec.Executable.adaptProgramName(package.name, 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].toString())}.');
        } else {
          log.warning('Executable ${log.bold(command)} was already installed '
              'from ${log.bold(collided[command].toString())}.');
        }
      }

      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.executablePaths;
    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.
  ///
  /// [snapshot] is a path to a snapshot file. If that snapshot exists 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, {
    required bool overwrite,
    required String snapshot,
  }) {
    var binStubPath = p.join(_binStubDir, executable);
    if (Platform.isWindows) 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.
    String? 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;
      }
    }

    late String binstub;
    // Batch files behave in funky ways if they are modified while updating.
    // To ensure that the byte-offsets of everything stays the same even if the
    // snapshot filename changes we insert some padding in lines containing the
    // snapshot.
    // 260 is the maximal short path length on Windows. Hopefully that is
    // enough.
    final padding = ' ' * (260 - snapshot.length);
    // We need an absolute path since relative ones won't be relative to the
    // right directory when the user runs this.
    snapshot = p.absolute(snapshot);
    if (Platform.isWindows) {
      binstub = '''
@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
if exist "$snapshot" $padding(
  call dart "$snapshot" $padding%*
  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 (
    goto error
  )
  call dart pub global run ${package.name}:$script %*
) else (
  call dart pub global run ${package.name}:$script %*
)
goto eof
:error
exit /b %errorlevel%
:eof
''';
    } else {
      binstub = '''
#!/usr/bin/env sh
# This file was created by pub v${sdk.version}.
# Package: ${package.name}
# Version: ${package.version}
# Executable: $executable
# Script: $script
if [ -f $snapshot ]; then
  dart "$snapshot" "\$@"
  # 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
  dart pub global run ${package.name}:$script "\$@"
else
  dart pub global run ${package.name}:$script "\$@"
fi
''';
    }

    // Write the binstub to a temporary location, make it executable and move
    // it into place afterwards to avoid races.
    final tempDir = cache.createTempDir();
    try {
      final tmpPath = p.join(tempDir, binStubPath);

      // Write this as the system encoding since the system is going to
      // execute it and it might contain non-ASCII characters in the
      // path names.
      writeTextFile(tmpPath, binstub, encoding: const SystemEncoding());

      if (Platform.isLinux || Platform.isMacOS) {
        // Make it executable.
        var result = Process.runSync('chmod', ['+x', tmpPath]);
        if (result.exitCode != 0) {
          // Couldn't make it executable so don't leave it laying around.
          fail('Could not make "$tmpPath" executable (exit code '
              '${result.exitCode}):\n${result.stderr}');
        }
      }
      File(tmpPath).renameSync(binStubPath);
    } finally {
      deleteEntry(tempDir);
    }

    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.isWindows) {
      // 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(
          r'$HOME',
          p.relative(binDir, from: Platform.environment['HOME']),
        );
      }
      final shellConfigFiles = Platform.isMacOS
          // zsh is default on mac - mention that first.
          ? '(.zshrc, .bashrc, .bash_profile, etc.)'
          : '(.bashrc, .bash_profile, .zshrc etc.)';
      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 "
          '$shellConfigFiles:\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 = RegExp(RegExp.escape(name) + r': ([a-zA-Z0-9_-]+)');
    var match = pattern.firstMatch(source);
    return match == null ? null : match[1];
  }
}
