// Copyright 2014 The Flutter Authors. 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 'package:meta/meta.dart';
import 'package:package_config/package_config.dart';
import 'package:process/process.dart';

import '../base/bot_detector.dart';
import '../base/common.dart';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart' as io;
import '../base/io.dart';
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../cache.dart';
import '../convert.dart';
import '../dart/package_map.dart';
import '../project.dart';
import '../reporting/reporting.dart';

/// The [Pub] instance.
Pub get pub => context.get<Pub>()!;

/// The console environment key used by the pub tool.
const String _kPubEnvironmentKey = 'PUB_ENVIRONMENT';

/// The console environment key used by the pub tool to find the cache directory.
const String _kPubCacheEnvironmentKey = 'PUB_CACHE';

typedef MessageFilter = String? Function(String message);

/// globalCachePath is the directory in which the content of the localCachePath will be moved in
void joinCaches({
  required FileSystem fileSystem,
  required Directory globalCacheDirectory,
  required Directory dependencyDirectory,
}) {
  for (final FileSystemEntity entity in dependencyDirectory.listSync()) {
    final String newPath = fileSystem.path.join(globalCacheDirectory.path, entity.basename);
    if (entity is File) {
      if (!fileSystem.file(newPath).existsSync()) {
        entity.copySync(newPath);
      }
    } else if (entity is Directory) {
      if (!globalCacheDirectory.childDirectory(entity.basename).existsSync()) {
        final Directory newDirectory = globalCacheDirectory.childDirectory(entity.basename);
        newDirectory.createSync();
        joinCaches(
          fileSystem: fileSystem,
          globalCacheDirectory: newDirectory,
          dependencyDirectory: entity,
        );
      }
    }
  }
}

Directory createDependencyDirectory(Directory pubGlobalDirectory, String dependencyName) {
  final Directory newDirectory = pubGlobalDirectory.childDirectory(dependencyName);
  newDirectory.createSync();
  return newDirectory;
}

bool tryDelete(Directory directory, Logger logger) {
  try {
    if (directory.existsSync()) {
      directory.deleteSync(recursive: true);
    }
  } on FileSystemException {
    logger.printWarning('Failed to delete directory at: ${directory.path}');
    return false;
  }
  return true;
}

/// When local cache (flutter_root/.pub-cache) and global cache (HOME/.pub-cache) are present a
/// merge needs to be done leaving only the global
///
/// Valid pubCache should look like this ./localCachePath/.pub-cache/hosted/pub.dartlang.org
bool needsToJoinCache({
  required FileSystem fileSystem,
  required String localCachePath,
  required Directory? globalDirectory,
}) {
  if (globalDirectory == null) {
    return false;
  }
  final Directory localDirectory = fileSystem.directory(localCachePath);

  return globalDirectory.childDirectory('hosted').childDirectory('pub.dartlang.org').existsSync() &&
    localDirectory.childDirectory('hosted').childDirectory('pub.dartlang.org').existsSync();
}

/// Represents Flutter-specific data that is added to the `PUB_ENVIRONMENT`
/// environment variable and allows understanding the type of requests made to
/// the package site on Flutter's behalf.
// DO NOT update without contacting kevmoo.
// We have server-side tooling that assumes the values are consistent.
class PubContext {
  PubContext._(this._values) {
    for (final String item in _values) {
      if (!_validContext.hasMatch(item)) {
        throw ArgumentError.value(
          _values, 'value', 'Must match RegExp ${_validContext.pattern}');
      }
    }
  }

  static PubContext getVerifyContext(String commandName) =>
      PubContext._(<String>['verify', commandName.replaceAll('-', '_')]);

  static final PubContext create = PubContext._(<String>['create']);
  static final PubContext createPackage = PubContext._(<String>['create_pkg']);
  static final PubContext createPlugin = PubContext._(<String>['create_plugin']);
  static final PubContext interactive = PubContext._(<String>['interactive']);
  static final PubContext pubGet = PubContext._(<String>['get']);
  static final PubContext pubUpgrade = PubContext._(<String>['upgrade']);
  static final PubContext pubForward = PubContext._(<String>['forward']);
  static final PubContext runTest = PubContext._(<String>['run_test']);
  static final PubContext flutterTests = PubContext._(<String>['flutter_tests']);
  static final PubContext updatePackages = PubContext._(<String>['update_packages']);

