diff --git a/lib/usePantry.ts b/lib/usePantry.ts index 52dde45f..be1e752f 100644 --- a/lib/usePantry.ts +++ b/lib/usePantry.ts @@ -1,5 +1,5 @@ import { isNumber, isPlainObject, isString, isArray, PlainObject } from "is-what" -import { Package, PackageRequirement, semver, utils, hooks } from "libpkgx" +import { Package, PackageRequirement, SemVer, semver, utils, hooks } from "libpkgx" import { getScript } from "./usePantry.getScript.ts" import getVersions from "./usePantry.getVersions.ts" @@ -60,17 +60,17 @@ const getPlatforms = async (pkg: Package | PackageRequirement) => { return rv } -const getRawDistributableURL = (yml: PlainObject) => { - if (isPlainObject(yml.distributable)) { - return validate.str(yml.distributable.url) - } else if (isString(yml.distributable)) { - return yml.distributable - } else if (yml.distributable === null || yml.distributable === undefined) { - return +const getRawDistributableURL = (dist: PlainObject) => { + if (isPlainObject(dist)) { + return validate.str(dist.url); + } else if (isString(dist)) { + return dist; + } else if (dist === null || dist === undefined) { + return; } else { - throw new Error(`invalid distributable node: ${yml.distributable}`) + throw new Error(`invalid distributable node: ${dist}`); } -} +}; const getGitDistribution = ({ pkg, url: urlstr, ref }: { pkg: Package, url: string, ref: string }) => { if (!ref) { @@ -90,33 +90,75 @@ const getGitDistribution = ({ pkg, url: urlstr, ref }: { pkg: Package, url: stri } const getDistributable = async (pkg: Package) => { - const moustaches = useMoustaches() - - const yml = await hooks.usePantry().project(pkg).yaml() - - if (yml.distributable?.git) { - console.warn("brewkit: using distributable.git instead of distributable.url is deprecated") - return getGitDistribution({ pkg, ...yml.distributable}) - } - if (yml.distributable?.url?.startsWith("git")) { - return getGitDistribution({ pkg, ...yml.distributable}) - } - - let urlstr = getRawDistributableURL(yml) - if (!urlstr) return - let stripComponents: number | undefined - if (isPlainObject(yml.distributable)) { - stripComponents = flatmap(yml.distributable["strip-components"], coerceNumber) + const moustaches = useMoustaches(); + + const yml = await hooks.usePantry().project(pkg).yaml(); + const dists = isArray(yml.distributable) ? yml.distributable : [yml.distributable] + for (const dist of dists) { + if (!dist) continue; + //FIXME: Add check for Git dists as well + if (dist.git) { + console.warn( + "brewkit: using distributable.git instead of distributable.url is deprecated", + ); + return getGitDistribution({ pkg, ...dist }); + } + + if (dist.url?.startsWith("git")) { + return getGitDistribution({ pkg, ...dist }); + } + + let urlstr = getRawDistributableURL(dist); + if (!urlstr) continue; + + let v = pkg.version + const stripComponents = flatmap(dist["strip-components"], coerceNumber) + + if (isPlainObject(dist)) { + if (dist.rewrite?.match) { + const v_raw = v.raw.replace( + new RegExp(dist.rewrite["match"], "gi"), + dist.rewrite["with"], + ); + v = { + raw: v_raw, + major: pkg.version.major, + minor: pkg.version.minor, + patch: pkg.version.patch, + components: pkg.version.components, + prerelease: pkg.version.prerelease, + build: pkg.version.build, + eq: pkg.version.eq, + neq: pkg.version.neq, + gt: pkg.version.gt, + gte: pkg.version.gte, + lt: pkg.version.lt, + lte: pkg.version.lte, + compare: pkg.version.compare, + } + } + + if (dist.if) { + const matched = new RegExp(dist.if).test(pkg.version.raw); + if (!matched) continue + } + } + + urlstr = moustaches.apply(urlstr, [ + ...moustaches.tokenize.version(v), + ...moustaches.tokenize.host(), + ]); + + const rsp = await fetch(urlstr, { method: "HEAD" }); + + if (rsp.status == 200) { + const url = new URL(urlstr); + return { url, ref: undefined, stripComponents, type: "url" } + } else { + console.warn(`brewkit: Could not fetch ${urlstr} [${rsp.status}]`) + } } - - urlstr = moustaches.apply(urlstr, [ - ...moustaches.tokenize.version(pkg.version), - ...moustaches.tokenize.host() - ]) - - const url = new URL(urlstr) - - return { url, ref: undefined, stripComponents, type: 'url' } + return; } // deno-lint-ignore no-explicit-any @@ -130,4 +172,4 @@ async function filepath(project: string) { if (project == pkg.project) return pkg.path } throw new Error(`package.yml not found: ${project}`) -} + } diff --git a/libexec/extract.ts b/libexec/extract.ts index c2d79245..06e95d84 100755 --- a/libexec/extract.ts +++ b/libexec/extract.ts @@ -19,8 +19,7 @@ const { flags: { outputDir, pkg: pkgname }, unknown } = parseFlags(Deno.args, { const pantry = usePantry() -let pkg: Package | PackageRequirement = utils.pkg.parse(pkgname) -pkg = { project: pkg.project, version: pkg.constraint.single() ?? panic() } +const pkg: Package | PackageRequirement = await usePantry().resolve(utils.pkg.parse(pkgname)) ?? panic const dstdir = Path.cwd().join(outputDir) diff --git a/libexec/query.ts b/libexec/query.ts index bc4bc424..2313dc6e 100755 --- a/libexec/query.ts +++ b/libexec/query.ts @@ -40,7 +40,10 @@ if (versions) { Deno.exit(0) } -const version = pkg.constraint.single() ?? panic() +//FIXME: There might be a better way of doing this. It retains the current behaviour for normal cases and fixes the version.raw for those which don't match +const pkg_version = pkg.constraint.single() ?? panic() +const pantry_ver = await usePantry().resolve(pkg) ?? panic() +const version = (pkg_version.raw == pantry_ver.version.raw) ? pkg_version : pantry_ver.version pkg = {project: pkg.project, version } if (src) {