diff --git a/src/cli/actions/remoteAction.ts b/src/cli/actions/remoteAction.ts index 992d4c95f..1cfbcf719 100644 --- a/src/cli/actions/remoteAction.ts +++ b/src/cli/actions/remoteAction.ts @@ -29,7 +29,7 @@ export const runRemoteAction = async ( spinner.start(); // Clone the repository - await cloneRepository(formatGitUrl(repoUrl), tempDirPath, { + await cloneRepository(formatGitUrl(repoUrl), tempDirPath, options.remoteBranch, { execGitShallowClone: deps.execGitShallowClone, }); @@ -73,6 +73,7 @@ export const createTempDirectory = async (): Promise => { export const cloneRepository = async ( url: string, directory: string, + branch?: string, deps = { execGitShallowClone: execGitShallowClone, }, @@ -81,7 +82,7 @@ export const cloneRepository = async ( logger.log(''); try { - await deps.execGitShallowClone(url, directory); + await deps.execGitShallowClone(url, directory, branch); } catch (error) { throw new RepomixError(`Failed to clone repository: ${(error as Error).message}`); } diff --git a/src/cli/cliRun.ts b/src/cli/cliRun.ts index 0693016bb..775ba5d9b 100644 --- a/src/cli/cliRun.ts +++ b/src/cli/cliRun.ts @@ -24,6 +24,7 @@ export interface CliOptions extends OptionValues { init?: boolean; global?: boolean; remote?: string; + remoteBranch?: string; } export const run = async () => { @@ -44,6 +45,7 @@ export const run = async () => { .option('--init', 'initialize a new repomix.config.json file') .option('--global', 'use global configuration (only applicable with --init)') .option('--remote ', 'process a remote Git repository') + .option('--remote-branch ', 'select a specific branch or commit id') .action((directory = '.', options: CliOptions = {}) => executeAction(directory, process.cwd(), options)); await program.parseAsync(process.argv); diff --git a/src/core/file/gitCommand.ts b/src/core/file/gitCommand.ts index c243f7e92..b8801ee7b 100644 --- a/src/core/file/gitCommand.ts +++ b/src/core/file/gitCommand.ts @@ -21,9 +21,10 @@ export const isGitInstalled = async ( export const execGitShallowClone = async ( url: string, directory: string, + branch?: string, deps = { execAsync, }, ) => { - await deps.execAsync(`git clone --depth 1 ${url} ${directory}`); + await deps.execAsync(`git clone --depth 1 ${branch ? `-b ${branch} ` : ''}${url} ${directory}`); }; diff --git a/tests/core/file/gitCommand.test.ts b/tests/core/file/gitCommand.test.ts index cc5c790c8..1864390bd 100644 --- a/tests/core/file/gitCommand.test.ts +++ b/tests/core/file/gitCommand.test.ts @@ -44,21 +44,34 @@ describe('gitCommand', () => { const mockExecAsync = vi.fn().mockResolvedValue({ stdout: '', stderr: '' }); const url = 'https://github.com/user/repo.git'; const directory = '/tmp/repo'; + const branch = 'master'; - await execGitShallowClone(url, directory, { execAsync: mockExecAsync }); + await execGitShallowClone(url, directory, branch, { execAsync: mockExecAsync }); - expect(mockExecAsync).toHaveBeenCalledWith(`git clone --depth 1 ${url} ${directory}`); + expect(mockExecAsync).toHaveBeenCalledWith(`git clone --depth 1 -b ${branch} ${url} ${directory}`); }); test('should throw error when git clone fails', async () => { const mockExecAsync = vi.fn().mockRejectedValue(new Error('Authentication failed')); const url = 'https://github.com/user/repo.git'; const directory = '/tmp/repo'; + const branch = 'master'; - await expect(execGitShallowClone(url, directory, { execAsync: mockExecAsync })).rejects.toThrow( + await expect(execGitShallowClone(url, directory, branch, { execAsync: mockExecAsync })).rejects.toThrow( 'Authentication failed', ); + expect(mockExecAsync).toHaveBeenCalledWith(`git clone --depth 1 -b ${branch} ${url} ${directory}`); + }); + + test('should execute without branch option if not specified by user', async () => { + const mockExecAsync = vi.fn().mockResolvedValue({ stdout: '', stderr: '' }); + const url = 'https://github.com/user/repo.git'; + const directory = '/tmp/repo'; + const branch = undefined; + + await execGitShallowClone(url, directory, branch, { execAsync: mockExecAsync }); + expect(mockExecAsync).toHaveBeenCalledWith(`git clone --depth 1 ${url} ${directory}`); }); });