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

/// Support for interacting with a git repository.
library;

import 'dart:convert';
import 'dart:io';

import 'package:analyzer/src/util/glob.dart';
import 'package:path/path.dart' as path;

import 'logger.dart';

/// A representation of the differences between two blobs.
class BlobDiff {
  /// The regular expression used to identify the beginning of a hunk.
  static final RegExp hunkHeaderRegExp = RegExp(
    r'@@ -([0-9]+)(?:,[0-9]+)? \+([0-9]+)(?:,[0-9]+)? @@',
  );

  /// A list of the hunks in the diff.
  List<DiffHunk> hunks = <DiffHunk>[];

  /// Initialize a newly created blob diff by parsing the result of the git diff
  /// command (the [input]).
  ///
  /// This is only intended to be invoked from [GitRepository.getBlobDiff].
  BlobDiff._(List<String> input) {
    _parseInput(input);
  }

  /// Parse the result of the git diff command (the [input]).
  void _parseInput(List<String> input) {
    for (var line in input) {
      _parseLine(line);
    }
  }

  /// Parse a single [line] from the result of the git diff command.
  void _parseLine(String line) {
    var currentHunk = hunks.isEmpty ? null : hunks.last;
    if (line.startsWith('@@')) {
      var match = hunkHeaderRegExp.matchAsPrefix(line)!;
      var srcLine = int.parse(match.group(1)!);
      var dstLine = int.parse(match.group(2)!);
      hunks.add(DiffHunk(srcLine, dstLine));
    } else if (currentHunk != null && line.startsWith('+')) {
      currentHunk.addLines.add(line.substring(1));
    } else if (currentHunk != null && line.startsWith('-')) {
      currentHunk.removeLines.add(line.substring(1));
    }
  }
}

/// A representation of the differences between two commits.
class CommitDelta {
  /// The length (in characters) of a SHA.
  static final int SHA_LENGTH = 40;

  /// The code-point for a colon (':').
  static final int COLON = ':'.codeUnitAt(0);

  /// The code-point for a nul character.
  static final int NUL = 0;

  /// The code-point for a tab.
  static final int TAB = '\t'.codeUnitAt(0);

  /// The repository from which the commits were taken.
  final GitRepository repository;

  /// The records of the files that were changed.
  final List<DiffRecord> diffRecords = <DiffRecord>[];

  /// Initialize a newly created representation of the differences between two
  /// commits. The differences are computed by parsing the result of a git diff
  /// command (the [diffResults]).
  ///
  /// This is only intended to be invoked from [GitRepository.getBlobDiff].
  CommitDelta._(this.repository, String diffResults) {
    _parseInput(diffResults);
  }

  /// Return `true` if there are differences.
  bool get hasDiffs => diffRecords.isNotEmpty;

  /// Return the absolute paths of all of the files in this commit whose name
  /// matches the given [fileName].
  Iterable<String> filesMatching(String fileName) {
    return diffRecords
        .where((DiffRecord record) => record.isFor(fileName))
        .map((DiffRecord record) => record.srcPath!);
  }

  /// Remove any diffs for files that are either (a) outside the given
  /// [inclusionPaths], or (b) are files that do not match one of the given
  /// [globPatterns].
  void filterDiffs(List<String> inclusionPaths, List<Glob> globPatterns) {
    diffRecords.retainWhere((DiffRecord record) {
      var filePath = (record.srcPath ?? record.dstPath)!;
      for (var inclusionPath in inclusionPaths) {
        if (path.isWithin(inclusionPath, filePath)) {
          for (var glob in globPatterns) {
            if (glob.matches(filePath)) {
              return true;
            }
          }
        }
      }
      return false;
    });
  }

  /// Return the index of the first nul character in the given [string] that is
  /// at or after the given [start] index.
  int _findEnd(String string, int start) {
    var length = string.length;
    var end = start;
    while (end < length && string.codeUnitAt(end) != NUL) {
      end++;
    }
    return end;
  }

  /// Return the result of converting the given [relativePath] to an absolute
  /// path. The path is assumed to be relative to the root of the repository.
  String _makeAbsolute(String relativePath) {
    return path.join(repository.path, relativePath);
  }

  /// Parse all of the diff records in the given [input].
  void _parseInput(String input) {
    var length = input.length;
    var start = 0;
    while (start < length) {
      start = _parseRecord(input, start);
    }
  }

