// Copyright (c) 2012, 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:pool/pool.dart';
import 'package:pub_semver/pub_semver.dart';

import '../exceptions.dart';
import '../git.dart' as git;
import '../io.dart';
import '../language_version.dart';
import '../log.dart' as log;
import '../package.dart';
import '../package_name.dart';
import '../path.dart';
import '../platform_info.dart';
import '../pubspec.dart';
import '../source.dart';
import '../system_cache.dart';
import '../utils.dart';
import 'cached.dart';
import 'path.dart';
import 'root.dart';

typedef TaggedVersion = ({Version version, String commitId});

/// A package source that gets packages from Git repos.
class GitSource extends CachedSource {
  static GitSource instance = GitSource._();

  GitSource._();

  @override
  final name = 'git';

  @override
  PackageRef parseRef(
    String name,
    Object? description, {
    ResolvedDescription? containingDescription,
    required LanguageVersion languageVersion,
  }) {
    String url;
    String? ref;
    String? path;
    String? tagPattern;
    if (description is String) {
      url = description;
    } else if (description is! Map) {
      throw const FormatException(
        'The description must be a Git URL or a map '
        "with a 'url' key.",
      );
    } else {
      final descriptionUrl = description['url'];
      if (descriptionUrl is! String) {
        throw const FormatException(
          "The 'url' field of a description must be a string.",
        );
      }
      url = descriptionUrl;

      final descriptionRef = description['ref'];
      if (descriptionRef is! String?) {
        throw const FormatException(
          "The 'ref' field of the description must be a "
          'string.',
        );
      }
      ref = descriptionRef;

      final descriptionPath = description['path'];
      if (descriptionPath is! String?) {
        throw const FormatException(
          "The 'path' field of the description must be a "
          'string.',
        );
      }
      path = descriptionPath;

      final descriptionTagPattern = description['tag_pattern'];

      if (descriptionTagPattern is! String?) {
        throw const FormatException(
          "The 'tag_pattern' field of the description "
          'must be a string or null.',
        );
      } else {
        if (descriptionTagPattern != null) {
          if (!languageVersion.supportsTagPattern) {
            throw FormatException(
              'Using `git: {tagPattern: }` '
              'is only supported with a minimum SDK '
              'constraint of ${LanguageVersion.firstVersionWithTagPattern}.',
            );
          }
          validateTagPattern(descriptionTagPattern);
        }
        tagPattern = descriptionTagPattern;
      }

      if (ref != null && tagPattern != null) {
        throw const FormatException(
          'A git description cannot have both a ref and a `tag_pattern`.',
        );
      }
      if (languageVersion.forbidsUnknownDescriptionKeys) {
        for (final key in description.keys) {
          if (!['url', 'ref', 'path', 'tag_pattern'].contains(key)) {
            throw FormatException('Unknown key "$key" in description.');
          }
        }
      }
    }

    final containingDir = switch (containingDescription?.description) {
      RootDescription(path: final path) => path,
      PathDescription(path: final path) => path,
      _ => null,
    };

    return PackageRef(
      name,
      GitDescription(
        url: url,
        containingDir: containingDir,
        ref: ref,
        path: _validatedPath(path),
        tagPattern: tagPattern,
      ),
    );
  }

  @override
  PackageId parseId(
    String name,
    Version version,
    Object? description, {
    String? containingDir,
  }) {
    if (description is! Map) {
      throw const FormatException(
        "The description must be a map with a 'url' "
        'key.',
      );
    }

    final ref = description['ref'];
    if (ref is! String?) {
      throw const FormatException(
        "The 'ref' field of the description must be a "
        'string.',
      );
    }

    final resolvedRef = description['resolved-ref'];
    if (resolvedRef is! String) {
      throw const FormatException(
        "The 'resolved-ref' field of the description "
        'must be a string.',
      );
    }

    final url = description['url'];
    if (url is! String) {
      throw const FormatException(
        "The 'url' field of the description "
        'must be a string.',
      );
    }

    final tagPattern = description['tag-pattern'];
    if (tagPattern is! String?) {
      throw const FormatException(
        "The 'tag_pattern' field of the description "
        'must be a string.',
      );
    }

    return PackageId(
      name,
      version,
      ResolvedGitDescription(
        GitDescription(
          url: url,
          ref: ref,
          path: _validatedPath(description['path']),
          containingDir: containingDir,
          tagPattern: tagPattern,
        ),
        resolvedRef,
      ),
    );
  }

