Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/@types/vscode.proposed.chatSessionsProvider.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -488,10 +488,11 @@ declare module 'vscode' {
*
* @param scheme The uri-scheme to register for. This must be unique.
* @param provider The provider to register.
* @param defaultChatParticipant The default {@link ChatParticipant chat participant} used in sessions provided by this provider.
*
* @returns A disposable that unregisters the provider when disposed.
*/
export function registerChatSessionContentProvider(scheme: string, provider: ChatSessionContentProvider, chatParticipant: ChatParticipant, capabilities?: ChatSessionCapabilities): Disposable;
export function registerChatSessionContentProvider(scheme: string, provider: ChatSessionContentProvider, defaultChatParticipant: ChatParticipant, capabilities?: ChatSessionCapabilities): Disposable;
}

export interface ChatContext {
Expand Down
22 changes: 21 additions & 1 deletion src/github/createPRViewProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { IAccount, ILabel, IMilestone, IProject, isITeam, ITeam, MergeMethod, Re
import { BaseBranchMetadata, PullRequestGitHelper } from './pullRequestGitHelper';
import { PullRequestModel } from './pullRequestModel';
import { getDefaultMergeMethod } from './pullRequestOverview';
import { branchPicks, getAssigneesQuickPickItems, getLabelOptions, getMilestoneFromQuickPick, getProjectFromQuickPick, reviewersQuickPick } from './quickPicks';
import { branchPicks, cachedBranchPicks, getAssigneesQuickPickItems, getLabelOptions, getMilestoneFromQuickPick, getProjectFromQuickPick, reviewersQuickPick } from './quickPicks';
import { ISSUE_EXPRESSION, parseIssueExpressionOutput, variableSubstitution } from './utils';
import { ChangeTemplateReply, DisplayLabel, PreReviewState } from './views';
import { RemoteInfo } from '../../common/types';
Expand Down Expand Up @@ -1010,9 +1010,22 @@ Don't forget to commit your template file to the repository so that it can be us
const params = await super.getCreateParams();
this.model.baseOwner = params.defaultBaseRemote!.owner;
this.model.baseBranch = params.defaultBaseBranch!;
// Pre-fetch branches so they're cached when the user opens the branch picker
this.prefetchBranches(params.defaultBaseRemote!);
return params;
}

private prefetchBranches(baseRemote: RemoteInfo): void {
const githubRepository = this._folderRepositoryManager.findRepo(
repo => repo.remote.owner === baseRemote.owner && repo.remote.repositoryName === baseRemote.repositoryName,
);
if (githubRepository) {
githubRepository.listBranches(baseRemote.owner, baseRemote.repositoryName, undefined).catch(e => {
Logger.debug(`Pre-fetching branches failed: ${e}`, CreatePullRequestViewProvider.ID);
});
}
}


private async remotePicks(isBase: boolean): Promise<(vscode.QuickPickItem & { remote?: RemoteInfo })[]> {
const remotes = isBase ? await this._folderRepositoryManager.getActiveGitHubRemotes(await this._folderRepositoryManager.getGitHubRemotes()) : this._folderRepositoryManager.gitHubRepositories.map(repo => repo.remote);
Expand Down Expand Up @@ -1141,6 +1154,13 @@ Don't forget to commit your template file to the repository so that it can be us
quickPick.show();
quickPick.busy = true;
if (githubRepository) {
// Show cached branches immediately if available, then refresh in the background
const cached = cachedBranchPicks(githubRepository, this._folderRepositoryManager, chooseDifferentRemote, isBase);
if (cached) {
quickPick.items = cached;
const activeItem = message.args.currentBranch ? quickPick.items.find(item => item.branch === message.args.currentBranch) : undefined;
quickPick.activeItems = activeItem ? [activeItem] : [];
}
await updateItems(githubRepository, undefined);
} else {
quickPick.items = await this.remotePicks(isBase);
Expand Down
14 changes: 14 additions & 0 deletions src/github/githubRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ export class GitHubRepository extends Disposable {
private _areQueriesLimited: boolean = false;
get areQueriesLimited(): boolean { return this._areQueriesLimited; }

private _branchesCache: Map<string, string[]> = new Map();

private _onDidAddPullRequest: vscode.EventEmitter<PullRequestModel> = this._register(new vscode.EventEmitter());
public readonly onDidAddPullRequest: vscode.Event<PullRequestModel> = this._onDidAddPullRequest.event;
private _onDidChangePullRequests: vscode.EventEmitter<PullRequestChangeEvent[]> = this._register(new vscode.EventEmitter());
Expand Down Expand Up @@ -1341,6 +1343,14 @@ export class GitHubRepository extends Disposable {
return data.repository?.ref?.target.oid;
}

private branchesCacheKey(owner: string, repositoryName: string): string {
return `${owner}/${repositoryName}`;
}

getCachedBranches(owner: string, repositoryName: string): string[] | undefined {
return this._branchesCache.get(this.branchesCacheKey(owner, repositoryName));
}

async listBranches(owner: string, repositoryName: string, prefix: string | undefined): Promise<string[]> {
const { query, remote, schema } = await this.ensure();
Logger.debug(`List branches for ${owner}/${repositoryName} - enter`, this.id);
Expand Down Expand Up @@ -1382,6 +1392,10 @@ export class GitHubRepository extends Disposable {
if (!branches.includes(defaultBranch)) {
branches.unshift(defaultBranch);
}
// Cache results for unprefixed queries
if (!prefix) {
this._branchesCache.set(this.branchesCacheKey(owner, repositoryName), branches);
}
return branches;
}

Expand Down
39 changes: 26 additions & 13 deletions src/github/quickPicks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -482,19 +482,7 @@ function getRecentlyUsedBranches(folderRepoManager: FolderRepositoryManager, own
return state.branches[repoKey] || [];
}

export async function branchPicks(githubRepository: GitHubRepository, folderRepoManager: FolderRepositoryManager, changeRepoMessage: string | undefined, isBase: boolean, prefix: string | undefined): Promise<(vscode.QuickPickItem & { remote?: RemoteInfo, branch?: string })[]> {
let branches: (string | Ref)[];
if (isBase) {
// For the base, we only want to show branches from GitHub.
branches = await githubRepository.listBranches(githubRepository.remote.owner, githubRepository.remote.repositoryName, prefix);
} else {
// For the compare, we only want to show local branches.
branches = (await folderRepoManager.repository.getBranches({ remote: false })).filter(branch => branch.name);
}


const branchNames = branches.map(branch => typeof branch === 'string' ? branch : branch.name!);

function buildBranchPickItems(branchNames: string[], githubRepository: GitHubRepository, folderRepoManager: FolderRepositoryManager, changeRepoMessage: string | undefined, isBase: boolean): (vscode.QuickPickItem & { remote?: RemoteInfo, branch?: string })[] {
// Get recently used branches for base branches only
let recentBranches: string[] = [];
let otherBranches: string[] = branchNames;
Expand Down Expand Up @@ -554,4 +542,29 @@ export async function branchPicks(githubRepository: GitHubRepository, folderRepo
});
}
return branchPicks;
}

export function cachedBranchPicks(githubRepository: GitHubRepository, folderRepoManager: FolderRepositoryManager, changeRepoMessage: string | undefined, isBase: boolean): (vscode.QuickPickItem & { remote?: RemoteInfo, branch?: string })[] | undefined {
if (!isBase) {
return undefined;
}
const cached = githubRepository.getCachedBranches(githubRepository.remote.owner, githubRepository.remote.repositoryName);
if (!cached) {
return undefined;
}
return buildBranchPickItems(cached, githubRepository, folderRepoManager, changeRepoMessage, isBase);
}

export async function branchPicks(githubRepository: GitHubRepository, folderRepoManager: FolderRepositoryManager, changeRepoMessage: string | undefined, isBase: boolean, prefix: string | undefined): Promise<(vscode.QuickPickItem & { remote?: RemoteInfo, branch?: string })[]> {
let branches: (string | Ref)[];
if (isBase) {
// For the base, we only want to show branches from GitHub.
branches = await githubRepository.listBranches(githubRepository.remote.owner, githubRepository.remote.repositoryName, prefix);
} else {
// For the compare, we only want to show local branches.
branches = (await folderRepoManager.repository.getBranches({ remote: false })).filter(branch => branch.name);
}

const branchNames = branches.map(branch => typeof branch === 'string' ? branch : branch.name!);
return buildBranchPickItems(branchNames, githubRepository, folderRepoManager, changeRepoMessage, isBase);
}
Loading