UNPKG

@mieweb/wikigdrive

Version:

Google Drive to MarkDown synchronization

107 lines (106 loc) 3.9 kB
import * as dntShim from "../../_dnt.shims.js"; import process from 'node:process'; const __filename = globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).filename; export function sanitize(txt) { txt = txt.replace(/[;"|]/g, ''); return txt; } export class GitExecuter { constructor(gitScanner) { Object.defineProperty(this, "gitScanner", { enumerable: true, configurable: true, writable: true, value: gitScanner }); Object.defineProperty(this, "rootPath", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "logger", { enumerable: true, configurable: true, writable: true, value: void 0 }); this.logger = gitScanner.logger; this.rootPath = gitScanner.rootPath; } sshOptsEnv(sshParams) { return { GIT_SSH_COMMAND: sshParams?.privateKeyFile ? `ssh -i ${sanitize(sshParams.privateKeyFile)} -o StrictHostKeyChecking=no -o IdentitiesOnly=yes` : '' }; } committerEnv(committer) { return { GIT_AUTHOR_NAME: committer.name, GIT_AUTHOR_EMAIL: committer.email, GIT_COMMITTER_NAME: committer.name, GIT_COMMITTER_EMAIL: committer.email, }; } async exec(cmd, opts = { env: {}, skipLogger: false, ignoreError: false }) { if (!opts.skipLogger) { this.logger.info(cmd, { stackOffset: 1, filename: __filename }); } let [stdout, stderr] = ['', '']; if (!opts.env) { opts.env = {}; } if (!opts.env['HOME']) { opts.env['HOME'] = process.env.HOME; } if (!opts.env['PATH']) { opts.env['PATH'] = process.env.PATH; } const command = new dntShim.Deno.Command('/bin/sh', { args: ['-c', cmd], cwd: this.rootPath, env: opts.env, stdout: 'piped', stderr: 'piped', }); const child = command.spawn(); const timer = setTimeout(() => { this.logger.error('Process timeout', { filename: __filename }); child.kill(); }, 300_000); const decoder = new TextDecoder(); const [status] = await Promise.all([ child.status, child.stdout.pipeTo(new WritableStream({ write: (chunk, controller) => { const text = decoder.decode(chunk); stdout += text; if (!opts.skipLogger) { this.logger.info(text, { filename: __filename }); } } })), child.stderr.pipeTo(new WritableStream({ write: (chunk, controller) => { const text = decoder.decode(chunk); stderr += text; if (!opts.skipLogger) { this.logger.error(text, { filename: __filename }); } } })) ]); clearTimeout(timer); if (!status.success && !opts.ignoreError) { this.logger.error('Process exited with status: ' + status.code, { filename: __filename }); throw new Error('Process exited with status: ' + status.code + '\n' + stderr); } return { stdout, stderr }; } async cmd(cmd, arg = '') { if (!['status', 'remote -v', 'ls-files --stage', 'branch -m'].includes(cmd)) { throw new Error('Forbidden command'); } const result = await this.exec('git ' + cmd + ' ' + (arg || ''), { skipLogger: !this.gitScanner.debug }); return { stdout: result.stdout, stderr: result.stderr }; } }