isogit-lfs/src/populateCache.ts

86 lines
2.2 KiB
TypeScript
Raw Normal View History

2022-12-07 23:39:09 +00:00
import { Buffer } from "buffer";
2021-11-25 12:27:33 +00:00
2022-12-07 23:49:43 +00:00
import git, {
GitProgressEvent,
HttpClient,
PromiseFsClient,
} from "isomorphic-git";
2021-11-25 12:27:33 +00:00
2022-12-07 23:39:09 +00:00
import { isVacantAndWriteable, pointsToLFS } from "./util";
import downloadBlobFromPointer from "./download";
2021-11-25 12:27:33 +00:00
import { readPointer } from "./pointers";
const SYMLINK_MODE = 40960;
2022-12-07 23:39:09 +00:00
type ProgressHandler = (progress: GitProgressEvent) => void;
2021-11-25 12:27:33 +00:00
/**
* Populates LFS cache for each repository object that is an LFS pointer.
*
* Does not touch working directory.
*
* 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.
2022-12-07 23:39:09 +00:00
*
* NOTE: This function skips objects silently in case of errors.
2022-12-07 23:39:09 +00:00
*
* NOTE: onProgress currently doesnt report loaded/total values accurately.
2021-11-25 12:27:33 +00:00
*/
export default async function populateCache(
2022-12-07 23:39:09 +00:00
fs: PromiseFsClient,
2022-12-07 23:49:43 +00:00
http: HttpClient,
workDir: string,
remoteURL: string,
2022-12-07 23:39:09 +00:00
ref: string = "HEAD",
onProgress?: ProgressHandler
) {
await git.walk({
2021-11-25 12:27:33 +00:00
fs,
dir: workDir,
trees: [git.TREE({ ref })],
map: async function lfsDownloadingWalker(filepath, entries) {
if (entries === null || entries[0] === null) {
return null;
}
2021-11-25 12:27:33 +00:00
onProgress?.({ phase: `skimming: ${filepath}`, loaded: 5, total: 10 });
2021-11-25 12:27:33 +00:00
const [entry] = entries;
const entryType = await entry.type();
2021-11-25 12:27:33 +00:00
2022-12-07 23:39:09 +00:00
if (entryType === "tree") {
// Walk children
return true;
2022-12-07 23:39:09 +00:00
} else if (
entryType === "blob" &&
(await entry.mode()) !== SYMLINK_MODE
) {
const content = await entry.content();
2021-11-25 12:27:33 +00:00
if (content) {
const buff = Buffer.from(content.buffer);
2021-11-25 12:27:33 +00:00
if (pointsToLFS(buff)) {
const pointer = readPointer({ dir: workDir, content: buff });
// Dont even start the download if LFS cache path is not accessible,
// or if it already exists
2022-12-07 23:39:09 +00:00
if ((await isVacantAndWriteable(pointer.objectPath)) === false)
return;
2022-12-07 23:39:09 +00:00
onProgress?.({
phase: `downloading: ${filepath}`,
loaded: 5,
total: 10,
});
2023-05-16 22:46:18 +00:00
await downloadBlobFromPointer(fs, remoteURL, {}, pointer);
2021-11-25 12:27:33 +00:00
}
}
}
return;
2022-12-07 23:39:09 +00:00
},
});
2021-11-25 12:27:33 +00:00
}