UNPKG

branch-remover

Version:

A small application for quickly removing unnecessary branches from GitHub.

236 lines 9.68 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BranchRemoverOptionsBuilder = void 0; const child_process_1 = __importDefault(require("child_process")); const humanize_duration_1 = __importDefault(require("humanize-duration")); const readline_1 = __importDefault(require("readline")); const util_1 = __importDefault(require("util")); const Core_1 = require("./Core"); const Formatters_1 = require("./Formatters"); const exec = util_1.default.promisify(child_process_1.default.exec); class BranchRemoverOptionsBuilder { constructor() { this._quiet = false; this._yes = false; this._details = false; this._mergedDate = null; this._staleDate = null; this._ignore = null; this._beforeRemove = null; this._afterRemove = null; this._cacheTimeout = 0; this._cachePath = BranchRemoverOptionsBuilder.DEFAULT_CACHE_PATH; this._debug = false; this.quiet = this.quiet.bind(this); this.merged = this.merged.bind(this); this.stale = this.stale.bind(this); this.yes = this.yes.bind(this); this.details = this.details.bind(this); this.ignore = this.ignore.bind(this); this.beforeRemove = this.beforeRemove.bind(this); this.afterRemove = this.afterRemove.bind(this); this.cacheTimeout = this.cacheTimeout.bind(this); this.cachePath = this.cachePath.bind(this); this.debug = this.debug.bind(this); this.build = this.build.bind(this); } quiet() { this._quiet = true; return this; } yes() { this._yes = true; return this; } details() { this._details = true; return this; } merged(date) { this._mergedDate = date; return this; } stale(date) { this._staleDate = date; return this; } ignore(value) { this._ignore = value; return this; } beforeRemove(command) { this._beforeRemove = command; return this; } afterRemove(command) { this._afterRemove = command; return this; } cacheTimeout(timeout) { this._cacheTimeout = Number(timeout); return this; } cachePath(path) { if (!path) { throw new Error('Parameter "path" cannot be null or empty.'); } this._cachePath = path; return this; } debug() { this._debug = true; return this; } build() { const displayDefaultAnswer = this._yes ? '[Y/n]' : '[y/N]'; const defaultAnswer = this._yes ? 'yes' : 'no'; const ignore = this.getRegExpOrNull(this._ignore); const mergedDate = this._mergedDate; const staleDate = this._staleDate; const quiet = this._quiet; const details = this._details; const beforeRemove = this._beforeRemove; const afterRemove = this._afterRemove; const cachePath = this._cachePath; const cacheTimeout = this._cacheTimeout; const cacheProvider = new Core_1.FileCacheProvider(cachePath); const logger = new Core_1.Logger(Core_1.Logger.defaultOptions(this._debug ? 'debug' : 'info')); return { logger, cache: { provider: cacheProvider, timeout: cacheTimeout, }, ignore: (e) => { if (ignore) { // When a regex has the global flag set, test() will advance the lastIndex of the regex. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test#using_test_on_a_regex_with_the_global_flag ignore.lastIndex = 0; if (ignore.test(e.branchName)) { return Promise.resolve(true); } } return Promise.resolve(false); }, remove: async (e) => { var _a, _b; const { branch, context: { logger, }, } = e; let result = false; if (branch.merged) { if (mergedDate) { if (branch.mergedDate <= mergedDate) { result = true; logger.debug('Can remove merged "{branch.name}", because the merged date {branch.mergedDate} is less or equal to {date}.', { branch, date: mergedDate, }); } else { result = Core_1.BranchRemoveCancelationReason.MergeDateOutOfRange; logger.debug('Cannot remove merged "{branch.name}", because the merged date {branch.mergedDate} is greater than {date}.', { branch, date: mergedDate, }); } } else { result = true; logger.debug('Can remove merged "{branch.name}", because no limit on merge date.', { branch, }); } } else { if (staleDate && branch.updatedDate <= staleDate) { result = true; logger.debug('Can remove "{branch.name}", because the updated date {branch.updatedDate} is less or equal to {date}.', { branch, date: staleDate, }); } else { result = Core_1.BranchRemoveCancelationReason.UpdateDateOutOfRange; } } if (result === true && !quiet) { const question = (query) => { const rl = readline_1.default.createInterface({ input: process.stdin, output: process.stdout, }); return new Promise((resolve) => { rl.question(query, (answer) => { resolve(answer); rl.close(); }); }); }; const now = new Date(); const duration = humanize_duration_1.default(now.getTime() - ((_b = (_a = branch.mergedDate) !== null && _a !== void 0 ? _a : branch.updatedDate) !== null && _b !== void 0 ? _b : now).getTime(), { largest: 1, round: true, }); const date = `${branch.merged ? 'Merged' : 'Updated'} ${duration} ago`; this.displayBranchInfo(branch); const answer = await question(`Do you want to remove ${branch.merged ? 'merged' : 'unmerged'} branch "${branch.name}"? ${date} ${displayDefaultAnswer} `); if (!/y(es|)+/gi.test(answer || defaultAnswer)) { result = Core_1.BranchRemoveCancelationReason.CanceledByUser; logger.debug('Removing branch "{branch.name}" canceled by user.', { branch, }); } } if (details && !quiet && result !== true) { this.displayBranchInfo(branch); } return result; }, beforeRemove: ({ branch, context }) => { if (beforeRemove) { return this.execCommand(beforeRemove, branch, context.logger); } else { return Promise.resolve(true); } }, afterRemove: async ({ branch, context }) => { if (afterRemove) { await this.execCommand(afterRemove, branch, context.logger); } }, }; } displayBranchInfo(branch) { console.log(Formatters_1.branchInfoFormatter(branch)); } getRegExpOrNull(value) { return value ? new RegExp(value, 'g') : null; } async execCommand(command, branch, logger) { const commandToExec = command .replace(/(\\)(.{1})/g, String.fromCharCode(0) + '$2$1') .replace(/\{branch\}/g, branch.name) .replace(/(\0)(.{1})(\\)/g, '$2'); logger.debug('Preparation for command execution. Source: "{source}". Command to execute: {parsed}.', { source: command, parsed: commandToExec, }); const { stdout, stderr, } = await exec(commandToExec); logger.debug('{command} > stdout - {stdout}, stderr - {stderr}', { command: commandToExec, stdout: stdout === null || stdout === void 0 ? void 0 : stdout.trim(), stderr: stderr === null || stderr === void 0 ? void 0 : stderr.trim(), }); return !stdout || (stdout && !/^(0|false)$/i.test(stdout)); } } exports.BranchRemoverOptionsBuilder = BranchRemoverOptionsBuilder; BranchRemoverOptionsBuilder.DEFAULT_CACHE_PATH = './.branch-remover.cache'; //# sourceMappingURL=BranchRemoverOptionsBuilder.js.map