Skip to content

Commit 2184638

Browse files
committed
git: pimp up CommandCenter
1 parent bd8a10e commit 2184638

1 file changed

Lines changed: 79 additions & 57 deletions

File tree

extensions/git/src/commands.ts

Lines changed: 79 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,8 @@
88
import { Uri, commands, scm, Disposable, SCMResourceGroup, SCMResource, window, workspace, QuickPickItem, OutputChannel } from 'vscode';
99
import { IRef, RefType } from './git';
1010
import { Model, Resource, Status } from './model';
11-
import { decorate } from 'core-decorators';
1211
import * as path from 'path';
1312

14-
function catchErrors(fn: (...args) => Promise<any>): (...args) => void {
15-
return (...args) => fn.call(this, ...args).catch(async err => {
16-
if (err.gitErrorCode) {
17-
let message: string;
18-
19-
switch (err.gitErrorCode) {
20-
case 'DirtyWorkTree':
21-
message = 'Please clean your repository working tree before checkout.';
22-
break;
23-
default:
24-
message = (err.stderr || err.message).replace(/^error: /, '');
25-
break;
26-
}
27-
28-
const outputChannel = this.outputChannel as OutputChannel;
29-
const openOutputChannelChoice = 'Open Git Log';
30-
const choice = await window.showErrorMessage(message, openOutputChannelChoice);
31-
32-
if (choice === openOutputChannelChoice) {
33-
outputChannel.show();
34-
}
35-
} else {
36-
console.error(err);
37-
}
38-
});
39-
}
40-
4113
function resolveGitURI(uri: Uri): SCMResource | SCMResourceGroup | undefined {
4214
if (uri.authority !== 'git') {
4315
return;
@@ -97,32 +69,71 @@ class CheckoutRemoteHeadItem extends CheckoutItem {
9769

9870
export class CommandCenter {
9971

100-
private disposables: Disposable[] = [];
72+
private static readonly Commands: { commandId: string; method: any; }[] = [];
73+
private static Command(commandId: string): Function {
74+
return (target: any, key: string, descriptor: any) => {
75+
if (!(typeof descriptor.value === 'function')) {
76+
throw new Error('not supported');
77+
}
78+
79+
CommandCenter.Commands.push({ commandId, method: descriptor.value });
80+
};
81+
}
82+
83+
private static CatchErrors(target: any, key: string, descriptor: any): void {
84+
if (!(typeof descriptor.value === 'function')) {
85+
throw new Error('not supported');
86+
}
87+
88+
const fn = descriptor.value;
89+
90+
descriptor.value = function (...args: any[]) {
91+
fn.apply(this, args).catch(async err => {
92+
if (err.gitErrorCode) {
93+
let message: string;
94+
95+
switch (err.gitErrorCode) {
96+
case 'DirtyWorkTree':
97+
message = 'Please clean your repository working tree before checkout.';
98+
break;
99+
default:
100+
message = (err.stderr || err.message).replace(/^error: /, '');
101+
break;
102+
}
103+
104+
const outputChannel = this.outputChannel as OutputChannel;
105+
const openOutputChannelChoice = 'Open Git Log';
106+
const choice = await window.showErrorMessage(message, openOutputChannelChoice);
107+
108+
if (choice === openOutputChannelChoice) {
109+
outputChannel.show();
110+
}
111+
} else if (err.message) {
112+
window.showErrorMessage(err.message);
113+
console.error(err);
114+
} else {
115+
console.error(err);
116+
}
117+
});
118+
};
119+
}
120+
121+
private disposables: Disposable[];
101122

102123
constructor(private model: Model, private outputChannel: OutputChannel) {
103-
this.disposables.push(
104-
commands.registerCommand('git.refresh', this.refresh, this),
105-
commands.registerCommand('git.openChange', this.openChange, this),
106-
commands.registerCommand('git.openFile', this.openFile, this),
107-
commands.registerCommand('git.stage', this.stage, this),
108-
commands.registerCommand('git.stageAll', this.stageAll, this),
109-
commands.registerCommand('git.unstage', this.unstage, this),
110-
commands.registerCommand('git.unstageAll', this.unstageAll, this),
111-
commands.registerCommand('git.clean', this.clean, this),
112-
commands.registerCommand('git.cleanAll', this.cleanAll, this),
113-
commands.registerCommand('git.checkout', this.checkout, this),
114-
commands.registerCommand('git.sync', this.sync, this),
115-
commands.registerCommand('git.publish', this.publish, this),
116-
commands.registerCommand('git.showOutput', this.showOutput, this),
117-
);
124+
this.disposables = CommandCenter.Commands
125+
.map(({ commandId, method }) => commands.registerCommand(commandId, method, this));
118126
}
119127

120-
@decorate(catchErrors)
128+
@CommandCenter.Command('git.refresh')
129+
@CommandCenter.CatchErrors
121130
async refresh(): Promise<void> {
122-
return await this.model.update();
131+
await this.model.update();
132+
throw new Error('OH MY LORD');
123133
}
124134

125-
@decorate(catchErrors)
135+
@CommandCenter.Command('git.openChange')
136+
@CommandCenter.CatchErrors
126137
async openChange(uri: Uri): Promise<void> {
127138
const resource = resolveGitResource(uri);
128139

@@ -200,7 +211,8 @@ export class CommandCenter {
200211
return '';
201212
}
202213

203-
@decorate(catchErrors)
214+
@CommandCenter.Command('git.openFile')
215+
@CommandCenter.CatchErrors
204216
async openFile(uri: Uri): Promise<void> {
205217
const resource = resolveGitResource(uri);
206218

@@ -211,7 +223,8 @@ export class CommandCenter {
211223
return commands.executeCommand<void>('vscode.open', resource.uri);
212224
}
213225

214-
@decorate(catchErrors)
226+
@CommandCenter.Command('git.stage')
227+
@CommandCenter.CatchErrors
215228
async stage(uri: Uri): Promise<void> {
216229
const resource = resolveGitResource(uri);
217230

@@ -222,12 +235,14 @@ export class CommandCenter {
222235
return await this.model.stage(resource);
223236
}
224237

225-
@decorate(catchErrors)
238+
@CommandCenter.Command('git.stageAll')
239+
@CommandCenter.CatchErrors
226240
async stageAll(): Promise<void> {
227241
return await this.model.stage();
228242
}
229243

230-
@decorate(catchErrors)
244+
@CommandCenter.Command('git.unstage')
245+
@CommandCenter.CatchErrors
231246
async unstage(uri: Uri): Promise<void> {
232247
const resource = resolveGitResource(uri);
233248

@@ -238,12 +253,14 @@ export class CommandCenter {
238253
return await this.model.unstage(resource);
239254
}
240255

241-
@decorate(catchErrors)
256+
@CommandCenter.Command('git.unstageAll')
257+
@CommandCenter.CatchErrors
242258
async unstageAll(): Promise<void> {
243259
return await this.model.unstage();
244260
}
245261

246-
@decorate(catchErrors)
262+
@CommandCenter.Command('git.clean')
263+
@CommandCenter.CatchErrors
247264
async clean(uri: Uri): Promise<void> {
248265
const resource = resolveGitResource(uri);
249266

@@ -264,7 +281,8 @@ export class CommandCenter {
264281
return await this.model.clean(resource);
265282
}
266283

267-
@decorate(catchErrors)
284+
@CommandCenter.Command('git.cleanAll')
285+
@CommandCenter.CatchErrors
268286
async cleanAll(): Promise<void> {
269287
const message = `Are you sure you want to clean all changes?`;
270288
const yes = 'Yes';
@@ -278,7 +296,8 @@ export class CommandCenter {
278296
return await this.model.clean(...this.model.workingTreeGroup.resources);
279297
}
280298

281-
@decorate(catchErrors)
299+
@CommandCenter.Command('git.checkout')
300+
@CommandCenter.CatchErrors
282301
async checkout(): Promise<void> {
283302
const config = workspace.getConfiguration('git');
284303
const checkoutType = config.get<string>('checkoutType');
@@ -305,12 +324,14 @@ export class CommandCenter {
305324
await choice.run(this.model);
306325
}
307326

308-
@decorate(catchErrors)
327+
@CommandCenter.Command('git.sync')
328+
@CommandCenter.CatchErrors
309329
async sync(): Promise<void> {
310330
await this.model.sync();
311331
}
312332

313-
@decorate(catchErrors)
333+
@CommandCenter.Command('git.publish')
334+
@CommandCenter.CatchErrors
314335
async publish(): Promise<void> {
315336
const branchName = this.model.HEAD && this.model.HEAD.name || '';
316337
const picks = this.model.remotes.map(r => r.name);
@@ -324,6 +345,7 @@ export class CommandCenter {
324345
await this.model.push(choice, branchName, { setUpstream: true });
325346
}
326347

348+
@CommandCenter.Command('git.showOutput')
327349
showOutput(): void {
328350
this.outputChannel.show();
329351
}

0 commit comments

Comments
 (0)