106 lines
3 KiB
TypeScript
106 lines
3 KiB
TypeScript
import { Command } from 'commander'
|
|
import { spawn } from 'node:child_process'
|
|
import { access } from 'node:fs/promises'
|
|
import { join } from 'node:path'
|
|
import { homedir } from 'node:os'
|
|
import { colors, logError } from '../utils/output.js'
|
|
|
|
const BITCH_DATA_DIR = join(homedir(), '.local', 'share', 'bitch')
|
|
const COMMITS_SCRIPT_PATH = join(BITCH_DATA_DIR, 'commits-daemon.sh')
|
|
const OLD_COMMITS_PATH = join(homedir(), '.local', 'bin', 'commits')
|
|
|
|
/**
|
|
* Check if commits script exists at a path
|
|
*/
|
|
async function scriptExists(path: string): Promise<boolean> {
|
|
try {
|
|
await access(path)
|
|
return true
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Find the commits script location
|
|
*/
|
|
async function findCommitsScript(): Promise<string | null> {
|
|
// Check bitch's copy first
|
|
if (await scriptExists(COMMITS_SCRIPT_PATH)) {
|
|
return COMMITS_SCRIPT_PATH
|
|
}
|
|
// Fall back to standalone
|
|
if (await scriptExists(OLD_COMMITS_PATH)) {
|
|
return OLD_COMMITS_PATH
|
|
}
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* Run the commits script with the 'commit' subcommand
|
|
*/
|
|
function runCommit(scriptPath: string, args: string[]): void {
|
|
const child = spawn('bash', [scriptPath, 'commit', ...args], {
|
|
stdio: 'inherit',
|
|
env: process.env,
|
|
})
|
|
|
|
child.on('close', (code) => {
|
|
process.exit(code || 0)
|
|
})
|
|
|
|
child.on('error', (err) => {
|
|
logError(`Failed to run commit: ${err.message}`)
|
|
process.exit(1)
|
|
})
|
|
}
|
|
|
|
export function createCommitCommand(): Command {
|
|
const cmd = new Command('commit')
|
|
.description('One-shot AI-generated commit (uses daemon if running, otherwise standalone)')
|
|
.option('-A, --all', 'Commit all configured repos (default: current directory only)')
|
|
.option('-p, --push', 'Push after committing (default: true)')
|
|
.option('--no-push', 'Commit without pushing')
|
|
.option('-n, --dry-run', 'Preview what would be committed without committing')
|
|
.allowUnknownOption(true)
|
|
.action(async (options, command) => {
|
|
// Build args for the Python CLI
|
|
const args: string[] = []
|
|
|
|
if (options.all) {
|
|
args.push('--all')
|
|
}
|
|
if (options.push === false) {
|
|
args.push('--no-push')
|
|
}
|
|
if (options.dryRun) {
|
|
args.push('--dry-run')
|
|
}
|
|
|
|
// Add any additional unknown args
|
|
const extraArgs = command.args.filter((arg: string) => !['commit'].includes(arg))
|
|
args.push(...extraArgs)
|
|
|
|
// Find the commits script
|
|
const scriptPath = await findCommitsScript()
|
|
|
|
if (!scriptPath) {
|
|
logError('Commits script not found.')
|
|
console.log()
|
|
console.log('To install:')
|
|
console.log('1. Install auto-commit-service:')
|
|
console.log(colors.dim(' cd ~/Code/@applications/@ml/auto-commit-service'))
|
|
console.log(colors.dim(' pip install -e .'))
|
|
console.log()
|
|
console.log('2. Copy the commits CLI script to ~/.local/bin/commits')
|
|
console.log()
|
|
console.log('3. Run:')
|
|
console.log(colors.cyan(' bitch commits install'))
|
|
process.exit(1)
|
|
}
|
|
|
|
runCommit(scriptPath, args)
|
|
})
|
|
|
|
return cmd
|
|
}
|