  final List<String> _values;

  static final RegExp _validContext = RegExp('[a-z][a-z_]*[a-z]');

  @override
  String toString() => 'PubContext: ${_values.join(':')}';

  String toAnalyticsString()  {
    return _values.map((String s) => s.replaceAll('_', '-')).toList().join('-');
  }
}

/// A handle for interacting with the pub tool.
abstract class Pub {
  /// Create a default [Pub] instance.
  factory Pub({
    required FileSystem fileSystem,
    required Logger logger,
    required ProcessManager processManager,
    required Platform platform,
    required BotDetector botDetector,
    required Usage usage,
  }) = _DefaultPub;

  /// Create a [Pub] instance with a mocked [stdio].
  @visibleForTesting
  factory Pub.test({
    required FileSystem fileSystem,
    required Logger logger,
    required ProcessManager processManager,
    required Platform platform,
    required BotDetector botDetector,
    required Usage usage,
    required Stdio stdio,
  }) = _DefaultPub.test;

  /// Runs `pub get` or `pub upgrade` for [project].
  ///
  /// [context] provides extra information to package server requests to
  /// understand usage.
  ///
  /// If [shouldSkipThirdPartyGenerator] is true, the overall pub get will be
  /// skipped if the package config file has a "generator" other than "pub".
  /// Defaults to true.
  /// Will also resolve dependencies in the example folder if present.
  Future<void> get({
    required PubContext context,
    required FlutterProject project,
    bool skipIfAbsent = false,
    bool upgrade = false,
    bool offline = false,
    String? flutterRootOverride,
    bool checkUpToDate = false,
    bool shouldSkipThirdPartyGenerator = true,
    bool printProgress = true,
  });

  /// Runs pub in 'batch' mode.
  ///
  /// forwarding complete lines written by pub to its stdout/stderr streams to
  /// the corresponding stream of this process, optionally applying filtering.
  /// The pub process will not receive anything on its stdin stream.
  ///
  /// The `--trace` argument is passed to `pub` when `showTraceForErrors`
  /// `isRunningOnBot` is true.
  ///
  /// [context] provides extra information to package server requests to
  /// understand usage.
  Future<void> batch(
    List<String> arguments, {
    required PubContext context,
    String? directory,
    MessageFilter? filter,
    String failureMessage = 'pub failed',
  });

  /// Runs pub in 'interactive' mode.
  ///
  /// directly piping the stdin stream of this process to that of pub, and the
  /// stdout/stderr stream of pub to the corresponding streams of this process.
  Future<void> interactively(
    List<String> arguments, {
    String? directory,
    required io.Stdio stdio,
    bool touchesPackageConfig = false,
    bool generateSyntheticPackage = false,
  });
}

class _DefaultPub implements Pub {
  _DefaultPub({
    required FileSystem fileSystem,
    required Logger logger,
    required ProcessManager processManager,
    required Platform platform,
    required BotDetector botDetector,
    required Usage usage,
  }) : _fileSystem = fileSystem,
       _logger = logger,
       _platform = platform,
       _botDetector = botDetector,
       _usage = usage,
       _processUtils = ProcessUtils(
         logger: logger,
         processManager: processManager,
       ),
       _processManager = processManager,
       _stdio = null;

  @visibleForTesting
  _DefaultPub.test({
    required FileSystem fileSystem,
    required Logger logger,
    required ProcessManager processManager,
    required Platform platform,
    required BotDetector botDetector,
    required Usage usage,
    required Stdio stdio,
  }) : _fileSystem = fileSystem,
       _logger = logger,
       _platform = platform,
       _botDetector = botDetector,
       _usage = usage,
       _processUtils = ProcessUtils(
         logger: logger,
         processManager: processManager,
       ),
       _processManager = processManager,
       _stdio = stdio;

