Spaces:
Configuration error
Configuration error
| import fs from "node:fs"; | |
| import path from "node:path"; | |
| import { spawnSync } from "node:child_process"; | |
| import { fileURLToPath } from "node:url"; | |
| const OXFMT_EXTENSIONS = new Set([ | |
| ".cjs", | |
| ".js", | |
| ".json", | |
| ".jsonc", | |
| ".jsx", | |
| ".mjs", | |
| ".ts", | |
| ".tsx", | |
| ]); | |
| function getRepoRoot() { | |
| const here = path.dirname(fileURLToPath(import.meta.url)); | |
| return path.resolve(here, ".."); | |
| } | |
| function runGitCommand(args, options = {}) { | |
| return spawnSync("git", args, { | |
| cwd: options.cwd, | |
| encoding: "utf-8", | |
| stdio: options.stdio ?? "pipe", | |
| }); | |
| } | |
| function splitNullDelimited(value) { | |
| if (!value) return []; | |
| const text = String(value); | |
| return text.split("\0").filter(Boolean); | |
| } | |
| function normalizeGitPath(filePath) { | |
| return filePath.replace(/\\/g, "/"); | |
| } | |
| function filterOxfmtTargets(paths) { | |
| return paths | |
| .map(normalizeGitPath) | |
| .filter((filePath) => | |
| (filePath.startsWith("src/") || filePath.startsWith("test/")) && | |
| OXFMT_EXTENSIONS.has(path.posix.extname(filePath)), | |
| ); | |
| } | |
| function findPartiallyStagedFiles(stagedFiles, unstagedFiles) { | |
| const unstaged = new Set(unstagedFiles.map(normalizeGitPath)); | |
| return stagedFiles.filter((filePath) => unstaged.has(normalizeGitPath(filePath))); | |
| } | |
| function filterOutPartialTargets(targets, partialTargets) { | |
| if (partialTargets.length === 0) return targets; | |
| const partial = new Set(partialTargets.map(normalizeGitPath)); | |
| return targets.filter((filePath) => !partial.has(normalizeGitPath(filePath))); | |
| } | |
| function resolveOxfmtCommand(repoRoot) { | |
| const binName = process.platform === "win32" ? "oxfmt.cmd" : "oxfmt"; | |
| const local = path.join(repoRoot, "node_modules", ".bin", binName); | |
| if (fs.existsSync(local)) { | |
| return { command: local, args: [] }; | |
| } | |
| const result = spawnSync("oxfmt", ["--version"], { stdio: "ignore" }); | |
| if (result.status === 0) { | |
| return { command: "oxfmt", args: [] }; | |
| } | |
| return null; | |
| } | |
| function getGitPaths(args, repoRoot) { | |
| const result = runGitCommand(args, { cwd: repoRoot }); | |
| if (result.status !== 0) return []; | |
| return splitNullDelimited(result.stdout ?? ""); | |
| } | |
| function formatFiles(repoRoot, oxfmt, files) { | |
| const result = spawnSync(oxfmt.command, ["--write", ...oxfmt.args, ...files], { | |
| cwd: repoRoot, | |
| stdio: "inherit", | |
| }); | |
| return result.status === 0; | |
| } | |
| function stageFiles(repoRoot, files) { | |
| if (files.length === 0) return true; | |
| const result = runGitCommand(["add", "--", ...files], { cwd: repoRoot, stdio: "inherit" }); | |
| return result.status === 0; | |
| } | |
| function main() { | |
| const repoRoot = getRepoRoot(); | |
| const staged = getGitPaths([ | |
| "diff", | |
| "--cached", | |
| "--name-only", | |
| "-z", | |
| "--diff-filter=ACMR", | |
| ], repoRoot); | |
| const targets = filterOxfmtTargets(staged); | |
| if (targets.length === 0) return; | |
| const unstaged = getGitPaths(["diff", "--name-only", "-z"], repoRoot); | |
| const partial = findPartiallyStagedFiles(targets, unstaged); | |
| if (partial.length > 0) { | |
| process.stderr.write("[pre-commit] Skipping partially staged files:\n"); | |
| for (const filePath of partial) { | |
| process.stderr.write(`- ${filePath}\n`); | |
| } | |
| process.stderr.write("Stage full files to format them automatically.\n"); | |
| } | |
| const filteredTargets = filterOutPartialTargets(targets, partial); | |
| if (filteredTargets.length === 0) return; | |
| const oxfmt = resolveOxfmtCommand(repoRoot); | |
| if (!oxfmt) { | |
| process.stderr.write("[pre-commit] oxfmt not found; skipping format.\n"); | |
| return; | |
| } | |
| if (!formatFiles(repoRoot, oxfmt, filteredTargets)) { | |
| process.exitCode = 1; | |
| return; | |
| } | |
| if (!stageFiles(repoRoot, filteredTargets)) { | |
| process.exitCode = 1; | |
| } | |
| } | |
| export { | |
| filterOxfmtTargets, | |
| filterOutPartialTargets, | |
| findPartiallyStagedFiles, | |
| getRepoRoot, | |
| normalizeGitPath, | |
| resolveOxfmtCommand, | |
| splitNullDelimited, | |
| }; | |
| if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { | |
| main(); | |
| } | |