// 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.

/// Helper functionality for invoking Git.
library;

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:collection/collection.dart';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';

import 'command_runner.dart';
import 'exceptions.dart';
import 'io.dart';
import 'log.dart' as log;
import 'utils.dart';

/// An exception thrown because a git command failed.
class GitException implements ApplicationException {
  /// The arguments to the git command.
  final List<String> args;

  /// The standard error emitted by git.
  final dynamic stderr;

  /// The standard out emitted by git.
  final dynamic stdout;

  /// The error code
  final int exitCode;

  @override
  String get message =>
      'Git error. Command: `git ${args.join(' ')}`\n'
      'stdout: ${stdout is String ? stdout : '<binary>'}\n'
      'stderr: ${stderr is String ? stderr : '<binary>'}\n'
      'exit code: $exitCode';

  GitException(Iterable<String> args, this.stdout, this.stderr, this.exitCode)
    : args = args.toList();

  @override
  String toString() => message;
}

/// Tests whether or not the git command-line app is available for use.
bool get isInstalled => command != null;

/// Splits the [output] of a git -z command at \0.
///
/// The first [skipPrefix] bytes of each substring will be ignored (useful for
/// `git status -z`). If there are not enough bytes to skip, throws a
/// [FormatException].
List<Uint8List> splitZeroTerminated(Uint8List output, {int skipPrefix = 0}) {
  final result = <Uint8List>[];
  var start = 0;

  for (var i = 0; i < output.length; i++) {
    if (output[i] != 0) {
      continue;
    }
    if (start + skipPrefix > i) {
      throw FormatException('Substring too short for prefix at $start');
    }
    result.add(
      Uint8List.sublistView(
        output,
        // The first 3 bytes are the modification status.
        // Skip those.
        start + skipPrefix,
        i,
      ),
    );

    start = i + 1;
  }
  return result;
}

/// Run a git process with [args] from [workingDir].
///
/// Returns the stdout if it succeeded. Completes to ans exception if it failed.
Future<String> run(
  List<String> args, {
  String? workingDir,
  Map<String, String>? environment,
  Encoding stdoutEncoding = systemEncoding,
  Encoding stderrEncoding = systemEncoding,
}) async {
  if (!isInstalled) {
    fail(
      'Cannot find a Git executable.\n'
      'Please ensure Git is correctly installed.',
    );
  }

  log.muteProgress();
  try {
    final result = await runProcess(
      command!,
      args,
      workingDir: workingDir,
      environment: {...?environment, 'LANG': 'en_GB'},
      stdoutEncoding: stdoutEncoding,
      stderrEncoding: stderrEncoding,
    );
    if (!result.success) {
      throw GitException(args, result.stdout, result.stderr, result.exitCode);
    }
    return result.stdout;
  } finally {
    log.unmuteProgress();
  }
}

/// Like [run], but synchronous.
String runSync(
  List<String> args, {
  String? workingDir,
  Map<String, String>? environment,
  Encoding stdoutEncoding = systemEncoding,
  Encoding stderrEncoding = systemEncoding,
}) {
  if (!isInstalled) {
    fail(
      'Cannot find a Git executable.\n'
      'Please ensure Git is correctly installed.',
    );
  }

  final result = runProcessSync(
    command!,
    args,
    workingDir: workingDir,
    environment: environment,
    stdoutEncoding: stdoutEncoding,
    stderrEncoding: stderrEncoding,
  );
  if (!result.success) {
    throw GitException(args, result.stdout, result.stderr, result.exitCode);
  }

  return result.stdout;
}

/// Like [run], but synchronous. Returns raw stdout as `Uint8List`.
Uint8List runSyncBytes(
  List<String> args, {
  String? workingDir,
  Map<String, String>? environment,
  Encoding stderrEncoding = systemEncoding,
}) {
  if (!isInstalled) {
    fail(
      'Cannot find a Git executable.\n'
      'Please ensure Git is correctly installed.',
    );
  }

  final result = runProcessSyncBytes(
    command!,
    args,
    workingDir: workingDir,
    environment: environment,
    stderrEncoding: stderrEncoding,
  );
  if (!result.success) {
    throw GitException(args, result.stdout, result.stderr, result.exitCode);
  }

  return result.stdout;
}

/// The name of the git command-line app, or `null` if Git could not be found on
/// the user's PATH.
final String? command = ['git', 'git.cmd'].firstWhereOrNull(_tryGitCommand);

/// Returns the root of the git repo [dir] belongs to. Returns `null` if not
/// in a git repo or git is not installed.
String? repoRoot(String dir) {
  if (isInstalled) {
    try {
      return p.normalize(
        runSync(['rev-parse', '--show-toplevel'], workingDir: dir).trim(),
      );
    } on GitException {
      // Not in a git folder.
      return null;
    }
  }
  return null;
}

/// '--recourse-submodules' was introduced in Git 2.14
/// (https://git-scm.com/book/en/v2/Git-Tools-Submodules).
final _minSupportedGitVersion = Version(2, 14, 0);

/// Checks whether [command] is the Git command for this computer.
bool _tryGitCommand(String command) {
  // If "git --version" prints something familiar, git is working.
  try {
    final result = runProcessSync(command, ['--version']);
    final output = result.stdout;

    // Some users may have configured commands such as autorun, which may
    // produce additional output, so we need to look for "git version"
    // in every line of the output.
    final match = RegExp(
      r'^git version (\d+)\.(\d+)\..*$',
      multiLine: true,
    ).matchAsPrefix(output);
    if (match == null) return false;
    final versionString = match[0]!.substring('git version '.length);
    // Git seems to use many parts in the version number. We just check the
    // first two.
    final major = int.parse(match[1]!);
    final minor = int.parse(match[2]!);
    if (Version(major, minor, 0) < _minSupportedGitVersion) {
      // We just warn here, as some features might work with older versions of
      // git.
      log.warning('''
You have a very old version of git (version $versionString),
for $topLevelProgram it is recommended to use git version 2.14 or newer.
''');
    }
    log.fine('Determined git command $command.');
    return true;
  } on RunProcessException catch (err) {
    // If the process failed, they probably don't have it.
    log.error('Git command is not "$command": $err');
    return false;
  }
}
