// 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:path/path.dart' as p;
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 '../pubspec.dart';
import '../source.dart';
import '../system_cache.dart';
import '../utils.dart';
import 'cached.dart';
import 'path.dart';
import 'root.dart';

/// 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, {
    Description? containingDescription,
    LanguageVersion? languageVersion,
  }) {
    String url;
    String? ref;
    String? path;
    if (description is String) {
      url = description;
    } else if (description is! Map) {
      throw 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 FormatException(
          "The 'url' field of a description must be a string.",
        );
      }
      url = descriptionUrl;

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

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

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

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

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

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

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

    final url = description['url'];
    if (url is! String) {
      throw FormatException("The 'url' field of the description "
          'must be a string.');
    }
    return PackageId(
      name,
      version,
      ResolvedGitDescription(
        GitDescription(
          url: url,
          ref: ref,
          path: _validatedPath(
            description['path'],
          ),
          containingDir: containingDir,
        ),
        resolvedRef,
      ),
    );
  }

  /// Throws a [FormatException] if [url] isn't a valid Git URL.
  static _ValidatedUrl _validatedUrl(String url, String? containingDir) {
    var relative = false;
    // If the URL contains an @, it's probably an SSH hostname, which we don't
    // know how to validate.
    if (!url.contains('@')) {
      // Otherwise, we use Dart's URL parser to validate the URL.
      final parsed = Uri.parse(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 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 FormatException(
        "The 'path' field of the description must be a relative path URL.",
      );
    }
    if (!p.url.isWithin('.', path) && !p.url.equals('.', path)) {
      throw FormatException(
          "The 'path' field of the description must not reach outside the "
          'repository.');
    }
    return p.url.normalize(parsed.toString());
  }

  /// Limit the number of concurrent git operations to 1.
  // TODO(sigurdm): Use RateLimitedScheduler.
  final Pool _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>{};

  /// 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,
  }) async {
    final description = GitDescription(
      url: url,
      ref: ref,
      path: path,
      containingDir: relativeTo,
    );
    return await _pool.withResource(() async {
      await _ensureRepoCache(description, cache);
      final path = _repoCachePath(description, cache);
      final revision = await _firstRevision(path, description.ref);
      final resolvedDescription = ResolvedGitDescription(description, revision);

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

  /// Lists the file as it is represented at the revision of [description].
  ///
  /// 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;

    late List<String> lines;
    try {
      // TODO(sigurdm): We should have a `git.run` alternative that gives back
      // a stream of stdout instead of the lines.
      lines = 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.');
    }
    return lines.join('\n');
  }

  @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 _pool.withResource(() async {
      await _ensureRepoCache(description, cache);
      final path = _repoCachePath(description, cache);
      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) {
    final description = id.description;
    if (description is! ResolvedGitDescription) {
      throw StateError('Called with wrong ref');
    }
    return _pool.withResource(
      () => _describeUncached(
        id.toRef(),
        description.resolvedRef,
        cache,
      ),
    );
  }

  /// 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');
    }
    await _ensureRevision(description, revision, cache);

    return Pubspec.parse(
      await _showFileAtRevision(
        ResolvedGitDescription(description, revision),
        'pubspec.yaml',
        cache,
      ),
      cache.sources,
      expectedName: ref.name,
      containingDescription: ref.description,
    );
  }

  /// 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 _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 _revisionCacheClones.putIfAbsent(revisionCachePath, () async {
        if (!entryExists(revisionCachePath)) {
          await _cloneViaTemp(
            _repoCachePath(description, cache),
            revisionCachePath,
            cache,
          );
          await _checkOut(revisionCachePath, resolvedRef);
          _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.
  @override
  Future<Iterable<RepairResult>> repairCachedPackages(SystemCache cache) 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 {
              return Package.load(
                packageDir,
                loadPubspec: Pubspec.loadRootWithSources(cache.sources),
              );
            } catch (error, stackTrace) {
              log.error('Failed to load package', error, stackTrace);
              final name = p.basename(revisionCachePath).split('-').first;
              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);

        result.add(
          RepairResult(package.name, package.version, this, success: true),
        );
      } on git.GitException 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 [ref]
  /// contains the given Git [revision].
  Future<bool> _ensureRevision(
    GitDescription description,
    String revision,
    SystemCache cache,
  ) async {
    final path = _repoCachePath(description, cache);
    if (_updatedRepos.contains(path)) return false;

    await _deleteGitRepoIfInvalid(path);

    if (!entryExists(path)) await _createRepoCache(description, cache);

    // 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 _firstRevision(path, revision);
    } on git.GitException catch (_) {
      await _updateRepoCache(description, cache);
      return true;
    }
    return false;
  }

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

  /// Runs "git fetch" in the canonical clone of the repository referred to by
  /// [ref].
  ///
  /// 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 (_updatedRepos.contains(path)) return false;
    await git.run([_gitDirArg(path), 'fetch'], workingDir: path);
    _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.join('\n') != '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');

  /// Runs "git rev-list" on [reference] in [path] and returns the first result.
  ///
  /// This assumes that the canonical clone already exists.
  Future<String> _firstRevision(String path, String reference) async {
    final List<String> lines;
    try {
      lines = await git.run(
        [_gitDirArg(path), 'rev-list', '--max-count=1', reference],
        workingDir: path,
      );
    } on git.GitException catch (e) {
      throw PackageNotFoundException(
        "Could not find git ref '$reference' (${e.stderr})",
      );
    }
    if (lines.isEmpty) {
      throw PackageNotFoundException("Could not find git ref '$reference'.");
    }
    return lines.first;
  }

  /// 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.
  ///
  /// If [shallow] is true, creates a shallow clone that contains no history
  /// for the repository.
  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', 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);
  }

  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
  /// [id] (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 [ref].
  ///
  /// 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;
  }
}

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;

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

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

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

  @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 == '.') return relativeUrl;
    return {
      'url': relativeUrl,
      if (ref != 'HEAD') 'ref': ref,
      if (path != '.') 'path': path,
    };
  }

  @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,
      );

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

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,
      'ref': description.ref,
      '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) {
  final forwardSlashPath =
      Platform.isWindows ? path.replaceAll('\\', '/') : path;
  return '--git-dir=$forwardSlashPath';
}
