// Copyright (c) 2013, 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.

/// Helper functionality to make working with IO easier.
library;

import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:async/async.dart';
import 'package:cli_util/cli_util.dart'
    show EnvironmentNotFoundException, applicationConfigHome;
import 'package:http/http.dart' show ByteStream;
import 'package:http_multi_server/http_multi_server.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
import 'package:pool/pool.dart';
import 'package:stack_trace/stack_trace.dart';
// ignore: prefer_relative_imports
import 'package:tar/tar.dart';

import 'error_group.dart';
import 'exceptions.dart';
import 'exit_codes.dart' as exit_codes;
import 'log.dart' as log;
import 'utils.dart';

export 'package:http/http.dart' show ByteStream;

/// Environment variable names that are recognized by pub.
class EnvironmentKeys {
  /// Overrides terminal detection for stdout.
  ///
  /// Supported values:
  /// * missing or `''` (empty string): dart:io terminal detection is used.
  /// * `"0"`: output as if no terminal is attached
  ///   - no animations
  ///   - no ANSI colors
  ///   - use unicode characters
  ///   - silent inside [log.errorsOnlyUnlessTerminal]).
  /// * `"1"`: output as if a terminal is attached
  ///   - animations
  ///   - ANSI colors (can be overriden again with NO_COLOR)
  ///   - no unicode on Windows
  ///   - normal verbosity in output inside
  ///   [log.errorsOnlyUnlessTerminal]).
  ///
  /// This variable is mainly for testing, and no forward compatibility
  /// guarantees are given.
  static const forceTerminalOutput = '_PUB_FORCE_TERMINAL_OUTPUT';
  // TODO(sigurdm): Add other environment keys here.
}

/// The pool used for restricting access to asynchronous operations that consume
/// file descriptors.
///
/// The maximum number of allocated descriptors is based on empirical tests that
/// indicate that beyond 32, additional file reads don't provide substantial
/// additional throughput.
final _descriptorPool = Pool(32);

/// The assumed default file mode on Linux and macOS
const _defaultMode = 420; // 644₈

/// Mask for executable bits in file modes.
const _executableMask = 0x49; // 001 001 001

/// Determines if a file or directory exists at [path].
bool entryExists(String path) =>
    dirExists(path) || fileExists(path) || linkExists(path);

/// Returns whether [link] exists on the file system.
///
/// This returns `true` for any symlink, regardless of what it points at or
/// whether it's broken.
bool linkExists(String link) => Link(link).existsSync();

/// Returns whether [file] exists on the file system.
///
/// This returns `true` for a symlink only if that symlink is unbroken and
/// points to a file.
bool fileExists(String file) => File(file).existsSync();

/// Stats [path], assuming it or the entry it is a link to is a file.
///
/// Returns `null` if it is not a file (eg. a directory or not existing).
FileStat? tryStatFile(String path) {
  var stat = File(path).statSync();
  if (stat.type == FileSystemEntityType.link) {
    stat = File(File(path).resolveSymbolicLinksSync()).statSync();
  }
  if (stat.type == FileSystemEntityType.file) {
    return stat;
  }
  return null;
}

/// Returns the canonical path for [pathString].
///
/// This is the normalized, absolute path, with symlinks resolved. As in
/// [transitiveTarget], broken or recursive symlinks will not be fully resolved.
///
/// This doesn't require [pathString] to point to a path that exists on the
/// filesystem; nonexistent or unreadable path entries are treated as normal
/// directories.
String canonicalize(String pathString) {
  final seen = <String>{};
  var components =
      Queue<String>.from(p.split(p.normalize(p.absolute(pathString))));

  // The canonical path, built incrementally as we iterate through [components].
  var newPath = components.removeFirst();

  // Move through the components of the path, resolving each one's symlinks as
  // necessary. A resolved component may also add new components that need to be
  // resolved in turn.
  while (components.isNotEmpty) {
    seen.add(p.join(newPath, p.joinAll(components)));
    final resolvedPath =
        _resolveLink(p.join(newPath, components.removeFirst()));
    final relative = p.relative(resolvedPath, from: newPath);

    // If the resolved path of the component relative to `newPath` is just ".",
    // that means component was a symlink pointing to its parent directory. We
    // can safely ignore such components.
    if (relative == '.') continue;

    final relativeComponents = Queue<String>.from(p.split(relative));

    // If the resolved path is absolute relative to `newPath`, that means it's
    // on a different drive. We need to canonicalize the entire target of that
    // symlink again.
    if (p.isAbsolute(relative)) {
      // If we've already tried to canonicalize the new path, we've encountered
      // a symlink loop. Avoid going infinite by treating the recursive symlink
      // as the canonical path.
      if (seen.contains(relative)) {
        newPath = relative;
      } else {
        newPath = relativeComponents.removeFirst();
        relativeComponents.addAll(components);
        components = relativeComponents;
      }
      continue;
    }

    // Pop directories off `newPath` if the component links upwards in the
    // directory hierarchy.
    while (relativeComponents.firstOrNull == '..') {
      newPath = p.dirname(newPath);
      relativeComponents.removeFirst();
    }

    // If there's only one component left, [resolveLink] guarantees that it's
    // not a link (or is a broken link). We can just add it to `newPath` and
    // continue resolving the remaining components.
    if (relativeComponents.length == 1) {
      newPath = p.join(newPath, relativeComponents.single);
      continue;
    }

    // If we've already tried to canonicalize the new path, we've encountered a
    // symlink loop. Avoid going infinite by treating the recursive symlink as
    // the canonical path.
    final newSubPath = p.join(newPath, p.joinAll(relativeComponents));
    if (seen.contains(newSubPath)) {
      newPath = newSubPath;
      continue;
    }

    // If there are multiple new components to resolve, add them to the
    // beginning of the queue.
    relativeComponents.addAll(components);
    components = relativeComponents;
  }
  return newPath;
}