  /// Throws a [FormatException] if [url] isn't a valid Git URL.
  static _ValidatedUrl _validatedUrl(String url, String? containingDir) {
    if (url.startsWith('-')) {
      throw FormatException('"$url" is not a valid Git URL.');
    }
    var relative = false;
    // An SCP-style SSH URL (e.g. git@github.com:org/repo.git) has '@' before
    // the first ':', which Dart's URI parser cannot parse.
    final atIndex = url.indexOf('@');
    final colonIndex = url.indexOf(':');
    final isScpUrl =
        atIndex != -1 && (colonIndex == -1 || atIndex < colonIndex);
    if (!isScpUrl) {
      // Otherwise, we use Dart's URL parser to validate the URL.
      final parsed = Uri.parse(url);
      if (parsed.hasScheme && parsed.scheme == 'ext') {
        throw FormatException('"$url" is not a valid Git URL.');
      }
      if (!parsed.hasAbsolutePath) {
        // Relative paths coming from pubspecs that are not on the local file
        // system aren't allowed. This can happen if a hosted or git dependency
        // has a git dependency.
        if (containingDir == null) {
          throw FormatException(
            '"$url" is a relative path, but this '
            'isn\'t a local pubspec.',
          );
        }
        // A relative path is stored internally as absolute resolved relative to
        // [containingPath].
        relative = true;
        url = p.url.normalize(
          p.url.join(
            p.toUri(p.absolute(containingDir)).toString(),
            parsed.toString(),
          ),
        );
      }
    }
    return _ValidatedUrl(url, relative);
  }

  /// Normalizes [path].
  ///
  /// Throws a [FormatException] if [path] isn't a [String] parsing as a
  /// relative URL or `null`.
  ///
  /// A relative url here has:
  /// - non-absolute path
  /// - no scheme
  /// - no authority
  String _validatedPath(dynamic path) {
    path ??= '.';
    if (path is! String) {
      throw const FormatException(
        "The 'path' field of the description must be a "
        'string.',
      );
    }

    // Use Dart's URL parser to validate the URL.
    final parsed = Uri.parse(path);
    if (parsed.hasAbsolutePath ||
        parsed.hasScheme ||
        parsed.hasAuthority ||
        parsed.hasFragment ||
        parsed.hasQuery) {
      throw const FormatException(
        "The 'path' field of the description must be a relative path URL.",
      );
    }
    if (!p.url.isWithin('.', path) && !p.url.equals('.', path)) {
      throw const FormatException(
        "The 'path' field of the description must not reach outside the "
        'repository.',
      );
    }
    return p.url.normalize(parsed.toString());
  }

  /// Given a Git repo that contains a pub package, gets the name of the pub
  /// package.
  ///
  /// Will download the repo to the system cache under the assumption that the
  /// package will be downloaded afterwards.
  Future<String> getPackageNameFromRepo(
    String url,
    String? ref,
    String? path,
    SystemCache cache, {
    required String? relativeTo,
    required String? tagPattern,
  }) async {
    assert(
      !(ref != null && tagPattern != null),
      'Cannot have both a `tagPattern` and a `ref`',
    );
    final description = GitDescription(
      url: url,
      ref: ref,
      path: path,
      containingDir: relativeTo,
      tagPattern: tagPattern,
    );
    return await cache.gitCache.pool.withResource(() async {
      await _ensureRepoCache(description, cache);
      final path = _repoCachePath(description, cache);

      final revision =
          tagPattern != null
              ? (await _listTaggedVersions(path, tagPattern)).last.commitId
              : await _firstRevision(path, description.ref);
      final resolvedDescription = ResolvedGitDescription(description, revision);

      return Pubspec.parse(
        await _showFileAtRevision(resolvedDescription, 'pubspec.yaml', cache),
        cache.sources,
        containingDescription: resolvedDescription,
      ).name;
    });
  }

  /// Lists the file as it is represented at the revision of
  /// [resolvedDescription].
  ///
  /// Assumes that revision is present in the cache already (can be done with
  /// [_ensureRevision]).
  Future<String> _showFileAtRevision(
    ResolvedGitDescription resolvedDescription,
    String pathInProject,
    SystemCache cache,
  ) async {
    final description = resolvedDescription.description;
    // Normalize the path because Git treats "./" at the beginning of a path
    // specially.
    var pathInCache = p.normalize(
      p.join(p.fromUri(description.path), pathInProject),
    );

    // Git doesn't recognize backslashes in paths, even on Windows.
    if (platform.isWindows) pathInCache = pathInCache.replaceAll('\\', '/');

    final repoPath = _repoCachePath(description, cache);
    final revision = resolvedDescription.resolvedRef;

    try {
      return await git.run([
        _gitDirArg(repoPath),
        'show',
        '$revision:$pathInCache',
      ], workingDir: repoPath);
    } on git.GitException catch (_) {
      fail(
        'Could not find a file named "$pathInCache" in '
        '${GitDescription.prettyUri(description.url)} $revision.',
      );
    }
  }

  @override
  Future<List<PackageId>> doGetVersions(
    PackageRef ref,
    Duration? maxAge,
    SystemCache cache,
  ) async {
    final description = ref.description;
    if (description is! GitDescription) {
      throw StateError('Called with wrong ref');
    }
    return await cache.gitCache.pool.withResource(() async {
      await _ensureRepoCache(description, cache);
      final path = _repoCachePath(description, cache);
      if (description.tagPattern case final String tagPattern) {
        final versions = await _listTaggedVersions(path, tagPattern);
        return [
          for (final version in versions)
            PackageId(
              ref.name,
              version.version,
              ResolvedGitDescription(description, version.commitId),
            ),
        ];
      } else {
        final revision = await _firstRevision(path, description.ref);
        final pubspec = await _describeUncached(ref, revision, cache);
        return [
          PackageId(
            ref.name,
            pubspec.version,
            ResolvedGitDescription(description, revision),
          ),
        ];
      }
    });
  }

