init
This commit is contained in:
commit
3d03526471
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"deno.enable": true
|
||||
}
|
16
deps.ts
Normal file
16
deps.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
export {
|
||||
type TarMeta,
|
||||
Untar,
|
||||
} from "https://deno.land/std@0.144.0/archive/tar.ts";
|
||||
export {
|
||||
copy,
|
||||
readerFromStreamReader,
|
||||
} from "https://deno.land/std@0.144.0/streams/mod.ts";
|
||||
export { join } from "https://deno.land/std@0.144.0/path/mod.ts";
|
||||
export {
|
||||
default as cacheDir,
|
||||
} from "https://deno.land/x/cache_dir@0.2.0/mod.ts";
|
||||
|
||||
import * as Transform from "https://deno.land/x/transform@v0.4.0/mod.ts";
|
||||
export { Transform };
|
||||
export const { GzDecoder } = Transform.Transformers;
|
120
mod.ts
Normal file
120
mod.ts
Normal file
|
@ -0,0 +1,120 @@
|
|||
import {
|
||||
cacheDir,
|
||||
copy,
|
||||
GzDecoder,
|
||||
join,
|
||||
readerFromStreamReader,
|
||||
TarMeta,
|
||||
Transform,
|
||||
Untar,
|
||||
} from "./deps.ts";
|
||||
|
||||
export const CACHE_DIR = join((await cacheDir()) ?? ".cache", "__pick_cache0");
|
||||
Deno.mkdir(CACHE_DIR).catch((_) => {});
|
||||
|
||||
type TarEntry = TarMeta & Deno.Reader;
|
||||
interface GithubPickOptions {
|
||||
repo: string;
|
||||
version: string;
|
||||
pick: RegExp[];
|
||||
}
|
||||
|
||||
export async function* githubPick({ repo, version, pick }: GithubPickOptions) {
|
||||
const _cached = await getFetchCache(`${repo}@${version}`);
|
||||
if (_cached) {
|
||||
const reader = await Deno.open(_cached);
|
||||
yield* tarGzPickFiles(reader, pick);
|
||||
} else {
|
||||
yield* githubPickFiles({ repo, version, pick });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads *.tar.gz file from a version tag and returns generator of the files that match the pick regex.
|
||||
*
|
||||
* @param {GithubPickOptions} opts - { repo: "denoland/deno", version: "v1.0.0", pick: [/\.ts$/] }
|
||||
* @returns {AsyncGenerator<TarEntry>}
|
||||
*/
|
||||
export async function* githubPickFiles(
|
||||
{ repo, version, pick }: GithubPickOptions,
|
||||
): AsyncGenerator<TarEntry> {
|
||||
const targz = await fetch(
|
||||
`https://github.com/${repo}/archive/refs/tags/${version}.tar.gz`,
|
||||
);
|
||||
await putFetchCache(targz.body, `${repo}@${version}`);
|
||||
const reader = readerFromStreamReader(targz.body!.getReader());
|
||||
yield* tarGzPickFiles(reader, pick);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick files from a tar.gz archive.
|
||||
*
|
||||
* @param {Deno.Reader} tar - Deno.open('archive.tar.gz')
|
||||
* @param {RegExp[]} pick - [ /\.ts$/ ]
|
||||
*/
|
||||
export async function* tarGzPickFiles(
|
||||
targz: Deno.Reader | Deno.FsFile,
|
||||
pick: RegExp[],
|
||||
) {
|
||||
const untar = new Untar(
|
||||
Transform.newReader(
|
||||
targz,
|
||||
new GzDecoder(),
|
||||
),
|
||||
);
|
||||
for await (const entry of untar) {
|
||||
if (entry.type === "file" && pick.some((re) => re.test(entry.fileName))) {
|
||||
yield entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes fetch body to a cache file.
|
||||
* @param body
|
||||
* @param name
|
||||
* @param opts
|
||||
*/
|
||||
export async function putFetchCache(body: Response["body"], name: string) {
|
||||
const reader = readerFromStreamReader(body!.getReader());
|
||||
const writer = await Deno.open(join(CACHE_DIR, name), { write: true });
|
||||
await copy(reader, writer);
|
||||
writer.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get either the path to the cache file or null if it doesn't exist.
|
||||
* @param {string} name
|
||||
* @returns {Promise<string | null>}
|
||||
*/
|
||||
export async function getFetchCache(name: string) {
|
||||
try {
|
||||
const _file = join(CACHE_DIR, name);
|
||||
await Deno.lstat(_file);
|
||||
return _file;
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean the fetch cache.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function cleanFetchCache() {
|
||||
return Deno.remove(CACHE_DIR, { recursive: true });
|
||||
}
|
||||
|
||||
export async function writeTarEntry(
|
||||
entry: TarEntry,
|
||||
dir: string,
|
||||
formatWritePath: (path: string) => string = (path) => path,
|
||||
) {
|
||||
const path = formatWritePath(entry.fileName);
|
||||
const file = await Deno.open(dir + path, {
|
||||
create: true,
|
||||
write: true,
|
||||
});
|
||||
await copy(entry, file);
|
||||
file.close();
|
||||
}
|
0
tests/.pick.yaml
Normal file
0
tests/.pick.yaml
Normal file
1
tests/mod_test.ts
Normal file
1
tests/mod_test.ts
Normal file
|
@ -0,0 +1 @@
|
|||
const { test } = Deno;
|
Loading…
Reference in a new issue