/// Returns the transitive target of [link] (if A links to B which links to C,
/// this will return C).
///
/// If [link] is part of a symlink loop (e.g. A links to B which links back to
/// A), this returns the path to the first repeated link (so
/// `transitiveTarget("A")` would return `"A"` and `transitiveTarget("A")` would
/// return `"B"`).
///
/// This accepts paths to non-links or broken links, and returns them as-is.
String _resolveLink(String link) {
  final seen = <String>{};
  while (linkExists(link) && seen.add(link)) {
    link = p.normalize(p.join(p.dirname(link), Link(link).targetSync()));
  }
  return link;
}

/// Reads the contents of the text file at [path].
String readTextFile(String path) => File(path).readAsStringSync();

/// Reads the contents of the text file at [path].
/// Returns `null` if the operation fails.
String? tryReadTextFile(String path) {
  try {
    return readTextFile(path);
  } on FileSystemException {
    // TODO: Consider handlind file-not-found differently from other exceptions.
    return null;
  }
}

/// Reads the contents of the text file [file].
Future<String> readTextFileAsync(String file) {
  return _descriptorPool.withResource(() => File(file).readAsString());
}

/// Reads the contents of the binary file [file].
Uint8List readBinaryFile(String file) {
  log.io('Reading binary file $file.');
  final contents = File(file).readAsBytesSync();
  log.io('Read ${contents.length} bytes from $file.');
  return contents;
}

/// Reads the contents of the binary file [file] as a [Stream].
Stream<List<int>> readBinaryFileAsStream(String file) {
  log.io('Reading binary file $file.');
  final contents = File(file).openRead();
  return contents;
}

/// Creates [file] and writes [contents] to it.
///
/// If [dontLogContents] is `true`, the contents of the file will never be
/// logged.
void writeTextFile(
  String file,
  String contents, {
  bool dontLogContents = false,
  Encoding encoding = utf8,
}) {
  // Sanity check: don't spew a huge file.
  log.io('Writing ${contents.length} characters to text file $file.');
  if (!dontLogContents && contents.length < 1024 * 1024) {
    log.fine('Contents:\n$contents');
  }

  deleteIfLink(file);
  File(file).writeAsStringSync(contents, encoding: encoding);
}

/// Reads the contents of the binary file [file].
void writeBinaryFile(String file, Uint8List data) {
  log.io('Writing ${data.length} bytes to file $file.');
  File(file).writeAsBytesSync(data);
}

/// Creates [file] and writes [contents] to it.
///
/// If [dontLogContents] is `true`, the contents of the file will never be
/// logged.
Future<void> writeTextFileAsync(
  String file,
  String contents, {
  bool dontLogContents = false,
  Encoding encoding = utf8,
}) async {
  // Sanity check: don't spew a huge file.
  log.io('Writing ${contents.length} characters to text file $file.');
  if (!dontLogContents && contents.length < 1024 * 1024) {
    log.fine('Contents:\n$contents');
  }

  deleteIfLink(file);
  await File(file).writeAsString(contents, encoding: encoding);
}

/// Writes [stream] to a new file at path [file].
///
/// Replaces any file already at that path. Completes when the file is done
/// being written.
Future<String> createFileFromStream(Stream<List<int>> stream, String file) {
  // TODO(nweiz): remove extra logging when we figure out the windows bot issue.
  log.io('Creating $file from stream.');

  return _descriptorPool.withResource(() async {
    deleteIfLink(file);
    await stream.pipe(File(file).openWrite());
    log.fine('Created $file from stream.');
    return file;
  });
}

void _chmod(int mode, String file) {
  runProcessSync('chmod', [mode.toRadixString(8), file]);
}

/// Deletes [file] if it's a symlink.
///
/// The [File] class overwrites the symlink targets when writing to a file,
/// which is never what we want, so this delete the symlink first if necessary.
void deleteIfLink(String file) {
  if (!linkExists(file)) return;
  log.io('Deleting symlink at $file.');
  Link(file).deleteSync();
}

/// Ensures that [dir] and all its parent directories exist.
///
/// If they don't exist, creates them.
String ensureDir(String dir) {
  Directory(dir).createSync(recursive: true);
  return dir;
}

/// Creates a temp directory in [dir], whose name will be [prefix] with
/// characters appended to it to make a unique name.
///
/// Returns the path of the created directory.
String createTempDir(String base, String prefix) {
  final tempDir = Directory(base).createTempSync(prefix);
  log.io('Created temp directory ${tempDir.path}');
  return tempDir.path;
}

