mirror of
https://github.com/ast-grep/ast-grep.git
synced 2026-05-06 06:06:46 -04:00
fix: replace postinstall script with binary resolution in ast-grep (#2595)
* fix: replace postinstall script with binary resolution in ast-grep * fix: restrict package name detection
This commit is contained in:
committed by
GitHub
parent
673b6c0fbf
commit
333e195155
Regular → Executable
+149
-3
@@ -1,3 +1,149 @@
|
||||
echo "ast-grep shim file was executed. This file exists so that npm tries to create the binary. It should be replaced after the 'postinstall' script is executed."
|
||||
echo "Did your package manager execute the post-install script? (N.B. not all of them do)"
|
||||
exit 1
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { spawn } = require("node:child_process");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const binaryName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
|
||||
|
||||
function detectPackageName() {
|
||||
const { platform, arch } = process;
|
||||
|
||||
switch (platform) {
|
||||
case "darwin":
|
||||
if (arch === "arm64") return "@ast-grep/cli-darwin-arm64";
|
||||
if (arch === "x64") return "@ast-grep/cli-darwin-x64";
|
||||
break;
|
||||
case "linux": {
|
||||
const { MUSL, familySync } = require("detect-libc");
|
||||
if (familySync() === MUSL) return null;
|
||||
if (arch === "arm64") return "@ast-grep/cli-linux-arm64-gnu";
|
||||
if (arch === "x64") return "@ast-grep/cli-linux-x64-gnu";
|
||||
break;
|
||||
}
|
||||
case "win32":
|
||||
if (arch === "arm64") return "@ast-grep/cli-win32-arm64-msvc";
|
||||
if (arch === "ia32") return "@ast-grep/cli-win32-ia32-msvc";
|
||||
if (arch === "x64") return "@ast-grep/cli-win32-x64-msvc";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function failToLocateBinary(pkgName, originalError) {
|
||||
const messages = ["Failed to locate the ast-grep native binary."];
|
||||
|
||||
if (pkgName) {
|
||||
messages.push(`Expected package: ${pkgName}`);
|
||||
} else {
|
||||
messages.push(
|
||||
"This platform does not have a published prebuilt ast-grep binary.",
|
||||
);
|
||||
}
|
||||
|
||||
if (originalError) {
|
||||
messages.push(`Underlying error: ${originalError.message}`);
|
||||
}
|
||||
|
||||
messages.push(
|
||||
"If you are installing from npm, ensure optional dependencies are enabled (e.g. do not use --no-optional).",
|
||||
);
|
||||
messages.push(
|
||||
"For local development, run `cargo build --release` before invoking this script.",
|
||||
);
|
||||
|
||||
console.error(messages.join("\n"));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function resolveBinaryPath() {
|
||||
const pkgName = detectPackageName();
|
||||
let moduleError = null;
|
||||
|
||||
if (pkgName) {
|
||||
try {
|
||||
const pkgDir = path.dirname(
|
||||
require.resolve(`${pkgName}/package.json`, { paths: [__dirname] }),
|
||||
);
|
||||
const candidate = path.join(pkgDir, binaryName);
|
||||
if (fs.existsSync(candidate)) {
|
||||
return { binaryPath: candidate, pkgName };
|
||||
}
|
||||
} catch (err) {
|
||||
moduleError = err;
|
||||
}
|
||||
}
|
||||
|
||||
const releaseCandidate = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"target",
|
||||
"release",
|
||||
binaryName,
|
||||
);
|
||||
if (fs.existsSync(releaseCandidate)) {
|
||||
return { binaryPath: releaseCandidate, pkgName: null };
|
||||
}
|
||||
|
||||
const debugCandidate = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"target",
|
||||
"debug",
|
||||
binaryName,
|
||||
);
|
||||
if (fs.existsSync(debugCandidate)) {
|
||||
return { binaryPath: debugCandidate, pkgName: null };
|
||||
}
|
||||
|
||||
failToLocateBinary(pkgName, moduleError);
|
||||
}
|
||||
|
||||
function attachChildLifecycle(child) {
|
||||
child.on("error", (error) => {
|
||||
console.error("Failed to execute ast-grep binary.");
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
const signals = ["SIGINT", "SIGTERM", "SIGHUP"];
|
||||
const forwarders = signals.map((signal) => {
|
||||
const handler = () => {
|
||||
if (child.killed) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
child.kill(signal);
|
||||
} catch (_) {
|
||||
// Ignore
|
||||
}
|
||||
};
|
||||
process.on(signal, handler);
|
||||
return { signal, handler };
|
||||
});
|
||||
|
||||
child.on("exit", (code, signal) => {
|
||||
forwarders.forEach(({ signal, handler }) => {
|
||||
process.removeListener(signal, handler);
|
||||
});
|
||||
|
||||
if (signal) {
|
||||
process.kill(process.pid, signal);
|
||||
} else {
|
||||
process.exit(code == null ? 1 : code);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function main() {
|
||||
const { binaryPath } = resolveBinaryPath();
|
||||
const child = spawn(binaryPath, process.argv.slice(2), {
|
||||
stdio: "inherit",
|
||||
});
|
||||
attachChildLifecycle(child);
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
+1
-5
@@ -20,15 +20,11 @@
|
||||
],
|
||||
"files": [
|
||||
"sg",
|
||||
"ast-grep",
|
||||
"postinstall.js"
|
||||
"ast-grep"
|
||||
],
|
||||
"dependencies": {
|
||||
"detect-libc": "2.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "node postinstall.js"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@ast-grep/cli-win32-arm64-msvc": "0.42.1",
|
||||
"@ast-grep/cli-win32-ia32-msvc": "0.42.1",
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
let fs = require('fs');
|
||||
let path = require('path');
|
||||
|
||||
let parts = [process.platform, process.arch];
|
||||
if (process.platform === 'linux') {
|
||||
const {MUSL, familySync} = require('detect-libc');
|
||||
if (familySync() === MUSL) {
|
||||
parts.push('musl');
|
||||
} else if (process.arch === 'arm') {
|
||||
parts.push('gnueabihf');
|
||||
} else {
|
||||
parts.push('gnu');
|
||||
}
|
||||
} else if (process.platform === 'win32') {
|
||||
parts.push('msvc');
|
||||
}
|
||||
|
||||
let binary = process.platform === 'win32' ? 'ast-grep.exe' : 'ast-grep';
|
||||
let alternative = process.platform === 'win32' ? 'sg.exe' : 'sg';
|
||||
|
||||
let pkgPath;
|
||||
try {
|
||||
pkgPath = path.dirname(require.resolve(`@ast-grep/cli-${parts.join('-')}/package.json`));
|
||||
} catch (err) {
|
||||
pkgPath = path.join(__dirname, '..', 'target', 'release');
|
||||
if (!fs.existsSync(path.join(pkgPath, binary))) {
|
||||
pkgPath = path.join(__dirname, '..', 'target', 'debug');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
fs.linkSync(path.join(pkgPath, binary), path.join(__dirname, binary));
|
||||
fs.linkSync(path.join(pkgPath, binary), path.join(__dirname, alternative));
|
||||
} catch (err) {
|
||||
try {
|
||||
fs.copyFileSync(path.join(pkgPath, binary), path.join(__dirname, binary));
|
||||
fs.copyFileSync(path.join(pkgPath, binary), path.join(__dirname, alternative));
|
||||
} catch (err) {
|
||||
console.error('Failed to move @ast-grep/cli binary into place.');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
try {
|
||||
fs.unlinkSync(path.join(__dirname, 'sg'));
|
||||
fs.unlinkSync(path.join(__dirname, 'ast-grep'));
|
||||
} catch (err) {}
|
||||
}
|
||||
Reference in New Issue
Block a user