Skip to content

Commit e488f54

Browse files
✨ Alpha 5: CommitManager implemented with full commit and staging functionality
1 parent 5680b54 commit e488f54

File tree

2 files changed

+248
-7
lines changed

2 files changed

+248
-7
lines changed

src/config/commandsList.ts

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,28 +180,78 @@ export const COMMANDS_LIST: PlainGitCommand[] = [
180180
handler: 'BranchManager.showAndList',
181181
},
182182

183+
// 📝 Commit Operations
183184
// 📝 Commit Operations
184185
{
185186
category: 'Commit',
186187
name: '🧩 Stage all changes',
187188
command: 'git add .',
188-
description: 'Add all modified files to staging.',
189+
description: 'Stage all modified and untracked files.',
189190
handler: 'CommitManager.stageAll',
190191
},
191192
{
192193
category: 'Commit',
193-
name: '📝 Commit all staged changes',
194+
name: '🧩 Stage specific files',
195+
command: 'git add <file>',
196+
description: 'Interactively select specific files to stage.',
197+
handler: 'CommitManager.stageFiles',
198+
},
199+
{
200+
category: 'Commit',
201+
name: '🗑️ Unstage files',
202+
command: 'git restore --staged <file>',
203+
description: 'Remove files from staging area (unstage).',
204+
handler: 'CommitManager.unstageFiles',
205+
},
206+
{
207+
category: 'Commit',
208+
name: '📝 Commit staged changes',
194209
command: "git commit -m '<message>'",
195-
description: 'Commit staged changes with a message.',
210+
description: 'Commit all staged changes with a message.',
196211
handler: 'CommitManager.commitChanges',
197212
},
198213
{
199214
category: 'Commit',
200-
name: '📜 Show commit history',
201-
command: 'git log --oneline',
202-
description: 'Show a compact list of previous commits.',
215+
name: '✏️ Amend last commit message',
216+
command: "git commit --amend -m '<new-message>'",
217+
description: 'Edit or replace the most recent commit message.',
218+
handler: 'CommitManager.amendLastCommit',
219+
},
220+
{
221+
category: 'Commit',
222+
name: '↩️ Undo last commit (keep changes)',
223+
command: 'git reset --soft HEAD~1',
224+
description: 'Undo the most recent commit but keep changes staged.',
225+
handler: 'CommitManager.undoLastCommit',
226+
},
227+
{
228+
category: 'Commit',
229+
name: '📜 Show last commit details',
230+
command: 'git show HEAD',
231+
description: 'View details of the most recent commit.',
232+
handler: 'CommitManager.showLastCommit',
233+
},
234+
{
235+
category: 'Commit',
236+
name: '📚 View commit history (graph)',
237+
command: 'git log --oneline --graph --decorate',
238+
description: 'Display commit history in graphical format.',
203239
handler: 'CommitManager.showLog',
204240
},
241+
{
242+
category: 'Commit',
243+
name: '🔍 View unstaged changes (diff)',
244+
command: 'git diff',
245+
description: 'Show changes not yet staged for commit.',
246+
handler: 'CommitManager.showDiff',
247+
},
248+
{
249+
category: 'Commit',
250+
name: '🔍 View staged changes (cached diff)',
251+
command: 'git diff --cached',
252+
description: 'Show differences between staged and last commit.',
253+
handler: 'CommitManager.showStagedDiff',
254+
},
205255