/// Creates a temp directory in the system temp directory, whose name will be
/// 'pub_' with characters appended to it to make a unique name.
///
/// Returns the path of the created directory.
Future<String> _createSystemTempDir() async {
  final tempDir = await Directory.systemTemp.createTemp('pub_');
  log.io('Created temp directory ${tempDir.path}');
  return tempDir.resolveSymbolicLinksSync();
}

String resolveSymlinksOfDir(String dir) {
  return Directory(dir).resolveSymbolicLinksSync();
}

/// Lists the contents of [dir].
///
/// If [recursive] is `true`, lists subdirectory contents (defaults to `false`).
/// If [includeHidden] is `true`, includes files and directories beginning with
/// `.` (defaults to `false`). If [includeDirs] is `true`, includes directories
/// as well as files (defaults to `true`).
///
/// [allowed] is a list of hidden filenames to include even when
/// [includeHidden] is `false`.
///
/// Note that dart:io handles recursive symlinks in an unfortunate way. You
/// end up with two copies of every entity that is within the recursive loop.
/// We originally had our own directory list code that addressed that, but it
/// had a noticeable performance impact. In the interest of speed, we'll just
/// live with that annoying behavior.
///
/// The returned paths are guaranteed to begin with [dir]. Broken symlinks won't
/// be returned.
List<String> listDir(
  String dir, {
  bool recursive = false,
  bool includeHidden = false,
  bool includeDirs = true,
  Iterable<String> allowed = const <String>[],
}) {
  final allowListFilter = createFileFilter(allowed);

  // This is used in some performance-sensitive paths and can list many, many
  // files. As such, it leans more heavily towards optimization as opposed to
  // readability than most code in pub. In particular, it avoids using the path
  // package, since re-parsing a path is very expensive relative to string
  // operations.
  return Directory(dir)
      .listSync(recursive: recursive)
      .where((entity) {
        if (!includeDirs && entity is Directory) return false;
        if (entity is Link) return false;
        if (includeHidden) return true;

        // Using substring here is generally problematic in cases where dir has one
        // or more trailing slashes. If you do listDir("foo"), you'll get back
        // paths like "foo/bar". If you do listDir("foo/"), you'll get "foo/bar"
        // (note the trailing slash was dropped. If you do listDir("foo//"), you'll
        // get "foo//bar".
        //
        // This means if you strip off the prefix, the resulting string may have a
        // leading separator (if the prefix did not have a trailing one) or it may
        // not. However, since we are only using the results of that to call
        // contains() on, the leading separator is harmless.
        assert(entity.path.startsWith(dir));
        var pathInDir = entity.path.substring(dir.length);

        // If the basename is in [allowed], don't count its "/." as making the
        // file hidden.

        if (allowListFilter.any(pathInDir.contains)) {
          final allowedBasename =
              allowListFilter.firstWhere(pathInDir.contains);
          pathInDir =
              pathInDir.substring(0, pathInDir.length - allowedBasename.length);
        }

        if (pathInDir.contains('/.')) return false;
        if (!Platform.isWindows) return true;
        return !pathInDir.contains('\\.');
      })
      .map((entity) => entity.path)
      .toList();
}

/// Returns whether [dir] exists on the file system.
///
/// This returns `true` for a symlink only if that symlink is unbroken and
/// points to a directory.
bool dirExists(String dir) => Directory(dir).existsSync();

/// Tries to resiliently perform [operation].
///
/// Some file system operations can intermittently fail on Windows because
/// other processes are locking a file. We've seen this with virus scanners
/// when we try to delete or move something while it's being scanned. To
/// mitigate that, on Windows, this will retry the operation a few times if it
/// fails.
///
/// For some operations it makes sense to handle ERROR_DIR_NOT_EMPTY
/// differently. They can pass [ignoreEmptyDir] = `true`.
void _attempt(
  String description,
  void Function() operation, {
  bool ignoreEmptyDir = false,
}) {
  if (!Platform.isWindows) {
    operation();
    return;
  }

  String? getErrorReason(FileSystemException error) {
    // ERROR_ACCESS_DENIED
    if (error.osError?.errorCode == 5) {
      return 'access was denied';
    }

    // ERROR_SHARING_VIOLATION
    if (error.osError?.errorCode == 32) {
      return 'it was in use by another process';
    }

    // ERROR_DIR_NOT_EMPTY
    if (!ignoreEmptyDir && _isDirectoryNotEmptyException(error)) {
      return 'of dart-lang/sdk#25353';
    }

    return null;
  }

  const maxRetries = 50;
  for (var i = 0; i < maxRetries; i++) {
    try {
      operation();
      break;
    } on FileSystemException catch (error) {
      final reason = getErrorReason(error);
      if (reason == null) rethrow;

      if (i < maxRetries - 1) {
        log.io('Pub failed to $description because $reason. '
            'Retrying in 50ms.');
        sleep(Duration(milliseconds: 50));
      } else {
        fail('Pub failed to $description because $reason.\n'
            'This may be caused by a virus scanner or having a file\n'
            'in the directory open in another application.');
      }
    }
  }
}

