Skip to content

Commit 86e02b2

Browse files
committed
Git data source refactoring
1 parent 2d0bdc0 commit 86e02b2

File tree

2 files changed

+64
-74
lines changed

2 files changed

+64
-74
lines changed

src/dataSource.ts

Lines changed: 64 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as cp from 'child_process';
22
import { Config } from './config';
3-
import { GitCommandStatus, GitCommit, GitCommitDetails, GitCommitNode, GitFileChangeType, GitRef, GitResetMode, GitUnsavedChangesCmdResp } from './types';
3+
import { GitCommandStatus, GitCommit, GitCommitDetails, GitCommitNode, GitFileChangeType, GitRef, GitResetMode, GitUnsavedChanges } from './types';
44

55
const eolRegex = /\r\n|\r|\n/g;
66
const gitLogSeparator = 'XX7Nal-YARtTpjCikii9nJxER19D6diSyk-AWkPb';
@@ -24,15 +24,15 @@ export class DataSource {
2424

2525
public isGitRepository() {
2626
return new Promise<boolean>((resolve) => {
27-
cp.exec(this.gitExecPath + ' rev-parse --git-dir', this.execOptions, (err) => {
27+
this.execGit('rev-parse --git-dir', (err) => {
2828
resolve(!err);
2929
});
3030
});
3131
}
3232

3333
public getBranches(showRemoteBranches: boolean) {
3434
return new Promise<string[]>((resolve) => {
35-
cp.exec(this.gitExecPath + ' branch' + (showRemoteBranches ? ' -a' : ''), this.execOptions, (err, stdout) => {
35+
this.execGit('branch' + (showRemoteBranches ? ' -a' : ''), (err, stdout) => {
3636
if (!err) {
3737
let lines = stdout.split(eolRegex);
3838
let branches: string[] = [];
@@ -106,7 +106,7 @@ export class DataSource {
106106
public async commitDetails(commitHash: string) {
107107
try {
108108
let details = await new Promise<GitCommitDetails>((resolve, reject) => {
109-
cp.exec(this.gitExecPath + ' show --quiet ' + commitHash + ' --format="' + gitCommitDetailsFormat + '"', this.execOptions, (err, stdout) => {
109+
this.execGit('show --quiet ' + commitHash + ' --format="' + gitCommitDetailsFormat + '"', (err, stdout) => {
110110
if (!err) {
111111
let lines = stdout.split(eolRegex);
112112
let commitInfo = lines[0].split(gitLogSeparator);
@@ -127,7 +127,7 @@ export class DataSource {
127127
});
128128
let fileLookup: { [file: string]: number } = {};
129129
await new Promise((resolve, reject) => {
130-
cp.exec(this.gitExecPath + ' diff-tree --name-status -r -m --root --find-renames --diff-filter=AMDR ' + commitHash, this.execOptions, (err, stdout) => {
130+
this.execGit('diff-tree --name-status -r -m --root --find-renames --diff-filter=AMDR ' + commitHash, (err, stdout) => {
131131
if (!err) {
132132
let lines = stdout.split(eolRegex);
133133
for (let i = 1; i < lines.length - 1; i++) {
@@ -144,7 +144,7 @@ export class DataSource {
144144
});
145145
});
146146
await new Promise((resolve, reject) => {
147-
cp.exec(this.gitExecPath + ' diff-tree --numstat -r -m --root --find-renames --diff-filter=AMDR ' + commitHash, this.execOptions, (err, stdout) => {
147+
this.execGit('diff-tree --numstat -r -m --root --find-renames --diff-filter=AMDR ' + commitHash, (err, stdout) => {
148148
if (!err) {
149149
let lines = stdout.split(eolRegex);
150150
for (let i = 1; i < lines.length - 1; i++) {
@@ -169,20 +169,8 @@ export class DataSource {
169169
}
170170
}
171171

172-
public async getCommitFile(commitHash: string, filePath: string) {
173-
return new Promise<string>((resolve) => {
174-
let args = ['show', commitHash + ':' + filePath], stdout = '', err = false;
175-
const cmd = cp.spawn(this.gitPath, args, this.execOptions);
176-
cmd.stdout.on('data', (d) => { stdout += d; });
177-
cmd.on('error', () => {
178-
resolve('');
179-
err = true;
180-
});
181-
cmd.on('exit', (code) => {
182-
if (err) return;
183-
resolve(code === 0 ? stdout : '');
184-
});
185-
});
172+
public getCommitFile(commitHash: string, filePath: string) {
173+
return this.spawnGit(['show', commitHash + ':' + filePath], stdout => stdout, '');
186174
}
187175

188176
public addTag(tagName: string, commitHash: string) {
@@ -225,22 +213,9 @@ export class DataSource {
225213
return this.runGitCommand('reset --' + resetMode + ' ' + commitHash);
226214
}
227215

228-
private async runGitCommand(command: string) {
229-
return new Promise<GitCommandStatus>((resolve) => {
230-
cp.exec(this.gitExecPath + ' ' + command, this.execOptions, (err) => {
231-
if (!err) {
232-
resolve(null);
233-
} else {
234-
let lines = err.message.split(eolRegex);
235-
resolve(lines.slice(1, lines.length - 1).join('\n'));
236-
}
237-
});
238-
});
239-
}
240-
241-
private async getRefs(showRemoteBranches: boolean) {
216+
private getRefs(showRemoteBranches: boolean) {
242217
return new Promise<GitRef[]>((resolve) => {
243-
cp.exec(this.gitExecPath + ' show-ref ' + (showRemoteBranches ? '' : '--heads --tags') + ' -d', this.execOptions, (err, stdout) => {
218+
this.execGit('show-ref ' + (showRemoteBranches ? '' : '--heads --tags') + ' -d', (err, stdout) => {
244219
if (!err) {
245220
let lines = stdout.split(eolRegex);
246221
let refs: GitRef[] = [];
@@ -267,56 +242,72 @@ export class DataSource {
267242
});
268243
}
269244

270-
private async getGitLog(branch: string, num: number, showRemoteBranches: boolean) {
271-
return new Promise<GitCommit[]>((resolve) => {
272-
let args = ['log', '--max-count=' + num, '--format=' + gitLogFormat, '--date-order'], stdout = '', err = false;
273-
if (branch !== '') {
274-
args.push(escapeRefName(branch));
275-
} else {
276-
args.push('--branches');
277-
if (showRemoteBranches) args.push('--remotes');
245+
private getGitLog(branch: string, num: number, showRemoteBranches: boolean) {
246+
let args = ['log', '--max-count=' + num, '--format=' + gitLogFormat, '--date-order'];
247+
if (branch !== '') {
248+
args.push(escapeRefName(branch));
249+
} else {
250+
args.push('--branches');
251+
if (showRemoteBranches) args.push('--remotes');
252+
}
253+
254+
return this.spawnGit(args, (stdout) => {
255+
let lines = stdout.split(eolRegex);
256+
let gitCommits: GitCommit[] = [];
257+
for (let i = 0; i < lines.length - 1; i++) {
258+
let line = lines[i].split(gitLogSeparator);
259+
if (line.length !== 6) break;
260+
gitCommits.push({ hash: line[0], parentHashes: line[1].split(' '), author: line[2], email: line[3], date: parseInt(line[4]), message: line[5] });
278261
}
262+
return gitCommits;
263+
}, []);
264+
}
265+
266+
private getGitUnsavedChanges() {
267+
return new Promise<GitUnsavedChanges | null>((resolve) => {
268+
this.execGit('status -s --branch --untracked-files --porcelain', (err, stdout) => {
269+
if (!err) {
270+
let lines = stdout.split(eolRegex);
271+
resolve(lines.length > 2 ? { branch: lines[0].substring(3).split('...')[0], changes: lines.length - 2 } : null);
272+
} else {
273+
resolve(null);
274+
}
275+
});
276+
});
277+
}
279278

279+
private runGitCommand(command: string) {
280+
return new Promise<GitCommandStatus>((resolve) => {
281+
this.execGit(command, (err) => {
282+
if (!err) {
283+
resolve(null);
284+
} else {
285+
let lines = err.message.split(eolRegex);
286+
resolve(lines.slice(1, lines.length - 1).join('\n'));
287+
}
288+
});
289+
});
290+
}
291+
292+
private execGit(command: string, callback: { (error: Error | null, stdout: string, stderr: string): void }) {
293+
cp.exec(this.gitExecPath + ' ' + command, this.execOptions, callback);
294+
}
295+
296+
private spawnGit<T>(args: string[], successValue: { (stdout: string): T }, errorValue: T) {
297+
return new Promise<T>((resolve) => {
298+
let stdout = '', err = false;
280299
const cmd = cp.spawn(this.gitPath, args, this.execOptions);
281300
cmd.stdout.on('data', (d) => { stdout += d; });
282301
cmd.on('error', () => {
283-
resolve([]);
302+
resolve(errorValue);
284303
err = true;
285304
});
286305
cmd.on('exit', (code) => {
287306
if (err) return;
288-
if (code === 0) {
289-
let lines = stdout.split(eolRegex);
290-
let gitCommits: GitCommit[] = [];
291-
for (let i = 0; i < lines.length - 1; i++) {
292-
let line = lines[i].split(gitLogSeparator);
293-
if (line.length !== 6) break;
294-
gitCommits.push({ hash: line[0], parentHashes: line[1].split(' '), author: line[2], email: line[3], date: parseInt(line[4]), message: line[5] });
295-
}
296-
resolve(gitCommits);
297-
} else {
298-
resolve([]);
299-
}
307+
resolve(code === 0 ? successValue(stdout) : errorValue);
300308
});
301309
});
302310
}
303-
304-
private getGitUnsavedChanges() {
305-
try {
306-
return new Promise<GitUnsavedChangesCmdResp>((resolve, reject) => {
307-
cp.exec(this.gitExecPath + ' status -s --branch --untracked-files --porcelain', this.execOptions, (err, stdout) => {
308-
if (!err) {
309-
let lines = stdout.split(eolRegex);
310-
resolve(lines.length > 2 ? { branch: lines[0].substring(3).split('...')[0], changes: lines.length - 2 } : null);
311-
} else {
312-
reject();
313-
}
314-
});
315-
});
316-
} catch (e) {
317-
return null;
318-
}
319-
}
320311
}
321312

322313
function escapeRefName(str: string) {

src/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ export type GraphStyle = 'rounded' | 'angular';
6464
export type GitCommandStatus = string | null;
6565
export type GitResetMode = 'soft' | 'mixed' | 'hard';
6666
export type GitFileChangeType = 'A' | 'M' | 'D' | 'R';
67-
export type GitUnsavedChangesCmdResp = GitUnsavedChanges | null;
6867

6968

7069
/* Request / Response Messages */

0 commit comments

Comments
 (0)