Skip to content

Commit 8e57734

Browse files
committed
Code reuse
1 parent be8587f commit 8e57734

3 files changed

Lines changed: 68 additions & 80 deletions

File tree

package.nls.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"githubPullRequests.hideViewedFiles.description": "Hide files that have been marked as viewed in the pull request changes tree.",
4040
"githubPullRequests.defaultDeletionMethod.selectLocalBranch.description": "When true, the option to delete the local branch will be selected by default when deleting a branch from a pull request.",
4141
"githubPullRequests.defaultDeletionMethod.selectRemote.description": "When true, the option to delete the remote will be selected by default when deleting a branch from a pull request.",
42-
"githubPullRequests.deleteBranchAfterMerge.description": "Automatically delete the branch after merging a pull request.",
42+
"githubPullRequests.deleteBranchAfterMerge.description": "Automatically delete the branch after merging a pull request. This setting only applies when the pull request is merged through this extension.",
4343
"githubPullRequests.terminalLinksHandler.description": "Default handler for terminal links.",
4444
"githubPullRequests.terminalLinksHandler.github": "Create the pull request on GitHub",
4545
"githubPullRequests.terminalLinksHandler.vscode": "Create the pull request in VS Code",

src/github/pullRequestGitHelper.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ export interface BaseBranchMetadata {
3333
branch: string;
3434
}
3535

