supernal-coding
Version:
Comprehensive development workflow CLI with kanban task management, project validation, git safety hooks, and cross-project distribution system
128 lines (105 loc) • 3.46 kB
JavaScript
// safe-git-wrapper.js - Git command wrapper with workflow protection
// Part of enhanced workflow guard system
const { execSync, spawn } = require('child_process');
const path = require('path');
const chalk = require('chalk');
class SafeGitWrapper {
constructor() {
this.projectRoot = process.cwd();
this.verbose = process.argv.includes('--verbose') || process.env.SC_VERBOSE === 'true';
}
/**
* Main wrapper for git commands
*/
async executeGitCommand(args) {
const command = args[0];
const gitArgs = args.slice(1);
// Intercept 'git add' commands
if (command === 'add') {
return this.handleGitAdd(gitArgs);
}
// For other git commands, pass through directly
return this.passThrough(['git', command, ...gitArgs]);
}
/**
* Handle git add with workflow protection
*/
async handleGitAdd(args) {
try {
// Check if --force flag is present
const hasForce = args.includes('--force') || args.includes('-f');
if (hasForce) {
// Remove --force flag and pass to real git
const cleanArgs = args.filter(arg => arg !== '--force' && arg !== '-f');
if (this.verbose) {
console.log(chalk.yellow('⚠️ Force flag detected, bypassing workflow guard'));
}
return this.passThrough(['git', 'add', ...cleanArgs]);
}
// Run pre-add validation
const WorkflowGuard = require('../development/workflow-guard');
const guard = new WorkflowGuard({
projectRoot: this.projectRoot,
verbose: this.verbose
});
// Set the files to be added for the guard
process.argv = ['node', 'workflow-guard.js', 'pre-add', ...args];
try {
await guard.execute('pre-add');
// If validation passes, execute real git add
return this.passThrough(['git', 'add', ...args]);
} catch (error) {
// Validation failed, exit with error
console.error(chalk.red('❌ Git add blocked by workflow guard'));
if (this.verbose) {
console.error(error.message);
}
process.exit(1);
}
} catch (error) {
console.error(chalk.red('❌ Error in git add wrapper:'), error.message);
process.exit(1);
}
}
/**
* Pass command through to real git
*/
passThrough(command) {
try {
const result = spawn(command[0], command.slice(1), {
stdio: 'inherit',
cwd: this.projectRoot
});
result.on('close', (code) => {
process.exit(code);
});
result.on('error', (error) => {
console.error(chalk.red('❌ Git command failed:'), error.message);
process.exit(1);
});
} catch (error) {
console.error(chalk.red('❌ Failed to execute git command:'), error.message);
process.exit(1);
}
}
}
// CLI interface
async function main() {
const args = process.argv.slice(2);
if (args.length === 0) {
console.error(chalk.red('❌ No git command provided'));
console.log(chalk.blue('Usage: safe-git <command> [args...]'));
process.exit(1);
}
const wrapper = new SafeGitWrapper();
await wrapper.executeGitCommand(args);
}
// Execute if called directly
if (require.main === module) {
main().catch(error => {
console.error(chalk.red('❌ Safe git wrapper error:'), error.message);
process.exit(1);
});
}
module.exports = { SafeGitWrapper };