UNPKG

git-yike-logger-hook

Version:

A TypeScript Git hook plugin for automatically generating commit logs with TODO/WIP comment scanning

196 lines 7.29 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.GitLogger = void 0; const fs = __importStar(require("fs")); const path = __importStar(require("path")); const git_utils_1 = require("./git-utils"); const comment_scanner_1 = require("./comment-scanner"); /** * Git 提交日志生成器 */ class GitLogger { constructor(config = {}) { this.gitUtils = new git_utils_1.GitUtils(); this.commentScanner = new comment_scanner_1.CommentScanner(); this.config = { logDir: '.git-logs', includeUnstaged: false, includeUntracked: false, ...config }; } /** * 生成并保存提交日志 */ async generateLog() { try { // 检查是否在 Git 仓库中 const isGitRepo = await this.gitUtils.isGitRepository(); if (!isGitRepo) { throw new Error('当前目录不是 Git 仓库'); } // 获取提交信息 const commitInfo = await this.gitUtils.getCurrentCommitInfo(); // 如果是首次提交,使用当前时间戳和临时信息 if (!commitInfo.commitHash) { const now = new Date().toISOString(); commitInfo.timestamp = now; commitInfo.message = '首次提交'; commitInfo.commitHash = 'initial-commit'; commitInfo.author = { name: 'Unknown', email: 'unknown@example.com' }; } // 获取分支信息 const branch = await this.gitUtils.getCurrentBranch(); // 获取远程仓库信息 const remote = await this.gitUtils.getRemoteInfo(); // 获取文件变更信息 const fileChanges = await this.gitUtils.getFileChanges(); // 扫描变更文件中的 TODO 和 WIP 注释 console.log('🔍 扫描代码注释...'); const comments = await this.commentScanner.scanChangedFiles(fileChanges); // 构建完整的日志对象 const logEntry = { author: commitInfo.author, timestamp: commitInfo.timestamp, message: commitInfo.message, commitHash: commitInfo.commitHash, changedFiles: fileChanges, branch, remote, comments: { todos: comments.todos, wips: comments.wips } }; // 确保日志目录存在 await this.ensureLogDirectory(); // 生成日志文件名 const logFileName = this.generateLogFileName(logEntry); const logFilePath = path.join(this.config.logDir, logFileName); // 写入日志文件 await this.writeLogFile(logFilePath, logEntry); console.log(`✅ 提交日志已生成: ${logFilePath}`); } catch (error) { console.error('❌ 生成提交日志失败:', error); process.exit(1); } } /** * 确保日志目录存在 */ async ensureLogDirectory() { if (!fs.existsSync(this.config.logDir)) { fs.mkdirSync(this.config.logDir, { recursive: true }); } } /** * 生成日志文件名 */ generateLogFileName(logEntry) { const timestamp = new Date(logEntry.timestamp); const dateStr = timestamp.toISOString().split('T')[0]; // YYYY-MM-DD const timeStr = timestamp.toTimeString().split(' ')[0].replace(/:/g, '-'); // HH-MM-SS const shortHash = logEntry.commitHash.substring(0, 8); return `${dateStr}_${timeStr}_${shortHash}.json`; } /** * 写入日志文件 */ async writeLogFile(filePath, logEntry) { const logContent = JSON.stringify(logEntry, null, 2); fs.writeFileSync(filePath, logContent, 'utf8'); } /** * 获取所有日志文件 */ async getAllLogs() { try { if (!fs.existsSync(this.config.logDir)) { return []; } const files = fs.readdirSync(this.config.logDir) .filter(file => file.endsWith('.json')) .sort() .reverse(); // 最新的在前 const logs = []; for (const file of files) { try { const filePath = path.join(this.config.logDir, file); const content = fs.readFileSync(filePath, 'utf8'); const log = JSON.parse(content); logs.push(log); } catch (error) { console.warn(`跳过损坏的日志文件: ${file}`, error); } } return logs; } catch (error) { console.error('读取日志文件失败:', error); return []; } } /** * 清理旧日志文件(保留最近 N 个) */ async cleanupLogs(keepCount = 100) { try { const logs = await this.getAllLogs(); if (logs.length <= keepCount) { return; } const filesToDelete = logs.slice(keepCount); for (const log of filesToDelete) { const fileName = this.generateLogFileName(log); const filePath = path.join(this.config.logDir, fileName); if (fs.existsSync(filePath)) { fs.unlinkSync(filePath); } } console.log(`🧹 已清理 ${filesToDelete.length} 个旧日志文件`); } catch (error) { console.error('清理日志文件失败:', error); } } } exports.GitLogger = GitLogger; //# sourceMappingURL=logger.js.map