From 49e7191581b6276bcc60233ce5364dbd60d57e2d Mon Sep 17 00:00:00 2001 From: Peter Somogyvari Date: Fri, 31 May 2024 13:04:03 -0700 Subject: [PATCH] refactor(tools): extract createTemporaryClone() utility function This makes the tooling code a more [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) and is a pre-requisite of some follow-up changes that are about to get proposed in a separate pull request by Peter that are specific to vendoring the openapi.json spec files. Signed-off-by: Peter Somogyvari --- tools/create-production-only-archive.ts | 69 +------------------- tools/create-temporary-clone.ts | 84 +++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 66 deletions(-) create mode 100644 tools/create-temporary-clone.ts diff --git a/tools/create-production-only-archive.ts b/tools/create-production-only-archive.ts index 5dfcc2269f..ee16efc778 100644 --- a/tools/create-production-only-archive.ts +++ b/tools/create-production-only-archive.ts @@ -3,16 +3,14 @@ import path from "path"; import { dirname } from "path"; import { fileURLToPath } from "url"; import { deleteAsync } from "del"; -import fs from "fs-extra"; import { globby, Options as GlobbyOptions } from "globby"; import { RuntimeError } from "run-time-error"; import yargs from "yargs"; import { hideBin } from "yargs/helpers"; -import { simpleGit, SimpleGit, SimpleGitOptions } from "simple-git"; -import { SimpleGitProgressEvent } from "simple-git"; -import fastSafeStringify from "fast-safe-stringify"; import AdmZip from "adm-zip"; +import { createTemporaryClone } from "./create-temporary-clone"; + const TAG = "[tools/create-production-only-archive.ts] "; export interface IFileDeletionV1 { @@ -123,67 +121,6 @@ async function getDeletionList( return out; } -async function createTemporaryClone(req: { - readonly osTmpRootPath: string; - readonly cloneUrl: string; -}): Promise<{ readonly clonePath: string; readonly gitCommitHash: string }> { - const fn = `${TAG}:createTemporaryClone()`; - const tmpDirPrefix = "cacti_tools_create_production_only_archive_"; - - if (!req) { - throw new RuntimeError(`${fn} req was falsy.`); - } - if (!req.cloneUrl) { - throw new RuntimeError(`${fn} req.cloneUrl was falsy.`); - } - if (typeof req.cloneUrl !== "string") { - throw new RuntimeError(`${fn} req.cloneUrl was non-string.`); - } - if (req.cloneUrl.length <= 0) { - throw new RuntimeError(`${fn} req.cloneUrl was blank string.`); - } - if (!req.osTmpRootPath) { - throw new RuntimeError(`${fn} req.osTmpRootPath was falsy.`); - } - if (typeof req.osTmpRootPath !== "string") { - throw new RuntimeError(`${fn} req.osTmpRootPath was non-string.`); - } - if (req.osTmpRootPath.length <= 0) { - throw new RuntimeError(`${fn} req.osTmpRootPath was blank string.`); - } - - console.log("%s req.osTmpRootPath=%s", fn, req.osTmpRootPath); - const tmpDirPathBase = path.join(req.osTmpRootPath, tmpDirPrefix); - console.log("%s tmpDirPathBase=%s", fn, tmpDirPathBase); - - const tmpDirPath = await fs.mkdtemp(tmpDirPathBase); - console.log("%s tmpDirPath=%s", fn, tmpDirPath); - console.log("%s Cloning into a temporary directory at %s...", fn, tmpDirPath); - - const options: Partial = { - baseDir: tmpDirPath, - binary: "git", - maxConcurrentProcesses: 6, - trimmed: false, - progress: (data: SimpleGitProgressEvent) => { - console.log("%s SimpleGit_Progress=%s", fn, fastSafeStringify(data)); - }, - }; - - // when setting all options in a single object - const git: SimpleGit = simpleGit(options); - - const cloneResponse = await git.clone(req.cloneUrl, tmpDirPath); - console.log("%s Cloned %s OK into %o", fn, req.cloneUrl, cloneResponse); - - await git.fetch("origin", "main"); - - const gitCommitHash = await git.revparse("HEAD"); - console.log("s Current git commit hash=%s", fn, gitCommitHash); - - return { clonePath: tmpDirPath, gitCommitHash }; -} - async function createProductionOnlyArchive( req: ICreateProductionOnlyArchiveV1Request, ): Promise { @@ -224,7 +161,7 @@ async function createProductionOnlyArchive( console.log("%s Getting deletion list OK: %o", fnTag, deletionList); const dateAndTime = new Date().toJSON().slice(0, 24).replaceAll(":", "-"); - const filename = `hyperledger_cacti_production_sources_${dateAndTime}_main_git_hash_${gitCommitHash}.zip`; + const filename = `hyperledger_cacti_temporary_clone_${dateAndTime}_main_git_hash_${gitCommitHash}.zip`; const zipFilePath = path.join(req.PROJECT_DIR, "./.tmp/", filename); console.log("%s Creating .zip archive at: %s", fnTag, zipFilePath); diff --git a/tools/create-temporary-clone.ts b/tools/create-temporary-clone.ts new file mode 100644 index 0000000000..b10c138198 --- /dev/null +++ b/tools/create-temporary-clone.ts @@ -0,0 +1,84 @@ +import path from "node:path"; +import { RuntimeError } from "run-time-error"; +import fs from "fs-extra"; +import { simpleGit, SimpleGit, SimpleGitOptions } from "simple-git"; +import { TaskOptions } from "simple-git"; +import { SimpleGitProgressEvent } from "simple-git"; +import fastSafeStringify from "fast-safe-stringify"; + +const TAG = "tools/create-temporary-clone.ts"; + +export async function createTemporaryClone(req: { + readonly osTmpRootPath: string; + readonly cloneUrl: string; + readonly checkoutTarget?: string; + readonly gitCloneOptions?: Record; +}): Promise<{ readonly clonePath: string; readonly gitCommitHash: string }> { + const fn = `${TAG}:createTemporaryClone()`; + const tmpDirPrefix = "cacti_tools_create_production_only_archive_"; + + if (!req) { + throw new RuntimeError(`${fn} req was falsy.`); + } + if (!req.cloneUrl) { + throw new RuntimeError(`${fn} req.cloneUrl was falsy.`); + } + if (typeof req.cloneUrl !== "string") { + throw new RuntimeError(`${fn} req.cloneUrl was non-string.`); + } + if (req.cloneUrl.length <= 0) { + throw new RuntimeError(`${fn} req.cloneUrl was blank string.`); + } + if (!req.osTmpRootPath) { + throw new RuntimeError(`${fn} req.osTmpRootPath was falsy.`); + } + if (typeof req.osTmpRootPath !== "string") { + throw new RuntimeError(`${fn} req.osTmpRootPath was non-string.`); + } + if (req.osTmpRootPath.length <= 0) { + throw new RuntimeError(`${fn} req.osTmpRootPath was blank string.`); + } + + console.log("%s req.osTmpRootPath=%s", fn, req.osTmpRootPath); + const tmpDirPathBase = path.join(req.osTmpRootPath, tmpDirPrefix); + console.log("%s tmpDirPathBase=%s", fn, tmpDirPathBase); + + const tmpDirPath = await fs.mkdtemp(tmpDirPathBase); + console.log("%s tmpDirPath=%s", fn, tmpDirPath); + console.log("%s Cloning into a temporary directory at %s...", fn, tmpDirPath); + + const options: Partial = { + baseDir: tmpDirPath, + binary: "git", + maxConcurrentProcesses: 6, + trimmed: false, + progress: (data: SimpleGitProgressEvent) => { + console.log("%s SimpleGit_Progress=%s", fn, fastSafeStringify(data)); + }, + }; + + // when setting all options in a single object + const git: SimpleGit = simpleGit(options); + + // depth 1 only clones the latest commit, saves us disk space and bandwith. + const cloneOpts: TaskOptions = { + "--depth": 1, + ...req.gitCloneOptions, + }; + console.log("%s git clone options effective: %o", cloneOpts); + const cloneResponse = await git.clone(req.cloneUrl, tmpDirPath, cloneOpts); + console.log("%s Cloned %s OK into %o", fn, req.cloneUrl, cloneResponse); + + await git.fetch("origin", "main"); + + if (req.checkoutTarget) { + await git.fetch("origin", req.checkoutTarget); + console.log("%s checking out target %s...", TAG, req.checkoutTarget); + await git.checkout(req.checkoutTarget); + } + + const gitCommitHash = await git.revparse("HEAD"); + console.log("s Current git commit hash=%s", fn, gitCommitHash); + + return { clonePath: tmpDirPath, gitCommitHash }; +}