  /// Parse a single record from the given [input], assuming that the record
  /// starts at the given [startIndex].
  ///
  /// Each record is formatted as a sequence of fields. The fields are, from the
  /// left to the right:
  ///
  /// 1. a colon.
  /// 2. mode for "src"; 000000 if creation or unmerged.
  /// 3. a space.
  /// 4. mode for "dst"; 000000 if deletion or unmerged.
  /// 5. a space.
  /// 6. sha1 for "src"; 0{40} if creation or unmerged.
  /// 7. a space.
  /// 8. sha1 for "dst"; 0{40} if creation, unmerged or "look at work tree".
  /// 9. a space.
  /// 10. status, followed by optional "score" number.
  /// 11. a tab or a NUL when -z option is used.
  /// 12. path for "src"
  /// 13. a tab or a NUL when -z option is used; only exists for C or R.
  /// 14. path for "dst"; only exists for C or R.
  /// 15. an LF or a NUL when -z option is used, to terminate the record.
  int _parseRecord(String input, int startIndex) {
    // Skip the first five fields.
    startIndex += 15;
    // Parse field 6
    var srcSha = input.substring(startIndex, startIndex + SHA_LENGTH);
    startIndex += SHA_LENGTH + 1;
    // Parse field 8
    var dstSha = input.substring(startIndex, startIndex + SHA_LENGTH);
    startIndex += SHA_LENGTH + 1;
    // Parse field 10
    var endIndex = _findEnd(input, startIndex);
    var status = input.substring(startIndex, endIndex);
    startIndex = endIndex + 1;
    // Parse field 12
    endIndex = _findEnd(input, startIndex);
    var srcPath = _makeAbsolute(input.substring(startIndex, endIndex));
    startIndex = endIndex + 1;
    // Parse field 14
    String? dstPath;
    if (status.startsWith('C') || status.startsWith('R')) {
      endIndex = _findEnd(input, startIndex);
      dstPath = _makeAbsolute(input.substring(startIndex, endIndex));
    }
    // Create the record.
    diffRecords.add(
      DiffRecord(repository, srcSha, dstSha, status, srcPath, dstPath),
    );
    return endIndex + 1;
  }
}

/// Representation of a single diff hunk.
class DiffHunk {
  /// The index of the first line that was changed in the src as returned by the
  /// diff command. The diff command numbers lines starting at 1, but it
  /// subtracts 1 from the line number if there are no lines on the source side
  /// of the hunk.
  int diffSrcLine;

  /// The index of the first line that was changed in the dst as returned by the
  /// diff command. The diff command numbers lines starting at 1, but it
  /// subtracts 1 from the line number if there are no lines on the destination
  /// side of the hunk.
  int diffDstLine;

  /// A list of the individual lines that were removed from the src.
  List<String> removeLines = <String>[];

  /// A list of the individual lines that were added to the dst.
  List<String> addLines = <String>[];

  /// Initialize a newly created hunk. The lines will be added after the object
  /// has been created.
  DiffHunk(this.diffSrcLine, this.diffDstLine);

  /// Return the index of the first line that was changed in the dst. Unlike the
  /// [diffDstLine] field, this getter adjusts the line number to be consistent
  /// whether or not there were any changed lines.
  int get dstLine {
    return addLines.isEmpty ? diffDstLine : diffDstLine - 1;
  }

  /// Return the index of the first line that was changed in the src. Unlike the
  /// [diffDstLine] field, this getter adjusts the line number to be consistent
  /// whether or not there were any changed lines.
  int get srcLine {
    return removeLines.isEmpty ? diffSrcLine : diffSrcLine - 1;
  }
}

/// A representation of a single line (record) from a raw diff.
class DiffRecord {
  /// The repository containing the file(s) that were modified.
  final GitRepository repository;

  /// The SHA1 of the blob in the src.
  final String srcBlob;

  /// The SHA1 of the blob in the dst.
  final String dstBlob;

  /// The status of the change. Valid values are:
  /// * A: addition of a file
  /// * C: copy of a file into a new one
  /// * D: deletion of a file
  /// * M: modification of the contents or mode of a file
  /// * R: renaming of a file
  /// * T: change in the type of the file
  /// * U: file is unmerged (you must complete the merge before it can be
  ///      committed)
  /// * X: "unknown" change type (most probably a bug, please report it)
  ///
  /// Status letters C and R are always followed by a score (denoting the
  /// percentage of similarity between the source and target of the move or
  /// copy), and are the only ones to be so.
  final String status;

  /// The path of the src.
  final String? srcPath;

  /// The path of the dst if this was either a copy or a rename operation.
  final String? dstPath;

  /// Initialize a newly created diff record.
  DiffRecord(
    this.repository,
    this.srcBlob,
    this.dstBlob,
    this.status,
    this.srcPath,
    this.dstPath,
  );

  /// Return `true` if this record represents a file that was added.
  bool get isAddition => status == 'A';

  /// Return `true` if this record represents a file that was copied.
  bool get isCopy => status.startsWith('C');

  /// Return `true` if this record represents a file that was deleted.
  bool get isDeletion => status == 'D';

  /// Return `true` if this record represents a file that was modified.
  bool get isModification => status == 'M';

  /// Return `true` if this record represents a file that was renamed.
  bool get isRename => status.startsWith('R');