  final FileSystem _fileSystem;
  final Logger _logger;
  final ProcessUtils _processUtils;
  final Platform _platform;
  final BotDetector _botDetector;
  final Usage _usage;
  final ProcessManager _processManager;
  final Stdio? _stdio;

  @override
  Future<void> get({
    required PubContext context,
    required FlutterProject project,
    bool skipIfAbsent = false,
    bool upgrade = false,
    bool offline = false,
    bool generateSyntheticPackage = false,
    bool generateSyntheticPackageForExample = false,
    String? flutterRootOverride,
    bool checkUpToDate = false,
    bool shouldSkipThirdPartyGenerator = true,
    bool printProgress = true,
  }) async {
    final String directory = project.directory.path;
    final File packageConfigFile = project.packageConfigFile;
    final Directory generatedDirectory = _fileSystem.directory(
      _fileSystem.path.join(directory, '.dart_tool', 'flutter_gen'));
    final File lastVersion = _fileSystem.file(
      _fileSystem.path.join(directory, '.dart_tool', 'version'));
    final File currentVersion = _fileSystem.file(
      _fileSystem.path.join(Cache.flutterRoot!, 'version'));
    final File pubspecYaml = project.pubspecFile;
    final File pubLockFile = _fileSystem.file(
      _fileSystem.path.join(directory, 'pubspec.lock')
    );

    if (shouldSkipThirdPartyGenerator && project.packageConfigFile.existsSync()) {
      Map<String, Object?> packageConfigMap;
      try {
        packageConfigMap = jsonDecode(
          project.packageConfigFile.readAsStringSync(),
        ) as Map<String, Object?>;
      } on FormatException {
        packageConfigMap = <String, Object?>{};
      }

      final bool isPackageConfigGeneratedByThirdParty =
          packageConfigMap.containsKey('generator') &&
          packageConfigMap['generator'] != 'pub';

      if (isPackageConfigGeneratedByThirdParty) {
        _logger.printTrace('Skipping pub get: generated by third-party.');
        return;
      }
    }

    // If the pubspec.yaml is older than the package config file and the last
    // flutter version used is the same as the current version skip pub get.
    // This will incorrectly skip pub on the master branch if dependencies
    // are being added/removed from the flutter framework packages, but this
    // can be worked around by manually running pub.
    if (checkUpToDate &&
        packageConfigFile.existsSync() &&
        pubLockFile.existsSync() &&
        pubspecYaml.lastModifiedSync().isBefore(pubLockFile.lastModifiedSync()) &&
        pubspecYaml.lastModifiedSync().isBefore(packageConfigFile.lastModifiedSync()) &&
        lastVersion.existsSync() &&
        lastVersion.readAsStringSync() == currentVersion.readAsStringSync()) {
      _logger.printTrace('Skipping pub get: version match.');
      return;
    }

    final String command = upgrade ? 'upgrade' : 'get';
    final bool verbose = _logger.isVerbose;
    final List<String> args = <String>[
      if (_logger.supportsColor)
        '--color',
      if (verbose)
        '--verbose',
      '--directory',
      _fileSystem.path.relative(directory),
      ...<String>[
        command,
      ],
      if (offline)
        '--offline',
      '--example',
    ];
    await _runWithStdioInherited(
      args,
      command: command,
      context: context,
      directory: directory,
      failureMessage: 'pub $command failed',
      retry: !offline,
      flutterRootOverride: flutterRootOverride,
      printProgress: printProgress
    );

    if (!packageConfigFile.existsSync()) {
      throwToolExit('$directory: pub did not create .dart_tools/package_config.json file.');
    }
    lastVersion.writeAsStringSync(currentVersion.readAsStringSync());
    await _updatePackageConfig(
      packageConfigFile,
      generatedDirectory,
      project.manifest.generateSyntheticPackage,
    );
    if (project.hasExampleApp && project.example.pubspecFile.existsSync()) {
      final Directory exampleGeneratedDirectory = _fileSystem.directory(
        _fileSystem.path.join(project.example.directory.path, '.dart_tool', 'flutter_gen'));
      await _updatePackageConfig(
        project.example.packageConfigFile,
        exampleGeneratedDirectory,
        project.example.manifest.generateSyntheticPackage,
      );
    }
  }

