UNPKG

debt-collector

Version:

a nodejs tool to identify, track and mesure technical debt

99 lines (98 loc) 3.41 kB
/* eslint-disable no-await-in-loop, no-restricted-syntax */ import path from 'path'; import { simpleGit } from 'simple-git'; const gitOptions = { baseDir: process.cwd(), binary: 'git', maxConcurrentProcesses: 6, }; const git = simpleGit(gitOptions); export const getIsHistoryDirty = async () => { const status = await git.status(); return status.files.length > 0; }; function timeout(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } export const checkoutTo = async (revision) => { await git.checkout([revision]); // we need to make sure that file system is ready to be used, and finished the checkout await timeout(1000); }; export const getCurrentBranch = async () => { const currentBranch = await git.revparse(['--abbrev-ref', 'HEAD']); return currentBranch; }; export const execWalkCommand = async (command) => git.raw(command.replace('git ', '').split(' ')); export const getRevList = async (command, parser, limit = 10) => { const commandResult = await git.raw(command.replace('git ', '').split(' ')); const result = parser(commandResult); return result.slice(0, limit); }; export const walkCommits = async (revList, { onCommitChange, onError, onEnd, }) => { const isHistoryDirty = await getIsHistoryDirty(); const currentBranch = await getCurrentBranch(); let walkIteratorResults = null; if (isHistoryDirty) { onError('You have uncommited changes, please commit or stash them'); return null; } try { // eslint-disable-next-line for (const [index, rev] of revList.entries()) { await git.checkout([rev.hash]); const previousResult = walkIteratorResults?.[index - 1] ?? null; const results = await onCommitChange({ rev, index, previousResult, }); if (!walkIteratorResults) { walkIteratorResults = []; } walkIteratorResults.push({ rev, results, }); } } catch (e) { onError(e instanceof Error ? e.message : 'Unknown error'); await checkoutTo(currentBranch); console.log(e); return null; } await checkoutTo(currentBranch); const results = await onEnd(walkIteratorResults); return results; }; export const getChangedFilesSinceRev = async (rev, commonAncestor) => { let results; if (commonAncestor) { // get last common commit between rev and Head // avoid comparing Head with out of sync base branch const commit = await git.raw(['merge-base', rev, 'HEAD']); results = await git.diff([ commit.replace('\n', ''), '--name-status', '--no-renames', ]); } else { results = await git.diff([rev, '--name-status', '--no-renames']); } const rootGitDir = await git.revparse(['--show-toplevel']); const currentGitDir = path.relative(rootGitDir, process.cwd()); const changedFilesSinceRev = results .replace(/\t/g, '|') .split('\n') .filter((item) => item !== '') .map((item) => { const [status, filePath] = item.split('|'); return { status, filePath: path.relative(currentGitDir, filePath ?? ''), }; }); return changedFilesSinceRev; };