  /// Since we don't have an easy way to read from a remote Git repo, this
  /// just installs [id] into the system cache, then describes it from there.
  @override
  Future<Pubspec> describeUncached(PackageId id, SystemCache cache) async {
    final description = id.description;
    if (description is! ResolvedGitDescription) {
      throw StateError('Called with wrong ref');
    }
    final pubspec = await cache.gitCache.pool.withResource(
      () => _describeUncached(id.toRef(), description.resolvedRef, cache),
    );
    if (pubspec.version != id.version) {
      throw PackageNotFoundException(
        'Expected ${id.name} version ${id.version} '
        'at commit ${description.resolvedRef}, '
        'found ${pubspec.version}.',
      );
    }
    return pubspec;
  }

  /// Like [describeUncached], but takes a separate [ref] and Git [revision]
  /// rather than a single ID.
  Future<Pubspec> _describeUncached(
    PackageRef ref,
    String revision,
    SystemCache cache,
  ) async {
    final description = ref.description;
    if (description is! GitDescription) {
      throw ArgumentError('Wrong source');
    }
    return cache.gitCache.pubspecAtRevisionCache[(
      ref,
      revision,
    )] ??= await () async {
      await _ensureRevision(description, revision, cache);
      final resolvedDescription = ResolvedGitDescription(description, revision);
      return Pubspec.parse(
        await _showFileAtRevision(resolvedDescription, 'pubspec.yaml', cache),
        cache.sources,
        expectedName: ref.name,
        containingDescription: resolvedDescription,
      );
    }();
  }

  /// Clones a Git repo to the local filesystem.
  ///
  /// The Git cache directory is a little idiosyncratic. At the top level, it
  /// contains a directory for each commit of each repository, named
  /// `<package name>-<commit hash>`. These are the canonical package
  /// directories that are linked to from the `.dart_tool/package_config.json`
  /// file.
  ///
  /// In addition, the Git system cache contains a subdirectory named `cache/`
  /// which contains a directory for each separate repository URL, named
  /// `<package name>-<url hash>`. These are used to check out the repository
  /// itself; each of the commit-specific directories are clones of a directory
  /// in `cache/`.
  @override
  Future<DownloadPackageResult> downloadToSystemCache(
    PackageId id,
    SystemCache cache,
  ) async {
    return await cache.gitCache.pool.withResource(() async {
      var didUpdate = false;
      final ref = id.toRef();
      final description = ref.description;
      if (description is! GitDescription) {
        throw ArgumentError('Wrong source');
      }
      if (!git.isInstalled) {
        fail(
          'Cannot get ${id.name} from Git (${description.url}).\n'
          'Please ensure Git is correctly installed.',
        );
      }

      ensureDir(p.join(cache.rootDirForSource(this), 'cache'));
      final resolvedRef =
          (id.description as ResolvedGitDescription).resolvedRef;

      didUpdate |= await _ensureRevision(description, resolvedRef, cache);

      final revisionCachePath = _revisionCachePath(id, cache);
      final path = description.path;
      await cache.gitCache.revisionCacheClones.putIfAbsent(
        revisionCachePath,
        () async {
          if (!entryExists(revisionCachePath)) {
            await _cloneViaTemp(
              _repoCachePath(description, cache),
              revisionCachePath,
              cache,
            );
            await git.run([
              'config',
              'remote.origin.lfsurl',
              description.url,
            ], workingDir: revisionCachePath);
            await _checkOut(revisionCachePath, resolvedRef);
            try {
              _validateSymlinks(
                revisionCachePath,
                packageName: id.name,
                url: description.url,
              );
            } catch (_) {
              tryDeleteEntry(revisionCachePath);
              rethrow;
            }
            _writePackageList(revisionCachePath, [path]);
            didUpdate = true;
          } else {
            didUpdate |= _updatePackageList(revisionCachePath, path);
          }
        },
      );
      return DownloadPackageResult(id, didUpdate: didUpdate);
    });
  }

  /// Returns the path to the revision-specific cache of [id].
  @override
  String getDirectoryInCache(PackageId id, SystemCache cache) {
    final description = id.toRef().description;
    if (description is! GitDescription) {
      throw ArgumentError('Wrong source');
    }
    return p.join(_revisionCachePath(id, cache), description.path);
  }

  @override
  List<Package> getCachedPackages(SystemCache cache) {
    // TODO(keertip): Implement getCachedPackages().
    throw UnimplementedError(
      "The git source doesn't support listing its cached packages yet.",
    );
  }