  /// Runs pub with [arguments] and [ProcessStartMode.inheritStdio] mode.
  ///
  /// Uses [ProcessStartMode.normal] and [Pub._stdio] if [Pub.test] constructor
  /// was used.
  ///
  /// Prints the stdout and stderr of the whole run.
  ///
  /// Sends an analytics event.
  Future<void> _runWithStdioInherited(
    List<String> arguments, {
    required String command,
    required bool printProgress,
    required PubContext context,
    required bool retry,
    required String directory,
    String failureMessage = 'pub failed',
    String? flutterRootOverride,
  }) async {
    int exitCode;

    _logger.printStatus('Running "flutter pub $command" in ${_fileSystem.path.basename(directory)}...');
    final List<String> pubCommand = _pubCommand(arguments);
    final Map<String, String> pubEnvironment = await _createPubEnvironment(context, flutterRootOverride);
    try {
      final io.Process process;
      final io.Stdio? stdio = _stdio;

      if (stdio != null) {
        // Omit mode parameter and direct pub output to [Pub._stdio] for tests.
        process = await _processUtils.start(
          pubCommand,
          workingDirectory: _fileSystem.path.current,
          environment: pubEnvironment,
        );

        final StreamSubscription<List<int>> stdoutSubscription =
          process.stdout.listen(stdio.stdout.add);
        final StreamSubscription<List<int>> stderrSubscription =
          process.stderr.listen(stdio.stderr.add);

        await Future.wait<void>(<Future<void>>[
          stdoutSubscription.asFuture<void>(),
          stderrSubscription.asFuture<void>(),
        ]);

        unawaited(stdoutSubscription.cancel());
        unawaited(stderrSubscription.cancel());
      } else {
        // Let pub inherit stdio for normal operation.
        process = await _processUtils.start(
          pubCommand,
          workingDirectory: _fileSystem.path.current,
          environment: pubEnvironment,
          mode: ProcessStartMode.inheritStdio,
        );
      }

      exitCode = await process.exitCode;
    // The exception is rethrown, so don't catch only Exceptions.
    } catch (exception) { // ignore: avoid_catches_without_on_clauses
      if (exception is io.ProcessException) {
        final StringBuffer buffer = StringBuffer('${exception.message}\n');
        final String directoryExistsMessage = _fileSystem.directory(directory).existsSync()
            ? 'exists'
            : 'does not exist';
        buffer.writeln('Working directory: "$directory" ($directoryExistsMessage)');
        final Map<String, String> env = await _createPubEnvironment(context, flutterRootOverride);
        buffer.write(_stringifyPubEnv(env));
        throw io.ProcessException(
          exception.executable,
          exception.arguments,
          buffer.toString(),
          exception.errorCode,
        );
      }
      rethrow;
    }

    final int code = exitCode;
    final String result = code == 0 ? 'success' : 'failure';
    PubResultEvent(
      context: context.toAnalyticsString(),
      result: result,
      usage: _usage,
    ).send();

    if (code != 0) {
      final StringBuffer buffer = StringBuffer('$failureMessage\n');
      buffer.writeln('command: "${pubCommand.join(' ')}"');
      buffer.write(_stringifyPubEnv(pubEnvironment));
      buffer.writeln('exit code: $code');
      throwToolExit(
        buffer.toString(),
        exitCode: code,
      );
    }
  }

  // For surfacing pub env in crash reporting
  String _stringifyPubEnv(Map<String, String> map, {String prefix = 'pub env'}) {
    if (map.isEmpty) {
      return '';
    }
    final StringBuffer buffer = StringBuffer();
    buffer.writeln('$prefix: {');
    for (final MapEntry<String, String> entry in map.entries) {
      buffer.writeln('  "${entry.key}": "${entry.value}",');
    }
    buffer.writeln('}');
    return buffer.toString();
  }

