/** * Git 管理器 * * 整合 GitRepo、AutoCommitManager、MessageGenerator、UndoManager * 提供统一的 Git 集成接口 */ import type { GitConfig, GitStatus, CommitResult, UndoResult, UndoEntry, DiffResult, CommitInfo, GitEvent, GitEventListener, } from './types.js'; import { DEFAULT_GIT_CONFIG } from './types.js'; import { GitRepo } from './repo.js'; import { AutoCommitManager } from './auto-commit.js'; import { MessageGenerator } from './message-generator.js'; import { UndoManager } from './undo-manager.js'; export class GitManager { private repo: GitRepo; private autoCommit: AutoCommitManager; private messageGenerator: MessageGenerator; private undoManager: UndoManager; private config: GitConfig; private workdir: string; /** 事件监听器 */ private eventListeners: GitEventListener[] = []; /** 是否已初始化 */ private initialized: boolean = false; constructor(workdir: string, config?: Partial) { this.workdir = workdir; this.config = { ...DEFAULT_GIT_CONFIG, ...config }; // 创建组件 this.repo = new GitRepo(workdir, this.config); this.messageGenerator = new MessageGenerator(this.config.messageFormat); this.autoCommit = new AutoCommitManager( this.repo, this.config.autoCommit, this.messageGenerator ); this.undoManager = new UndoManager(this.repo, this.config.undo); // 设置自动提交回调 this.autoCommit.setOnCommit((result) => { if (result.success && result.shortHash && result.message) { // 记录到 undo 历史 const files = this.autoCommit.getPendingFiles(); this.undoManager.recordCommit( result.hash!, result.shortHash, result.message, files ); // 发送事件 this.emitEvent('commit', { hash: result.shortHash, message: result.message, auto: true, }); } }); } /** * 初始化 Git 管理器 */ async initialize(): Promise { if (!this.config.enabled) { return false; } const isRepo = await this.repo.initialize(); this.initialized = isRepo; return isRepo; } /** * 检查是否已初始化 */ isInitialized(): boolean { return this.initialized; } /** * 获取仓库状态 */ async getStatus(): Promise { return this.repo.getStatus(); } /** * 文件变更后调用(由工具执行器调用) */ async onFileChanged( filePath: string, changeType: 'create' | 'modify' | 'delete' ): Promise { if (!this.initialized || !this.config.enabled) { return; } await this.autoCommit.onFileChanged(filePath, changeType); } /** * 手动提交 */ async commit(options: { message?: string; files?: string[]; all?: boolean; } = {}): Promise { if (!this.initialized) { return { success: false, error: 'Git not initialized' }; } // 如果有待提交的文件,先处理 if (this.autoCommit.hasPendingFiles()) { await this.autoCommit.flush(); } // 获取差异用于生成消息 const diff = await this.repo.getDiff({ staged: options.all }); const message = options.message || this.messageGenerator.generate(diff); const result = await this.repo.commit({ message, files: options.files, all: options.all, aiEdits: true, }); if (result.success && result.shortHash && result.message) { // 记录到 undo 历史 const files = options.files || []; this.undoManager.recordCommit( result.hash!, result.shortHash, result.message, files ); // 发送事件 this.emitEvent('commit', { hash: result.shortHash, message: result.message, auto: false, }); } return result; } /** * 撤销上一次 AI 提交 */ async undo(): Promise { if (!this.initialized) { return { success: false, message: 'Git not initialized' }; } const result = await this.undoManager.undo(); if (result.success) { this.emitEvent('undo', { hash: result.commitHash, files: result.restoredFiles, }); } return result; } /** * 获取 undo 预览 */ getUndoPreview(): UndoEntry | null { return this.undoManager.getUndoPreview(); } /** * 获取 undo 历史 */ getUndoHistory(): UndoEntry[] { return this.undoManager.getHistory(); } /** * 检查是否可以 undo */ async canUndo(): Promise<{ canUndo: boolean; reason?: string }> { return this.undoManager.canUndo(); } /** * 获取差异 */ async getDiff(options: { staged?: boolean; file?: string; commit?: string; } = {}): Promise { return this.repo.getDiff(options); } /** * 获取最近的提交 */ async getRecentCommits(count: number = 10): Promise { return this.repo.getRecentCommits(count); } /** * 获取当前分支 */ async getCurrentBranch(): Promise { return this.repo.getCurrentBranch(); } /** * 强制刷新待提交 */ async flushPendingCommits(): Promise { return this.autoCommit.flush(); } /** * 获取待提交文件 */ getPendingFiles(): string[] { return this.autoCommit.getPendingFiles(); } /** * 添加事件监听器 */ addEventListener(listener: GitEventListener): void { this.eventListeners.push(listener); } /** * 移除事件监听器 */ removeEventListener(listener: GitEventListener): void { const index = this.eventListeners.indexOf(listener); if (index !== -1) { this.eventListeners.splice(index, 1); } } /** * 发送事件 */ private emitEvent(type: GitEvent['type'], data: unknown): void { const event: GitEvent = { type, timestamp: Date.now(), data, }; for (const listener of this.eventListeners) { try { listener(event); } catch (error) { console.error('Git event listener error:', error); } } } /** * 获取配置 */ getConfig(): GitConfig { return { ...this.config }; } /** * 更新配置 */ updateConfig(config: Partial): void { this.config = { ...this.config, ...config }; } } // 全局 Git 管理器实例 let gitManager: GitManager | null = null; /** * 获取全局 Git 管理器 */ export function getGitManager(): GitManager | null { return gitManager; } /** * 初始化全局 Git 管理器 */ export async function initGitManager( workdir: string, config?: Partial ): Promise { gitManager = new GitManager(workdir, config); const initialized = await gitManager.initialize(); if (!initialized) { gitManager = null; return null; } return gitManager; } /** * 重置全局 Git 管理器 */ export function resetGitManager(): void { gitManager = null; }