  /// Resets all cached packages back to the pristine state of the Git
  /// repository at the revision they are pinned to.
  ///
  /// If [packageFilter] is provided, only packages whose names are in the set
  /// will be repaired.
  @override
  Future<Iterable<RepairResult>> repairCachedPackages(
    SystemCache cache, {
    bool Function(String name, Version version)? packageFilter,
  }) async {
    final rootDir = cache.rootDirForSource(this);
    if (!dirExists(rootDir)) return [];

    final result = <RepairResult>[];

    final packages =
        listDir(rootDir)
            .where((entry) => dirExists(p.join(entry, '.git')))
            .expand((revisionCachePath) {
              return _readPackageList(revisionCachePath).map((relative) {
                // If we've already failed to load another package from this
                // repository, ignore it.
                if (!dirExists(revisionCachePath)) return null;

                final packageDir = p.join(revisionCachePath, relative);
                try {
                  final package = Package.load(
                    packageDir,
                    loadPubspec: Pubspec.loadRootWithSources(cache.sources),
                  );
                  if (packageFilter != null &&
                      !packageFilter(package.name, package.version)) {
                    return null;
                  }
                  return package;
                } catch (error, stackTrace) {
                  final name = p.basename(revisionCachePath).split('-').first;
                  if (packageFilter != null &&
                      !packageFilter(name, Version.none)) {
                    return null;
                  }
                  log.error('Failed to load package', error, stackTrace);
                  result.add(
                    RepairResult(name, Version.none, this, success: false),
                  );
                  tryDeleteEntry(revisionCachePath);
                  return null;
                }
              });
            })
            .nonNulls
            .toList();

    // Note that there may be multiple packages with the same name and version
    // (pinned to different commits). The sort order of those is unspecified.
    packages.sort(Package.orderByNameAndVersion);

    for (var package in packages) {
      // If we've already failed to repair another package in this repository,
      // ignore it.
      if (!dirExists(package.dir)) continue;

      log.message(
        'Resetting Git repository for '
        '${log.bold(package.name)} ${package.version}...',
      );

      try {
        // Remove all untracked files.
        await git.run([
          'clean',
          '-d',
          '--force',
          '-x',
        ], workingDir: package.dir);

        // Discard all changes to tracked files.
        await git.run(['reset', '--hard', 'HEAD'], workingDir: package.dir);

        final repoRoot = git.repoRoot(package.dir);
        if (repoRoot != null) {
          _validateSymlinks(repoRoot, packageName: package.name, url: repoRoot);
        }

        result.add(
          RepairResult(package.name, package.version, this, success: true),
        );
      } catch (error, stackTrace) {
        log.error(
          'Failed to reset ${log.bold(package.name)} '
          '${package.version}. Error:\n$error',
        );
        log.fine(stackTrace.toString());
        result.add(
          RepairResult(package.name, package.version, this, success: false),
        );

        // Delete the revision cache path, not the subdirectory that contains
        // the package.
        final repoRoot = git.repoRoot(package.dir);
        if (repoRoot != null) tryDeleteEntry(repoRoot);
      }
    }

    return result;
  }

  /// Ensures that the canonical clone of the repository referred to by
  /// [description] contains the given Git [revision].
  ///
  /// Throws a [PackageNotFoundException] if [revision] doesn't exist in the
  /// repository even after updating the cache.
  ///
  /// Returns `true` if it had to update anything.
  Future<bool> _ensureRevision(
    GitDescription description,
    String revision,
    SystemCache cache,
  ) async {
    final path = _repoCachePath(description, cache);
    if (cache.gitCache.updatedRepos.contains(path)) {
      await _firstRevision(path, revision);
      return false;
    }

    await _deleteGitRepoIfInvalid(path);

    if (!entryExists(path)) {
      await _createRepoCache(description, cache);
      await _firstRevision(path, revision);
      return true;
    }

    // Try to list the revision. If it doesn't exist, git will fail and we'll
    // know we have to update the repository.
    try {
      await _revParse(path, revision);
      return false;
    } on git.GitException catch (_) {
      await _updateRepoCache(description, cache);
      await _firstRevision(path, revision);
      return true;
    }
  }

  /// Ensures that the canonical clone of the repository referred to by
  /// [description] exists and is up-to-date.
  ///
  /// Returns `true` if it had to update anything.
  Future<bool> _ensureRepoCache(
    GitDescription description,
    SystemCache cache,
  ) async {
    final path = _repoCachePath(description, cache);
    if (cache.gitCache.updatedRepos.contains(path)) return false;

    await _deleteGitRepoIfInvalid(path);

    if (!entryExists(path)) {
      await _createRepoCache(description, cache);
      return true;
    } else {
      return await _updateRepoCache(description, cache);
    }
  }

  /// Creates the canonical clone of the repository referred to by
  /// [description].
  ///
  /// This assumes that the canonical clone doesn't yet exist.
  Future<void> _createRepoCache(
    GitDescription description,
    SystemCache cache,
  ) async {
    final path = _repoCachePath(description, cache);
    assert(!cache.gitCache.updatedRepos.contains(path));
    try {
      await _cloneViaTemp(description.url, path, cache, mirror: true);
    } catch (_) {
      await _deleteGitRepoIfInvalid(path);
      rethrow;
    }
    cache.gitCache.updatedRepos.add(path);
  }