  @override
  Future<void> batch(
    List<String> arguments, {
    required PubContext context,
    String? directory,
    MessageFilter? filter,
    String failureMessage = 'pub failed',
    String? flutterRootOverride,
  }) async {
    final bool showTraceForErrors = await _botDetector.isRunningOnBot;

    String lastPubMessage = 'no message';
    String? filterWrapper(String line) {
      lastPubMessage = line;
      if (filter == null) {
        return line;
      }
      return filter(line);
    }

    if (showTraceForErrors) {
      arguments.insert(0, '--trace');
    }
    final Map<String, String> pubEnvironment = await _createPubEnvironment(context, flutterRootOverride);
    final List<String> pubCommand = _pubCommand(arguments);
    final int code = await _processUtils.stream(
        pubCommand,
        workingDirectory: directory,
        mapFunction: filterWrapper, // may set versionSolvingFailed, lastPubMessage
        environment: pubEnvironment,
      );

    String result = 'success';
    if (code != 0) {
      result = 'failure';
    }
    PubResultEvent(
      context: context.toAnalyticsString(),
      result: result,
      usage: _usage,
    ).send();

    if (code != 0) {
      final StringBuffer buffer = StringBuffer('$failureMessage\n');
      buffer.writeln('command: "${pubCommand.join(' ')}"');
      buffer.write(_stringifyPubEnv(pubEnvironment));
      buffer.writeln('exit code: $code');
      buffer.writeln('last line of pub output: "${lastPubMessage.trim()}"');
      throwToolExit(
        buffer.toString(),
        exitCode: code,
      );
    }
  }

  @override
  Future<void> interactively(
    List<String> arguments, {
    String? directory,
    required io.Stdio stdio,
    bool touchesPackageConfig = false,
    bool generateSyntheticPackage = false,
  }) async {
    // Fully resolved pub or pub.bat is calculated based on current platform.
    final io.Process process = await _processUtils.start(
      _pubCommand(<String>[
          if (_logger.supportsColor) '--color',
          ...arguments,
      ]),
      workingDirectory: directory,
      environment: await _createPubEnvironment(PubContext.interactive),
    );

    // Pipe the Flutter tool stdin to the pub stdin.
    unawaited(process.stdin.addStream(stdio.stdin)
      // If pub exits unexpectedly with an error, that will be reported below
      // by the tool exit after the exit code check.
      .catchError((dynamic err, StackTrace stack) {
        _logger.printTrace('Echoing stdin to the pub subprocess failed:');
        _logger.printTrace('$err\n$stack');
      }
    ));

    // Pipe the pub stdout and stderr to the tool stdout and stderr.
    try {
      await Future.wait<dynamic>(<Future<dynamic>>[
        stdio.addStdoutStream(process.stdout),
        stdio.addStderrStream(process.stderr),
      ]);
    } on Exception catch (err, stack) {
      _logger.printTrace('Echoing stdout or stderr from the pub subprocess failed:');
      _logger.printTrace('$err\n$stack');
    }

    // Wait for pub to exit.
    final int code = await process.exitCode;
    if (code != 0) {
      throwToolExit('pub finished with exit code $code', exitCode: code);
    }

    if (touchesPackageConfig) {
      final String targetDirectory = directory ?? _fileSystem.currentDirectory.path;
      final File packageConfigFile = _fileSystem.file(
        _fileSystem.path.join(targetDirectory, '.dart_tool', 'package_config.json'));
      final Directory generatedDirectory = _fileSystem.directory(
        _fileSystem.path.join(targetDirectory, '.dart_tool', 'flutter_gen'));
      final File lastVersion = _fileSystem.file(
        _fileSystem.path.join(targetDirectory, '.dart_tool', 'version'));
      final File currentVersion = _fileSystem.file(
        _fileSystem.path.join(Cache.flutterRoot!, 'version'));
        lastVersion.writeAsStringSync(currentVersion.readAsStringSync());
      await _updatePackageConfig(
        packageConfigFile,
        generatedDirectory,
        generateSyntheticPackage,
      );
    }
  }

