UNPKG

@morodomi/ait3

Version:

AIT³ Development Platform - AI + Ticket + Test + Tool driven development methodology

100 lines (99 loc) 3.77 kB
import { simpleGit } from 'simple-git'; export class SimpleGitService { git; constructor(basePath) { this.git = simpleGit(basePath); } async isRepository() { try { return await this.git.checkIsRepo(); } catch { return false; } } async hasUncommittedChanges() { const status = await this.git.status(); return status.files.length > 0; } async fetch() { await this.git.fetch(); } async findBranches(pattern) { const branchSummary = await this.git.branch(['-a']); return branchSummary.all .filter(branch => branch.includes(pattern)) .map(branch => this.cleanBranchName(branch)); } cleanBranchName(branch) { // Convert remotes/origin/feature/xxx to origin/feature/xxx if (branch.startsWith('remotes/')) { return branch.replace('remotes/', ''); } return branch; } async createBranch(name) { await this.git.checkoutBranch(name, 'HEAD'); } async checkout(name) { await this.git.checkout(name); } async getCurrentBranch() { const result = await this.git.revparse(['--abbrev-ref', 'HEAD']); return result.trim(); } async getMergeBase(branch1, branch2) { const result = await this.git.raw(['merge-base', branch1, branch2]); return result.trim(); } async getCommits(base) { const log = await this.git.log({ from: base, to: 'HEAD' }); return log.all.map(commit => ({ hash: commit.hash, message: commit.message })); } async moveFile(oldPath, newPath) { try { await this.git.raw(['mv', oldPath, newPath]); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); // Enhanced error classification for better debugging if (errorMessage.includes('does not exist in index')) { throw new Error(`Git file not tracked: ${oldPath} is not under version control`); } if (errorMessage.includes('Permission denied')) { throw new Error(`Permission denied: Cannot move ${oldPath} to ${newPath}`); } if (errorMessage.includes('destination already exists')) { throw new Error(`Destination exists: ${newPath} already exists`); } if (errorMessage.includes('fatal: not a git repository')) { throw new Error('Not a Git repository: Cannot use git mv outside a Git repository'); } // Re-throw original error with additional context throw new Error(`Git move failed: ${errorMessage}`); } } async removeFile(filePath) { try { await this.git.raw(['rm', filePath]); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); // Enhanced error classification for better debugging if (errorMessage.includes('does not exist in index')) { throw new Error(`Git file not tracked: ${filePath} is not under version control`); } if (errorMessage.includes('Permission denied')) { throw new Error(`Permission denied: Cannot remove ${filePath}`); } if (errorMessage.includes('fatal: not a git repository')) { throw new Error('Not a Git repository: Cannot use git rm outside a Git repository'); } // Re-throw original error with additional context throw new Error(`Git remove failed: ${errorMessage}`); } } }