UNPKG

fy-convertor

Version:

Convert excel/xml/json/bin/protocl/ts/as ...

123 lines 5.24 kB
import fs from 'fs-extra'; import path from 'path'; import { runCommand } from '../tools/vendor.js'; export class GitHelper { static ins; static get Instance() { if (!GitHelper.ins) GitHelper.ins = new GitHelper(); return GitHelper.ins; } async partialCloneDirectory(options) { const sparsePaths = this.normalizeSparsePaths(options.sparsePath); const localPath = path.resolve(options.localPath); if (await this.isGitRepository(localPath)) { await this.updateSparseRepository(localPath, options.gitUrl, sparsePaths, options.branch); return; } if (await fs.pathExists(localPath)) { throw new Error(`localPath exists but is not a git repository: ${localPath}`); } await fs.mkdirp(path.dirname(localPath)); const cloneArgs = ['clone', '--filter=blob:none', '--sparse']; if (options.branch) cloneArgs.push('--branch', options.branch); cloneArgs.push(options.gitUrl, localPath); await this.git(cloneArgs); await this.setSparseCheckout(localPath, sparsePaths); await this.ensureSparsePathsExist(localPath, sparsePaths); } async commitAndPush(msg, ...paths) { const repoPaths = await this.groupPathsByRepository(paths); let output = ''; for (const [repoPath, items] of repoPaths) { await this.git(['add', '--', ...items], repoPath); const status = await this.git(['status', '--porcelain', '--', ...items], repoPath); if (status.trim().length == 0) { continue; } output += status; output += await this.git(['commit', '-m', msg, '--', ...items], repoPath); output += await this.git(['push'], repoPath); } return output; } async updateSparseRepository(localPath, gitUrl, sparsePaths, branch) { await this.git(['remote', 'set-url', 'origin', gitUrl], localPath); await this.git(['fetch', '--prune', 'origin'], localPath); if (branch) { await this.git(['checkout', branch], localPath); await this.git(['pull', '--ff-only', 'origin', branch], localPath); } else { await this.git(['pull', '--ff-only'], localPath); } await this.setSparseCheckout(localPath, sparsePaths); await this.ensureSparsePathsExist(localPath, sparsePaths); } async setSparseCheckout(localPath, sparsePaths) { const patterns = sparsePaths.map((item) => `/${item}/`); await this.git(['sparse-checkout', 'init', '--no-cone'], localPath); await this.git(['sparse-checkout', 'set', '--no-cone', '--', ...patterns], localPath); } async ensureSparsePathsExist(localPath, sparsePaths) { for (const item of sparsePaths) { if (!await fs.pathExists(path.join(localPath, item))) { throw new Error(`sparsePath not found in git repository: ${item}`); } } } normalizeSparsePaths(raw) { const values = (Array.isArray(raw) ? raw : [raw]) .map((item) => item.replace(/\\/g, '/').replace(/^\/+|\/+$/g, '').trim()) .filter((item) => item.length > 0); if (values.length == 0) { throw new Error('sparsePath is required.'); } for (const item of values) { if (item == '.' || item.includes('..')) { throw new Error(`invalid sparsePath: ${item}`); } } return values; } async isGitRepository(localPath) { return fs.pathExists(path.join(localPath, '.git')); } async groupPathsByRepository(paths) { const repoPaths = new Map(); for (const item of paths) { const fullPath = path.resolve(item); const repoPath = (await this.git(['rev-parse', '--show-toplevel'], fullPath)).trim(); const values = repoPaths.get(repoPath) ?? []; values.push(fullPath); repoPaths.set(repoPath, values); } return repoPaths; } git(args, cwd) { return runCommand('git', args, { cwd, env: this.getGitAuthEnv() }); } getGitAuthEnv() { const username = process.env.GIT_USERNAME; const password = process.env.GIT_PASSWORD; if (!username && !password) { return undefined; } if (!username || !password) { throw new Error('GIT_USERNAME and GIT_PASSWORD must be set together.'); } const index = this.getGitConfigIndex(); const token = Buffer.from(`${username}:${password}`).toString('base64'); return { GIT_CONFIG_COUNT: `${index + 1}`, [`GIT_CONFIG_KEY_${index}`]: 'http.extraHeader', [`GIT_CONFIG_VALUE_${index}`]: `Authorization: Basic ${token}` }; } getGitConfigIndex() { const count = Number(process.env.GIT_CONFIG_COUNT ?? 0); return Number.isInteger(count) && count >= 0 ? count : 0; } } //# sourceMappingURL=GitHelper.js.map