/// Deletes whatever's at [path], whether it's a file, directory, or symlink.
///
/// If it's a directory, it will be deleted recursively.
void deleteEntry(String path) {
  _attempt('delete entry', () {
    if (linkExists(path)) {
      log.io('Deleting link $path.');
      Link(path).deleteSync();
    } else if (dirExists(path)) {
      log.io('Deleting directory $path.');
      Directory(path).deleteSync(recursive: true);
    } else if (fileExists(path)) {
      log.io('Deleting file $path.');
      File(path).deleteSync();
    }
  });
}

/// Attempts to delete whatever's at [path], but doesn't throw an exception if
/// the deletion fails.
void tryDeleteEntry(String path) {
  try {
    deleteEntry(path);
  } catch (error, stackTrace) {
    log.fine('Pub failed to delete $path: $error\n'
        '${Chain.forTrace(stackTrace)}');
  }
}

/// "Cleans" [dir].
///
/// If that directory already exists, it is deleted. Then a new empty directory
/// is created.
void cleanDir(String dir) {
  if (entryExists(dir)) deleteEntry(dir);
  ensureDir(dir);
}

/// Renames (i.e. moves) the directory [from] to [to].
void renameDir(String from, String to) {
  _attempt(
    'rename directory',
    () {
      log.io('Renaming directory $from to $to.');
      Directory(from).renameSync(to);
    },
    ignoreEmptyDir: true,
  );
}

/// Renames directory [from] to [to].
/// If it fails with "destination not empty" we log and continue, assuming
/// another process got there before us.
void tryRenameDir(String from, String to) {
  ensureDir(p.dirname(to));
  try {
    renameDir(from, to);
  } on FileSystemException catch (e) {
    tryDeleteEntry(from);
    if (!_isDirectoryNotEmptyException(e)) {
      rethrow;
    }
    log.fine('''
Destination directory $to already existed.
Assuming a concurrent pub invocation installed it.''');
  }
}

void copyFile(String from, String to) {
  log.io('Copying "$from" to "$to".');
  File(from).copySync(to);
}

void renameFile(String from, String to) {
  log.io('Renaming "$from" to "$to".');
  File(from).renameSync(to);
}

bool _isDirectoryNotEmptyException(FileSystemException e) {
  final errorCode = e.osError?.errorCode;
  return
      // On Linux rename will fail with ENOTEMPTY if directory exists:
      // https://man7.org/linux/man-pages/man2/rename.2.html
      // #define	ENOTEMPTY	39	/* Directory not empty */
      // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/errno.h#n20
      (Platform.isLinux && errorCode == 39) ||
          // On Windows this may fail with ERROR_DIR_NOT_EMPTY or ERROR_ALREADY_EXISTS
          // https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
          (Platform.isWindows && (errorCode == 145 || errorCode == 183)) ||
          // On MacOS rename will fail with ENOTEMPTY if directory exists.
          // #define ENOTEMPTY       66              /* Directory not empty */
          // https://github.com/apple-oss-distributions/xnu/blob/bb611c8fecc755a0d8e56e2fa51513527c5b7a0e/bsd/sys/errno.h#L190
          (Platform.isMacOS && errorCode == 66);
}

/// Creates a new symlink at path [symlink] that points to [target].
///
/// Returns a [Future] which completes to the path to the symlink file.
///
/// If [relative] is true, creates a symlink with a relative path from the
/// symlink to the target. Otherwise, uses the [target] path unmodified.
///
/// Note that on Windows, only directories may be symlinked to.
void createSymlink(String target, String symlink, {bool relative = false}) {
  if (relative) {
    // Relative junction points are not supported on Windows. Instead, just
    // make sure we have a clean absolute path because it will interpret a
    // relative path to be relative to the cwd, not the symlink, and will be
    // confused by forward slashes.
    if (Platform.isWindows) {
      target = p.normalize(p.absolute(target));
    } else {
      // If the directory where we're creating the symlink was itself reached
      // by traversing a symlink, we want the relative path to be relative to
      // it's actual location, not the one we went through to get to it.
      final symlinkDir = canonicalize(p.dirname(symlink));
      target = p.normalize(p.relative(target, from: symlinkDir));
    }
  }

  log.fine('Creating $symlink pointing to $target');
  Link(symlink).createSync(target);
}

/// Creates a new symlink that creates an alias at [symlink] that points to the
/// `lib` directory of package [target].
///
/// If [target] does not have a `lib` directory, this shows a warning if
/// appropriate and then does nothing.
///
/// If [relative] is true, creates a symlink with a relative path from the
/// symlink to the target. Otherwise, uses the [target] path unmodified.
void createPackageSymlink(
  String name,
  String target,
  String symlink, {
  bool isSelfLink = false,
  bool relative = false,
}) {
  // See if the package has a "lib" directory. If not, there's nothing to
  // symlink to.
  target = p.join(target, 'lib');
  if (!dirExists(target)) return;

  log.fine("Creating ${isSelfLink ? "self" : ""}link for package '$name'.");
  createSymlink(target, symlink, relative: relative);
}

