UNPKG

@sbeeredd04/auto-git

Version:

AI-powered Git automation with intelligent commit decisions using Gemini function calling, smart diff optimization, push control, and enhanced interactive terminal session with persistent command history

108 lines (96 loc) 3.07 kB
import { execa } from 'execa'; import logger from '../utils/logger.js'; export async function isGitRepository() { try { await execa('git', ['rev-parse', '--git-dir']); return true; } catch { return false; } } export async function hasChanges() { try { const { stdout } = await execa('git', ['status', '--porcelain']); return stdout.trim().length > 0; } catch (error) { throw new Error(`Failed to check git status: ${error.message}`); } } export async function getDiff() { try { // Get both staged and unstaged changes const [unstaged, staged] = await Promise.all([ execa('git', ['diff']).then(r => r.stdout).catch(() => ''), execa('git', ['diff', '--cached']).then(r => r.stdout).catch(() => '') ]); let diff = ''; if (unstaged) diff += `Unstaged changes:\n${unstaged}\n\n`; if (staged) diff += `Staged changes:\n${staged}\n\n`; // If no diff from standard commands, check for untracked files if (!diff.trim()) { const { stdout: untracked } = await execa('git', ['ls-files', '--others', '--exclude-standard']); if (untracked.trim()) { diff = `New untracked files:\n${untracked}`; } } return diff.trim(); } catch (error) { throw new Error(`Failed to get git diff: ${error.message}`); } } export async function getStatus() { try { const { stdout } = await execa('git', ['status', '--porcelain']); return stdout; } catch (error) { throw new Error(`Failed to get git status: ${error.message}`); } } export async function addAll() { try { logger.debug('Staging all changes with git add .'); await execa('git', ['add', '.']); } catch (error) { throw new Error(`Failed to stage changes: ${error.message}`); } } export async function commit(message) { try { logger.debug(`Executing git commit with message: "${message}"`); await execa('git', ['commit', '-m', message]); } catch (error) { throw new Error(`Failed to commit: ${error.message}`); } } export async function push() { try { logger.debug('Pushing changes to remote repository'); await execa('git', ['push']); } catch (error) { // Check if it's because no upstream is set if (error.message.includes('no upstream branch')) { const { stdout } = await execa('git', ['branch', '--show-current']); const currentBranch = stdout.trim(); logger.debug(`Setting upstream for branch "${currentBranch}"`); await execa('git', ['push', '--set-upstream', 'origin', currentBranch]); } else { throw new Error(`Failed to push: ${error.message}`); } } } export async function getCurrentBranch() { try { const { stdout } = await execa('git', ['branch', '--show-current']); return stdout.trim(); } catch (error) { throw new Error(`Failed to get current branch: ${error.message}`); } } export async function hasRemote() { try { const { stdout } = await execa('git', ['remote']); return stdout.trim().length > 0; } catch { return false; } }