@@ -5,8 +5,10 @@ import { afterEach, describe, expect, it } from "vitest";
55import { createGitClient } from "./client" ;
66import {
77 detectDefaultBranch ,
8+ getAllBranches ,
89 getBranchDiffPatchesByPath ,
910 getChangedFilesDetailed ,
11+ getGitBusyState ,
1012 splitUnifiedDiffByFile ,
1113} from "./queries" ;
1214
@@ -312,3 +314,85 @@ describe("getChangedFilesDetailed > untracked line counts", () => {
312314 } ) ;
313315 } ) ;
314316} ) ;
317+
318+ describe ( "getAllBranches" , ( ) => {
319+ let repoDir : string | undefined ;
320+
321+ afterEach ( async ( ) => {
322+ if ( repoDir ) {
323+ await rm ( repoDir , { recursive : true , force : true } ) ;
324+ repoDir = undefined ;
325+ }
326+ } ) ;
327+
328+ async function setupRebaseConflict ( dir : string ) : Promise < void > {
329+ const git = createGitClient ( dir ) ;
330+ await git . checkoutLocalBranch ( "feature" ) ;
331+ await writeFile ( path . join ( dir , "file.txt" ) , "feature change\n" ) ;
332+ await git . add ( [ "file.txt" ] ) ;
333+ await git . commit ( "on feature" ) ;
334+ await git . checkout ( "main" ) ;
335+ await writeFile ( path . join ( dir , "file.txt" ) , "main change\n" ) ;
336+ await git . add ( [ "file.txt" ] ) ;
337+ await git . commit ( "on main" ) ;
338+ await git . checkout ( "feature" ) ;
339+ try {
340+ await git . rebase ( [ "main" ] ) ;
341+ } catch {
342+ // expected: rebase pauses on conflict, leaving HEAD on a pseudo-branch
343+ }
344+ }
345+
346+ it ( "returns only real branches, not the rebase pseudo-branch" , async ( ) => {
347+ repoDir = await setupRepo ( "main" ) ;
348+ await setupRebaseConflict ( repoDir ) ;
349+
350+ const branches = await getAllBranches ( repoDir ) ;
351+ expect ( branches ) . toEqual ( expect . arrayContaining ( [ "main" , "feature" ] ) ) ;
352+ expect ( branches ) . not . toContain ( "(no" ) ;
353+ expect ( branches . every ( ( b ) => ! b . startsWith ( "(" ) ) ) . toBe ( true ) ;
354+ } ) ;
355+ } ) ;
356+
357+ describe ( "getGitBusyState" , ( ) => {
358+ let repoDir : string | undefined ;
359+
360+ afterEach ( async ( ) => {
361+ if ( repoDir ) {
362+ await rm ( repoDir , { recursive : true , force : true } ) ;
363+ repoDir = undefined ;
364+ }
365+ } ) ;
366+
367+ it ( "reports busy=false in a clean repo" , async ( ) => {
368+ repoDir = await setupRepo ( "main" ) ;
369+ expect ( await getGitBusyState ( repoDir ) ) . toEqual ( { busy : false } ) ;
370+ } ) ;
371+
372+ it ( "detects an in-progress rebase" , async ( ) => {
373+ repoDir = await setupRepo ( "main" ) ;
374+ const git = createGitClient ( repoDir ) ;
375+
376+ await git . checkoutLocalBranch ( "feature" ) ;
377+ await writeFile ( path . join ( repoDir , "file.txt" ) , "feature change\n" ) ;
378+ await git . add ( [ "file.txt" ] ) ;
379+ await git . commit ( "on feature" ) ;
380+
381+ await git . checkout ( "main" ) ;
382+ await writeFile ( path . join ( repoDir , "file.txt" ) , "main change\n" ) ;
383+ await git . add ( [ "file.txt" ] ) ;
384+ await git . commit ( "on main" ) ;
385+
386+ await git . checkout ( "feature" ) ;
387+ try {
388+ await git . rebase ( [ "main" ] ) ;
389+ } catch {
390+ // expected: conflict
391+ }
392+
393+ expect ( await getGitBusyState ( repoDir ) ) . toEqual ( {
394+ busy : true ,
395+ operation : "rebase" ,
396+ } ) ;
397+ } ) ;
398+ } ) ;
0 commit comments