/// Whether the current process is a pub subprocess being run from a test.
///
/// The "_PUB_TESTING" variable is automatically set for all the test code's
/// invocations of pub.
final bool runningFromTest =
    Platform.environment.containsKey('_PUB_TESTING') && _assertionsEnabled;

final bool _assertionsEnabled = () {
  try {
    assert(false);
    // ignore: avoid_catching_errors
  } on AssertionError {
    return true;
  }
  return false;
}();

final bool runningFromFlutter =
    Platform.environment.containsKey('PUB_ENVIRONMENT') &&
        (Platform.environment['PUB_ENVIRONMENT'] ?? '').contains('flutter_cli');

/// A regular expression to match the script path of a pub script running from
/// source in the Dart repo.
final _dartRepoRegExp = RegExp(r'/third_party/pkg/pub/('
    r'bin/pub\.dart'
    r'|'
    r'test/.*_test\.dart'
    r')$');

/// Whether pub is running from source in the Dart repo.
///
/// This can happen when running tests against the repo, as well as when
/// building Observatory.
final bool runningFromDartRepo = Platform.script.path.contains(_dartRepoRegExp);

/// The path to the root of the Dart repo.
///
/// This throws a [StateError] if it's called when not running pub from source
/// in the Dart repo.
final String dartRepoRoot = (() {
  if (!runningFromDartRepo) {
    throw StateError('Not running from source in the Dart repo.');
  }

  // Get the URL of the repo root in a way that works when either both running
  // as a test or as a pub executable.
  final url = Platform.script
      .replace(path: Platform.script.path.replaceAll(_dartRepoRegExp, ''));
  return p.fromUri(url);
})();

/// Displays a message and reads a yes/no confirmation from the user.
///
/// Returns a [Future] that completes to `true` if the user confirms or `false`
/// if they do not.
///
/// This will automatically append " (y/N)?" to the message, so [message]
/// should just be a fragment like, "Are you sure you want to proceed". The
/// default for an empty response, or any response not starting with `y` or `Y`
/// is false.
Future<bool> confirm(String message) async {
  final reply = await stdinPrompt('$message (y/N)?');
  return RegExp(r'^[yY]').hasMatch(reply);
}

/// Writes [prompt] and reads a line from stdin.
Future<String> stdinPrompt(String prompt, {bool? echoMode}) async {
  if (runningFromTest) {
    log.message(prompt);
  } else {
    stdout.write('$prompt ');
  }
  if (echoMode != null && stdin.hasTerminal) {
    final previousEchoMode = stdin.echoMode;
    try {
      stdin.echoMode = echoMode;
      final result = stdin.readLineSync() ?? '';
      stdout.write('\n');
      return result;
    } finally {
      stdin.echoMode = previousEchoMode;
    }
  } else {
    return stdin.readLineSync() ?? '';
  }
}

/// Returns `true` if [stdout] should be treated as a terminal.
///
/// The detected behaviour can be overridden with the environment variable
/// [EnvironmentKeys.forceTerminalOutput].
bool get terminalOutputForStdout {
  final environmentValue =
      Platform.environment[EnvironmentKeys.forceTerminalOutput];
  if (environmentValue == null || environmentValue == '') {
    return stdout.hasTerminal;
  } else if (environmentValue == '0') {
    return false;
  } else if (environmentValue == '1') {
    return true;
  } else {
    throw DataException(
      'Environment variable ${EnvironmentKeys.forceTerminalOutput} has unsupported value: $environmentValue.',
    );
  }
}

/// Flushes the stdout and stderr streams, then exits the program with the given
/// status code.
///
/// This returns a Future that will never complete, since the program will have
/// exited already. This is useful to prevent Future chains from proceeding
/// after you've decided to exit.
Future flushThenExit(int status) {
  return Future.wait([stdout.close(), stderr.close()])
      .then((_) => exit(status));
}

/// Returns a [EventSink] that pipes all data to [consumer] and a [Future] that
/// will succeed when [EventSink] is closed or fail with any errors that occur
/// while writing.
(EventSink<T> consumerSink, Future done) _consumerToSink<T>(
  StreamConsumer<T> consumer,
) {
  final controller = StreamController<T>(sync: true);
  final done = controller.stream.pipe(consumer);
  return (controller.sink, done);
}

/// Spawns and runs the process located at [executable], passing in [args].
///
/// Returns a [Future] that will complete with the results of the process after
/// it has ended.
///
/// The spawned process will inherit its parent's environment variables. If
/// [environment] is provided, that will be used to augment (not replace) the
/// the inherited variables.
Future<PubProcessResult> runProcess(
  String executable,
  List<String> args, {
  String? workingDir,
  Map<String, String>? environment,
  bool runInShell = false,
  Encoding? stdoutEncoding = systemEncoding,
  Encoding? stderrEncoding = systemEncoding,
}) {
  ArgumentError.checkNotNull(executable, 'executable');

  return _descriptorPool.withResource(() async {
    ProcessResult result;
    try {
      (executable, args) =
          _sanitizeExecutablePath(executable, args, workingDir: workingDir);
      result = await Process.run(
        executable,
        args,
        workingDirectory: workingDir,
        environment: environment,
        runInShell: runInShell,
        stdoutEncoding: stdoutEncoding,
        stderrEncoding: stderrEncoding,
      );
    } on IOException catch (e) {
      throw RunProcessException(
        'Pub failed to run subprocess `$executable`: $e',
      );
    }

    final pubResult = PubProcessResult(
      result.stdout as String,
      result.stderr as String,
      result.exitCode,
    );
    log.processResult(executable, pubResult);
    return pubResult;
  });
}

