77import * as vscode from 'vscode' ;
88import { FolderRepositoryManager } from './folderRepositoryManager' ;
99import { IAccount , isITeam , ITeam , MergeMethod , PullRequestMergeability , reviewerId , ReviewState } from './interface' ;
10+ import { BranchInfo } from './pullRequestGitHelper' ;
1011import { PullRequestModel } from './pullRequestModel' ;
1112import { PullRequest , ReadyForReviewReply , ReviewType , SubmitReviewReply } from './views' ;
12- import Logger from '../common/logger' ;
1313import { DEFAULT_DELETION_METHOD , PR_SETTINGS_NAMESPACE , SELECT_LOCAL_BRANCH , SELECT_REMOTE } from '../common/settingKeys' ;
1414import { ReviewEvent , TimelineEvent } from '../common/timelineEvent' ;
1515import { 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