fy-convertor
Version:
Convert excel/xml/json/bin/protocl/ts/as ...
123 lines • 5.24 kB
JavaScript
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