36+
export type BranchInfo = {
37+
branch: string;
38+
remote?: string;
39+
createdForPullRequest?: boolean;
40+
remoteInUse?: boolean;
41+
};
42+
3643
export class PullRequestGitHelper {
3744
static ID = 'PullRequestGitHelper';
3845
static async checkoutFromFork(
@@ -202,12 +209,7 @@ export class PullRequestGitHelper {
202209
static async getBranchNRemoteForPullRequest(
203210
repository: Repository,
204211
pullRequest: PullRequestModel,
205-
): Promise<{
206-
branch: string;
207-
remote?: string;
208-
createdForPullRequest?: boolean;
209-
remoteInUse?: boolean;
210-
} | null> {
212+
): Promise<BranchInfo | null> {
211213
let branchName: string | null = null;
212214
try {
213215
const key = PullRequestGitHelper.buildPullRequestMetadata(pullRequest);

src/github/pullRequestReviewCommon.ts

Lines changed: 59 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
import * as vscode from 'vscode';
88
import { FolderRepositoryManager } from './folderRepositoryManager';
99
import { IAccount, isITeam, ITeam, MergeMethod, PullRequestMergeability, reviewerId, ReviewState } from './interface';
10+
import { BranchInfo } from './pullRequestGitHelper';
1011
import { PullRequestModel } from './pullRequestModel';
1112
import { PullRequest, ReadyForReviewReply, ReviewType, SubmitReviewReply } from './views';
12-
import Logger from '../common/logger';
1313
import { DEFAULT_DELETION_METHOD, PR_SETTINGS_NAMESPACE, SELECT_LOCAL_BRANCH, SELECT_REMOTE } from '../common/settingKeys';
1414
import { ReviewEvent, TimelineEvent } from '../common/timelineEvent';
1515
import { Schemes } from '../common/uri';
@@ -275,9 +275,13 @@ export namespace PullRequestReviewCommon {
275275
}
276276
}
277277

278+
interface SelectedAction {
279+
type: 'remoteHead' | 'local' | 'remote' | 'suspend'
280+
};
281+
278282
export async function deleteBranch(folderRepositoryManager: FolderRepositoryManager, item: PullRequestModel): Promise<{ isReply: boolean, message: any }> {
279283
const branchInfo = await folderRepositoryManager.getBranchNameForPullRequest(item);
280-
const actions: (vscode.QuickPickItem & { type: 'remoteHead' | 'local' | 'remote' | 'suspend' })[] = [];
284+
const actions: (vscode.QuickPickItem & SelectedAction)[] = [];
281285
const defaultBranch = await folderRepositoryManager.getPullRequestRepositoryDefaultBranch(item);
282286

283287
if (item.isResolved()) {
@@ -342,51 +346,9 @@ export namespace PullRequestReviewCommon {
342346
ignoreFocusOut: true,
343347
});
344348

345-
const deletedBranchTypes: string[] = [];
346349

347350
if (selectedActions) {
348-
const isBranchActive = item.equals(folderRepositoryManager.activePullRequest) || (folderRepositoryManager.repository.state.HEAD?.name && folderRepositoryManager.repository.state.HEAD.name === branchInfo?.branch);
349-
350-
const promises = selectedActions.map(async action => {
351-
switch (action.type) {
352-
case 'remoteHead':
353-
await folderRepositoryManager.deleteBranch(item);
354-
deletedBranchTypes.push(action.type);
355-
await folderRepositoryManager.repository.fetch({ prune: true });
356-
// If we're in a remote repository, then we should checkout the default branch.
357-
if (folderRepositoryManager.repository.rootUri.scheme === Schemes.VscodeVfs) {
358-
await folderRepositoryManager.repository.checkout(defaultBranch);
359-
}
360-
return;
361-
case 'local':
362-
if (isBranchActive) {
363-
if (folderRepositoryManager.repository.state.workingTreeChanges.length) {
364-
const yes = vscode.l10n.t('Yes');
365-
const response = await vscode.window.showWarningMessage(
366-
vscode.l10n.t('Your local changes will be lost, do you want to continue?'),
367-
{ modal: true },
368-
yes,
369-
);
370-
if (response === yes) {
371-
await vscode.commands.executeCommand('git.cleanAll');
372-
} else {
373-
return;
374-
}
375-
}
376-
await folderRepositoryManager.checkoutDefaultBranch(defaultBranch);
377-
}
378-
await folderRepositoryManager.repository.deleteBranch(branchInfo!.branch, true);
379-
return deletedBranchTypes.push(action.type);
380-
case 'remote':
381-
deletedBranchTypes.push(action.type);
382-
return folderRepositoryManager.repository.removeRemote(branchInfo!.remote!);
383-
case 'suspend':
384-
deletedBranchTypes.push(action.type);
385-
return vscode.commands.executeCommand('github.codespaces.disconnectSuspend');
386-
}
387-
});
388-
389-
await Promise.all(promises);
351+
const deletedBranchTypes: string[] = await performBranchDeletion(folderRepositoryManager, item, defaultBranch, branchInfo!, selectedActions);
390352

391353
return {
392354
isReply: false,
@@ -405,6 +367,53 @@ export namespace PullRequestReviewCommon {
405367
}
406368
}
407369

370+
async function performBranchDeletion(folderRepositoryManager: FolderRepositoryManager, item: PullRequestModel, defaultBranch: string, branchInfo: BranchInfo, selectedActions: SelectedAction[]): Promise<string[]> {
371+
const isBranchActive = item.equals(folderRepositoryManager.activePullRequest) || (folderRepositoryManager.repository.state.HEAD?.name && folderRepositoryManager.repository.state.HEAD.name === branchInfo?.branch);
372+
const deletedBranchTypes: string[] = [];
373+
374+
const promises = selectedActions.map(async action => {
375+
switch (action.type) {
376+
case 'remoteHead':
377+
await folderRepositoryManager.deleteBranch(item);
378+
deletedBranchTypes.push(action.type);
379+
await folderRepositoryManager.repository.fetch({ prune: true });
380+
// If we're in a remote repository, then we should checkout the default branch.
381+
if (folderRepositoryManager.repository.rootUri.scheme === Schemes.VscodeVfs) {
382+
await folderRepositoryManager.repository.checkout(defaultBranch);
383+
}
384+
return;
385+
case 'local':
386+
if (isBranchActive) {
387+
if (folderRepositoryManager.repository.state.workingTreeChanges.length) {
388+
const yes = vscode.l10n.t('Yes');
389+
const response = await vscode.window.showWarningMessage(
390+
vscode.l10n.t('Your local changes will be lost, do you want to continue?'),
391+
{ modal: true },
392+
yes,
393+
);
394+
if (response === yes) {
395+
await vscode.commands.executeCommand('git.cleanAll');
396+
} else {
397+
return;
398+
}
399+
}
400+
await folderRepositoryManager.checkoutDefaultBranch(defaultBranch);
401+
}
402+
await folderRepositoryManager.repository.deleteBranch(branchInfo!.branch, true);
403+
return deletedBranchTypes.push(action.type);
404+
case 'remote':
405+
deletedBranchTypes.push(action.type);
406+
return folderRepositoryManager.repository.removeRemote(branchInfo!.remote!);
407+
case 'suspend':
408+
deletedBranchTypes.push(action.type);
409+
return vscode.commands.executeCommand('github.codespaces.disconnectSuspend');
410+
}
411+
});
412+
413+
await Promise.all(promises);
414+
return deletedBranchTypes;
415+
}
416+
408417
/**
409418
* Automatically delete branches after merge based on user preferences.
410419
* This function does not show any prompts - it uses the default deletion method preferences.
@@ -422,50 +431,27 @@ export namespace PullRequestReviewCommon {
422431
.getConfiguration(PR_SETTINGS_NAMESPACE)
423432
.get<boolean>(`${DEFAULT_DELETION_METHOD}.${SELECT_REMOTE}`, true);
424433

425-
const promises: Promise<void>[] = [];
434+
const selectedActions: SelectedAction[] = [];
426435

427436
// Delete remote head branch if it's not the default branch
428437
if (item.isResolved()) {
429438
const isDefaultBranch = defaultBranch === item.head.ref;
430439
if (!isDefaultBranch && !item.isRemoteHeadDeleted) {
431-
promises.push(
432-
folderRepositoryManager.deleteBranch(item).then(() => {
433-
return folderRepositoryManager.repository.fetch({ prune: true });
434-
}).catch(e => {
435-
Logger.warn(`Failed to delete remote branch for PR #${item.number}: ${e}`, 'PullRequestReviewCommon');
436-
})
437-
);
440+
selectedActions.push({ type: 'remoteHead' });
438441
}
439442
}
440443

441444
// Delete local branch if preference is set
442445
if (branchInfo && deleteLocalBranch) {
443-
const isBranchActive = item.equals(folderRepositoryManager.activePullRequest) ||
444-
(folderRepositoryManager.repository.state.HEAD?.name && folderRepositoryManager.repository.state.HEAD.name === branchInfo.branch);
445-
446-
promises.push(
447-
(async () => {
448-
if (isBranchActive) {
449-
// Checkout default branch before deleting the active branch
450-
await folderRepositoryManager.checkoutDefaultBranch(defaultBranch);
451-
}
452-
await folderRepositoryManager.repository.deleteBranch(branchInfo.branch, true);
453-
})().catch(e => {
454-
Logger.warn(`Failed to delete local branch ${branchInfo.branch} for PR #${item.number}: ${e}`, 'PullRequestReviewCommon');
455-
})
456-
);
446+
selectedActions.push({ type: 'local' });
457447
}
458448

459449
// Delete remote if it's no longer used and preference is set
460450
if (branchInfo && branchInfo.remote && branchInfo.createdForPullRequest && !branchInfo.remoteInUse && deleteRemote) {
461-
promises.push(
462-
folderRepositoryManager.repository.removeRemote(branchInfo.remote).catch(e => {
463-
Logger.warn(`Failed to delete remote ${branchInfo.remote} for PR #${item.number}: ${e}`, 'PullRequestReviewCommon');
464-
})
465-
);
451+
selectedActions.push({ type: 'remote' });
466452
}
467453

468454
// Execute all deletions in parallel
469-
await Promise.all(promises);
455+
await performBranchDeletion(folderRepositoryManager, item, defaultBranch, branchInfo!, selectedActions);
470456
}
471457
}

0 commit comments

Comments
 (0)