CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
131 lines
3.3 KiB
TypeScript
131 lines
3.3 KiB
TypeScript
import { lstat, mkdir, readdir, rm, symlink } from "fs/promises"
|
|
import { join, relative } from "path"
|
|
|
|
type PackageManifest = {
|
|
name?: string
|
|
bin?: string | Record<string, string>
|
|
}
|
|
|
|
const root = process.cwd()
|
|
const bunRoot = join(root, "node_modules/.bun")
|
|
const bunEntries = (await readdir(bunRoot)).sort()
|
|
let rewritten = 0
|
|
|
|
for (const entry of bunEntries) {
|
|
const modulesRoot = join(bunRoot, entry, "node_modules")
|
|
if (!(await exists(modulesRoot))) {
|
|
continue
|
|
}
|
|
const binRoot = join(modulesRoot, ".bin")
|
|
await rm(binRoot, { recursive: true, force: true })
|
|
await mkdir(binRoot, { recursive: true })
|
|
|
|
const packageDirs = await collectPackages(modulesRoot)
|
|
for (const packageDir of packageDirs) {
|
|
const manifest = await readManifest(packageDir)
|
|
if (!manifest) {
|
|
continue
|
|
}
|
|
const binField = manifest.bin
|
|
if (!binField) {
|
|
continue
|
|
}
|
|
const seen = new Set<string>()
|
|
if (typeof binField === "string") {
|
|
const fallback = manifest.name ?? packageDir.split("/").pop()
|
|
if (fallback) {
|
|
await linkBinary(binRoot, fallback, packageDir, binField, seen)
|
|
}
|
|
} else {
|
|
const entries = Object.entries(binField).sort((a, b) => a[0].localeCompare(b[0]))
|
|
for (const [name, target] of entries) {
|
|
await linkBinary(binRoot, name, packageDir, target, seen)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log(`[normalize-bun-binaries] rebuilt ${rewritten} links`)
|
|
|
|
async function collectPackages(modulesRoot: string) {
|
|
const found: string[] = []
|
|
const topLevel = (await readdir(modulesRoot)).sort()
|
|
for (const name of topLevel) {
|
|
if (name === ".bin" || name === ".bun") {
|
|
continue
|
|
}
|
|
const full = join(modulesRoot, name)
|
|
if (!(await isDirectory(full))) {
|
|
continue
|
|
}
|
|
if (name.startsWith("@")) {
|
|
const scoped = (await readdir(full)).sort()
|
|
for (const child of scoped) {
|
|
const scopedDir = join(full, child)
|
|
if (await isDirectory(scopedDir)) {
|
|
found.push(scopedDir)
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
found.push(full)
|
|
}
|
|
return found.sort()
|
|
}
|
|
|
|
async function readManifest(dir: string) {
|
|
const file = Bun.file(join(dir, "package.json"))
|
|
if (!(await file.exists())) {
|
|
return null
|
|
}
|
|
const data = (await file.json()) as PackageManifest
|
|
return data
|
|
}
|
|
|
|
async function linkBinary(binRoot: string, name: string, packageDir: string, target: string, seen: Set<string>) {
|
|
if (!name || !target) {
|
|
return
|
|
}
|
|
const normalizedName = normalizeBinName(name)
|
|
if (seen.has(normalizedName)) {
|
|
return
|
|
}
|
|
const resolved = join(packageDir, target)
|
|
const script = Bun.file(resolved)
|
|
if (!(await script.exists())) {
|
|
return
|
|
}
|
|
seen.add(normalizedName)
|
|
const destination = join(binRoot, normalizedName)
|
|
const relativeTarget = relative(binRoot, resolved) || "."
|
|
await rm(destination, { force: true })
|
|
await symlink(relativeTarget, destination)
|
|
rewritten++
|
|
}
|
|
|
|
async function exists(path: string) {
|
|
try {
|
|
await lstat(path)
|
|
return true
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
async function isDirectory(path: string) {
|
|
try {
|
|
const info = await lstat(path)
|
|
return info.isDirectory()
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
function normalizeBinName(name: string) {
|
|
const slash = name.lastIndexOf("/")
|
|
if (slash >= 0) {
|
|
return name.slice(slash + 1)
|
|
}
|
|
return name
|
|
}
|