Something went wrong. Try again.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105/** * cwd classification tests (saga j8dtju.5 — phase 1). * * Real-git coverage of the three-class conservative classification: non-Git, main checkout, * linked/user worktree — plus the pure `classifyResolved` against a hand-built identity. * Classification never persists/binds/creates anything (no catalog calls here). */import { describe, expect, it } from 'bun:test';import { join } from 'node:path';import { classifyCwd, classifyResolved, createClassifier, defaultGitRunner, GitRepositoryResolver, type ResolvedWorkspaceIdentity,} from '@/core/git';import { addLinkedWorktree, buildMainRepo, detachHead, dispose, freshTmp,} from '../../helpers/git-fixtures';
/** A hand-built resolved identity with select paths (avoids any git call). */function identity(commonDir: string, toplevel: string, gitDir: string): ResolvedWorkspaceIdentity { return { repository: { commonDir, commonDirFingerprint: 'fp-' + commonDir }, worktree: { toplevel, toplevelFingerprint: 'fp-' + toplevel, gitDir }, head: { commit: '0'.repeat(40), branch: 'refs/heads/main' }, };}
describe('classifyResolved (pure)', () => { it('classifies gitDir === commonDir as main-checkout', () => { const id = identity('/r/.git', '/r', '/r/.git'); expect(classifyResolved(id).kind).toBe('main-checkout'); });
it('classifies a gitDir under commonDir/worktrees as linked-worktree', () => { const id = identity('/r/.git', '/r/linked', '/r/.git/worktrees/linked'); expect(classifyResolved(id).kind).toBe('linked-worktree'); });});
describe('classifyCwd — real-git', () => { it('classifies a main checkout as `main-checkout`', async () => { const repo = freshTmp('shard-classify-main-'); try { await buildMainRepo(repo); const resolver = new GitRepositoryResolver(defaultGitRunner); const out = await classifyCwd(repo, resolver); expect(out.kind).toBe('main-checkout'); } finally { dispose(repo); } });
it('classifies a linked worktree as `linked-worktree` while the main checkout stays main', async () => { const parent = freshTmp('shard-classify-linked-'); const main = join(parent, 'main'); const linked = join(parent, 'linked'); try { await buildMainRepo(main); await addLinkedWorktree(main, linked, 'feature'); const { resolver, classify } = createClassifier(defaultGitRunner); expect((await classify(main)).kind).toBe('main-checkout'); expect((await classify(linked)).kind).toBe('linked-worktree'); // Both share the same repo fingerprint (sanity for the catalog's dedup later). const mainOut = await resolver.resolveIdentity(main); const linkedOut = await resolver.resolveIdentity(linked); if (mainOut.kind === 'ok' && linkedOut.kind === 'ok') { expect(linkedOut.identity.repository.commonDirFingerprint).toBe( mainOut.identity.repository.commonDirFingerprint, ); } } finally { dispose(parent); } });
it('classifies a detached-HEAD checkout as the worktree kind it is (main here)', async () => { const repo = freshTmp('shard-classify-detached-'); try { await buildMainRepo(repo); await detachHead(repo); const out = await classifyCwd(repo, new GitRepositoryResolver(defaultGitRunner)); expect(out.kind).toBe('main-checkout'); } finally { dispose(repo); } });
it('classifies a non-Git cwd as `non-git`', async () => { const dir = freshTmp('shard-classify-nongit-'); try { const out = await classifyCwd(dir, new GitRepositoryResolver(defaultGitRunner)); expect(out.kind).toBe('non-git'); } finally { dispose(dir); } });});