Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/platform/git/node/localGitService.ts
13394 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as cp from 'child_process';
7
import { CancellationError } from '../../../base/common/errors.js';
8
import { generateUuid } from '../../../base/common/uuid.js';
9
import { ILocalGitService } from '../common/localGitService.js';
10
import { ILogService } from '../../log/common/log.js';
11
12
export class LocalGitService implements ILocalGitService {
13
declare readonly _serviceBrand: undefined;
14
15
private _runningProcesses = new Map<string, cp.ChildProcess>();
16
17
constructor(
18
@ILogService private readonly _logService: ILogService,
19
) { }
20
21
private _exec(operationId: string, args: string[], cwd?: string): Promise<string> {
22
return new Promise((resolve, reject) => {
23
this._logService.trace(`[LocalGitService] git ${args.join(' ')}${cwd ? ` (cwd: ${cwd})` : ''}`);
24
const proc = cp.execFile('git', args, { cwd, encoding: 'utf8' }, (err, stdout, stderr) => {
25
if (!this._runningProcesses.delete(operationId)) {
26
reject(new CancellationError());
27
return;
28
}
29
if (err) {
30
this._logService.error(`[LocalGitService] git ${args[0]} failed:`, err.message, stderr);
31
reject(err);
32
return;
33
}
34
resolve(stdout);
35
});
36
37
this._runningProcesses.set(operationId, proc);
38
});
39
}
40
41
async clone(operationId: string, cloneUrl: string, targetPath: string, ref?: string): Promise<void> {
42
const args = ['clone'];
43
if (ref) {
44
args.push('--branch', ref);
45
}
46
args.push('--', cloneUrl, targetPath);
47
await this._exec(operationId, args);
48
}
49
50
async pull(operationId: string, repoPath: string): Promise<boolean> {
51
const before = (await this._exec(operationId, ['rev-parse', 'HEAD'], repoPath)).trim();
52
await this._exec(operationId, ['pull', '--ff-only'], repoPath);
53
const after = (await this._exec(operationId, ['rev-parse', 'HEAD'], repoPath)).trim();
54
return before !== after;
55
}
56
57
async checkout(operationId: string, repoPath: string, treeish: string, detached?: boolean): Promise<void> {
58
const args = detached
59
? ['checkout', '--detach', treeish]
60
: ['checkout', treeish];
61
await this._exec(operationId, args, repoPath);
62
}
63
64
async revParse(repoPath: string, ref: string): Promise<string> {
65
return (await this._exec(generateUuid(), ['rev-parse', ref], repoPath)).trim();
66
}
67
68
async fetch(operationId: string, repoPath: string): Promise<void> {
69
await this._exec(operationId, ['fetch'], repoPath);
70
}
71
72
async revListCount(repoPath: string, fromRef: string, toRef: string): Promise<number> {
73
const result = await this._exec(generateUuid(), ['rev-list', '--count', `${fromRef}..${toRef}`], repoPath);
74
return Number(result.trim()) || 0;
75
}
76
77
async cancel(operationId: string): Promise<void> {
78
const proc = this._runningProcesses.get(operationId);
79
if (proc) {
80
this._runningProcesses.delete(operationId);
81
proc.kill();
82
}
83
}
84
}
85
86