Bladeren bron

Adds better caching to avoid duplicate queries

main
Eric Amodio 3 jaren geleden
bovenliggende
commit
c5502b254b
1 gewijzigde bestanden met toevoegingen van 110 en 61 verwijderingen
  1. +110
    -61
      src/git/gitService.ts

+ 110
- 61
src/git/gitService.ts Bestand weergeven

@ -137,13 +137,13 @@ export class GitService implements Disposable {
private readonly _repositoryTree: TernarySearchTree<string, Repository>;
private _repositoriesLoadingPromise: Promise<void> | undefined;
private readonly _branchesCache = new Map<string, GitBranch[]>();
private readonly _contributorsCache = new Map<string, GitContributor[]>();
private readonly _branchesCache = new Map<string, Promise<GitBranch[]>>();
private readonly _contributorsCache = new Map<string, Promise<GitContributor[]>>();
private readonly _mergeStatusCache = new Map<string, GitMergeStatus | null>();
private readonly _rebaseStatusCache = new Map<string, GitRebaseStatus | null>();
private readonly _remotesWithApiProviderCache = new Map<string, GitRemote<RichRemoteProvider> | null>();
private readonly _stashesCache = new Map<string, GitStash | null>();
private readonly _tagsCache = new Map<string, GitTag[]>();
private readonly _tagsCache = new Map<string, Promise<GitTag[]>>();
private readonly _trackedCache = new Map<string, boolean | Promise<boolean>>();
private readonly _userMapCache = new Map<string, GitUser | null>();
@ -1298,49 +1298,64 @@ export class GitService implements Disposable {
): Promise<GitBranch[]> {
if (repoPath == null) return [];
let branches = this.useCaching ? this._branchesCache.get(repoPath) : undefined;
if (branches == null) {
const data = await Git.for_each_ref__branch(repoPath, { all: true });
// If we don't get any data, assume the repo doesn't have any commits yet so check if we have a current branch
if (data == null || data.length === 0) {
let current;
const data = await Git.rev_parse__currentBranch(repoPath, Container.config.advanced.commitOrdering);
if (data != null) {
const [name, upstream] = data[0].split('\n');
const [rebaseStatus, committerDate] = await Promise.all([
GitBranch.isDetached(name) ? this.getRebaseStatus(repoPath) : undefined,
Git.log__recent_committerdate(repoPath, Container.config.advanced.commitOrdering),
]);
current = new GitBranch(
repoPath,
rebaseStatus?.incoming.name ?? name,
false,
true,
committerDate != null ? new Date(Number(committerDate) * 1000) : undefined,
data[1],
{ name: upstream, missing: false },
undefined,
undefined,
undefined,
rebaseStatus != null,
);
}
let branchesPromise = this.useCaching ? this._branchesCache.get(repoPath) : undefined;
if (branchesPromise == null) {
async function load(this: GitService) {
try {
const data = await Git.for_each_ref__branch(repoPath!, { all: true });
// If we don't get any data, assume the repo doesn't have any commits yet so check if we have a current branch
if (data == null || data.length === 0) {
let current;
const data = await Git.rev_parse__currentBranch(
repoPath!,
Container.config.advanced.commitOrdering,
);
if (data != null) {
const [name, upstream] = data[0].split('\n');
const [rebaseStatus, committerDate] = await Promise.all([
GitBranch.isDetached(name) ? this.getRebaseStatus(repoPath!) : undefined,
Git.log__recent_committerdate(repoPath!, Container.config.advanced.commitOrdering),
]);
current = new GitBranch(
repoPath!,
rebaseStatus?.incoming.name ?? name,
false,
true,
committerDate != null ? new Date(Number(committerDate) * 1000) : undefined,
data[1],
{ name: upstream, missing: false },
undefined,
undefined,
undefined,
rebaseStatus != null,
);
}
branches = current != null ? [current] : [];
} else {
branches = GitBranchParser.parse(data, repoPath);
return current != null ? [current] : [];
}
return GitBranchParser.parse(data, repoPath!);
} catch (ex) {
this._branchesCache.delete(repoPath!);
return [];
}
}
branchesPromise = load.call(this);
if (this.useCaching) {
const repo = await this.getRepository(repoPath);
if (repo?.supportsChangeEvents) {
this._branchesCache.set(repoPath, branches);
this._branchesCache.set(repoPath, branchesPromise);
if (!(await this.getRepository(repoPath))?.supportsChangeEvents) {
this._branchesCache.delete(repoPath);
}
}
}
let branches = await branchesPromise;
if (options.filter != null) {
branches = branches.filter(options.filter);
}
@ -1520,19 +1535,29 @@ export class GitService implements Disposable {
let contributors = this.useCaching ? this._contributorsCache.get(repoPath) : undefined;
if (contributors == null) {
try {
const currentUser = await this.getCurrentUser(repoPath);
async function load(this: GitService) {
try {
const currentUser = await this.getCurrentUser(repoPath);
const data = await Git.log(repoPath, options?.ref, { all: options?.all, format: 'shortlog' });
const shortlog = GitShortLogParser.parseFromLog(data, repoPath, currentUser);
return shortlog != null ? shortlog.contributors : [];
} catch (ex) {
this._contributorsCache.delete(repoPath);
const data = await Git.log(repoPath, options?.ref, { all: options?.all, format: 'shortlog' });
const shortlog = GitShortLogParser.parseFromLog(data, repoPath, currentUser);
contributors = shortlog != null ? shortlog.contributors : [];
return [];
}
}
contributors = load.call(this);
if (this.useCaching) {
this._contributorsCache.set(repoPath, contributors);
const repo = await this.getRepository(repoPath);
if (repo?.supportsChangeEvents) {
this._contributorsCache.set(repoPath, contributors);
if (!(await this.getRepository(repoPath))?.supportsChangeEvents) {
this._contributorsCache.delete(repoPath);
}
} catch (ex) {
return [];
}
}
@ -2564,9 +2589,12 @@ export class GitService implements Disposable {
};
}
const repo = await this.getRepository(repoPath);
if (repo?.supportsChangeEvents) {
if (this.useCaching) {
this._mergeStatusCache.set(repoPath, status ?? null);
if (!(await this.getRepository(repoPath))?.supportsChangeEvents) {
this._mergeStatusCache.delete(repoPath);
}
}
}
@ -2641,9 +2669,12 @@ export class GitService implements Disposable {
};
}
const repo = await this.getRepository(repoPath);
if (repo?.supportsChangeEvents) {
if (this.useCaching) {
this._rebaseStatusCache.set(repoPath, status ?? null);
if (!(await this.getRepository(repoPath))?.supportsChangeEvents) {
this._rebaseStatusCache.delete(repoPath);
}
}
}
@ -3605,6 +3636,7 @@ export class GitService implements Disposable {
return repositoryTree.count();
}
@gate()
@log()
async getStash(repoPath: string | undefined): Promise<GitStash | undefined> {
if (repoPath == null) return undefined;
@ -3616,9 +3648,12 @@ export class GitService implements Disposable {
});
stash = GitStashParser.parse(data, repoPath);
const repo = await this.getRepository(repoPath);
if (repo?.supportsChangeEvents) {
if (this.useCaching) {
this._stashesCache.set(repoPath, stash ?? null);
if (!(await this.getRepository(repoPath))?.supportsChangeEvents) {
this._stashesCache.delete(repoPath);
}
}
}
@ -3690,17 +3725,31 @@ export class GitService implements Disposable {
): Promise<GitTag[]> {
if (repoPath == null) return [];
let tags = this.useCaching ? this._tagsCache.get(repoPath) : undefined;
if (tags == null) {
const data = await Git.tag(repoPath);
tags = GitTagParser.parse(data, repoPath) ?? [];
let tagsPromise = this.useCaching ? this._tagsCache.get(repoPath) : undefined;
if (tagsPromise == null) {
async function load(this: GitService) {
try {
const data = await Git.tag(repoPath!);
return GitTagParser.parse(data, repoPath!) ?? [];
} catch (ex) {
this._tagsCache.delete(repoPath!);
const repo = await this.getRepository(repoPath);
if (repo?.supportsChangeEvents) {
this._tagsCache.set(repoPath, tags);
return [];
}
}
tagsPromise = load.call(this);
if (this.useCaching) {
this._tagsCache.set(repoPath, tagsPromise);
if (!(await this.getRepository(repoPath))?.supportsChangeEvents) {
this._tagsCache.delete(repoPath);
}
}
}
let tags = await tagsPromise;
if (options.filter != null) {
tags = tags.filter(options.filter);
}

Laden…
Annuleren
Opslaan