code996
Version:
通过分析 Git commit 的时间分布,计算出项目的'996指数'
161 lines • 6.34 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TrendExecutor = void 0;
const chalk_1 = __importDefault(require("chalk"));
const ora_1 = __importDefault(require("ora"));
const git_collector_1 = require("../../git/git-collector");
const trend_analyzer_1 = require("../../core/trend-analyzer");
const trend_printer_1 = require("./report/trend-printer");
const terminal_1 = require("../../utils/terminal");
const commit_guard_1 = require("../common/commit-guard");
/**
* 趋势分析命令执行器
*/
class TrendExecutor {
/**
* 执行趋势分析
*/
static async execute(path, options) {
try {
const collector = new git_collector_1.GitCollector();
// 计算时间范围
const { since, until } = await this.resolveTimeRange(collector, path, options);
// 显示分析开始信息
console.log(chalk_1.default.blue('🔍 趋势分析仓库:'), path || process.cwd());
console.log(chalk_1.default.blue('📅 时间范围:'), `${since} 至 ${until}`);
console.log();
let authorPattern;
if (options.self) {
const authorInfo = await collector.resolveSelfAuthor(path);
authorPattern = authorInfo.pattern;
console.log(chalk_1.default.blue('🙋 作者过滤:'), authorInfo.displayLabel);
console.log();
}
// 构造采样参数,确保 commit 过滤条件与趋势统计一致
const collectOptions = {
path,
since,
until,
authorPattern,
};
// 趋势分析同样需要足够的样本量
const hasEnoughCommits = await (0, commit_guard_1.ensureCommitSamples)(collector, collectOptions, 20, '趋势分析');
if (!hasEnoughCommits) {
return;
}
// 创建进度指示器
const spinner = (0, ora_1.default)('📦 开始月度趋势分析...').start();
// 执行趋势分析
const trendResult = await trend_analyzer_1.TrendAnalyzer.analyzeTrend(path, since, until, authorPattern);
spinner.succeed('趋势分析完成!');
// 输出趋势报告
(0, trend_printer_1.printTrendReport)(trendResult);
}
catch (error) {
console.error(chalk_1.default.red('❌ 趋势分析失败:'), error.message);
process.exit(1);
}
}
/**
* 解析时间范围
*/
static async resolveTimeRange(collector, path, options) {
// 全时间范围
if (options.allTime) {
const firstCommit = await collector.getFirstCommitDate({ path });
const lastCommit = await collector.getLastCommitDate({ path });
if (!firstCommit || !lastCommit) {
throw new Error('无法获取仓库的提交历史时间范围');
}
return {
since: firstCommit,
until: lastCommit,
};
}
// 年份参数
if (options.year) {
const yearRange = this.parseYearOption(options.year);
if (yearRange) {
return {
since: yearRange.since,
until: yearRange.until,
};
}
}
// 自定义时间范围
if (options.since && options.until) {
return {
since: options.since,
until: options.until,
};
}
// 部分自定义时间范围(补全缺失的部分)
if (options.since || options.until) {
const fallback = (0, terminal_1.calculateTimeRange)(false);
return {
since: options.since || fallback.since,
until: options.until || fallback.until,
};
}
// 默认:基于最后一次提交回溯365天
try {
const lastCommitDate = await collector.getLastCommitDate({ path });
if (lastCommitDate) {
const until = lastCommitDate;
const untilDate = new Date(lastCommitDate);
untilDate.setFullYear(untilDate.getFullYear() - 1);
const since = untilDate.toISOString().split('T')[0];
return { since, until };
}
}
catch {
// 失败则使用当前日期回溯
}
// 兜底:当前日期回溯365天
const fallback = (0, terminal_1.calculateTimeRange)(false);
return {
since: fallback.since,
until: fallback.until,
};
}
/**
* 解析年份参数
*/
static parseYearOption(yearStr) {
yearStr = yearStr.trim();
// 年份范围格式:2023-2025
const rangeMatch = yearStr.match(/^(\d{4})-(\d{4})$/);
if (rangeMatch) {
const startYear = parseInt(rangeMatch[1], 10);
const endYear = parseInt(rangeMatch[2], 10);
if (startYear < 1970 || endYear < 1970 || startYear > endYear) {
console.error(chalk_1.default.red('❌ 年份格式错误: 起始年份不能大于结束年份,且年份必须 >= 1970'));
process.exit(1);
}
return {
since: `${startYear}-01-01`,
until: `${endYear}-12-31`,
};
}
// 单年格式:2025
const singleMatch = yearStr.match(/^(\d{4})$/);
if (singleMatch) {
const year = parseInt(singleMatch[1], 10);
if (year < 1970) {
console.error(chalk_1.default.red('❌ 年份格式错误: 年份必须 >= 1970'));
process.exit(1);
}
return {
since: `${year}-01-01`,
until: `${year}-12-31`,
};
}
console.error(chalk_1.default.red('❌ 年份格式错误: 请使用 "2025" 或 "2023-2025" 格式'));
process.exit(1);
}
}
exports.TrendExecutor = TrendExecutor;
//# sourceMappingURL=trend.js.map