'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
var _regeneratorRuntime = require('@babel/runtime/regenerator');
var tslib_es6 = require('../tslib.es6-0d92ef81.js');
var node_nodeCommand = require('../node/node-command.js');
var nodejs_child_process = require('../nodejs/child_process.js');
var nodejs_fs = require('../nodejs/fs.js');
var nodejs_path = require('../nodejs/path.js');
var thirdParty_chalk = require('../third-party/chalk.js');
require('@babel/runtime/helpers/typeof');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var _slicedToArray__default = /*#__PURE__*/_interopDefaultLegacy(_slicedToArray);
var _regeneratorRuntime__default = /*#__PURE__*/_interopDefaultLegacy(_regeneratorRuntime);

/**
 * 异步执行命令，返回 stdout 字符串
 */
function execAsync(command, cwd) {
  return new Promise(function (resolve) {
    var _getChildProcess = nodejs_child_process.getChildProcess(),
      exec = _getChildProcess.exec;
    exec(command, {
      cwd: cwd,
      encoding: 'utf-8'
    }, function (err, stdout) {
      resolve(err ? '' : stdout || '');
    });
  });
}
/**
 * 检查单个 git 仓库的状态（是否 clean、是否已 push）
 * @param {string} subDir - git 仓库目录路径
 * @param {*} chalk - chalk 实例
 */
function checkSingleRepo(subDir, chalk) {
  return tslib_es6.__awaiter(this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee() {
    var _yield$Promise$all, _yield$Promise$all2, statusOutput, aheadCount, count;
    return _regeneratorRuntime__default["default"].wrap(function (_context) {
      while (1) switch (_context.prev = _context.next) {
        case 0:
          _context.next = 1;
          return Promise.all([execAsync('git status --porcelain', subDir), execAsync('git rev-list --count @{u}..HEAD', subDir)]);
        case 1:
          _yield$Promise$all = _context.sent;
          _yield$Promise$all2 = _slicedToArray__default["default"](_yield$Promise$all, 2);
          statusOutput = _yield$Promise$all2[0];
          aheadCount = _yield$Promise$all2[1];
          if (statusOutput.trim()) {
            console.log(chalk.red('[not clean] '), subDir);
          }
          count = parseInt(aheadCount.trim(), 10);
          if (count > 0) {
            console.log(chalk.blue('[not push]'), subDir);
          }
        case 2:
        case "end":
          return _context.stop();
      }
    }, _callee);
  }));
}
/**
 * 异步并行检查目录下所有 git 仓库的工作区状态
 * 相比同步版本，在仓库数量较多时有显著的性能提升
 * @param dir - 要检查的父目录路径
 * @example
 * ```ts
 * // 并行检查 ~/Documents/git 下所有子仓库
 * await checkGitClean('/Users/foo/Documents/git');
 * // 控制台会输出：
 * // [not clean]   /Users/foo/Documents/git/repoA
 * // [not push]    /Users/foo/Documents/git/repoB
 * ```
 */
function checkGitClean(dir) {
  return tslib_es6.__awaiter(this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee2() {
    var fs, path, chalk, list, tasks;
    return _regeneratorRuntime__default["default"].wrap(function (_context2) {
      while (1) switch (_context2.prev = _context2.next) {
        case 0:
          fs = nodejs_fs.getFs();
          path = nodejs_path.getPath();
          chalk = thirdParty_chalk.getChalk();
          if (fs.existsSync(dir)) {
            _context2.next = 1;
            break;
          }
          console.error("Not Exist ".concat(dir));
          return _context2.abrupt("return");
        case 1:
          list = fs.readdirSync(dir); // 筛选出所有 git 仓库，并行检查
          tasks = list.map(function (file) {
            return path.resolve(dir, file);
          }).filter(function (subDir) {
            return fs.existsSync(path.resolve(subDir, '.git'));
          }).map(function (subDir) {
            return checkSingleRepo(subDir, chalk);
          });
          _context2.next = 2;
          return Promise.all(tasks);
        case 2:
        case "end":
          return _context2.stop();
      }
    }, _callee2);
  }));
}
/**
 * 同步版本，保持向后兼容
 * @param dir - 要检查的父目录路径
 * @example
 * ```ts
 * checkGitCleanSync('/Users/foo/Documents/git');
 * // 同步依次检查，仓库有变动或未推送会打印警告
 * ```
 */
function checkGitCleanSync(dir) {
  var fs = nodejs_fs.getFs();
  var path = nodejs_path.getPath();
  var chalk = thirdParty_chalk.getChalk();
  if (!fs.existsSync(dir)) {
    console.error("Not Exist ".concat(dir));
    return;
  }
  var list = fs.readdirSync(dir);
  list.forEach(function (file) {
    var subDir = path.resolve(dir, file);
    var dotGit = path.resolve(subDir, '.git');
    var isGitRepo = fs.existsSync(dotGit);
    if (isGitRepo) {
      var statusOutput = node_nodeCommand.execCommand('git status --porcelain', subDir, 'pipe');
      if (statusOutput.trim()) {
        console.log(chalk.red('[not clean] '), subDir);
      }
      var aheadCount = node_nodeCommand.execCommand('git rev-list --count @{u}..HEAD 2>/dev/null || echo 0', subDir, 'pipe');
      if (aheadCount.trim() && parseInt(aheadCount.trim(), 10) > 0) {
        console.log(chalk.blue('[not push]'), subDir);
      }
    }
  });
}

exports.checkGitClean = checkGitClean;
exports.checkGitCleanSync = checkGitCleanSync;