206256
// 🚀 Remote Operations
207257
{

src/managers/CommitManager.ts

Lines changed: 192 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,192 @@
1-
export const CommitManager = {}
1+
/**
2+
* 📝 CommitManager.ts
3+
* -------------------------------------------------------------
4+
* Handles all commit-related operations such as adding,
5+
* committing, viewing logs, diffs, and undoing commits.
6+
* -------------------------------------------------------------
7+
*/
8+
9+
import inquirer from 'inquirer';
10+
import chalk from 'chalk';
11+
import { execSync } from 'child_process';
12+
import { GitExecutor } from '../core/GitExecutor';
13+
import { Logger } from '../utils/Logger';
14+
15+
/**
16+
* Helper: get list of modified/untracked files
17+
*/
18+
function getModifiedFiles(): string[] {
19+
try {
20+
const output = execSync('git status --porcelain', { encoding: 'utf-8' });
21+
return output
22+
.split('\n')
23+
.map((l) => l.trim())
24+
.filter(Boolean)
25+
.map((l) => l.replace(/^.. /, ''));
26+
} catch {
27+
return [];
28+
}
29+
}
30+
31+
export const CommitManager = {
32+
/**
33+
* Stage all files (git add .)
34+
*/
35+
async stageAll() {
36+
Logger.info('🧩 Staging all modified and new files...');
37+
await GitExecutor.run('git add .');
38+
Logger.success('✅ All files staged successfully!');
39+
},
40+
41+
/**
42+
* Stage specific files interactively
43+
*/
44+
async stageFiles() {
45+
const files = getModifiedFiles();
46+
if (!files.length) {
47+
Logger.info('⚠️ No modified or untracked files found.');
48+
return;
49+
}
50+
51+
const { selected } = await inquirer.prompt([
52+
{
53+
type: 'checkbox',
54+
name: 'selected',
55+
message: 'Select files to stage:',
56+
choices: files,
57+
},
58+
]);
59+
60+
if (selected.length === 0) {
61+
Logger.info('No files selected.');
62+
return;
63+
}
64+
65+
const cmd = `git add ${selected.join(' ')}`;
66+
Logger.info(`🧩 Staging ${selected.length} file(s)...`);
67+
await GitExecutor.run(cmd);
68+
Logger.success(`✅ Staged ${selected.length} file(s).`);
69+
},
70+
71+
/**
72+
* Unstage files (git restore --staged)
73+
*/
74+
async unstageFiles() {
75+
const files = getModifiedFiles();
76+
if (!files.length) {
77+
Logger.info('⚠️ No files to unstage.');
78+
return;
79+
}
80+
81+
const { selected } = await inquirer.prompt([
82+
{
83+
type: 'checkbox',
84+
name: 'selected',
85+
message: 'Select files to unstage:',
86+
choices: files,
87+
},
88+
]);
89+
90+
if (selected.length === 0) {
91+
Logger.info('No files selected.');
92+
return;
93+
}
94+
95+
const cmd = `git restore --staged ${selected.join(' ')}`;
96+
Logger.info(`🗑️ Unstaging ${selected.length} file(s)...`);
97+
await GitExecutor.run(cmd);
98+
Logger.success(`✅ Unstaged ${selected.length} file(s).`);
99+
},
100+
101+
/**
102+
* Commit staged files with message
103+
*/
104+
async commitChanges() {
105+
const { message } = await inquirer.prompt([
106+
{ type: 'input', name: 'message', message: '📝 Enter commit message:' },
107+
]);
108+
109+
if (!message.trim()) {
110+
Logger.info('⚠️ Commit message cannot be empty.');
111+
return;
112+
}
113+
114+
const cmd = `git commit -m "${message}"`;
115+
Logger.info('💾 Committing changes...');
116+
await GitExecutor.run(cmd);
117+
Logger.success('✅ Commit completed!');
118+
},
119+
120+
/**
121+
* Amend last commit message (fix last commit)
122+
*/
123+
async amendLastCommit() {
124+
const { message } = await inquirer.prompt([
125+
{
126+
type: 'input',
127+
name: 'message',
128+
message: 'Enter new commit message for the last commit:',
129+
},
130+
]);
131+
132+
const cmd = `git commit --amend -m "${message}"`;
133+
Logger.info('✏️ Amending last commit...');
134+
await GitExecutor.run(cmd);
135+
Logger.success('✅ Last commit amended successfully!');
136+
},
137+
138+
/**
139+
* Undo last commit (keep changes staged)
140+
*/
141+
async undoLastCommit() {
142+
Logger.info('↩️ Undoing last commit (keeping changes)...');
143+
await GitExecutor.run('git reset --soft HEAD~1');
144+
Logger.success('✅ Last commit undone. Changes remain staged.');
145+
},
146+
147+
/**
148+
* Show last commit details
149+
*/
150+
async showLastCommit() {
151+
Logger.info('📜 Showing last commit details...');
152+
await GitExecutor.run('git show HEAD --stat --pretty=medium');
153+
},
154+
155+
/**
156+
* View commit history (graph)
157+
*/
158+
async showLog() {
159+
const { format } = await inquirer.prompt([
160+
{
161+
type: 'list',
162+
name: 'format',
163+
message: 'Select log format:',
164+
choices: [
165+
{ name: 'Compact (oneline)', value: '--oneline' },
166+
{ name: 'Detailed (default)', value: '' },
167+
{ name: 'Graph view', value: '--oneline --graph --decorate' },
168+
],
169+
},
170+
]);
171+
172+
const cmd = `git log ${format}`;
173+
Logger.info('📜 Viewing commit history...');
174+
await GitExecutor.run(cmd);
175+
},
176+
177+
/**
178+
* Show unstaged diff
179+
*/
180+
async showDiff() {
181+
Logger.info('🔍 Showing unstaged changes...');
182+
await GitExecutor.run('git diff');
183+
},
184+
185+
/**
186+
* Show staged diff
187+
*/
188+
async showStagedDiff() {
189+
Logger.info('🔍 Showing staged (cached) changes...');
190+
await GitExecutor.run('git diff --cached');
191+
},
192+
};

0 commit comments

Comments
 (0)