  /// Return `true` if this record represents an entity whose type was changed
  /// (for example, from a file to a directory).
  bool get isTypeChange => status == 'T';

  /// Return a representation of the individual blobs within this diff.
  BlobDiff getBlobDiff() => repository.getBlobDiff(srcBlob, dstBlob);

  /// Return `true` if this diff applies to a file with the given name.
  bool isFor(String fileName) {
    var srcPath = this.srcPath;
    var dstPath = this.dstPath;
    return (srcPath != null && fileName == path.basename(srcPath)) ||
        (dstPath != null && fileName == path.basename(dstPath));
  }

  @override
  String toString() => srcPath ?? dstPath ?? '<unknown>';
}

/// A representation of a git repository.
class GitRepository {
  /// The absolute path of the directory containing the repository.
  final String path;

  /// The logger to which git commands should be written, or `null` if the
  /// commands should not be written.
  final Logger? logger;

  /// Initialize a newly created repository to represent the git repository at
  /// the given [path].
  ///
  /// If a [commandSink] is provided, any calls to git will be written to it.
  GitRepository(this.path, {this.logger});

  /// Checkout the given [commit] from the repository. This is done by running
  /// the command `git checkout <sha>`.
  void checkout(String commit) {
    _run(['checkout', commit]);
  }

  /// Return details about the differences between the two blobs identified by
  /// the SHA1 of the [srcBlob] and the SHA1 of the [dstBlob]. This is done by
  /// running the command `git diff <blob> <blob>`.
  BlobDiff getBlobDiff(String srcBlob, String dstBlob) {
    var result = _run(['diff', '-U0', srcBlob, dstBlob]);
    var diffResults = LineSplitter.split(result.stdout as String).toList();
    return BlobDiff._(diffResults);
  }

  /// Return details about the differences between the two commits identified by
  /// the [srcCommit] and [dstCommit]. This is done by running the command
  /// `git diff --raw --no-abbrev --no-renames -z <sha> <sha>`.
  CommitDelta getCommitDiff(String srcCommit, String dstCommit) {
    // Consider --find-renames instead of --no-renames if rename information is
    // desired.
    var result = _run([
      'diff',
      '--raw',
      '--no-abbrev',
      '--no-renames',
      '-z',
      srcCommit,
      dstCommit,
    ]);
    return CommitDelta._(this, result.stdout as String);
  }

  /// Return a representation of the history of this repository. This is done by
  /// running the command `git rev-list --first-parent HEAD`.
  LinearCommitHistory getCommitHistory() {
    var result = _run(['rev-list', '--first-parent', 'HEAD']);
    var commitIds = LineSplitter.split(result.stdout as String).toList();
    return LinearCommitHistory(this, commitIds);
  }

  /// Synchronously run the given [executable] with the given [arguments].
  /// Return the result of running the process.
  ProcessResult _run(List<String> arguments) {
    logger?.log('git', 'git', arguments: arguments);
    return Process.runSync(
      'git',
      arguments,
      stderrEncoding: utf8,
      stdoutEncoding: utf8,
      workingDirectory: path,
    );
  }
}

/// A representation of the history of a Git repository. This only represents a
/// single linear path in the history graph.
class LinearCommitHistory {
  /// The repository whose history is being represented.
  final GitRepository repository;

  /// The id's (SHA's) of the commits in the repository, with the most recent
  /// commit being first and the oldest commit being last.
  final List<String> commitIds;

  /// Initialize a commit history for the given [repository] to have the given
  /// [commitIds].
  LinearCommitHistory(this.repository, this.commitIds);

  /// Return an iterator that can be used to iterate over this commit history.
  LinearCommitHistoryIterator iterator() {
    return LinearCommitHistoryIterator(this);
  }
}

/// An iterator over the history of a Git repository.
class LinearCommitHistoryIterator {
  /// The commit history being iterated over.
  final LinearCommitHistory history;

  /// The index of the current commit in the list of [commitIds].
  late int currentCommit;

  /// Initialize a newly created iterator to iterate over the commits with the
  /// given [commitIds];
  LinearCommitHistoryIterator(this.history) {
    currentCommit = history.commitIds.length;
  }

  /// Return the SHA1 of the commit after the current commit (the 'dst' of the
  /// [next] diff).
  String get dstCommit => history.commitIds[currentCommit - 1];

  /// Return the SHA1 of the current commit (the 'src' of the [next] diff).
  String get srcCommit => history.commitIds[currentCommit];

  /// Advance to the next commit in the history. Return `true` if it is safe to
  /// ask for the [next] diff.
  bool moveNext() {
    if (currentCommit <= 1) {
      return false;
    }
    currentCommit--;
    return true;
  }

  /// Return the difference between the current commit and the commit that
  /// followed it.
  CommitDelta next() => history.repository.getCommitDiff(srcCommit, dstCommit);
}
