Skip to content

Commit 2fa61a1

Browse files
authored
Git - Extract querying for status so that it can run in parallel with the other operations (#163990)
1 parent 76191c7 commit 2fa61a1

File tree

2 files changed

+68
-59
lines changed

2 files changed

+68
-59
lines changed

extensions/git/src/git.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1954,7 +1954,7 @@ export class Repository {
19541954

19551955
const child = this.stream(args, { env });
19561956

1957-
const onExit = (exitCode: number) => {
1957+
const onClose = (exitCode: number) => {
19581958
if (exitCode !== 0) {
19591959
const stderr = stderrData.join('');
19601960
return e(new GitError({
@@ -1975,7 +1975,7 @@ export class Repository {
19751975
parser.update(raw);
19761976

19771977
if (limit !== 0 && parser.status.length > limit) {
1978-
child.removeListener('exit', onExit);
1978+
child.removeListener('close', onClose);
19791979
child.stdout!.removeListener('data', onStdoutData);
19801980
child.kill();
19811981

@@ -1991,7 +1991,7 @@ export class Repository {
19911991
child.stderr!.on('data', raw => stderrData.push(raw as string));
19921992

19931993
child.on('error', cpErrorHandler(e));
1994-
child.on('exit', onExit);
1994+
child.on('close', onClose);
19951995
});
19961996
}
19971997

extensions/git/src/repository.ts

Lines changed: 65 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,6 +1937,45 @@ export class Repository implements Disposable {
19371937

19381938
@throttle
19391939
private async updateModelState(): Promise<void> {
1940+
const config = workspace.getConfiguration('git');
1941+
let sort = config.get<'alphabetically' | 'committerdate'>('branchSortOrder') || 'alphabetically';
1942+
if (sort !== 'alphabetically' && sort !== 'committerdate') {
1943+
sort = 'alphabetically';
1944+
}
1945+
1946+
const [HEAD, refs, remotes, submodules, status, rebaseCommit, mergeInProgress, commitTemplate] =
1947+
await Promise.all([
1948+
this.repository.getHEADBranch(),
1949+
this.repository.getRefs({ sort }),
1950+
this.repository.getRemotes(),
1951+
this.repository.getSubmodules(),
1952+
this.getStatus(),
1953+
this.getRebaseCommit(),
1954+
this.isMergeInProgress(),
1955+
this.getInputTemplate()]);
1956+
1957+
this._HEAD = HEAD;
1958+
this._refs = refs!;
1959+
this._remotes = remotes!;
1960+
this._submodules = submodules!;
1961+
this.rebaseCommit = rebaseCommit;
1962+
this.mergeInProgress = mergeInProgress;
1963+
1964+
// set resource groups
1965+
this.mergeGroup.resourceStates = status.merge;
1966+
this.indexGroup.resourceStates = status.index;
1967+
this.workingTreeGroup.resourceStates = status.workingTree;
1968+
this.untrackedGroup.resourceStates = status.untracked;
1969+
1970+
// set count badge
1971+
this.setCountBadge();
1972+
1973+
this._onDidChangeStatus.fire();
1974+
1975+
this._sourceControl.commitTemplate = commitTemplate;
1976+
}
1977+
1978+
private async getStatus(): Promise<{ index: Resource[]; workingTree: Resource[]; merge: Resource[]; untracked: Resource[] }> {
19401979
const scopedConfig = workspace.getConfiguration('git', Uri.file(this.repository.root));
19411980
const untrackedChanges = scopedConfig.get<'mixed' | 'separate' | 'hidden'>('untrackedChanges');
19421981
const ignoreSubmodules = scopedConfig.get<boolean>('ignoreSubmodules');
@@ -1947,6 +1986,8 @@ export class Repository implements Disposable {
19471986
const { status, statusLength, didHitLimit } = await this.repository.getStatus({ limit, ignoreSubmodules, untrackedChanges });
19481987
const totalTime = new Date().getTime() - start;
19491988

1989+
this.isRepositoryHuge = didHitLimit ? { limit } : false;
1990+
19501991
if (didHitLimit) {
19511992
/* __GDPR__
19521993
"statusLimit" : {
@@ -1960,12 +2001,28 @@ export class Repository implements Disposable {
19602001
this.telemetryReporter.sendTelemetryEvent('statusLimit', { ignoreSubmodules: String(ignoreSubmodules) }, { limit, statusLength, totalTime });
19612002
}
19622003

2004+
if (totalTime > 5000) {
2005+
/* __GDPR__
2006+
"statusSlow" : {
2007+
"owner": "digitarald",
2008+
"comment": "Reports when git status is slower than 5s",
2009+
"expiration": "1.73",
2010+
"ignoreSubmodules": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Setting indicating whether submodules are ignored" },
2011+
"didHitLimit": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Total number of status entries" },
2012+
"didWarnAboutLimit": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "True when the user was warned about slow git status" },
2013+
"statusLength": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "comment": "Total number of status entries" },
2014+
"totalTime": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "comment": "Total number of ms the operation took" }
2015+
}
2016+
*/
2017+
this.telemetryReporter.sendTelemetryEvent('statusSlow', { ignoreSubmodules: String(ignoreSubmodules), didHitLimit: String(didHitLimit), didWarnAboutLimit: String(this.didWarnAboutLimit) }, { statusLength, totalTime });
2018+
}
2019+
2020+
// Triggers or clears any validation warning
2021+
this._sourceControl.inputBox.validateInput = this._sourceControl.inputBox.validateInput;
2022+
19632023
const config = workspace.getConfiguration('git');
19642024
const shouldIgnore = config.get<boolean>('ignoreLimitWarning') === true;
19652025
const useIcons = !config.get<boolean>('decorations.enabled', true);
1966-
this.isRepositoryHuge = didHitLimit ? { limit } : false;
1967-
// Triggers or clears any validation warning
1968-
this._sourceControl.inputBox.validateInput = this._sourceControl.inputBox.validateInput;
19692026

19702027
if (didHitLimit && !shouldIgnore && !this.didWarnAboutLimit) {
19712028
const knownHugeFolderPaths = await this.findKnownHugeFolderPathsToIgnore();
@@ -2001,47 +2058,10 @@ export class Repository implements Disposable {
20012058
}
20022059
}
20032060

2004-
if (totalTime > 5000) {
2005-
/* __GDPR__
2006-
"statusSlow" : {
2007-
"owner": "digitarald",
2008-
"comment": "Reports when git status is slower than 5s",
2009-
"expiration": "1.73",
2010-
"ignoreSubmodules": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Setting indicating whether submodules are ignored" },
2011-
"didHitLimit": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Total number of status entries" },
2012-
"didWarnAboutLimit": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "True when the user was warned about slow git status" },
2013-
"statusLength": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "comment": "Total number of status entries" },
2014-
"totalTime": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "comment": "Total number of ms the operation took" }
2015-
}
2016-
*/
2017-
this.telemetryReporter.sendTelemetryEvent('statusSlow', { ignoreSubmodules: String(ignoreSubmodules), didHitLimit: String(didHitLimit), didWarnAboutLimit: String(this.didWarnAboutLimit) }, { statusLength, totalTime });
2018-
}
2019-
2020-
let sort = config.get<'alphabetically' | 'committerdate'>('branchSortOrder') || 'alphabetically';
2021-
if (sort !== 'alphabetically' && sort !== 'committerdate') {
2022-
sort = 'alphabetically';
2023-
}
2024-
const [HEAD, refs, remotes, submodules, rebaseCommit, mergeInProgress, commitTemplate] =
2025-
await Promise.all([
2026-
this.repository.getHEADBranch(),
2027-
this.repository.getRefs({ sort }),
2028-
this.repository.getRemotes(),
2029-
this.repository.getSubmodules(),
2030-
this.getRebaseCommit(),
2031-
this.isMergeInProgress(),
2032-
this.getInputTemplate()]);
2033-
2034-
this._HEAD = HEAD;
2035-
this._refs = refs!;
2036-
this._remotes = remotes!;
2037-
this._submodules = submodules!;
2038-
this.rebaseCommit = rebaseCommit;
2039-
this.mergeInProgress = mergeInProgress;
2040-
2041-
const index: Resource[] = [];
2042-
const workingTree: Resource[] = [];
2043-
const merge: Resource[] = [];
2044-
const untracked: Resource[] = [];
2061+
const index: Resource[] = [],
2062+
workingTree: Resource[] = [],
2063+
merge: Resource[] = [],
2064+
untracked: Resource[] = [];
20452065

20462066
status.forEach(raw => {
20472067
const uri = Uri.file(path.join(this.repository.root, raw.path));
@@ -2086,18 +2106,7 @@ export class Repository implements Disposable {
20862106
return undefined;
20872107
});
20882108

2089-
// set resource groups
2090-
this.mergeGroup.resourceStates = merge;
2091-
this.indexGroup.resourceStates = index;
2092-
this.workingTreeGroup.resourceStates = workingTree;
2093-
this.untrackedGroup.resourceStates = untracked;
2094-
2095-
// set count badge
2096-
this.setCountBadge();
2097-
2098-
this._onDidChangeStatus.fire();
2099-
2100-
this._sourceControl.commitTemplate = commitTemplate;
2109+
return { index, workingTree, merge, untracked };
21012110
}
21022111

21032112
private setCountBadge(): void {

0 commit comments

Comments
 (0)