lockfile-guardian
Version:
Never forget to install dependencies again! Automatically detect when your lock files change after git operations and warn you (or auto-install) when your dependencies are out of sync.
128 lines • 5.17 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.installGitHooks = installGitHooks;
exports.uninstallGitHooks = uninstallGitHooks;
exports.areHooksInstalled = areHooksInstalled;
const fs_1 = require("fs");
const path_1 = require("path");
const utils_1 = require("./utils");
const HOOK_SHEBANG = "#!/bin/sh";
const HOOK_COMMAND = "npx lockfile-guardian check --hook";
const GIT_HOOKS = [
{ name: "post-checkout", path: "post-checkout" },
{ name: "post-merge", path: "post-merge" },
{ name: "post-rewrite", path: "post-rewrite" },
];
function createHookContent(existingContent, isHusky = false) {
const hookLine = HOOK_COMMAND;
// If there's existing content, preserve it and add our hook
if (existingContent && existingContent.trim()) {
const lines = existingContent.split("\n");
// Check if our hook is already present
if (lines.some((line) => line.includes(HOOK_COMMAND))) {
return existingContent;
}
// For Husky hooks, we want to add our command at the end to run after other hooks
// For traditional hooks, we add after the shebang
if (isHusky) {
// Husky hooks don't need shebang handling, just append
return existingContent + "\n\n# Lockfile Guardian\n" + hookLine;
}
else {
// Traditional git hooks - add after shebang
const shebangIndex = lines.findIndex((line) => line.startsWith("#!"));
if (shebangIndex >= 0) {
lines.splice(shebangIndex + 1, 0, "", `# Lockfile Guardian`, hookLine);
}
else {
lines.unshift(HOOK_SHEBANG, "", "# Lockfile Guardian", hookLine);
}
return lines.join("\n");
}
}
// Create new hook content
if (isHusky) {
// Husky hooks are simpler - just the command with a comment
return ["# Lockfile Guardian", hookLine, ""].join("\n");
}
else {
// Traditional hooks need shebang
return [HOOK_SHEBANG, "", "# Lockfile Guardian", hookLine, ""].join("\n");
}
}
function removeHookContent(content, isHusky = false) {
const lines = content.split("\n");
const filteredLines = lines.filter((line) => !line.includes(HOOK_COMMAND) && !line.includes("# Lockfile Guardian"));
const remainingContent = filteredLines.join("\n").trim();
if (isHusky) {
// For Husky hooks, if no content remains, remove the file
if (remainingContent === "") {
return null;
}
return filteredLines.join("\n");
}
else {
// For traditional hooks, if only shebang remains, remove the file entirely
if (remainingContent === HOOK_SHEBANG || remainingContent === "") {
return null;
}
return filteredLines.join("\n");
}
}
function installGitHooks(cwd = process.cwd()) {
if (!(0, utils_1.isGitRepository)(cwd)) {
throw new Error("Not a git repository. Please run this command in a git repository.");
}
const isHusky = (0, utils_1.isHuskyProject)(cwd);
const hooksDir = (0, utils_1.getActiveHooksDir)(cwd);
// Create hooks directory if it doesn't exist
if (!(0, fs_1.existsSync)(hooksDir)) {
(0, fs_1.mkdirSync)(hooksDir, { recursive: true });
}
for (const hook of GIT_HOOKS) {
const hookPath = (0, path_1.join)(hooksDir, hook.path);
let existingContent = "";
if ((0, fs_1.existsSync)(hookPath)) {
existingContent = (0, fs_1.readFileSync)(hookPath, "utf8");
}
const newContent = createHookContent(existingContent, isHusky);
(0, fs_1.writeFileSync)(hookPath, newContent, "utf8");
// Make executable (important for both traditional and Husky hooks)
(0, fs_1.chmodSync)(hookPath, 0o755);
}
}
function uninstallGitHooks(cwd = process.cwd()) {
if (!(0, utils_1.isGitRepository)(cwd)) {
return; // Silently skip if not a git repository
}
const isHusky = (0, utils_1.isHuskyProject)(cwd);
const hooksDir = (0, utils_1.getActiveHooksDir)(cwd);
for (const hook of GIT_HOOKS) {
const hookPath = (0, path_1.join)(hooksDir, hook.path);
if ((0, fs_1.existsSync)(hookPath)) {
const content = (0, fs_1.readFileSync)(hookPath, "utf8");
const newContent = removeHookContent(content, isHusky);
if (newContent === null) {
(0, fs_1.unlinkSync)(hookPath);
}
else {
(0, fs_1.writeFileSync)(hookPath, newContent, "utf8");
}
}
}
}
function areHooksInstalled(cwd = process.cwd()) {
if (!(0, utils_1.isGitRepository)(cwd)) {
return false;
}
const hooksDir = (0, utils_1.getActiveHooksDir)(cwd);
return GIT_HOOKS.every((hook) => {
const hookPath = (0, path_1.join)(hooksDir, hook.path);
if (!(0, fs_1.existsSync)(hookPath)) {
return false;
}
const content = (0, fs_1.readFileSync)(hookPath, "utf8");
return content.includes(HOOK_COMMAND);
});
}
//# sourceMappingURL=git-hooks.js.map