|
4 | 4 | *--------------------------------------------------------------------------------------------*/ |
5 | 5 |
|
6 | 6 | import * as vscode from 'vscode'; |
7 | | -import * as fs from 'fs'; |
8 | | -import * as os from 'os'; |
9 | | -import * as path from 'path'; |
10 | 7 | import { SinonSandbox, createSandbox } from 'sinon'; |
11 | 8 | import { default as assert } from 'assert'; |
12 | 9 |
|
@@ -143,73 +140,78 @@ describe('RepositoriesManager', function () { |
143 | 140 | }); |
144 | 141 | }); |
145 | 142 |
|
146 | | - describe('removeMissingRepos', function () { |
147 | | - let tmpDir: string; |
| 143 | + describe('worktree change detection', function () { |
| 144 | + it('removes folder manager when its worktree is removed from the main repo', function () { |
| 145 | + const mainRepo = new MockRepository(); |
| 146 | + mainRepo.rootUri = vscode.Uri.file('/main-repo'); |
| 147 | + mainRepo.addRemote('origin', '[email protected]:aaa/bbb'); |
148 | 148 |
|
149 | | - beforeEach(function () { |
150 | | - tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'vscode-pr-test-')); |
151 | | - }); |
152 | | - |
153 | | - afterEach(function () { |
154 | | - fs.rmSync(tmpDir, { recursive: true, force: true }); |
155 | | - }); |
156 | | - |
157 | | - it('removes folder managers whose root URIs no longer exist on disk', async function () { |
158 | | - const existingDir = path.join(tmpDir, 'existing-repo'); |
159 | | - fs.mkdirSync(existingDir); |
| 149 | + const worktreeRepo = new MockRepository(); |
| 150 | + worktreeRepo.rootUri = vscode.Uri.file('/main-repo/worktrees/feature'); |
| 151 | + worktreeRepo.addRemote('origin', '[email protected]:aaa/bbb'); |
160 | 152 |
|
161 | | - const removedDir = path.join(tmpDir, 'removed-worktree'); |
162 | | - fs.mkdirSync(removedDir); |
163 | | - |
164 | | - const repo1 = new MockRepository(); |
165 | | - repo1.rootUri = vscode.Uri.file(existingDir); |
166 | | - repo1.addRemote('origin', '[email protected]:aaa/bbb'); |
| 153 | + reposManager.insertFolderManager(new FolderRepositoryManager(0, context, mainRepo, telemetry, new GitApiImpl(reposManager), credentialStore, createPrHelper, mockThemeWatcher)); |
| 154 | + reposManager.insertFolderManager(new FolderRepositoryManager(1, context, worktreeRepo, telemetry, new GitApiImpl(reposManager), credentialStore, createPrHelper, mockThemeWatcher)); |
167 | 155 |
|
168 | | - const repo2 = new MockRepository(); |
169 | | - repo2.rootUri = vscode.Uri.file(removedDir); |
170 | | - repo2.addRemote('origin', '[email protected]:aaa/bbb'); |
| 156 | + assert.strictEqual(reposManager.folderManagers.length, 2); |
171 | 157 |
|
172 | | - reposManager.insertFolderManager(new FolderRepositoryManager(0, context, repo1, telemetry, new GitApiImpl(reposManager), credentialStore, createPrHelper, mockThemeWatcher)); |
173 | | - reposManager.insertFolderManager(new FolderRepositoryManager(1, context, repo2, telemetry, new GitApiImpl(reposManager), credentialStore, createPrHelper, mockThemeWatcher)); |
| 158 | + // Set initial worktrees on the main repo (includes the worktree) |
| 159 | + mainRepo.setWorktrees([ |
| 160 | + { name: 'main-repo', path: '/main-repo', ref: 'main', main: true, detached: false }, |
| 161 | + { name: 'feature', path: '/main-repo/worktrees/feature', ref: 'feature', main: false, detached: false }, |
| 162 | + ]); |
174 | 163 |
|
175 | 164 | assert.strictEqual(reposManager.folderManagers.length, 2); |
176 | 165 |
|
177 | | - // Remove the directory to simulate worktree deletion |
178 | | - fs.rmSync(removedDir, { recursive: true }); |
179 | | - |
180 | | - await reposManager.removeMissingRepos(); |
| 166 | + // Worktree is removed - main repo state changes with updated worktrees |
| 167 | + mainRepo.setWorktrees([ |
| 168 | + { name: 'main-repo', path: '/main-repo', ref: 'main', main: true, detached: false }, |
| 169 | + ]); |
181 | 170 |
|
182 | 171 | assert.strictEqual(reposManager.folderManagers.length, 1); |
183 | | - assert.strictEqual(reposManager.folderManagers[0].repository.rootUri.toString(), repo1.rootUri.toString()); |
| 172 | + assert.strictEqual(reposManager.folderManagers[0].repository.rootUri.toString(), mainRepo.rootUri.toString()); |
184 | 173 | }); |
185 | 174 |
|
186 | | - it('keeps all repos when all paths exist on disk', async function () { |
187 | | - const dir1 = path.join(tmpDir, 'repo1'); |
188 | | - fs.mkdirSync(dir1); |
| 175 | + it('does not remove folder managers when worktrees remain unchanged', function () { |
| 176 | + const mainRepo = new MockRepository(); |
| 177 | + mainRepo.rootUri = vscode.Uri.file('/main-repo'); |
| 178 | + mainRepo.addRemote('origin', '[email protected]:aaa/bbb'); |
189 | 179 |
|
190 | | - const dir2 = path.join(tmpDir, 'repo2'); |
191 | | - fs.mkdirSync(dir2); |
| 180 | + const worktreeRepo = new MockRepository(); |
| 181 | + worktreeRepo.rootUri = vscode.Uri.file('/main-repo/worktrees/feature'); |
| 182 | + worktreeRepo.addRemote('origin', '[email protected]:aaa/bbb'); |
192 | 183 |
|
193 | | - const repo1 = new MockRepository(); |
194 | | - repo1.rootUri = vscode.Uri.file(dir1); |
195 | | - repo1.addRemote('origin', '[email protected]:aaa/bbb'); |
| 184 | + reposManager.insertFolderManager(new FolderRepositoryManager(0, context, mainRepo, telemetry, new GitApiImpl(reposManager), credentialStore, createPrHelper, mockThemeWatcher)); |
| 185 | + reposManager.insertFolderManager(new FolderRepositoryManager(1, context, worktreeRepo, telemetry, new GitApiImpl(reposManager), credentialStore, createPrHelper, mockThemeWatcher)); |
196 | 186 |
|
197 | | - const repo2 = new MockRepository(); |
198 | | - repo2.rootUri = vscode.Uri.file(dir2); |
199 | | - repo2.addRemote('origin', '[email protected]:ccc/ddd'); |
200 | | - |
201 | | - reposManager.insertFolderManager(new FolderRepositoryManager(0, context, repo1, telemetry, new GitApiImpl(reposManager), credentialStore, createPrHelper, mockThemeWatcher)); |
202 | | - reposManager.insertFolderManager(new FolderRepositoryManager(1, context, repo2, telemetry, new GitApiImpl(reposManager), credentialStore, createPrHelper, mockThemeWatcher)); |
| 187 | + // Set initial worktrees |
| 188 | + mainRepo.setWorktrees([ |
| 189 | + { name: 'main-repo', path: '/main-repo', ref: 'main', main: true, detached: false }, |
| 190 | + { name: 'feature', path: '/main-repo/worktrees/feature', ref: 'feature', main: false, detached: false }, |
| 191 | + ]); |
203 | 192 |
|
204 | | - await reposManager.removeMissingRepos(); |
| 193 | + // Fire state change again with same worktrees |
| 194 | + mainRepo.setWorktrees([ |
| 195 | + { name: 'main-repo', path: '/main-repo', ref: 'main', main: true, detached: false }, |
| 196 | + { name: 'feature', path: '/main-repo/worktrees/feature', ref: 'feature', main: false, detached: false }, |
| 197 | + ]); |
205 | 198 |
|
206 | 199 | assert.strictEqual(reposManager.folderManagers.length, 2); |
207 | 200 | }); |
208 | 201 |
|
209 | | - it('does nothing when there are no folder managers', async function () { |
210 | | - assert.strictEqual(reposManager.folderManagers.length, 0); |
211 | | - await reposManager.removeMissingRepos(); |
212 | | - assert.strictEqual(reposManager.folderManagers.length, 0); |
| 202 | + it('does nothing when worktrees property is not available', function () { |
| 203 | + const repo = new MockRepository(); |
| 204 | + repo.rootUri = vscode.Uri.file('/repo'); |
| 205 | + repo.addRemote('origin', '[email protected]:aaa/bbb'); |
| 206 | + |
| 207 | + reposManager.insertFolderManager(new FolderRepositoryManager(0, context, repo, telemetry, new GitApiImpl(reposManager), credentialStore, createPrHelper, mockThemeWatcher)); |
| 208 | + |
| 209 | + assert.strictEqual(reposManager.folderManagers.length, 1); |
| 210 | + |
| 211 | + // Fire state change without setting worktrees (stays undefined) |
| 212 | + (repo as any)._onDidChangeState.fire(); |
| 213 | + |
| 214 | + assert.strictEqual(reposManager.folderManagers.length, 1); |
213 | 215 | }); |
214 | 216 | }); |
215 | 217 | }); |
0 commit comments