/// Spawns the process located at [executable], passing in [args].
///
/// Returns a [Future] that will complete with the [Process] once it's been
/// started.
///
/// The spawned process will inherit its parent's environment variables. If
/// [environment] is provided, that will be used to augment (not replace) the
/// the inherited variables.
@visibleForTesting
Future<PubProcess> startProcess(
  String executable,
  List<String> args, {
  String? workingDir,
  Map<String, String>? environment,
  bool runInShell = false,
}) {
  return _descriptorPool.request().then((resource) async {
    Process ioProcess;
    try {
      (executable, args) =
          _sanitizeExecutablePath(executable, args, workingDir: workingDir);
      ioProcess = await Process.start(
        executable,
        args,
        workingDirectory: workingDir,
        environment: environment,
        runInShell: runInShell,
      );
    } on IOException catch (e) {
      throw RunProcessException(
        'Pub failed to run subprocess `$executable`: $e',
      );
    }

    final process = PubProcess(ioProcess);
    unawaited(process.exitCode.whenComplete(resource.release));
    return process;
  });
}

/// Like [runProcess], but synchronous.
PubProcessResult runProcessSync(
  String executable,
  List<String> args, {
  String? workingDir,
  Map<String, String>? environment,
  bool runInShell = false,
  Encoding? stdoutEncoding = systemEncoding,
  Encoding? stderrEncoding = systemEncoding,
}) {
  ArgumentError.checkNotNull(executable, 'executable');
  ProcessResult result;
  try {
    (executable, args) =
        _sanitizeExecutablePath(executable, args, workingDir: workingDir);
    result = Process.runSync(
      executable,
      args,
      workingDirectory: workingDir,
      environment: environment,
      runInShell: runInShell,
      stdoutEncoding: stdoutEncoding,
      stderrEncoding: stderrEncoding,
    );
  } on IOException catch (e) {
    throw RunProcessException('Pub failed to run subprocess `$executable`: $e');
  }
  final pubResult = PubProcessResult(
    result.stdout as String,
    result.stderr as String,
    result.exitCode,
  );
  log.processResult(executable, pubResult);
  return pubResult;
}

/// A wrapper around [Process] that exposes `dart:async`-style APIs.
class PubProcess {
  /// The underlying `dart:io` [Process].
  final Process _process;

  /// The mutable field for [stdin].
  late EventSink<List<int>> _stdin;

  /// The mutable field for [stdinClosed].
  late Future _stdinClosed;

  /// The mutable field for [stdout].
  late ByteStream _stdout;

  /// The mutable field for [stderr].
  late ByteStream _stderr;

  /// The mutable field for [exitCode].
  late Future<int> _exitCode;

  /// The sink used for passing data to the process's standard input stream.
  ///
  /// Errors on this stream are surfaced through [stdinClosed], [stdout],
  /// [stderr], and [exitCode], which are all members of an [ErrorGroup].
  EventSink<List<int>> get stdin => _stdin;

  // TODO(nweiz): write some more sophisticated Future machinery so that this
  // doesn't surface errors from the other streams/futures, but still passes its
  // unhandled errors to them. Right now it's impossible to recover from a stdin
  // error and continue interacting with the process.
  /// A [Future] that completes when [stdin] is closed, either by the user or by
  /// the process itself.
  ///
  /// This is in an [ErrorGroup] with [stdout], [stderr], and [exitCode], so any
  /// error in process will be passed to it, but won't reach the top-level error
  /// handler unless nothing has handled it.
  Future get stdinClosed => _stdinClosed;

  /// The process's standard output stream.
  ///
  /// This is in an [ErrorGroup] with [stdinClosed], [stderr], and [exitCode],
  /// so any error in process will be passed to it, but won't reach the
  /// top-level error handler unless nothing has handled it.
  ByteStream get stdout => _stdout;

  /// The process's standard error stream.
  ///
  /// This is in an [ErrorGroup] with [stdinClosed], [stdout], and [exitCode],
  /// so any error in process will be passed to it, but won't reach the
  /// top-level error handler unless nothing has handled it.
  ByteStream get stderr => _stderr;

  /// A [Future] that will complete to the process's exit code once the process
  /// has finished running.
  ///
  /// This is in an [ErrorGroup] with [stdinClosed], [stdout], and [stderr], so
  /// any error in process will be passed to it, but won't reach the top-level
  /// error handler unless nothing has handled it.
  Future<int> get exitCode => _exitCode;

  /// Creates a new [PubProcess] wrapping [process].
  PubProcess(Process process) : _process = process {
    final errorGroup = ErrorGroup();

    final (consumerSink, done) = _consumerToSink(process.stdin);
    _stdin = consumerSink;
    _stdinClosed = errorGroup.registerFuture(done);

    _stdout = ByteStream(errorGroup.registerStream(process.stdout));
    _stderr = ByteStream(errorGroup.registerStream(process.stderr));

    final exitCodeCompleter = Completer<int>();
    _exitCode = errorGroup.registerFuture(exitCodeCompleter.future);
    _process.exitCode.then(exitCodeCompleter.complete);
  }

