UNPKG

git-yike-logger-hook

Version:

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

790 lines (612 loc) 18.5 kB
# Git Logger Hook 一个用 TypeScript 编写的 Git hook 插件,用于在每次 commit 时自动生成详细的提交日志,并扫描代码中的 TODO 和 WIP 注释。 ## 📋 目录 - [功能特性](#功能特性) - [开发思路](#开发思路) - [技术架构](#技术架构) - [依赖说明](#依赖说明) - [模块详解](#模块详解) - [快速开始](#快速开始) - [配置选项](#配置选项) - [日志格式](#日志格式) - [注释扫描功能](#注释扫描功能) - [API 文档](#api-文档) - [开发指南](#开发指南) - [故障排除](#故障排除) - [许可证](#许可证) ## 功能特性 - 🔍 **自动记录提交信息**:记录提交人、提交时间、提交消息和提交哈希 - 📁 **文件变更跟踪**:详细记录新增、修改、删除和重命名的文件 - 🌿 **分支信息**:记录当前分支和远程仓库信息 - 💬 **代码注释扫描**:自动扫描 JavaScript/TypeScript 文件中的 TODO 和 WIP 注释 - 📊 **JSON 格式**:结构化的 JSON 日志,便于后续处理和分析 - 🧹 **自动清理**:可配置保留最近 N 个日志文件 - ⚙️ **易于配置**:支持自定义日志目录和文件过滤 - 🚀 **零配置启动**:安装后即可使用,无需额外配置 ## 开发思路 ### 核心设计理念 1. **自动化优先**:通过 Git hook 机制实现完全自动化的日志记录 2. **最小侵入性**:不影响现有开发流程,透明地记录信息 3. **结构化数据**:使用 JSON 格式便于后续分析和处理 4. **可扩展性**:模块化设计,易于添加新功能 ### 技术选型理由 - **TypeScript**:提供类型安全,减少运行时错误 - **simple-git**:简化 Git 操作,避免直接调用 Git 命令 - **Node.js**:跨平台支持,与 Git 生态良好集成 - **Git Hooks**:利用 Git 原生机制,无需额外工具 ### 工作流程 ```mermaid graph TD A[开发者执行 git commit] --> B[触发 pre-commit hook] B --> C[GitLogger 开始工作] C --> D[获取提交信息] D --> E[获取文件变更] E --> F[扫描代码注释] F --> G[生成 JSON 日志] G --> H[保存到 .git-logs 目录] H --> I[提交继续执行] ``` ## 技术架构 ### 整体架构图 ```mermaid graph TB subgraph "Git Hook 层" A[pre-commit hook] --> B[hook.ts] end subgraph "核心模块" B --> C[GitLogger] C --> D[GitUtils] C --> E[CommentScanner] end subgraph "数据层" D --> F[Git 仓库] E --> G[JavaScript/TypeScript 文件] C --> H[JSON 日志文件] end subgraph "类型系统" I[types.ts] --> C I --> D I --> E end ``` ### 模块依赖关系 - `hook.ts``GitLogger``GitUtils` + `CommentScanner` - 所有模块都依赖 `types.ts` 进行类型定义 - `install.ts` 独立运行,负责 Git hook 的安装和卸载 ## 依赖说明 ### 核心依赖 | 依赖 | 版本 | 作用 | 选择理由 | |------|------|------|----------| | `simple-git` | ^3.19.0 | Git 操作封装 | 简化 Git 命令调用,提供 Promise 接口 | | `@types/node` | ^20.0.0 | Node.js 类型定义 | 提供 Node.js API 的类型支持 | | `typescript` | ^5.0.0 | TypeScript 编译器 | 编译 TypeScript 代码 | ### 依赖作用详解 #### simple-git ```typescript // 示例:获取提交信息 const git = simpleGit(); const log = await git.log({ maxCount: 1 }); const commit = log.latest; ``` **为什么选择 simple-git?** - 提供统一的 Promise 接口 - 自动处理 Git 命令的复杂参数 - 内置错误处理和重试机制 - 支持所有主流 Git 操作 #### TypeScript - 提供编译时类型检查 - 增强代码可读性和维护性 - 提供智能代码补全和重构支持 ## 模块详解 ### 核心模块 #### 1. `types.ts` - 类型定义模块 ```typescript // 核心数据结构定义 export interface CommitLog { ... } export interface CodeComment { ... } export interface GitStatus { ... } export interface LoggerConfig { ... } ``` **作用:** - 定义所有模块使用的数据结构 - 提供类型安全保障 - 作为模块间的契约 **关键点:** - 使用接口而非类型别名,便于扩展 - 所有字段都有明确的注释说明 - 支持可选字段,增强灵活性 #### 2. `git-utils.ts` - Git 操作工具类 ```typescript export class GitUtils { async getCurrentCommitInfo(): Promise<Partial<CommitLog>> async getCurrentBranch(): Promise<string> async getRemoteInfo(): Promise<{ name: string; url: string } | undefined> async getFileChanges(): Promise<{ added: string[]; modified: string[]; ... }> } ``` **作用:** - 封装所有 Git 相关操作 - 提供统一的错误处理 - 处理首次提交等边界情况 **关键点:** - 使用 simple-git 简化 Git 操作 - 完善的错误处理和降级策略 - 支持首次提交的特殊处理 #### 3. `comment-scanner.ts` - 代码注释扫描器 ```typescript export class CommentScanner { async scanDirectory(dirPath: string): Promise<{ todos: CodeComment[]; wips: CodeComment[] }> async scanFile(filePath: string): Promise<{ todos: CodeComment[]; wips: CodeComment[] }> async scanChangedFiles(changedFiles: {...}): Promise<{ todos: CodeComment[]; wips: CodeComment[] }> } ``` **作用:** - 扫描 JavaScript/TypeScript 文件中的注释 - 支持多种注释格式(单行、多行、@todo@wip 等) - 智能过滤文件类型和目录 **关键点:** - 使用正则表达式匹配注释模式 - 支持多种文件扩展名 - 自动跳过 node_modules 等目录 - 提供精确的行号和文件路径信息 #### 4. `logger.ts` - 日志生成器(核心模块) ```typescript export class GitLogger { constructor(config: Partial<LoggerConfig> = {}) async generateLog(): Promise<void> async getAllLogs(): Promise<CommitLog[]> async cleanupLogs(keepCount: number): Promise<void> } ``` **作用:** - 协调各个模块完成日志生成 - 管理日志文件的存储和清理 - 提供统一的配置接口 **关键点:** - 组合模式:协调 GitUtils 和 CommentScanner - 异步处理:所有操作都是异步的 - 错误处理:完善的错误处理和用户提示 - 文件管理:自动创建目录和清理旧文件 #### 5. `hook.ts` - Git Hook 入口点 ```typescript #!/usr/bin/env node async function main() { const logger = new GitLogger(); await logger.generateLog(); await logger.cleanupLogs(100); } ``` **作用:** - 作为 Git hook 的入口点 - 处理命令行参数 - 提供用户友好的输出 **关键点:** - 使用 shebang 支持直接执行 - 完善的错误处理和退出码 - 清晰的用户反馈 #### 6. `install.ts` - Hook 安装器 ```typescript export class HookInstaller { async install(): Promise<void> async uninstall(): Promise<void> private createPreCommitHook(): void private createPostCommitHook(): void } ``` **作用:** - 自动安装和卸载 Git hooks - 生成跨平台的 hook 脚本 - 验证 Git 仓库环境 **关键点:** - 跨平台支持(Windows/Unix) - 自动检测 Git 仓库 - 生成可执行的 hook 脚本 ### 辅助模块 #### `index.ts` - 模块导出 ```typescript export { GitLogger } from './logger'; export { GitUtils } from './git-utils'; export { CommentScanner } from './comment-scanner'; export { CommitLog, GitStatus, LoggerConfig, CodeComment } from './types'; ``` **作用:** - 提供统一的模块导出接口 - 简化外部使用 - 支持默认导出 ## 快速开始 ### 1. 安装依赖 ```bash npm install ``` ### 2. 编译项目 ```bash npm run build ``` ### 3. 安装 Git Hook ```bash npm run install-hook ``` ### 4. 开始使用 现在每次执行 `git commit` 时,插件会自动在 `.git-logs` 目录中生成一个 JSON 日志文件。 ## 日志格式 生成的日志文件格式如下: ```json { "author": { "name": "用户名", "email": "user@example.com" }, "timestamp": "2024-01-01T12:00:00.000Z", "message": "提交信息", "commitHash": "abc123def456...", "changedFiles": { "added": ["新文件1.js", "新文件2.ts"], "modified": ["修改的文件.js"], "deleted": ["删除的文件.js"], "renamed": [ { "from": "旧文件名.js", "to": "新文件名.js" } ] }, "branch": "main", "remote": { "name": "origin", "url": "https://github.com/user/repo.git" }, "comments": { "todos": [ { "type": "TODO", "content": "实现这个功能", "filePath": "src/example.js", "lineNumber": 10, "fullLine": "// TODO: 实现这个功能" } ], "wips": [ { "type": "WIP", "content": "这个功能还在开发中", "filePath": "src/example.js", "lineNumber": 15, "fullLine": "// WIP: 这个功能还在开发中" } ] } } ``` ## 配置选项 可以通过修改 `src/logger.ts` 中的配置来自定义行为: ```typescript const logger = new GitLogger({ logDir: '.git-logs', // 日志文件保存目录 includeUnstaged: false, // 是否包含未暂存的更改 includeUntracked: false, // 是否包含未跟踪的文件 filePatterns: ['*.js', '*.ts'], // 文件过滤模式(可选) }); ``` ## 可用脚本 - `npm run build` - 编译 TypeScript 代码 - `npm run dev` - 监听模式编译 - `npm run install-hook` - 安装 Git hook - `node dist/install.js uninstall` - 卸载 Git hook ## 项目结构 ``` src/ ├── index.ts # 主入口文件 ├── types.ts # TypeScript 类型定义 ├── git-utils.ts # Git 操作工具类 ├── comment-scanner.ts # 代码注释扫描器 ├── logger.ts # 日志生成器 ├── hook.ts # Git hook 入口点 └── install.ts # Hook 安装器 ``` ## 日志文件命名 日志文件按以下格式命名: ``` YYYY-MM-DD_HH-MM-SS_<commit-hash>.json ``` 例如:`2024-01-01_12-30-45_abc12345.json` ## 自动清理 插件会自动保留最近的 100 个日志文件,超出部分会被自动删除。可以通过修改 `logger.ts` 中的 `cleanupLogs(100)` 来调整保留数量。 ## 卸载 如果需要卸载 Git hook: ```bash node dist/install.js uninstall ``` ## API 文档 ### GitLogger 类 #### 构造函数 ```typescript constructor(config?: Partial<LoggerConfig>) ``` **参数:** - `config` (可选): 配置选项,支持以下属性: - `logDir`: 日志文件保存目录,默认 `.git-logs` - `includeUnstaged`: 是否包含未暂存的更改,默认 `false` - `includeUntracked`: 是否包含未跟踪的文件,默认 `false` - `filePatterns`: 文件过滤模式,默认 `undefined` #### 方法 ##### generateLog() ```typescript async generateLog(): Promise<void> ``` 生成并保存当前提交的日志。 **返回值:** `Promise<void>` **异常:** - 如果不在 Git 仓库中,抛出错误 - 如果无法获取提交信息,抛出错误 ##### getAllLogs() ```typescript async getAllLogs(): Promise<CommitLog[]> ``` 获取所有日志文件。 **返回值:** `Promise<CommitLog[]>` - 按时间倒序排列的日志数组 ##### cleanupLogs() ```typescript async cleanupLogs(keepCount: number): Promise<void> ``` 清理旧日志文件。 **参数:** - `keepCount`: 保留的日志文件数量 **返回值:** `Promise<void>` ### GitUtils 类 #### 方法 ##### getCurrentCommitInfo() ```typescript async getCurrentCommitInfo(): Promise<Partial<CommitLog>> ``` 获取当前提交信息。 **返回值:** `Promise<Partial<CommitLog>>` - 包含提交人、时间、消息、哈希等信息 ##### getCurrentBranch() ```typescript async getCurrentBranch(): Promise<string> ``` 获取当前分支名称。 **返回值:** `Promise<string>` - 分支名称,如果无法获取则返回 'unknown' ##### getFileChanges() ```typescript async getFileChanges(): Promise<{ added: string[]; modified: string[]; deleted: string[]; renamed: Array<{ from: string; to: string }>; }> ``` 获取文件变更信息。 **返回值:** 包含新增、修改、删除、重命名文件的对象 ### CommentScanner 类 #### 方法 ##### scanDirectory() ```typescript async scanDirectory(dirPath: string): Promise<{ todos: CodeComment[]; wips: CodeComment[]; }> ``` 扫描目录下所有 JavaScript/TypeScript 文件。 **参数:** - `dirPath`: 要扫描的目录路径 **返回值:** 包含 TODO 和 WIP 注释的对象 ##### scanFile() ```typescript async scanFile(filePath: string): Promise<{ todos: CodeComment[]; wips: CodeComment[]; }> ``` 扫描单个文件。 **参数:** - `filePath`: 文件路径 **返回值:** 包含 TODO 和 WIP 注释的对象 ##### scanChangedFiles() ```typescript async scanChangedFiles(changedFiles: { added: string[]; modified: string[]; deleted: string[]; }): Promise<{ todos: CodeComment[]; wips: CodeComment[]; }> ``` 扫描变更的文件。 **参数:** - `changedFiles`: 变更文件列表 **返回值:** 包含 TODO 和 WIP 注释的对象 ## 开发指南 ### 环境要求 - Node.js >= 16.0.0 - Git >= 2.0.0 - TypeScript >= 5.0.0 ### 开发环境设置 1. **克隆项目** ```bash git clone <repository-url> cd git-logger-hook ``` 2. **安装依赖** ```bash npm install ``` 3. **编译项目** ```bash npm run build ``` 4. **开发模式** ```bash npm run dev # 监听模式编译 ``` ### 添加新功能 #### 1. 添加新的注释类型`src/comment-scanner.ts` 中添加新的正则表达式模式: ```typescript private newCommentPatterns = [ /\/\/\s*FIXME\s*:?\s*(.+)/gi, /\/\*\s*FIXME\s*:?\s*(.+?)\s*\*\//gi ]; ``` #### 2. 扩展日志数据结构`src/types.ts` 中添加新的字段: ```typescript export interface CommitLog { // ... 现有字段 newField?: string; // 新字段 } ``` #### 3. 添加新的 Git 操作`src/git-utils.ts` 中添加新方法: ```typescript async getNewGitInfo(): Promise<any> { // 实现新的 Git 操作 } ``` ### 测试 #### 单元测试 ```bash # 运行测试(需要先配置测试框架) npm test ``` #### 集成测试 ```bash # 创建测试提交 git add . git commit -m "测试提交" ``` #### 手动测试 ```bash # 直接运行 hook node dist/hook.js ``` ### 调试 #### 启用详细日志 ```typescript // 在 logger.ts 中添加 console.log('调试信息:', data); ``` #### 检查 Git Hook ```bash # 查看 pre-commit hook 内容 cat .git/hooks/pre-commit ``` #### 检查日志文件 ```bash # 查看最新日志 ls -la .git-logs/ cat .git-logs/最新日志文件.json ``` ### 性能优化 #### 1. 文件扫描优化 - 只扫描变更的文件,不扫描整个项目 - 使用文件扩展名过滤,减少不必要的文件读取 - 跳过 node_modules 等大型目录 #### 2. 内存优化 - 及时清理旧日志文件 - 使用流式处理大文件 - 避免在内存中保存大量数据 #### 3. 错误处理 - 提供降级策略 - 记录详细的错误信息 - 避免因单个文件错误导致整个流程失败 ## 故障排除 ### 常见问题 #### 1. Hook 不执行 **症状:** 提交时没有生成日志文件 **解决方案:** ```bash # 检查 hook 是否存在 ls -la .git/hooks/pre-commit # 重新安装 hook node dist/install.js install # 检查 hook 权限(Unix 系统) chmod +x .git/hooks/pre-commit ``` #### 2. 编译错误 **症状:** `npm run build` 失败 **解决方案:** ```bash # 清理并重新安装依赖 rm -rf node_modules package-lock.json npm install # 检查 TypeScript 配置 npx tsc --noEmit ``` #### 3. 权限错误 **症状:** 无法写入日志文件 **解决方案:** ```bash # 检查目录权限 ls -la .git-logs/ # 创建目录 mkdir -p .git-logs chmod 755 .git-logs ``` #### 4. Git 操作失败 **症状:** 无法获取 Git 信息 **解决方案:** ```bash # 检查是否在 Git 仓库中 git status # 检查 Git 配置 git config --list ``` ### 调试技巧 #### 1. 启用详细输出 ```typescript // 在代码中添加调试信息 console.log('当前目录:', process.cwd()); console.log('Git 状态:', await git.status()); ``` #### 2. 检查环境变量 ```bash # 检查 Node.js 版本 node --version # 检查 Git 版本 git --version # 检查环境变量 echo $PATH ``` #### 3. 查看错误日志 ```bash # 查看 Git hook 错误 git commit -m "测试" 2>&1 | tee error.log ``` ## 注释扫描功能 插件会自动扫描变更的 JavaScript/TypeScript 文件,提取以下类型的注释: ### 支持的注释格式 **TODO 注释:** - `// TODO: 描述内容` - `/* TODO: 描述内容 */` - `// @todo: 描述内容` - `/* @todo: 描述内容 */` **WIP 注释:** - `// WIP: 描述内容` - `/* WIP: 描述内容 */` - `// @wip: 描述内容` - `/* @wip: 描述内容 */` - `// WORK IN PROGRESS: 描述内容` - `/* WORK IN PROGRESS: 描述内容 */` ### 支持的文件类型 - `.js` - JavaScript 文件 - `.jsx` - React JSX 文件 - `.ts` - TypeScript 文件 - `.tsx` - React TypeScript 文件 - `.vue` - Vue 单文件组件 - `.svelte` - Svelte 组件 ### 注释信息结构 每个提取的注释包含: - `type`: 注释类型(TODO 或 WIP) - `content`: 注释内容 - `filePath`: 文件路径 - `lineNumber`: 行号 - `fullLine`: 完整的注释行 ## 注意事项 1. 确保在 Git 仓库根目录中运行安装命令 2. 需要先编译项目才能使用 hook 3. 在 Windows 系统上,hook 文件会同时创建 `.sh``.cmd` 版本 4. 日志文件默认保存在 `.git-logs` 目录中,该目录已被添加到 `.gitignore` 5. 注释扫描只针对变更的文件,不会扫描整个项目 ## 许可证 MIT License