  /// Runs "git fetch" in the canonical clone of the repository referred to by
  /// [description].
  ///
  /// This assumes that the canonical clone already exists.
  ///
  /// Returns `true` if it had to update anything.
  Future<bool> _updateRepoCache(
    GitDescription description,
    SystemCache cache,
  ) async {
    final path = _repoCachePath(description, cache);
    if (cache.gitCache.updatedRepos.contains(path)) return false;
    await git.run([_gitDirArg(path), 'fetch'], workingDir: path);
    cache.gitCache.updatedRepos.add(path);
    return true;
  }

  /// Clean-up [dirPath] if it's an invalid git repository.
  ///
  /// The git clones in the `PUB_CACHE` folder should never be invalid. But this
  /// can happen if the clone operation failed in some way, and the program did
  /// not exit gracefully, leaving the cache git clone in a dirty state.
  Future<void> _deleteGitRepoIfInvalid(String dirPath) async {
    if (!dirExists(dirPath)) {
      return;
    }
    var isValid = true;
    try {
      final result = await git.run([
        _gitDirArg(dirPath),
        'rev-parse',
        '--is-inside-git-dir',
      ], workingDir: dirPath);
      if (result.trim() != 'true') {
        isValid = false;
      }
    } on git.GitException {
      isValid = false;
    }
    // If [dirPath] is not a valid git repository we remove it.
    if (!isValid) {
      deleteEntry(dirPath);
    }
  }

  /// Updates the package list file in [revisionCachePath] to include [path], if
  /// necessary.
  ///
  /// Returns `true` if it had to update anything.
  bool _updatePackageList(String revisionCachePath, String path) {
    final packages = _readPackageList(revisionCachePath);
    if (packages.contains(path)) return false;

    _writePackageList(revisionCachePath, packages..add(path));
    return true;
  }

  /// Returns the list of packages in [revisionCachePath].
  List<String> _readPackageList(String revisionCachePath) {
    final path = _packageListPath(revisionCachePath);

    // If there's no package list file, this cache was created by an older
    // version of pub where pubspecs were only allowed at the root of the
    // repository.
    if (!fileExists(path)) return ['.'];
    return readTextFile(path).split('\n');
  }

  /// Writes a package list indicating that [packages] exist in
  /// [revisionCachePath].
  void _writePackageList(String revisionCachePath, List<String> packages) {
    writeTextFile(_packageListPath(revisionCachePath), packages.join('\n'));
  }

  /// The path in a revision cache repository in which we keep a list of the
  /// packages in the repository.
  String _packageListPath(String revisionCachePath) =>
      p.join(revisionCachePath, '.git/pub-packages');

  /// List all tags in [path] and returns all versions matching
  /// [tagPattern].
  Future<List<TaggedVersion>> _listTaggedVersions(
    String path,
    String tagPattern,
  ) async {
    // For annotated tags, the `*` means we list the hash of the tagged object,
    // not the tag itself. For lightweight tags, it lists the tag itself, which
    // is the tagged object.
    const objectFormat =
        '%(if)%(*objectname)%(then)%(*objectname)%(else)%(objectname)%(end)';
    final output = await git.run([
      _gitDirArg(path),
      'tag',
      '--list',
      '--format',
      // We can use space here, as it is not allowed in a git tag
      // https://git-scm.com/docs/git-check-ref-format
      '%(refname:lstrip=2) $objectFormat',
    ], workingDir: path);
    final lines = output.trim().split('\n');
    final result = <TaggedVersion>[];
    final compiledTagPattern = compileTagPattern(tagPattern);
    for (final line in lines) {
      final parts = line.split(' ');
      if (parts.length != 2) {
        throw PackageNotFoundException('Bad output from `git tag --list`');
      }
      final match = compiledTagPattern.firstMatch(parts[0]);
      if (match == null) continue;

      final Version version;

      try {
        version = Version.parse(match[1]!);
      } on FormatException catch (e) {
        throw StateError(
          'Matched part "${match[1]}" did not match version: $e.',
        );
      }
      result.add((version: version, commitId: parts[1]));
    }
    return result;
  }

  /// Runs "git rev-list" on [reference] in [path] and returns the first result.
  ///
  /// Throws a [git.GitException] if [reference] cannot be resolved.
  /// This assumes that the canonical clone already exists.
  Future<String> _revParse(String path, String reference) async {
    final args = [_gitDirArg(path), 'rev-list', '--max-count=1', reference];
    final output = (await git.run(args, workingDir: path)).trim();
    if (output.isEmpty) {
      throw git.GitException(args, 'Empty output from git rev-list', '', 1);
    }
    return output;
  }

  /// Resolves [reference] to a commit hash in [path], throwing a
  /// [PackageNotFoundException] if it cannot be found.
  ///
  /// This assumes that the canonical clone already exists.
  Future<String> _firstRevision(String path, String reference) async {
    try {
      return await _revParse(path, reference);
    } on git.GitException catch (e) {
      throw PackageNotFoundException(
        "Could not find git ref '$reference' (${e.stderr})",
      );
    }
  }