  /// Sends [signal] to the underlying process.
  bool kill([ProcessSignal signal = ProcessSignal.sigterm]) =>
      _process.kill(signal);
}

/// Sanitizes the executable path on windows for [Process.start], [Process.run]
/// and [Process.runSync].
(String, List<String>) _sanitizeExecutablePath(
  String executable,
  List<String> args, {
  String? workingDir,
}) {
  // TODO(rnystrom): Should dart:io just handle this?
  // Spawning a process on Windows will not look for the executable in the
  // system path. So, if executable looks like it needs that (i.e. it doesn't
  // have any path separators in it), then spawn it through a shell.
  if (Platform.isWindows && !executable.contains('\\')) {
    args = ['/c', executable, ...args];
    executable = 'cmd';
  }

  log.process(executable, args, workingDir ?? '.');
  return (executable, args);
}

/// Updates [path]'s modification time.
void touch(String path) {
  log.fine('Touching `$path`');
  File(path).setLastModifiedSync(DateTime.now());
}

/// Creates a temporary directory and passes its path to [fn].
///
/// Once the [Future] returned by [fn] completes, the temporary directory and
/// all its contents are deleted. [fn] can also return `null`, in which case
/// the temporary directory is deleted immediately afterwards.
///
/// Returns a future that completes to the value that the future returned from
/// [fn] completes to.
Future<T> withTempDir<T>(FutureOr<T> Function(String path) fn) async {
  final tempDir = await _createSystemTempDir();
  try {
    return await fn(tempDir);
  } finally {
    deleteEntry(tempDir);
  }
}

/// Binds an [HttpServer] to [host] and [port].
///
/// If [host] is "localhost", this will automatically listen on both the IPv4
/// and IPv6 loopback addresses.
Future<HttpServer> bindServer(String host, int port) async {
  final server = host == 'localhost'
      ? await HttpMultiServer.loopback(port)
      : await HttpServer.bind(host, port);
  server.autoCompress = true;
  return server;
}

/// Extracts a single file from a `.tar.gz` [stream].
///
/// [filename] should be the relative path inside the archive (with unix
/// separators '/').
///
/// Throws a `FormatException` if that file did not exist.
Future<Uint8List> extractFileFromTarGz(
  Stream<List<int>> stream,
  String filename,
) async {
  final reader = TarReader(stream.transform(gzip.decoder));
  filename = p.posix.normalize(filename);
  while (await reader.moveNext()) {
    final entry = reader.current;
    if (p.posix.normalize(entry.name) != filename) continue;
    if (!(entry.type == TypeFlag.reg || entry.type == TypeFlag.regA)) {
      // Can only read regular files.
      throw FormatException('$filename is not a file');
    }
    return await collectBytes(entry.contents);
  }
  throw FormatException('Could not find $filename in archive');
}

/// Extracts a `.tar.gz` file from [stream] to [destination].
Future<void> extractTarGz(Stream<List<int>> stream, String destination) async {
  log.fine('Extracting .tar.gz stream to $destination.');

  destination = p.absolute(destination);
  final reader = TarReader(stream.transform(gzip.decoder));
  final paths = <String>{};
  while (await reader.moveNext()) {
    final entry = reader.current;

    final filePath = p.joinAll([
      destination,
      // Tar file names always use forward slashes
      ...p.posix.split(entry.name),
    ]);
    if (!paths.add(filePath)) {
      // The tar file contained the same entry twice. Assume it is broken.
      await reader.cancel();
      throw FormatException('Tar file contained duplicate path ${entry.name}');
    }

    if (!p.isWithin(destination, filePath)) {
      // The tar contains entries that would be written outside of the
      // destination. That doesn't happen by accident, assume that the tar file
      // is malicious.
      await reader.cancel();
      throw FormatException('Invalid tar entry: ${entry.name}');
    }

    final parentDirectory = p.dirname(filePath);

    bool checkValidTarget(String linkTarget) {
      final isValid = p.isWithin(destination, linkTarget);
      if (!isValid) {
        log.fine('Skipping ${entry.name}: Invalid link target');
      }

      return isValid;
    }

    switch (entry.type) {
      case TypeFlag.dir:
        ensureDir(filePath);
        break;
      case TypeFlag.reg:
      case TypeFlag.regA:
        // Regular file
        deleteIfLink(filePath);
        ensureDir(parentDirectory);
        await createFileFromStream(entry.contents, filePath);

        if (Platform.isLinux || Platform.isMacOS) {
          // Apply executable bits from tar header, but don't change r/w bits
          // from the default
          final mode = _defaultMode | (entry.header.mode & _executableMask);

          if (mode != _defaultMode) {
            _chmod(mode, filePath);
          }
        }
        break;
      case TypeFlag.symlink:
        // Link to another file in this tar, relative from this entry.
        final resolvedTarget = p.joinAll(
          [parentDirectory, ...p.posix.split(entry.header.linkName!)],
        );
        if (!checkValidTarget(resolvedTarget)) {
          // Don't allow links to files outside of this tar.
          break;
        }

        ensureDir(parentDirectory);
        createSymlink(
          p.relative(resolvedTarget, from: parentDirectory),
          filePath,
        );
        break;
      case TypeFlag.link:
        // We generate hardlinks as symlinks too, but their linkName is relative
        // to the root of the tar file (unlike symlink entries, whose linkName
        // is relative to the entry itself).
        final fromDestination = p.join(destination, entry.header.linkName);
        if (!checkValidTarget(fromDestination)) {
          break; // Link points outside of the tar file.
        }

        final fromFile = p.relative(fromDestination, from: parentDirectory);
        ensureDir(parentDirectory);
        createSymlink(fromFile, filePath);
        break;
      default:
        // Only extract files
        continue;
    }
  }

  log.fine('Extracted .tar.gz to $destination.');
}

