@@ -32,6 +32,7 @@ import { chooseItem } from './github/quickPicks';
3232import { RepositoriesManager } from './github/repositoriesManager' ;
3333import { codespacesPrLink , getIssuesUrl , getPullsUrl , isInCodespaces , ISSUE_OR_URL_EXPRESSION , parseIssueExpressionOutput , vscodeDevPrLink } from './github/utils' ;
3434import { BaseContext , OverviewContext } from './github/views' ;
35+ import { checkoutPRInWorktree } from './github/worktree' ;
3536import { IssueChatContextItem } from './lm/issueContextProvider' ;
3637import { PRChatContextItem } from './lm/pullRequestContextProvider' ;
3738import { isNotificationTreeItem , NotificationTreeItem } from './notifications/notificationItem' ;
@@ -845,117 +846,13 @@ export function registerCommands(
845846 return vscode . window . showErrorMessage ( vscode . l10n . t ( 'No pull request was selected to checkout, please try again.' ) ) ;
846847 }
847848
848- // Validate that the PR has a valid head branch
849- if ( ! pullRequestModel . head ) {
850- return vscode . window . showErrorMessage ( vscode . l10n . t ( 'Unable to checkout pull request: missing head branch information.' ) ) ;
851- }
852-
853- // Store validated head to avoid non-null assertions later
854- const prHead = pullRequestModel . head ;
855-
856849 // Get the folder manager to access the repository
857850 const folderManager = reposManager . getManagerForIssueModel ( pullRequestModel ) ;
858851 if ( ! folderManager ) {
859852 return vscode . window . showErrorMessage ( vscode . l10n . t ( 'Unable to find repository for this pull request.' ) ) ;
860853 }
861854
862- const repositoryToUse = repository || folderManager . repository ;
863-
864- /* __GDPR__
865- "pr.checkoutInWorktree" : {}
866- */
867- telemetry . sendTelemetryEvent ( 'pr.checkoutInWorktree' ) ;
868-
869- // Prepare for operations
870- const repoRootPath = repositoryToUse . rootUri . fsPath ;
871- const parentDir = pathLib . dirname ( repoRootPath ) ;
872- const defaultWorktreePath = pathLib . join ( parentDir , `pr-${ pullRequestModel . number } ` ) ;
873- const branchName = prHead . ref ;
874- const remoteName = pullRequestModel . remote . remoteName ;
875-
876- // Ask user for worktree location first (not in progress)
877- const worktreeUri = await vscode . window . showSaveDialog ( {
878- defaultUri : vscode . Uri . file ( defaultWorktreePath ) ,
879- title : vscode . l10n . t ( 'Select Worktree Location' ) ,
880- saveLabel : vscode . l10n . t ( 'Create Worktree' ) ,
881- } ) ;
882-
883- if ( ! worktreeUri ) {
884- return ; // User cancelled
885- }
886-
887- const worktreePath = worktreeUri . fsPath ;
888- const trackedBranchName = `${ remoteName } /${ branchName } ` ;
889-
890- try {
891- // Check if the createWorktree API is available
892- if ( ! repositoryToUse . createWorktree ) {
893- throw new Error ( vscode . l10n . t ( 'Git worktree API is not available. Please update VS Code to the latest version.' ) ) ;
894- }
895-
896- // Start progress for fetch and worktree creation
897- await vscode . window . withProgress (
898- {
899- location : vscode . ProgressLocation . Notification ,
900- title : vscode . l10n . t ( 'Creating worktree for Pull Request #{0}...' , pullRequestModel . number ) ,
901- } ,
902- async ( ) => {
903- // Fetch the PR branch first
904- try {
905- await repositoryToUse . fetch ( { remote : remoteName , ref : branchName } ) ;
906- } catch ( e ) {
907- const errorMessage = e instanceof Error ? e . message : String ( e ) ;
908- Logger . appendLine ( `Failed to fetch branch ${ branchName } : ${ errorMessage } ` , logId ) ;
909- // Continue even if fetch fails - the branch might already be available locally
910- }
911-
912- // Check if the branch already exists locally
913- let branchExists = false ;
914- try {
915- await repositoryToUse . getBranch ( branchName ) ;
916- branchExists = true ;
917- } catch {
918- // Branch doesn't exist locally, we'll create it
919- branchExists = false ;
920- }
921-
922- // Use the git extension's createWorktree API
923- // If branch already exists, don't specify the branch parameter to avoid "branch already exists" error
924- if ( branchExists ) {
925- await repositoryToUse . createWorktree ! ( {
926- path : worktreePath ,
927- commitish : branchName
928- } ) ;
929- } else {
930- await repositoryToUse . createWorktree ! ( {
931- path : worktreePath ,
932- commitish : trackedBranchName ,
933- branch : branchName
934- } ) ;
935- }
936- }
937- ) ;
938-
939- // Ask user how they want to open the worktree (modal dialog)
940- const openInNewWindow = vscode . l10n . t ( 'New Window' ) ;
941- const openInCurrentWindow = vscode . l10n . t ( 'Current Window' ) ;
942- const result = await vscode . window . showInformationMessage (
943- vscode . l10n . t ( 'Worktree created for Pull Request #{0}. How would you like to open it?' , pullRequestModel . number ) ,
944- { modal : true } ,
945- openInNewWindow ,
946- openInCurrentWindow
947- ) ;
948-
949- if ( result === openInNewWindow ) {
950- await commands . openFolder ( worktreeUri , { forceNewWindow : true } ) ;
951- } else if ( result === openInCurrentWindow ) {
952- await commands . openFolder ( worktreeUri , { forceNewWindow : false } ) ;
953- }
954- } catch ( e ) {
955- const errorMessage = e instanceof Error ? e . message : String ( e ) ;
956- Logger . error ( `Failed to create worktree: ${ errorMessage } ` , logId ) ;
957- return vscode . window . showErrorMessage ( vscode . l10n . t ( 'Failed to create worktree: {0}' , errorMessage ) ) ;
958- }
855+ return checkoutPRInWorktree ( telemetry , folderManager , pullRequestModel , repository ) ;
959856 } ) ,
960857 ) ;
961858
@@ -967,7 +864,7 @@ export function registerCommands(
967864 if ( ! resolved ) {
968865 return vscode . window . showErrorMessage ( vscode . l10n . t ( 'Unable to resolve pull request for checkout.' ) ) ;
969866 }
970- return vscode . commands . executeCommand ( 'pr.pickInWorktree' , resolved . pr ) ;
867+ return checkoutPRInWorktree ( telemetry , resolved . folderManager , resolved . pr , undefined ) ;
971868 } ) ) ;
972869
973870 context . subscriptions . push ( vscode . commands . registerCommand ( 'pr.checkoutOnVscodeDevFromDescription' , async ( context : BaseContext | undefined ) => {
0 commit comments