  /// Clones the repo at the URI [from] to the path [to] on the local
  /// filesystem.
  ///
  /// If [mirror] is true, creates a bare, mirrored clone. This doesn't check
  /// out the working tree, but instead makes the repository a local mirror of
  /// the remote repository. See the manpage for `git clone` for more
  /// information.
  Future<void> _clone(String from, String to, {bool mirror = false}) async {
    // Git on Windows does not seem to automatically create the destination
    // directory.
    ensureDir(to);
    final args = [
      'clone',
      if (mirror) '--mirror' else '--no-checkout',
      '--',
      from,
      to,
    ];

    await git.run(args);
  }

  /// Like [_clone], but clones to a temporary directory (inside the [cache])
  /// and moves
  Future<void> _cloneViaTemp(
    String from,
    String to,
    SystemCache cache, {
    bool mirror = false,
  }) async {
    final tempDir = cache.createTempDir();
    try {
      await _clone(from, tempDir, mirror: mirror);
    } catch (_) {
      deleteEntry(tempDir);
      rethrow;
    }
    // Now that the clone has succeeded, move it to the real location in the
    // cache.
    //
    // If this fails with a "directory not empty" exception we assume that
    // another pub process has installed the same package version while we
    // cloned. In that case [tryRenameDir] will delete the folder for us.
    tryRenameDir(tempDir, to);
  }

  /// Checks out the reference [ref] in [repoPath].
  Future<void> _checkOut(String repoPath, String ref) {
    return git
        .run(['checkout', ref], workingDir: repoPath)
        .then((result) => null);
  }

