1+ import { execFile } from 'node:child_process' ;
12import { mkdtemp , rm , writeFile } from 'node:fs/promises' ;
23import { createRequire } from 'node:module' ;
34import { tmpdir } from 'node:os' ;
45import { join } from 'node:path' ;
6+ import { promisify } from 'node:util' ;
57import { expect , test } from 'vite-plus/test' ;
68
79const require = createRequire ( import . meta. url ) ;
@@ -12,7 +14,10 @@ const { getInitialRepositoryPath, parseCommandLineArguments, parseGitHubRemoteUr
1214 launchOptions : {
1315 codexSessionId ?: string ;
1416 repositoryPathProvided : boolean ;
15- source ?: { ref : string ; type : 'commit' } | { type : 'pull-request' ; url : string } ;
17+ source ?:
18+ | { ref : string ; type : 'branch' }
19+ | { ref : string ; type : 'commit' }
20+ | { type : 'pull-request' ; url : string } ;
1621 walkthrough : boolean ;
1722 walkthroughContext ?: unknown ;
1823 } ,
@@ -23,7 +28,10 @@ const { getInitialRepositoryPath, parseCommandLineArguments, parseGitHubRemoteUr
2328 launchOptions : {
2429 codexSessionId ?: string ;
2530 repositoryPathProvided : boolean ;
26- source ?: { ref : string ; type : 'commit' } | { type : 'pull-request' ; url : string } ;
31+ source ?:
32+ | { ref : string ; type : 'branch' }
33+ | { ref : string ; type : 'commit' }
34+ | { type : 'pull-request' ; url : string } ;
2735 walkthrough : boolean ;
2836 walkthroughContext ?: unknown ;
2937 } ;
@@ -33,6 +41,12 @@ const { getInitialRepositoryPath, parseCommandLineArguments, parseGitHubRemoteUr
3341 parseGitHubRemoteUrl : ( value : string ) => { owner : string ; repo : string } | null ;
3442 } ;
3543
44+ const execFileAsync = promisify ( execFile ) ;
45+
46+ const git = async ( repo : string , args : ReadonlyArray < string > ) => {
47+ await execFileAsync ( 'git' , [ '-C' , repo , ...args ] , { encoding : 'utf8' } ) ;
48+ } ;
49+
3650const defaultLaunchOptions = {
3751 repositoryPathProvided : false ,
3852 walkthrough : false ,
@@ -83,6 +97,82 @@ test('parses positional HEAD revisions as commit sources', () => {
8397 } ) ;
8498} ) ;
8599
100+ test ( 'parses plain refs as branch sources' , async ( ) => {
101+ const repositoryPath = await mkdtemp ( join ( tmpdir ( ) , 'codiff-branch-ref-' ) ) ;
102+ const previousCwd = process . cwd ( ) ;
103+
104+ try {
105+ await git ( repositoryPath , [ 'init' ] ) ;
106+ await git ( repositoryPath , [ 'config' , 'user.email' , 'codiff@example.com' ] ) ;
107+ await git ( repositoryPath , [ 'config' , 'user.name' , 'Codiff Test' ] ) ;
108+ await git ( repositoryPath , [ 'commit' , '--allow-empty' , '-m' , 'initial commit' ] ) ;
109+ await git ( repositoryPath , [ 'checkout' , '-b' , 'feature' ] ) ;
110+ process . chdir ( repositoryPath ) ;
111+
112+ expect ( parseCommandLineArguments ( [ 'codiff' , 'feature' ] ) ) . toEqual ( {
113+ launchOptions : {
114+ repositoryPathProvided : false ,
115+ source : {
116+ ref : 'feature' ,
117+ type : 'branch' ,
118+ } ,
119+ walkthrough : false ,
120+ } ,
121+ pullRequestNumber : null ,
122+ repositoryPath : null ,
123+ } ) ;
124+
125+ expect ( parseCommandLineArguments ( [ 'codiff' , 'feature' , repositoryPath ] ) ) . toEqual ( {
126+ launchOptions : {
127+ repositoryPathProvided : true ,
128+ source : {
129+ ref : 'feature' ,
130+ type : 'branch' ,
131+ } ,
132+ walkthrough : false ,
133+ } ,
134+ pullRequestNumber : null ,
135+ repositoryPath,
136+ } ) ;
137+ } finally {
138+ process . chdir ( previousCwd ) ;
139+ await rm ( repositoryPath , { force : true , recursive : true } ) ;
140+ }
141+ } ) ;
142+
143+ test ( 'parses hex-like refs as commits before branches' , async ( ) => {
144+ const repositoryPath = await mkdtemp ( join ( tmpdir ( ) , 'codiff-hex-ref-' ) ) ;
145+ const previousCwd = process . cwd ( ) ;
146+
147+ try {
148+ await git ( repositoryPath , [ 'init' ] ) ;
149+ await git ( repositoryPath , [ 'config' , 'user.email' , 'codiff@example.com' ] ) ;
150+ await git ( repositoryPath , [ 'config' , 'user.name' , 'Codiff Test' ] ) ;
151+ await git ( repositoryPath , [ 'commit' , '--allow-empty' , '-m' , 'initial commit' ] ) ;
152+ const { stdout } = await execFileAsync ( 'git' , [ '-C' , repositoryPath , 'rev-parse' , 'HEAD' ] , {
153+ encoding : 'utf8' ,
154+ } ) ;
155+ const shortHash = stdout . trim ( ) . slice ( 0 , 8 ) ;
156+ await git ( repositoryPath , [ 'branch' , shortHash ] ) ;
157+ process . chdir ( repositoryPath ) ;
158+
159+ expect ( parseCommandLineArguments ( [ 'codiff' , shortHash ] ) . launchOptions . source ) . toEqual ( {
160+ ref : shortHash ,
161+ type : 'commit' ,
162+ } ) ;
163+
164+ expect (
165+ parseCommandLineArguments ( [ 'codiff' , '--branch' , shortHash ] ) . launchOptions . source ,
166+ ) . toEqual ( {
167+ ref : shortHash ,
168+ type : 'branch' ,
169+ } ) ;
170+ } finally {
171+ process . chdir ( previousCwd ) ;
172+ await rm ( repositoryPath , { force : true , recursive : true } ) ;
173+ }
174+ } ) ;
175+
86176test ( 'parses Codex walkthrough seed command-line options' , async ( ) => {
87177 const directory = await mkdtemp ( join ( tmpdir ( ) , 'codiff-context-' ) ) ;
88178 const contextPath = join ( directory , 'seed.json' ) ;
0 commit comments