UNPKG

forge-deploy-cli

Version:

Professional CLI for local deployments with automatic subdomain routing, SSL certificates, and infrastructure management

181 lines 6.88 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.GitService = void 0; const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); const child_process_1 = require("child_process"); const chalk_1 = __importDefault(require("chalk")); const os_1 = require("os"); class GitService { /** * Clone a Git repository to a local directory */ static async cloneRepository(repoUrl, options = {}) { try { const { branch = 'main', depth = 1, recursive = false, targetDir } = options; // Ensure clone directory exists await fs_extra_1.default.ensureDir(this.DEFAULT_CLONE_DIR); // Generate unique directory name const repoName = this.extractRepoName(repoUrl); const timestamp = Date.now(); const cloneDir = targetDir || path_1.default.join(this.DEFAULT_CLONE_DIR, `${repoName}-${timestamp}`); console.log(chalk_1.default.cyan(`Cloning repository: ${repoUrl}`)); console.log(chalk_1.default.gray(`Target directory: ${cloneDir}`)); // Build git clone command const gitArgs = [ 'clone', '--single-branch', '--branch', branch, '--depth', depth.toString() ]; if (recursive) { gitArgs.push('--recursive'); } gitArgs.push(repoUrl, cloneDir); // Execute git clone (0, child_process_1.execSync)(`git ${gitArgs.join(' ')}`, { stdio: 'pipe', encoding: 'utf8' }); console.log(chalk_1.default.green('Repository cloned successfully')); return { success: true, localPath: cloneDir }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); console.error(chalk_1.default.red(`Failed to clone repository: ${errorMessage}`)); return { success: false, error: errorMessage }; } } /** * Update an existing cloned repository */ static async updateRepository(localPath, branch = 'main') { try { if (!await fs_extra_1.default.pathExists(localPath)) { throw new Error(`Repository path does not exist: ${localPath}`); } console.log(chalk_1.default.cyan(`Updating repository at: ${localPath}`)); // Fetch latest changes (0, child_process_1.execSync)('git fetch origin', { cwd: localPath, stdio: 'pipe' }); // Reset to latest commit on the specified branch (0, child_process_1.execSync)(`git reset --hard origin/${branch}`, { cwd: localPath, stdio: 'pipe' }); console.log(chalk_1.default.green('Repository updated successfully')); return { success: true, localPath }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); console.error(chalk_1.default.red(`Failed to update repository: ${errorMessage}`)); return { success: false, error: errorMessage }; } } /** * Clean up old cloned repositories */ static async cleanupOldRepositories(maxAge = 24 * 60 * 60 * 1000) { try { if (!await fs_extra_1.default.pathExists(this.DEFAULT_CLONE_DIR)) { return; } const entries = await fs_extra_1.default.readdir(this.DEFAULT_CLONE_DIR, { withFileTypes: true }); const now = Date.now(); for (const entry of entries) { if (entry.isDirectory()) { const dirPath = path_1.default.join(this.DEFAULT_CLONE_DIR, entry.name); const stats = await fs_extra_1.default.stat(dirPath); if (now - stats.mtime.getTime() > maxAge) { console.log(chalk_1.default.gray(`Cleaning up old repository: ${entry.name}`)); await fs_extra_1.default.remove(dirPath); } } } } catch (error) { console.warn(chalk_1.default.yellow(`Failed to cleanup old repositories: ${error}`)); } } /** * Check if a directory is a valid git repository */ static async isGitRepository(path) { try { (0, child_process_1.execSync)('git rev-parse --git-dir', { cwd: path, stdio: 'pipe' }); return true; } catch { return false; } } /** * Get repository information */ static async getRepositoryInfo(localPath) { try { const currentBranch = (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD', { cwd: localPath, encoding: 'utf8' }).trim(); const currentCommit = (0, child_process_1.execSync)('git rev-parse HEAD', { cwd: localPath, encoding: 'utf8' }).trim(); const remoteUrl = (0, child_process_1.execSync)('git remote get-url origin', { cwd: localPath, encoding: 'utf8' }).trim(); return { branch: currentBranch, commit: currentCommit, remoteUrl, shortCommit: currentCommit.substring(0, 7) }; } catch (error) { throw new Error(`Failed to get repository info: ${error}`); } } /** * Extract repository name from URL */ static extractRepoName(repoUrl) { const match = repoUrl.match(/\/([^\/]+)\/([^\/]+?)(?:\.git)?(?:\/)?$/); return match ? `${match[1]}-${match[2]}` : 'unknown-repo'; } /** * Validate repository URL */ static isValidGitUrl(url) { const gitUrlPatterns = [ /^https?:\/\/(www\.)?(github|gitlab|bitbucket)\.com\/[^\/]+\/[^\/]+/, /^git@(github|gitlab|bitbucket)\.com:[^\/]+\/[^\/]+\.git$/, /^https?:\/\/[^\/]+\/[^\/]+\/[^\/]+\.git$/ ]; return gitUrlPatterns.some(pattern => pattern.test(url)); } } exports.GitService = GitService; GitService.DEFAULT_CLONE_DIR = path_1.default.join((0, os_1.tmpdir)(), 'forge-repos'); //# sourceMappingURL=git.js.map