t-comm
Version:
专业、稳定、纯粹的工具库
140 lines (137 loc) • 4.86 kB
JavaScript
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import _regeneratorRuntime from '@babel/runtime/regenerator';
import { _ as __awaiter } from '../tslib.es6-848120af.js';
import { execCommand } from '../node/node-command.mjs';
import { getChildProcess } from '../nodejs/child_process.mjs';
import { getFs } from '../nodejs/fs.mjs';
import { getPath } from '../nodejs/path.mjs';
import { getChalk } from '../third-party/chalk.mjs';
import '@babel/runtime/helpers/typeof';
/**
* 异步执行命令,返回 stdout 字符串
*/
function execAsync(command, cwd) {
return new Promise(function (resolve) {
var _getChildProcess = 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 __awaiter(this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
var _yield$Promise$all, _yield$Promise$all2, statusOutput, aheadCount, count;
return _regeneratorRuntime.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(_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 __awaiter(this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
var fs, path, chalk, list, tasks;
return _regeneratorRuntime.wrap(function (_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
fs = getFs();
path = getPath();
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 = getFs();
var path = getPath();
var 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 = execCommand('git status --porcelain', subDir, 'pipe');
if (statusOutput.trim()) {
console.log(chalk.red('[not clean] '), subDir);
}
var aheadCount = 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);
}
}
});
}
export { checkGitClean, checkGitCleanSync };