  /// The command used for running pub.
  List<String> _pubCommand(List<String> arguments) {
    // TODO(zanderso): refactor to use artifacts.
    final String sdkPath = _fileSystem.path.joinAll(<String>[
      Cache.flutterRoot!,
      'bin',
      'cache',
      'dart-sdk',
      'bin',
      'dart',
    ]);
    if (!_processManager.canRun(sdkPath)) {
      throwToolExit(
        'Your Flutter SDK download may be corrupt or missing permissions to run. '
        'Try re-downloading the Flutter SDK into a directory that has read/write '
        'permissions for the current user.'
      );
    }
    return <String>[sdkPath, '__deprecated_pub', ...arguments];
  }

  // Returns the environment value that should be used when running pub.
  //
  // Includes any existing environment variable, if one exists.
  //
  // [context] provides extra information to package server requests to
  // understand usage.
  Future<String> _getPubEnvironmentValue(PubContext pubContext) async {
    // DO NOT update this function without contacting kevmoo.
    // We have server-side tooling that assumes the values are consistent.
    final String? existing = _platform.environment[_kPubEnvironmentKey];
    final List<String> values = <String>[
      if (existing != null && existing.isNotEmpty) existing,
      if (await _botDetector.isRunningOnBot) 'flutter_bot',
      'flutter_cli',
      ...pubContext._values,
    ];
    return values.join(':');
  }

  /// There are 3 ways to get the pub cache location
  ///
  /// 1) Provide the _kPubCacheEnvironmentKey.
  /// 2) There is a local cache (in the Flutter SDK) but not a global one (in the user's home directory).
  /// 3) If both local and global are available then merge the local into global and return the global.
  String? _getPubCacheIfAvailable() {
    if (_platform.environment.containsKey(_kPubCacheEnvironmentKey)) {
      return _platform.environment[_kPubCacheEnvironmentKey];
    }

    final String localCachePath = _fileSystem.path.join(Cache.flutterRoot!, '.pub-cache');
    final Directory? globalDirectory;
    if (_platform.isWindows) {
      globalDirectory = _getWindowsGlobalDirectory;
    }
    else {
      if (_platform.environment['HOME'] == null) {
        globalDirectory = null;
      } else {
        final String homeDirectoryPath = _platform.environment['HOME']!;
        globalDirectory = _fileSystem.directory(_fileSystem.path.join(homeDirectoryPath, '.pub-cache'));
      }
    }

    if (needsToJoinCache(
      fileSystem: _fileSystem,
      localCachePath: localCachePath,
      globalDirectory: globalDirectory,
    )) {
      final Directory localDirectoryPub = _fileSystem.directory(
        _fileSystem.path.join(localCachePath, 'hosted', 'pub.dartlang.org')
      );
      final Directory globalDirectoryPub = _fileSystem.directory(
        _fileSystem.path.join(globalDirectory!.path, 'hosted', 'pub.dartlang.org')
      );
      for (final FileSystemEntity entity in localDirectoryPub.listSync()) {
        if (entity is Directory && !globalDirectoryPub.childDirectory(entity.basename).existsSync()){
          try {
            final Directory newDirectory = createDependencyDirectory(globalDirectoryPub, entity.basename);
            joinCaches(
              fileSystem: _fileSystem,
              globalCacheDirectory: newDirectory,
              dependencyDirectory: entity,
            );
          } on FileSystemException {
            if (!tryDelete(globalDirectoryPub.childDirectory(entity.basename), _logger)) {
              _logger.printWarning('The join of pub-caches failed');
              _logger.printStatus('Running "dart pub cache repair"');
              _processManager.runSync(<String>['dart', 'pub', 'cache', 'repair']);
            }
          }
        }
      }
      tryDelete(_fileSystem.directory(localCachePath), _logger);
      return globalDirectory.path;
    } else if (globalDirectory != null && globalDirectory.existsSync()) {
      return globalDirectory.path;
    } else if (_fileSystem.directory(localCachePath).existsSync()) {
      return localCachePath;
    }
    // Use pub's default location by returning null.
    return null;
  }