/// Create a .tar.gz archive from a list of entries.
///
/// Each entry can be a [String], [Directory], or [File] object. The root of
/// the archive is considered to be [baseDir], which defaults to the current
/// working directory.
///
/// Returns a [ByteStream] that emits the contents of the archive.
ByteStream createTarGz(
  List<String> contents, {
  required String baseDir,
}) {
  final buffer = StringBuffer();
  buffer.write('Creating .tar.gz stream containing:\n');
  contents.forEach(buffer.writeln);
  log.fine(buffer.toString());

  ArgumentError.checkNotNull(baseDir, 'baseDir');
  baseDir = p.normalize(p.absolute(baseDir));

  final tarContents = Stream.fromIterable(
    contents.map((entry) {
      entry = p.normalize(p.absolute(entry));
      if (!p.isWithin(baseDir, entry)) {
        throw ArgumentError('Entry $entry is not inside $baseDir.');
      }

      final relative = p.relative(entry, from: baseDir);
      // On Windows, we can't open some files without normalizing them
      final file = File(p.normalize(entry));
      final stat = file.statSync();

      if (stat.type == FileSystemEntityType.link) {
        log.message('$entry is a link locally, but will be uploaded as a '
            'duplicate file.');
      }

      return TarEntry(
        TarHeader(
          // Ensure paths in tar files use forward slashes
          name: p.url.joinAll(p.split(relative)),
          // We want to keep executable bits, but otherwise use the default
          // file mode
          mode: _defaultMode | (stat.mode & _executableMask),
          size: stat.size,
          modified: stat.changed,
          userName: 'pub',
          groupName: 'pub',
        ),
        file.openRead(),
      );
    }),
  );

  return ByteStream(
    tarContents
        .transform(tarWriterWith(format: OutputFormat.gnuLongName))
        .transform(gzip.encoder),
  );
}

/// Contains the results of invoking a [Process] and waiting for it to complete.
class PubProcessResult {
  final List<String> stdout;
  final List<String> stderr;
  final int exitCode;

  PubProcessResult(String stdout, String stderr, this.exitCode)
      : stdout = _toLines(stdout),
        stderr = _toLines(stderr);

  // TODO(rnystrom): Remove this and change to returning one string.
  static List<String> _toLines(String output) {
    final lines = splitLines(output);
    if (lines.isNotEmpty && lines.last == '') lines.removeLast();
    return lines;
  }

  bool get success => exitCode == exit_codes.SUCCESS;
}

/// The location for dart-specific configuration.
///
/// `null` if no config dir could be found.
final String? dartConfigDir = () {
  if (runningFromTest &&
      Platform.environment.containsKey('_PUB_TEST_CONFIG_DIR')) {
    return p.join(Platform.environment['_PUB_TEST_CONFIG_DIR']!, 'dart');
  }
  try {
    return applicationConfigHome('dart');
  } on EnvironmentNotFoundException {
    return null;
  }
}();

/// Escape [x] for users to copy-paste in bash.
///
/// If x is alphanumeric we leave it as is.
///
/// Otherwise, wrap with single quotation, and use '\'' to insert single quote.
String escapeShellArgument(String x) =>
    RegExp(r'^[a-zA-Z0-9-_=@.^]+$').stringMatch(x) == null
        ? "'${x.replaceAll(r'\', r'\\').replaceAll("'", r"'\''")}'"
        : x;

/// Returns all parent directories of [path], starting from [path] to the
/// filesystem root.
///
/// If [path] is relative the directories will also be.
///
/// If [from] is passed, directories are made relative to that.
///
/// Examples:
///   parentDirs('/a/b/c') => ('/a/b/c', '/a/b', '/a', '/')
///   parentDirs('./d/e', from: '/a/b/c') => ('./d/e', './d', '.', '..', '../..', '../../..')
Iterable<String> parentDirs(String path, {String? from}) sync* {
  var relative = false;
  var d = path;
  while (true) {
    if (relative) {
      yield p.relative(d, from: from);
    } else {
      yield d;
    }
    if (!p.isWithin(from ?? p.current, d)) {
      d = p.normalize(p.join(from ?? p.current, d));
      relative = true;
    }
    final parent = p.dirname(d);
    if (parent == d) break;
    d = parent;
  }
}
