@@ -242,6 +242,7 @@ import {
242242 listWorktrees ,
243243 getMainWorktreePath ,
244244 removeWorktree ,
245+ moveWorktree ,
245246 getCommitRangeDiff ,
246247 getCommitRangeChangedFiles ,
247248 updateRemoteHEAD ,
@@ -257,7 +258,6 @@ import {
257258 IConfigValueOrigin ,
258259 unstageAll ,
259260 git ,
260- moveWorktree ,
261261} from '../git'
262262import {
263263 installGlobalLFSFilters ,
@@ -3140,13 +3140,30 @@ export class AppStore extends TypedBaseStore<IAppState> {
31403140 this . updateMenuLabelsForSelectedRepository ( )
31413141 }
31423142
3143+ /**
3144+ * Determine whether the worktree dropdown is currently shown in the toolbar.
3145+ *
3146+ * This mirrors the render condition in `App.renderWorktreeToolbarButton`: the
3147+ * dropdown is shown when worktree support is enabled and either the selected
3148+ * repository has at least one linked worktree (i.e. more than just the main
3149+ * worktree) or the worktree foldout is currently open (which lets the user
3150+ * create their first worktree from the toolbar).
3151+ */
31433152 private isWorktreeDropdownVisible ( ) : boolean {
3153+ if ( ! enableWorktreeSupport ( ) || ! this . showWorktrees ) {
3154+ return false
3155+ }
3156+
3157+ if ( this . currentFoldout ?. type === FoldoutType . Worktree ) {
3158+ return true
3159+ }
3160+
31443161 const repository = this . selectedRepository
31453162 const worktreeCount =
31463163 repository instanceof Repository
31473164 ? this . repositoryStateCache . get ( repository ) . worktrees . length
31483165 : 0
3149- return enableWorktreeSupport ( ) && this . showWorktrees && worktreeCount > 1
3166+ return worktreeCount > 1
31503167 }
31513168
31523169 /**
@@ -3206,8 +3223,10 @@ export class AppStore extends TypedBaseStore<IAppState> {
32063223 this . stashedFilesWidth = constrain ( this . stashedFilesWidth , 100 , filesMax )
32073224
32083225 // Allocate worktree first (highest priority), then branch, then
3209- // push-pull. Each subsequent allocation uses the clamped value of the
3210- // previous to prevent the total from exceeding the available space.
3226+ // push-pull. The foldouts are laid out in this order, so the width
3227+ // constraints should follow the same order. Each subsequent allocation
3228+ // uses the clamped value of the previous to prevent the total from
3229+ // exceeding the available space.
32113230 const worktreeDropdownMax =
32123231 available - defaultBranchDropdownWidth - defaultPushPullButtonWidth
32133232 this . worktreeDropdownWidth = constrain (
@@ -5081,6 +5100,14 @@ export class AppStore extends TypedBaseStore<IAppState> {
50815100 /** This shouldn't be called directly. See `Dispatcher`. */
50825101 public async _showFoldout ( foldout : Foldout ) : Promise < void > {
50835102 this . currentFoldout = foldout
5103+
5104+ // Showing the worktree foldout makes the worktree dropdown visible even
5105+ // when there are no linked worktrees, so the toolbar width allocation has
5106+ // to be recalculated to reserve space for it.
5107+ if ( foldout . type === FoldoutType . Worktree ) {
5108+ this . updateResizableConstraints ( )
5109+ }
5110+
50845111 this . emitUpdate ( )
50855112
50865113 // If the user is opening the repository list and we haven't yet
@@ -5101,7 +5128,14 @@ export class AppStore extends TypedBaseStore<IAppState> {
51015128 return
51025129 }
51035130
5131+ const wasWorktreeFoldout = this . currentFoldout . type === FoldoutType . Worktree
5132+
51045133 this . currentFoldout = null
5134+
5135+ if ( wasWorktreeFoldout ) {
5136+ this . updateResizableConstraints ( )
5137+ }
5138+
51055139 this . emitUpdate ( )
51065140 }
51075141
@@ -5115,7 +5149,14 @@ export class AppStore extends TypedBaseStore<IAppState> {
51155149 return
51165150 }
51175151
5152+ const wasWorktreeFoldout = this . currentFoldout . type === FoldoutType . Worktree
5153+
51185154 this . currentFoldout = null
5155+
5156+ if ( wasWorktreeFoldout ) {
5157+ this . updateResizableConstraints ( )
5158+ }
5159+
51195160 this . emitUpdate ( )
51205161 }
51215162
@@ -6999,6 +7040,10 @@ export class AppStore extends TypedBaseStore<IAppState> {
69997040 throw new Error ( 'Could not find main worktree' )
70007041 }
70017042
7043+ // Switch to the main worktree before deleting the current one since the
7044+ // current worktree path will be deleted after the switch. Use the
7045+ // resulting repository (with the updated path) for the subsequent
7046+ // remove and refresh calls.
70027047 repository = await this . _switchWorktree ( repository , main )
70037048 }
70047049
@@ -7014,23 +7059,41 @@ export class AppStore extends TypedBaseStore<IAppState> {
70147059 error : e ,
70157060 originalWorktree,
70167061 } )
7062+ return
70177063 }
70187064
70197065 await this . _refreshWorktrees ( repository )
70207066 this . statsStore . increment ( 'worktreeDeletedCount' )
70217067 }
70227068
7069+ /** This shouldn't be called directly. See 'Dispatcher'. */
70237070 public async _moveWorktree (
70247071 repository : Repository ,
70257072 worktreePath : string ,
70267073 newPath : string
70277074 ) : Promise < void > {
70287075 await moveWorktree ( repository , worktreePath , newPath )
7029- const result = await this . repositoriesStore . switchWorktree (
7030- repository ,
7031- newPath
7032- )
7033- await this . _refreshWorktrees ( result . repository )
7076+
7077+ // If the worktree being renamed is the currently selected one, switch to
7078+ // its new path so that the subsequent refresh (and any further git calls)
7079+ // operate on the renamed directory rather than the now non-existing one.
7080+ if ( repository . path === worktreePath ) {
7081+ const result = await this . repositoriesStore . switchWorktree (
7082+ repository ,
7083+ newPath
7084+ )
7085+
7086+ // Renaming changes the repository's path and therefore its hash, which
7087+ // is the key used by the state cache. Carry the existing state over to
7088+ // the new identity so we don't reset the UI (e.g. a typed commit
7089+ // message) just because the worktree was renamed.
7090+ this . repositoryStateCache . transferState ( repository , result . repository )
7091+
7092+ await this . _selectRepository ( result . repository )
7093+ await this . _refreshWorktrees ( result . repository )
7094+ } else {
7095+ await this . _refreshWorktrees ( repository )
7096+ }
70347097 }
70357098
70367099 public _setWorktreeDropdownWidth ( width : number ) : Promise < void > {
0 commit comments