  Directory? get _getWindowsGlobalDirectory {
    // %LOCALAPPDATA% is preferred as the cache location over %APPDATA%, because the latter is synchronised between
    // devices when the user roams between them, whereas the former is not.
    // The default cache dir used to be in %APPDATA%, so to avoid breaking old installs,
    // we use the old dir in %APPDATA% if it exists. Else, we use the new default location
    // in %LOCALAPPDATA%.
    for (final String envVariable in <String>['APPDATA', 'LOCALAPPDATA']) {
      if (_platform.environment[envVariable] != null) {
        final String homePath = _platform.environment[envVariable]!;
        final Directory globalDirectory = _fileSystem.directory(_fileSystem.path.join(homePath, 'Pub', 'Cache'));
        if (globalDirectory.existsSync()) {
          return globalDirectory;
        }
      }
    }
    return null;
  }

  /// The full environment used when running pub.
  ///
  /// [context] provides extra information to package server requests to
  /// understand usage.
  Future<Map<String, String>> _createPubEnvironment(PubContext context, [ String? flutterRootOverride ]) async {
    final Map<String, String> environment = <String, String>{
      'FLUTTER_ROOT': flutterRootOverride ?? Cache.flutterRoot!,
      _kPubEnvironmentKey: await _getPubEnvironmentValue(context),
    };
    final String? pubCache = _getPubCacheIfAvailable();
    if (pubCache != null) {
      environment[_kPubCacheEnvironmentKey] = pubCache;
    }
    return environment;
  }

  /// Update the package configuration file.
  ///
  /// Creates a corresponding `package_config_subset` file that is used by the build
  /// system to avoid rebuilds caused by an updated pub timestamp.
  ///
  /// if [generateSyntheticPackage] is true then insert flutter_gen synthetic
  /// package into the package configuration. This is used by the l10n localization
  /// tooling to insert a new reference into the package_config file, allowing the import
  /// of a package URI that is not specified in the pubspec.yaml
  ///
  /// For more information, see:
  ///   * [generateLocalizations], `in lib/src/localizations/gen_l10n.dart`
  Future<void> _updatePackageConfig(
    File packageConfigFile,
    Directory generatedDirectory,
    bool generateSyntheticPackage,
  ) async {
    final PackageConfig packageConfig = await loadPackageConfigWithLogging(packageConfigFile, logger: _logger);

    packageConfigFile.parent
      .childFile('package_config_subset')
      .writeAsStringSync(_computePackageConfigSubset(
        packageConfig,
        _fileSystem,
      ));

    if (!generateSyntheticPackage) {
      return;
    }
    if (packageConfig.packages.any((Package package) => package.name == 'flutter_gen')) {
      return;
    }

    // TODO(jonahwillams): Using raw json manipulation here because
    // savePackageConfig always writes to local io, and it changes absolute
    // paths to relative on round trip.
    // See: https://github.com/dart-lang/package_config/issues/99,
    // and: https://github.com/dart-lang/package_config/issues/100.

    // Because [loadPackageConfigWithLogging] succeeded [packageConfigFile]
    // we can rely on the file to exist and be correctly formatted.
    final Map<String, dynamic> jsonContents =
        json.decode(packageConfigFile.readAsStringSync()) as Map<String, dynamic>;

    (jsonContents['packages'] as List<dynamic>).add(<String, dynamic>{
      'name': 'flutter_gen',
      'rootUri': 'flutter_gen',
      'languageVersion': '2.12',
    });

    packageConfigFile.writeAsStringSync(json.encode(jsonContents));
  }

  // Subset the package config file to only the parts that are relevant for
  // rerunning the dart compiler.
  String _computePackageConfigSubset(PackageConfig packageConfig, FileSystem fileSystem) {
    final StringBuffer buffer = StringBuffer();
    for (final Package package in packageConfig.packages) {
      buffer.writeln(package.name);
      buffer.writeln(package.languageVersion);
      buffer.writeln(package.root);
      buffer.writeln(package.packageUriRoot);
    }
    buffer.writeln(packageConfig.version);
    return buffer.toString();
  }
}
