// 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 analysis_server.test.stress.utilities.git;

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

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

/**
 * 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 =
      new 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 (String line in input) {
      _parseLine(line);
    }
  }

  /**
   * Parse a single [line] from the result of the git diff command.
   */
  void _parseLine(String line) {
    DiffHunk currentHunk = hunks.isEmpty ? null : hunks.last;
    if (line.startsWith('@@')) {
      Match match = hunkHeaderRegExp.matchAsPrefix(line);
      int srcLine = int.parse(match.group(1));
      int dstLine = int.parse(match.group(2));
      hunks.add(new 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) {
      String filePath = record.srcPath ?? record.dstPath;
      for (String inclusionPath in inclusionPaths) {
        if (path.isWithin(inclusionPath, filePath)) {
          for (Glob 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) {
    int length = string.length;
    int 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) {
    int length = input.length;
    int 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
    String srcSha = input.substring(startIndex, startIndex + SHA_LENGTH);
    startIndex += SHA_LENGTH + 1;
    // Parse field 8
    String dstSha = input.substring(startIndex, startIndex + SHA_LENGTH);
    startIndex += SHA_LENGTH + 1;
    // Parse field 10
    int endIndex = _findEnd(input, startIndex);
    String status = input.substring(startIndex, endIndex);
    startIndex = endIndex + 1;
    // Parse field 12
    endIndex = _findEnd(input, startIndex);
    String srcPath = _makeAbsolute(input.substring(startIndex, endIndex));
    startIndex = endIndex + 1;
    // Parse field 14
    String dstPath = null;
    if (status.startsWith('C') || status.startsWith('R')) {
      endIndex = _findEnd(input, startIndex);
      dstPath = _makeAbsolute(input.substring(startIndex, endIndex));
    }
    // Create the record.
    diffRecords.add(
        new 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) =>
      (srcPath != null && fileName == path.basename(srcPath)) ||
      (dstPath != null && fileName == path.basename(dstPath));

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

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

  /**
   * Initialize a newly created repository to represent the git repository at
   * the given [path].
   */
  GitRepository(this.path);

  /**
   * 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) {
    ProcessResult result = _run(['diff', '-U0', srcBlob, dstBlob]);
    List<String> diffResults = LineSplitter.split(result.stdout).toList();
    return new 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.
    ProcessResult result = _run([
      'diff',
      '--raw',
      '--no-abbrev',
      '--no-renames',
      '-z',
      srcCommit,
      dstCommit
    ]);
    return new CommitDelta._(this, result.stdout);
  }

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

  /**
   * Synchronously run the given [executable] with the given [arguments]. Return
   * the result of running the process.
   */
  ProcessResult _run(List<String> 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 new 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].
   */
  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);
}
