UNPKG

branch-remover

Version:

A small application for quickly removing unnecessary branches from GitHub.

183 lines 7.69 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BranchRemover = void 0; const chalk_1 = __importDefault(require("chalk")); const Core_1 = require("./Core"); const Formatters_1 = require("./Formatters"); class BranchRemover { constructor(provider) { this._provider = provider; this.execute = this.execute.bind(this); } get provider() { return this._provider; } // TODO: I forgot why I made test a separate parameter from the options, // it probably makes sense to combine async execute(options, test) { var _a, _b, _c; // TODO: PackageInfo service const { name: packageName, version: packageVersion, } = require('../package.json'); const logger = options.logger || new Core_1.Logger(); const cache = (_a = options.cache) === null || _a === void 0 ? void 0 : _a.provider; const cacheTimeout = (_c = (_b = options.cache) === null || _b === void 0 ? void 0 : _b.timeout) !== null && _c !== void 0 ? _c : 0; const isCacheAvailable = cache && cacheTimeout > 0; logger.info('{package} v{version}', { package: packageName, version: packageVersion, }); if (isCacheAvailable) { cache.load(); } try { await this.processBranches(logger, options, test !== null && test !== void 0 ? test : false); } catch (error) { // TODO: Output the number of processed branches and the elapsed time throw new Error(error.message); } finally { if (isCacheAvailable) { cache.save(); } } } buildIgnoreFunction(value) { if (typeof value === 'function') { return value; } if (typeof value === 'string') { return (e) => { return Promise.resolve(e.branchName === value); }; } if (value instanceof RegExp) { return (e) => { return Promise.resolve(value.test(e.branchName)); }; } if (Array.isArray(value)) { return (e) => { return Promise.resolve(value.includes(e.branchName)); }; } return () => Promise.resolve(false); } async processBranches(logger, options, test) { var _a, _b, _c; const start = new Date(); const ignore = this.buildIgnoreFunction(options.ignore); const remove = options.remove; const dummy = () => Promise.resolve(true); const beforeRemove = options.beforeRemove || dummy; const afterRemove = options.afterRemove || dummy; const context = { test, logger, }; const cache = (_a = options.cache) === null || _a === void 0 ? void 0 : _a.provider; const cacheTimeout = (_c = (_b = options.cache) === null || _b === void 0 ? void 0 : _b.timeout) !== null && _c !== void 0 ? _c : 0; const isCacheAvailable = cache && cacheTimeout > 0; const addCache = (key, reason) => { if (isCacheAvailable) { cache.add(key, reason, cacheTimeout); } }; logger.info('Processing branches using {provider} provider in {mode} mode.', { provider: chalk_1.default.yellow(this._provider.name), mode: test ? chalk_1.default.yellow('test') : chalk_1.default.bold(chalk_1.default.red('REMOVE')), }); const branches = await this._provider.getListBranches(); let totalRemoved = 0; for (let i = 0, ic = branches.length; i < ic; ++i) { const { name, lastCommitHash } = branches[i]; const cacheKey = `branch-${name}`; logger.info('Processing branch {index} of {count} - {branch}', { index: chalk_1.default.blue(i + 1), count: chalk_1.default.blue(ic), branch: name, }); if (isCacheAvailable) { if (cache.has(cacheKey)) { logger.info('Skip cached branch "{branch}" until {ttl}: {reason}.', { branch: name, ttl: new Date(cache.getTtl(cacheKey)), reason: Formatters_1.branchRemoveCancelationReasonFormatter(cache.get(cacheKey)), }); continue; } } // NOTE: we have to check before getting branch details // because, depending on the provider, there may be limits on the number of requests; // for example, GitHub currently allows no more than 5,000 requests per hour for free const ignored = await ignore({ branchName: name, context, }); if (ignored) { addCache(cacheKey, Core_1.BranchRemoveCancelationReason.Ignored); logger.info('Skip branch "{branch}", because it matches an ignored value.', { branch: name, }); continue; } const branch = await this._provider.getBranch(name, lastCommitHash); if (!branch) { addCache(cacheKey, Core_1.BranchRemoveCancelationReason.BranchNotFound); logger.info('Skip branch "{branch}", because no detailed information.', { branch: name, }); continue; } const args = { branch, context, }; const canRemove = await remove(args); if (canRemove === true) { logger.info('Removing "{branch}"...', { branch: name, }); if (test) { logger.info('Removing is not applicable in test mode.'); } else { // TODO: not sure if we need additional checking, // this is probably redundant, // need to think about this question const canStillRemove = await beforeRemove(args); if (canStillRemove) { await this._provider.removeBranch(name); ++totalRemoved; logger.info('Successfully removed "{branch}".', { branch: name, }); await afterRemove(args); } else { addCache(cacheKey, Core_1.BranchRemoveCancelationReason.CanceledByBeforeHandler); logger.info('Removing branch "{branch}" canceled by the result of the {handler} handler.', { branch: name, handler: 'beforeRemove', }); } } } else { addCache(cacheKey, typeof canRemove === 'boolean' ? Core_1.BranchRemoveCancelationReason.Other : canRemove); } } logger.info('Removed {totalRemoved} out of {totalCount} branches in {duration} seconds.', { totalRemoved, totalCount: branches.length, duration: (new Date().getTime() - start.getTime()) / 1000, }); } } exports.BranchRemover = BranchRemover; //# sourceMappingURL=BranchRemover.js.map