PHP WebShell

Текущая директория: /opt/BitGoJS/scripts

Просмотр файла: vendor-github-repo.ts

import { ChildProcess, execFile } from 'child_process';
import * as fs from 'fs/promises';
import * as tmp from 'tmp';
import * as yargs from 'yargs';

function isErrorExists(e: NodeJS.ErrnoException): boolean {
  return e.code === 'EEXIST';
}

type GithubSource = {
  org: string;
  repo: string;
} & ({ tag: string } | { ref: string });

async function wait(p: ChildProcess): Promise<void> {
  p.stderr?.pipe(process.stderr);
  p.stdout?.pipe(process.stdout);
  return new Promise((resolve, reject) => {
    p.on('exit', (code) => {
      if (code === 0) {
        resolve();
      } else {
        reject(new Error(`Process exited with code ${code}`));
      }
    });
  });
}

function getUrl(lib: GithubSource): string {
  if ('tag' in lib) {
    const { org, repo, tag } = lib;
    return `https://github.com/${org}/${repo}/archive/refs/tags/${tag}.tar.gz`;
  }
  if ('ref' in lib) {
    const { org, repo, ref } = lib;
    return `https://github.com/${org}/${repo}/tarball/${ref}`;
  }
  throw new Error('Unsupported lib');
}

function getArchivePath(lib: GithubSource): string {
  return tmp.fileSync({ postfix: `-${lib.repo}.tar.gz` }).name;
}

async function fetchArchive(lib: GithubSource, outfile: string): Promise<void> {
  try {
    const result = await fs.stat(outfile);
    if (result.size > 0) {
      console.log(`Archive already exists: ${outfile}`);
      return;
    }
  } catch (e) {}
  const url = getUrl(lib);
  const result = await fetch(url);
  if (!result.ok) {
    throw new Error(`Failed to fetch ${url}: ${result.status} ${result.statusText}`);
  }
  await fs.writeFile(outfile, Buffer.from(await result.arrayBuffer()));
}

async function extractArchive(archivePath: string, targetDir: string): Promise<void> {
  try {
    await fs.mkdir(targetDir, { recursive: true });
  } catch (e) {
    if (!isErrorExists(e)) {
      throw e;
    }
  }
  await wait(execFile('tar', ['-C', targetDir, '--strip-components', '1', '-xzf', archivePath]));
}

type VendorConfig = GithubSource & {
  targetDir: string;
};

async function main(cfgs: VendorConfig[]) {
  for (const cfg of cfgs) {
    const archivePath = getArchivePath(cfg);
    await fetchArchive(cfg, archivePath);
    await extractArchive(archivePath, cfg.targetDir);
  }
}

const vendorConfigs: VendorConfig[] = [
  {
    org: 'babylonlabs-io',
    repo: 'btc-staking-ts',
    tag: 'v1.0.3',
    targetDir: 'modules/babylonlabs-io-btc-staking-ts',
  },
];

yargs
  .command({
    command: 'vendor',
    builder(a) {
      return a.options({ name: { type: 'string' } });
    },
    async handler(a) {
      const matches = vendorConfigs.filter((cfg) => a.name === cfg.repo);
      if (matches.length === 0) {
        throw new Error(`no such vendor config ${a.name}`);
      }
      if (matches.length > 1) {
        throw new Error(`ambiguous vendor config ${a.name}`);
      }
      await main(matches);
    },
  })
  .help()
  .strict()
  .demandCommand().argv;

Выполнить команду


Для локальной разработки. Не используйте в интернете!