-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathgflow.js
More file actions
executable file
·207 lines (182 loc) · 8.26 KB
/
Copy pathgflow.js
File metadata and controls
executable file
·207 lines (182 loc) · 8.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/env node
/**
* gflow - Enhanced Complete Git Workflow
*
* Complete git workflow: add → commit → push
*
* Usage:
* gflow "commit message" - Add ALL changes, commit, push
* gflow "commit message" file1.js file2.js - Add SPECIFIC files, commit, push
* gflow "commit message" src/ docs/ - Add SPECIFIC folders, commit, push
* gflow "commit message" file.js src/ README.md - Add MIX of files and folders
* gflow --help - Show this help
*
* Logic:
* - First argument: commit message (required, must be quoted)
* - Remaining arguments: files/folders to add (optional)
* - If no files specified: adds all changes (git add .)
* - Always commits and pushes after adding
*
* Features:
* - Smart file validation (checks if files exist)
* - Repository safety checks
* - Detailed progress display with colors
* - Error handling and recovery suggestions
*/
import { execSync } from 'child_process';
import path from 'path';
import chalk from 'chalk';
import fs from 'fs';
// Check if we're in a git repository
function validateRepository() {
try {
execSync('git rev-parse --is-inside-work-tree', { stdio: 'pipe' });
return true;
} catch (error) {
console.log(chalk.red('❌ Error: Not a git repository'));
console.log(chalk.yellow('💡 Initialize with: git init'));
return false;
}
}
// Execute git command with progress display
function runGitCommand(command, description, showOutput = false) {
try {
console.log(chalk.cyan(` 🔧 Running: ${command}`));
const result = execSync(command, {
encoding: 'utf8',
stdio: showOutput ? 'inherit' : 'pipe'
});
console.log(chalk.green(' ✓ Operation completed successfully!'));
return { success: true, output: result };
} catch (error) {
console.log(chalk.red(` ❌ Failed: ${error.message}`));
return { success: false, error: error.message };
}
}
// Show enhanced help
function showHelp() {
console.log(chalk.bold.magenta(`
⚡ gflow - Enhanced Complete Git Workflow
`));
console.log(chalk.cyan('📋 SYNTAX:'));
console.log(` ${chalk.green('gflow "commit message" [files/folders...]')}`);
console.log('');
console.log(chalk.cyan('📖 LOGIC:'));
console.log(` ${chalk.blue('1.')} First argument = commit message (required, quoted)`);
console.log(` ${chalk.blue('2.')} Remaining arguments = files/folders to add (optional)`);
console.log(` ${chalk.blue('3.')} If no files given → adds ALL changes (git add .)`);
console.log(` ${chalk.blue('4.')} Always commits and pushes after adding`);
console.log(chalk.cyan('\n💡 EXAMPLES:'));
console.log(` ${chalk.green('gflow "Initial commit"')} ${chalk.gray('→ Add ALL changes')}`);
console.log(` ${chalk.green('gflow "Fix bug" src/auth.js')} ${chalk.gray('→ Add ONLY src/auth.js')}`);
console.log(` ${chalk.green('gflow "Update docs" README.md docs/')} ${chalk.gray('→ Add README.md + docs/ folder')}`);
console.log(` ${chalk.green('gflow "Release" src/ tests/ package.json')} ${chalk.gray('→ Add multiple items')}`);
console.log(chalk.cyan('\n🔄 WORKFLOW:'));
console.log(` ${chalk.blue('①')} Validate git repository`);
console.log(` ${chalk.blue('②')} Add files (specific files OR all changes)`);
console.log(` ${chalk.blue('③')} Commit with message`);
console.log(` ${chalk.blue('④')} Push to remote`);
console.log(chalk.cyan('\n⚠️ IMPORTANT:'));
console.log(` ${chalk.yellow('•')} Commit message MUST be quoted`);
console.log(` ${chalk.yellow('•')} Files/folders are validated before adding`);
console.log(` ${chalk.yellow('•')} Process stops on any error for safety`);
console.log(` ${chalk.yellow('•')} No files specified = add everything`);
console.log(chalk.gray('\n═══════════════════════════════════════════════════════════'));
}
// Main workflow function
async function main() {
const args = process.argv.slice(2);
// Help functionality
if (args.includes('-h') || args.includes('--help') || args.length === 0) {
showHelp();
return;
}
// Validate repository
if (!validateRepository()) {
process.exit(1);
}
// Extract commit message (first argument) and files (remaining arguments)
const commitMessage = args[0];
const filesToAdd = args.slice(1); // Remaining arguments are files/folders
// Validate commit message
if (!commitMessage || commitMessage.trim().length < 3) {
console.log(chalk.red('❌ Error: Commit message is required and must be at least 3 characters'));
console.log(chalk.yellow('💡 Usage: gflow "your commit message" [files/folders...]'));
console.log(chalk.gray('💡 Or run: gflow --help for more information'));
process.exit(1);
}
console.log(chalk.bold.magenta('\n⚡ Starting Complete Git Workflow...'));
console.log(chalk.gray('══════════════════════════════════════════════════'));
console.log(chalk.blue('📝 Commit message:'), chalk.white(`"${commitMessage}"`));
if (filesToAdd.length > 0) {
console.log(chalk.blue('📁 Files to add:'), chalk.white(filesToAdd.join(', ')));
} else {
console.log(chalk.blue('📁 Adding:'), chalk.white('All changes (git add .)'));
}
try {
// Step 1: Add files or all changes
console.log(chalk.cyan.bold('\n📁 Step 1: Adding changes...'));
if (filesToAdd.length > 0) {
// Validate that files exist before adding
const nonExistentFiles = [];
for (const file of filesToAdd) {
if (!fs.existsSync(file)) {
nonExistentFiles.push(file);
}
}
if (nonExistentFiles.length > 0) {
console.log(chalk.yellow(`⚠️ Warning: These files don't exist: ${nonExistentFiles.join(', ')}`));
console.log(chalk.yellow(' Continuing with existing files only...'));
}
// Add existing files
const existingFiles = filesToAdd.filter(file => fs.existsSync(file));
if (existingFiles.length > 0) {
const addCommand = `git add ${existingFiles.join(' ')}`;
const result = runGitCommand(addCommand, `Adding ${existingFiles.length} file(s)`);
if (!result.success) {
throw new Error(`Failed to add files: ${result.error}`);
}
} else {
console.log(chalk.red('❌ No valid files to add'));
process.exit(1);
}
} else {
// Add all changes
const result = runGitCommand('git add .', 'Adding all changes');
if (!result.success) {
throw new Error(`Failed to add changes: ${result.error}`);
}
}
console.log(chalk.green('✅ Changes added to staging area'));
// Step 2: Commit changes
console.log(chalk.cyan.bold('\n💾 Step 2: Committing changes...'));
const commitResult = runGitCommand(`git commit -m "${commitMessage}"`, 'Creating commit', true);
if (!commitResult.success) {
throw new Error(`Failed to commit: ${commitResult.error}`);
}
console.log(chalk.green('✅ Changes committed successfully'));
// Step 3: Push to remote
console.log(chalk.cyan.bold('\n🚀 Step 3: Pushing to remote repository...'));
const pushResult = runGitCommand('git push', 'Pushing to remote', true);
if (!pushResult.success) {
throw new Error(`Failed to push: ${pushResult.error}`);
}
console.log(chalk.green('✅ Changes pushed to remote'));
// Success message
console.log(chalk.green.bold('\n🎉 Complete workflow finished successfully!'));
console.log(chalk.blue('💡 Your changes are now live on the remote repository'));
} catch (error) {
console.log(chalk.red.bold('\n❌ Workflow failed!'));
console.log(chalk.red(`Error: ${error.message}`));
console.log(chalk.yellow('\n💡 You may need to resolve the issue and try again'));
console.log(chalk.gray(' Check git status and resolve any conflicts'));
process.exit(1);
}
}
// Run as standalone script
if (import.meta.url === `file://${process.argv[1]}`) {
main().catch(error => {
console.error(chalk.red('❌ Unexpected error:'), error.message);
process.exit(1);
});
}