From d22df35cfc77224d4bbceb45116633626aabf027 Mon Sep 17 00:00:00 2001 From: Anton Strogonoff Date: Mon, 29 Nov 2021 03:06:19 +0100 Subject: [PATCH] =?UTF-8?q?refactor(populateCache):=20support=20onProgress?= =?UTF-8?q?;=20don=E2=80=99t=20read=20remote=20URL=20from=20Git=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/populateCache.ts | 82 ++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/src/populateCache.ts b/src/populateCache.ts index 69c17de..e6b1be7 100644 --- a/src/populateCache.ts +++ b/src/populateCache.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import git from 'isomorphic-git'; -import http from 'isomorphic-git/http/node'; +import http, { GitProgressEvent } from 'isomorphic-git/http/node'; import { isVacantAndWriteable, pointsToLFS } from './util'; import downloadBlobFromPointer from './download'; @@ -11,6 +11,9 @@ import { readPointer } from "./pointers"; const SYMLINK_MODE = 40960; +type ProgressHandler = (progress: GitProgressEvent) => void + + /** * Populates LFS cache for each repository object that is an LFS pointer. * @@ -18,55 +21,60 @@ const SYMLINK_MODE = 40960; * * NOTE: If LFS cache path, as extracted from the pointer, * is not writeable at the time of download start, - * the object will be silently skipped; - * if LFS cache path is not writeable at the time download completes, - * an error will be thrown. + * the object will be silently skipped. + * + * NOTE: This function skips objects silently in case of errors. + * + * NOTE: onProgress currently doesn’t report loaded/total values accurately. */ -export default async function populateCache(workDir: string, ref: string = 'HEAD') { - const remoteURL = await git.getConfig({ +export default async function populateCache( + workDir: string, + remoteURL: string, + ref: string = 'HEAD', + onProgress?: ProgressHandler, +) { + await git.walk({ fs, dir: workDir, - path: 'remote.origin.url', - }); - if (remoteURL) { - await git.walk({ - fs, - dir: workDir, - trees: [git.TREE({ ref })], - map: async function lfsDownloadingWalker(filepath, entries) { - if (entries === null || entries[0] === null) { - return null; - } + trees: [git.TREE({ ref })], + map: async function lfsDownloadingWalker(filepath, entries) { - const [entry] = entries; - const entryType = await entry.type(); + if (entries === null || entries[0] === null) { + return null; + } - if (entryType === 'tree') { - // Walk children - return true; + onProgress?.({ phase: `skimming: ${filepath}`, loaded: 5, total: 10 }); - } else if (entryType === 'blob' && (await entry.mode()) !== SYMLINK_MODE) { - const content = await entry.content(); + const [entry] = entries; + const entryType = await entry.type(); - if (content) { - const buff = Buffer.from(content.buffer); + if (entryType === 'tree') { + // Walk children + return true; - if (pointsToLFS(buff)) { - const pointer = readPointer({ dir: workDir, content: buff }); + } else if (entryType === 'blob' && (await entry.mode()) !== SYMLINK_MODE) { + const content = await entry.content(); - // Don’t even start the download if LFS cache path is not accessible, - // or if it already exists - if (await isVacantAndWriteable(pointer.objectPath) === false) - return; + if (content) { + const buff = Buffer.from(content.buffer); + if (pointsToLFS(buff)) { - await downloadBlobFromPointer({ http, url: remoteURL }, pointer); + const pointer = readPointer({ dir: workDir, content: buff }); + + // Don’t even start the download if LFS cache path is not accessible, + // or if it already exists + if (await isVacantAndWriteable(pointer.objectPath) === false) + return; + + onProgress?.({ phase: `downloading: ${filepath}`, loaded: 5, total: 10 }); + + await downloadBlobFromPointer({ http, url: remoteURL }, pointer); - } } } - return; } - }); - } + return; + } + }); }