  /// Validates that no symbolic link in [repoRoot] points outside of
  /// [repoRoot], including any intermediate symlinks, chained links, or
  /// directory symlinks.
  ///
  /// For every symbolic link found in [repoRoot]:
  /// - Absolute links (starting with `/`, `\`, or Windows drive letters) are
  ///   rejected.
  /// - Relative links are resolved segment-by-segment. If a path segment
  ///   encounters an intermediate directory symlink, that link is recursively
  ///   dereferenced and resolved to ensure no combination of symlinks and `..`
  ///   traversals can escape [repoRoot].
  /// - Cycles in symlink chains are detected and rejected.
  /// - If any link or chain resolves to a location outside [repoRoot], a
  ///   [PackageNotFoundException] is thrown.
  ///
  /// Note: Git repositories do not support hardlinks in tree objects or working
  /// tree checkouts (Git tree entries are limited to regular files, executable
  /// files, symlinks, and submodules), so only symbolic links need to be
  /// validated here.
  void _validateSymlinks(
    String repoRoot, {
    required String packageName,
    required String url,
  }) {
    if (!dirExists(repoRoot)) return;

    final normalizedRepoRoot = p.normalize(p.absolute(repoRoot));

    String resolveLinkTarget(String linkPath, {required Set<String> visited}) {
      final canonicalLinkPath = p.normalize(p.absolute(linkPath));
      if (!visited.add(canonicalLinkPath)) {
        final relLinkPath = p.relative(linkPath, from: normalizedRepoRoot);
        throw PackageNotFoundException(
          'Package "$packageName" from "${GitDescription.prettyUri(url)}" '
          'contains a circular symbolic link at "$relLinkPath".',
        );
      }

      final target = readLink(linkPath);
      if (p.isAbsolute(target) ||
          target.startsWith('/') ||
          target.startsWith(r'\') ||
          RegExp(r'^[a-zA-Z]:').hasMatch(target)) {
        final relLinkPath = p.relative(linkPath, from: normalizedRepoRoot);
        throw PackageNotFoundException(
          'Package "$packageName" from "${GitDescription.prettyUri(url)}" '
          'contains a symbolic link "$relLinkPath" targeting "$target" '
          'which points outside the repository.',
        );
      }

      final segments = target.split(RegExp(r'[/\\]'));
      var current = p.normalize(p.absolute(p.dirname(linkPath)));

      for (final segment in segments) {
        if (segment == '' || segment == '.') {
          continue;
        } else if (segment == '..') {
          current = p.dirname(current);
          if (!p.isWithin(normalizedRepoRoot, current) &&
              !p.equals(normalizedRepoRoot, current)) {
            final relLinkPath = p.relative(linkPath, from: normalizedRepoRoot);
            throw PackageNotFoundException(
              'Package "$packageName" from "${GitDescription.prettyUri(url)}" '
              'contains a symbolic link "$relLinkPath" targeting "$target" '
              'which points outside the repository.',
            );
          }
        } else {
          final next = p.normalize(p.join(current, segment));
          if (linkExists(next)) {
            current = resolveLinkTarget(next, visited: Set.of(visited));
          } else {
            current = next;
          }
          if (!p.isWithin(normalizedRepoRoot, current) &&
              !p.equals(normalizedRepoRoot, current)) {
            final relLinkPath = p.relative(linkPath, from: normalizedRepoRoot);
            throw PackageNotFoundException(
              'Package "$packageName" from "${GitDescription.prettyUri(url)}" '
              'contains a symbolic link "$relLinkPath" targeting "$target" '
              'which points outside the repository.',
            );
          }
        }
      }

      return current;
    }

    for (final linkPath in listSymlinks(repoRoot)) {
      resolveLinkTarget(linkPath, visited: {});
    }
  }

  String _revisionCachePath(PackageId id, SystemCache cache) => p.join(
    cache.rootDirForSource(this),
    '${_repoName(id.description.description as GitDescription)}-'
    '${(id.description as ResolvedGitDescription).resolvedRef}',
  );

  /// Returns the path to the canonical clone of the repository referred to by
  /// [description] (the one in `<system cache>/git/cache`).
  String _repoCachePath(GitDescription description, SystemCache cache) {
    final repoCacheName = '${_repoName(description)}-${sha1(description.url)}';
    return p.join(cache.rootDirForSource(this), 'cache', repoCacheName);
  }

  /// Returns a short, human-readable name for the repository URL in
  /// [description].
  ///
  /// This name is not guaranteed to be unique.
  String _repoName(GitDescription description) {
    var name = p.url.basename(description.url);
    if (name.endsWith('.git')) {
      name = name.substring(0, name.length - '.git'.length);
    }
    name = name.replaceAll(RegExp('[^a-zA-Z0-9._-]'), '_');
    // Shorten name to 50 chars for sanity.
    if (name.length > 50) {
      name = name.substring(0, 50);
    }
    return name;
  }

  @override
  Future<List<String>> entriesToGc(
    SystemCache cache,
    Set<String> alivePackages,
  ) async {
    final rootDir = p.canonicalize(cache.rootDirForSource(this));
    if (!entryExists(rootDir)) return const [];

    final gitDirsToRemove = <String>{};
    // First enumerate all git repos inside [rootDir].
    for (final entry in listDir(rootDir)) {
      final gitEntry = p.join(entry, '.git');
      if (!entryExists(gitEntry)) continue;
      gitDirsToRemove.add(p.canonicalize(entry));
    }
    final cacheDirsToRemove = <String>{};
    try {
      cacheDirsToRemove.addAll(
        listDir(p.join(rootDir, 'cache')).map(p.canonicalize),
      );
    } on IOException {
      // Most likely the directory didn't exist.
      // ignore.
    }
    // For each package walk up parent directories to find the containing git
    // repo, and mark it alive by removing from `gitDirsToRemove`.
    for (final alivePackage in alivePackages) {
      var candidate = p.canonicalize(alivePackage);
      while (!p.equals(candidate, rootDir)) {
        if (gitDirsToRemove.remove(candidate)) {
          // Package is alive, now also retain its cachedir.
          //
          // TODO(sigurdm): Should we just GC all cache-dirs? They are not
          // needed for consuming packages, and most likely will be recreated
          // when needed.
          final gitEntry = p.join(candidate, '.git');
          try {
            if (dirExists(gitEntry)) {
              final path =
                  (await git.run([
                    'remote',
                    'get-url',
                    'origin',
                  ], workingDir: candidate)).split('\n').first;
              cacheDirsToRemove.remove(p.canonicalize(path));
            } else if (fileExists(gitEntry)) {
              // Potential future - using worktrees.
              final path =
                  (await git.run([
                    'worktree',
                    'list',
                    '--porcelain',
                  ], workingDir: candidate)).split('\n').first.split(' ').last;
              cacheDirsToRemove.remove(p.canonicalize(path));
            }
          } on git.GitException catch (e) {
            log.fine('Failed to find canonical cache for $candidate, $e');
          }
          break;
        }
        // Try the parent directory
        candidate = p.dirname(candidate);
      }
    }

    return [...cacheDirsToRemove, ...gitDirsToRemove];
  }
}

class GitDescription extends Description {
  /// The url of the repo of this package.
  ///
  /// If the url was relative in the pubspec.yaml it will be resolved relative
  /// to the pubspec location, and stored here as an absolute file url, and
  /// [relative] will be true.
  ///
  /// This will not always parse as a [Uri] due the fact that `Uri.parse` does
  /// not allow strings of the form: 'git@github.com:dart-lang/pub.git'.
  final String url;

  /// A string containing [tagPatternVersionMarker] used to match version
  /// numbers in a git tag. For example "v{{version}}".
  ///
  /// Only one of [ref] and [tagPattern] can be non-`null` at a time.
  final String? tagPattern;

  /// `true` if [url] was parsed from a relative url.
  final bool relative;

  /// The git ref to resolve for finding the commit.
  final String ref;

  /// Relative path of the package inside the git repo.
  ///
  /// Represented as a relative url.
  final String path;

  late final RegExp compiledTagPattern = compileTagPattern(tagPattern!);

  GitDescription.raw({
    required this.url,
    required this.relative,
    required String? ref,
    required String? path,
    required this.tagPattern,
  }) : ref = ref ?? 'HEAD',
       path = path ?? '.';

  factory GitDescription({
    required String url,
    required String? ref,
    required String? path,
    required String? containingDir,
    required String? tagPattern,
  }) {
    final validatedUrl = GitSource._validatedUrl(url, containingDir);
    return GitDescription.raw(
      url: validatedUrl.url,
      relative: validatedUrl.wasRelative,
      ref: ref,
      path: path,
      tagPattern: tagPattern,
    );
  }

