UNPKG

aico-pack

Version:

A tool to pack repository contents to single file for AI consumption

165 lines 8.16 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import * as fs from 'node:fs/promises'; import os from 'node:os'; import path from 'node:path'; import pc from 'picocolors'; import { execGitShallowClone } from '../../core/git/gitCommand.js'; import { downloadGitHubArchive, isArchiveDownloadSupported } from '../../core/git/gitHubArchive.js'; import { getRemoteRefs } from '../../core/git/gitRemoteHandle.js'; import { isGitHubRepository, parseGitHubRepoInfo, parseRemoteValue } from '../../core/git/gitRemoteParse.js'; import { isGitInstalled } from '../../core/git/gitRepositoryHandle.js'; import { RepomixError } from '../../shared/errorHandle.js'; import { logger } from '../../shared/logger.js'; import { Spinner } from '../cliSpinner.js'; import { runDefaultAction } from './defaultAction.js'; export const runRemoteAction = (repoUrl_1, cliOptions_1, ...args_1) => __awaiter(void 0, [repoUrl_1, cliOptions_1, ...args_1], void 0, function* (repoUrl, cliOptions, deps = { isGitInstalled, execGitShallowClone, getRemoteRefs, runDefaultAction, downloadGitHubArchive, isGitHubRepository, parseGitHubRepoInfo, isArchiveDownloadSupported, }) { var _a; let tempDirPath = yield createTempDirectory(); let result; let downloadMethod = 'git'; try { // Check if this is a GitHub repository and archive download is supported const githubRepoInfo = deps.parseGitHubRepoInfo(repoUrl); const shouldTryArchive = githubRepoInfo && deps.isArchiveDownloadSupported(githubRepoInfo); if (shouldTryArchive) { // Try GitHub archive download first const spinner = new Spinner('Downloading repository archive...', cliOptions); try { spinner.start(); // Override ref with CLI option if provided const repoInfoWithBranch = Object.assign(Object.assign({}, githubRepoInfo), { ref: (_a = cliOptions.remoteBranch) !== null && _a !== void 0 ? _a : githubRepoInfo.ref }); yield deps.downloadGitHubArchive(repoInfoWithBranch, tempDirPath, { timeout: 60000, // 1 minute timeout for large repos retries: 2, }, (progress) => { if (progress.percentage !== null) { spinner.update(`Downloading repository archive... (${progress.percentage}%)`); } else { // Show downloaded bytes when percentage is not available const downloadedMB = (progress.downloaded / 1024 / 1024).toFixed(1); spinner.update(`Downloading repository archive... (${downloadedMB} MB)`); } }); downloadMethod = 'archive'; spinner.succeed('Repository archive downloaded successfully!'); logger.log(''); } catch (archiveError) { spinner.fail('Archive download failed, trying git clone...'); logger.trace('Archive download error:', archiveError.message); // Clear the temp directory for git clone attempt yield cleanupTempDirectory(tempDirPath); tempDirPath = yield createTempDirectory(); // Fall back to git clone yield performGitClone(repoUrl, tempDirPath, cliOptions, deps); downloadMethod = 'git'; } } else { // Use git clone directly yield performGitClone(repoUrl, tempDirPath, cliOptions, deps); downloadMethod = 'git'; } // Run the default action on the downloaded/cloned repository result = yield deps.runDefaultAction([tempDirPath], tempDirPath, cliOptions); // Copy output file only when not in stdout mode // In stdout mode, output is written directly to stdout without creating a file, // so attempting to copy a non-existent file would cause an error and exit code 1 if (!cliOptions.stdout) { yield copyOutputToCurrentDirectory(tempDirPath, process.cwd(), result.config.output.filePath); } logger.trace(`Repository obtained via ${downloadMethod} method`); } finally { // Cleanup the temporary directory yield cleanupTempDirectory(tempDirPath); } return result; }); /** * Performs git clone operation with spinner and error handling */ const performGitClone = (repoUrl, tempDirPath, cliOptions, deps) => __awaiter(void 0, void 0, void 0, function* () { // Check if git is installed only when we actually need to use git if (!(yield deps.isGitInstalled())) { throw new RepomixError('Git is not installed or not in the system PATH.'); } // Get remote refs let refs = []; try { refs = yield deps.getRemoteRefs(parseRemoteValue(repoUrl).repoUrl); logger.trace(`Retrieved ${refs.length} refs from remote repository`); } catch (error) { logger.trace('Failed to get remote refs, proceeding without them:', error.message); } // Parse the remote URL with the refs information const parsedFields = parseRemoteValue(repoUrl, refs); const spinner = new Spinner('Cloning repository...', cliOptions); try { spinner.start(); // Clone the repository yield cloneRepository(parsedFields.repoUrl, tempDirPath, cliOptions.remoteBranch || parsedFields.remoteBranch, { execGitShallowClone: deps.execGitShallowClone, }); spinner.succeed('Repository cloned successfully!'); logger.log(''); } catch (error) { spinner.fail('Error during repository cloning. cleanup...'); throw error; } }); export const createTempDirectory = () => __awaiter(void 0, void 0, void 0, function* () { const tempDir = yield fs.mkdtemp(path.join(os.tmpdir(), 'repomix-')); logger.trace(`Created temporary directory. (path: ${pc.dim(tempDir)})`); return tempDir; }); export const cloneRepository = (url_1, directory_1, remoteBranch_1, ...args_1) => __awaiter(void 0, [url_1, directory_1, remoteBranch_1, ...args_1], void 0, function* (url, directory, remoteBranch, deps = { execGitShallowClone, }) { logger.log(`Clone repository: ${url} to temporary directory. ${pc.dim(`path: ${directory}`)}`); logger.log(''); try { yield deps.execGitShallowClone(url, directory, remoteBranch); } catch (error) { throw new RepomixError(`Failed to clone repository: ${error.message}`); } }); export const cleanupTempDirectory = (directory) => __awaiter(void 0, void 0, void 0, function* () { logger.trace(`Cleaning up temporary directory: ${directory}`); yield fs.rm(directory, { recursive: true, force: true }); }); export const copyOutputToCurrentDirectory = (sourceDir, targetDir, outputFileName) => __awaiter(void 0, void 0, void 0, function* () { const sourcePath = path.resolve(sourceDir, outputFileName); const targetPath = path.resolve(targetDir, outputFileName); try { logger.trace(`Copying output file from: ${sourcePath} to: ${targetPath}`); // Create target directory if it doesn't exist yield fs.mkdir(path.dirname(targetPath), { recursive: true }); yield fs.copyFile(sourcePath, targetPath); } catch (error) { throw new RepomixError(`Failed to copy output file: ${error.message}`); } }); //# sourceMappingURL=remoteAction.js.map