@@ -191,6 +191,83 @@ public void ConcurrentWorktreeAddCommitRemove()
191191 }
192192 }
193193
194+ [ TestCase ]
195+ public void WorktreeOutsideEnlistmentTree ( )
196+ {
197+ string suffix = Guid . NewGuid ( ) . ToString ( "N" ) . Substring ( 0 , 8 ) ;
198+ string tempDir = Path . Combine ( Path . GetTempPath ( ) , $ "gvfs-remote-wt-{ suffix } ") ;
199+ string worktreePath = Path . Combine ( tempDir , "wt" ) ;
200+ string branchName = $ "remote-wt-test-{ suffix } ";
201+
202+ try
203+ {
204+ Directory . CreateDirectory ( tempDir ) ;
205+
206+ // 1. Create worktree outside the enlistment tree
207+ ProcessResult addResult = GitHelpers . InvokeGitAgainstGVFSRepo (
208+ this . Enlistment . RepoRoot ,
209+ $ "worktree add -b { branchName } \" { worktreePath } \" ") ;
210+ addResult . ExitCode . ShouldEqual ( 0 ,
211+ $ "worktree add failed: { addResult . Errors } ") ;
212+
213+ // 2. Verify GVFS mount is running
214+ this . AssertWorktreeMounted ( worktreePath , "remote worktree" ) ;
215+
216+ // 3. Verify git status works from the worktree root
217+ ProcessResult statusResult = GitHelpers . InvokeGitAgainstGVFSRepo (
218+ worktreePath , "status --porcelain" ) ;
219+ statusResult . ExitCode . ShouldEqual ( 0 ,
220+ $ "git status from worktree root failed: { statusResult . Errors } ") ;
221+ statusResult . Output . Trim ( ) . ShouldBeEmpty (
222+ "Remote worktree should have clean status" ) ;
223+
224+ // 4. Verify projected files are visible
225+ File . Exists ( Path . Combine ( worktreePath , "Readme.md" ) ) . ShouldBeTrue (
226+ "Readme.md should be projected in remote worktree" ) ;
227+
228+ // 5. Verify git status works from a subdirectory
229+ string subDir = Path . Combine ( worktreePath , "GVFS" ) ;
230+ Directory . Exists ( subDir ) . ShouldBeTrue (
231+ "Subdirectory GVFS should be projected" ) ;
232+ ProcessResult subDirStatus = GitHelpers . InvokeGitAgainstGVFSRepo (
233+ subDir , "status --porcelain" ) ;
234+ subDirStatus . ExitCode . ShouldEqual ( 0 ,
235+ $ "git status from subdirectory failed: { subDirStatus . Errors } ") ;
236+
237+ // 6. Verify commits work
238+ File . WriteAllText (
239+ Path . Combine ( worktreePath , "remote-test.txt" ) ,
240+ "created in remote worktree" ) ;
241+ GitHelpers . InvokeGitAgainstGVFSRepo ( worktreePath , "add remote-test.txt" )
242+ . ExitCode . ShouldEqual ( 0 ) ;
243+ GitHelpers . InvokeGitAgainstGVFSRepo (
244+ worktreePath , "commit -m \" commit from remote worktree\" " )
245+ . ExitCode . ShouldEqual ( 0 ) ;
246+
247+ // 7. Verify commit is visible from primary repo
248+ GitHelpers . InvokeGitAgainstGVFSRepo (
249+ this . Enlistment . RepoRoot , $ "log -1 --format=%s { branchName } ")
250+ . Output . ShouldContain ( expectedSubstrings : new [ ] { "commit from remote worktree" } ) ;
251+
252+ // 8. Remove worktree
253+ ProcessResult removeResult = GitHelpers . InvokeGitAgainstGVFSRepo (
254+ this . Enlistment . RepoRoot ,
255+ $ "worktree remove --force \" { worktreePath } \" ") ;
256+ removeResult . ExitCode . ShouldEqual ( 0 ,
257+ $ "worktree remove failed: { removeResult . Errors } ") ;
258+ Directory . Exists ( worktreePath ) . ShouldBeFalse (
259+ "Remote worktree directory should be deleted" ) ;
260+ }
261+ finally
262+ {
263+ this . ForceCleanupWorktree ( worktreePath , branchName ) ;
264+ if ( Directory . Exists ( tempDir ) )
265+ {
266+ try { Directory . Delete ( tempDir , recursive : true ) ; } catch { }
267+ }
268+ }
269+ }
270+
194271 private void InitWorktreeArrays ( int count , out string [ ] paths , out string [ ] branches )
195272 {
196273 paths = new string [ count ] ;
0 commit comments