  @override
  String format() {
    var result =
        '${prettyUri(url)} at '
        '$ref';
    if (path != '.') result += ' in $path';
    return result;
  }

  @override
  Object? serializeForPubspec({
    required String? containingDir,
    required LanguageVersion languageVersion,
  }) {
    final relativeUrl =
        containingDir != null && relative
            ? p.url.relative(
              url,
              from: p.toUri(p.normalize(p.absolute(containingDir))).toString(),
            )
            : url;
    if (ref == 'HEAD' && path == '.' && tagPattern == null) return relativeUrl;
    return {
      'url': relativeUrl,
      if (ref != 'HEAD') 'ref': ref,
      if (path != '.') 'path': path,
      if (tagPattern != null) 'tag_pattern': tagPattern,
    };
  }

  @override
  GitSource get source => GitSource.instance;

  @override
  bool operator ==(Object other) {
    return other is GitDescription &&
        other.url == url &&
        other.ref == ref &&
        other.path == path;
  }

  GitDescription withRef(String newRef) => GitDescription.raw(
    url: url,
    relative: relative,
    ref: newRef,
    path: path,
    tagPattern: tagPattern,
  );

  @override
  int get hashCode => Object.hash(url, ref, path);

  // Similar in intend to [p.prettyUri] but does not fail if the input doesn't
  // parse with [Uri.parse].
  static String prettyUri(String url) {
    // HACK: Working around the fact that `Uri.parse` does not allow strings of
    // the form: 'git@github.com:dart-lang/pub.git'.
    final parsedAsUri = Uri.tryParse(url);
    if (parsedAsUri == null) {
      return url;
    }
    return p.prettyUri(url);
  }

  @override
  bool get hasMultipleVersions => tagPattern != null;
}

class ResolvedGitDescription extends ResolvedDescription {
  @override
  GitDescription get description => super.description as GitDescription;

  final String resolvedRef;

  ResolvedGitDescription(GitDescription super.description, this.resolvedRef);

  @override
  String format() {
    var result =
        '${GitDescription.prettyUri(description.url)} at '
        '${resolvedRef.substring(0, 6)}';
    if (description.path != '.') result += ' in ${description.path}';
    return result;
  }

  @override
  Object? serializeForLockfile({required String? containingDir}) {
    final url =
        description.relative && containingDir != null
            ? p.url.relative(
              description.url,
              from: Uri.file(p.absolute(containingDir)).toString(),
            )
            : description.url;
    return {
      'url': url,

      if (description.tagPattern == null)
        'ref': description.ref
      else
        'tag-pattern': description.tagPattern,
      'resolved-ref': resolvedRef,
      'path': description.path,
    };
  }

  @override
  bool operator ==(Object other) {
    return other is ResolvedGitDescription &&
        other.description == description &&
        other.resolvedRef == resolvedRef;
  }

  @override
  int get hashCode => Object.hash(description, resolvedRef);
}

class _ValidatedUrl {
  final String url;
  final bool wasRelative;
  _ValidatedUrl(this.url, this.wasRelative);
}

String _gitDirArg(String path) {
  path = p.absolute(path);
  final forwardSlashPath =
      platform.isWindows ? path.replaceAll('\\', '/') : path;
  return '--git-dir=$forwardSlashPath';
}

const String tagPatternVersionMarker = '{{version}}';

// Adapted from pub_semver-2.1.4/lib/src/version.dart
const versionPattern =
    r'(\d+)\.(\d+)\.(\d+)' // Version number.
    r'(-([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?' // Pre-release.
    r'(\+([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?'; // build

/// Throws [FormatException] if it doesn't contain a single instance of
/// [tagPatternVersionMarker].
void validateTagPattern(String tagPattern) {
  final parts = tagPattern.split(tagPatternVersionMarker);
  if (parts.length != 2) {
    throw const FormatException(
      'The `tag_pattern` must contain a single "{{version}}" '
      'to match different versions',
    );
  }
}

/// Takes a [tagPattern] and returns a [RegExp] matching the relevant tags.
///
/// The tagPattern should contain '{{version}}' which will match a pub_semver
/// version. The rest of the tagPattern is matched verbatim.
///
/// Assumes that [tagPattern] has a single occurence of
/// [tagPatternVersionMarker].
RegExp compileTagPattern(String tagPattern) {
  final parts = tagPattern.split(tagPatternVersionMarker);
  final before = RegExp.escape(parts[0]);
  final after = RegExp.escape(parts[1]);

  return RegExp(
    r'^'
    '$before($versionPattern)$after'
    r'$',
  );
}

/// State that is cached for the GitSource.
final class GitSourceCache {
  /// Limit the number of concurrent git operations to 1.
  final pool = Pool(1);

  /// A map from revision cache locations to futures that will complete once
  /// they're finished being cloned.
  ///
  /// This lets us avoid race conditions when getting multiple different
  /// packages from the same repository.
  final revisionCacheClones = <String, Future<void>>{};

  /// The paths to the canonical clones of repositories for which "git fetch"
  /// has already been run during this run of pub.
  final updatedRepos = <String>{};

  final pubspecAtRevisionCache = <(PackageRef, String), Pubspec>{};
}
