Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions jest.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/** @type {import('jest').Config} */
module.exports = {
testEnvironment: 'node',
transform: {
'^.+\\.tsx?$': [
'ts-jest',
{
tsconfig: 'tsconfig.json',
useESM: true,
},
],
},
extensionsToTreatAsEsm: ['.ts'],
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
},
};
9 changes: 0 additions & 9 deletions jest.config.ts

This file was deleted.

12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"prettier": "^3.6.2",
"rimraf": "^6.0.1",
"semantic-release": "^24.0.0",
"ts-jest": "^29.4.2",
"ts-jest": "^29.4.3",
"ts-node": "^10.9.2",
"typescript": "^5.9.2"
}
Expand Down
15 changes: 11 additions & 4 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#!/usr/bin/env node
import { Command } from './types.js';
import { log } from './utils/log.js';
import { handleResetHooks } from './commands/resetHooks.js';
import { handleInit } from './commands/init.js';
import { handleInstall } from './commands/install.js';
import { handleResetHooks } from './commands/resetHooks.js';
import { handleUninstall } from './commands/uninstall.js';
import { handleInit } from './commands/init.js';
import { Command } from './types.js';
import { isGitRepository } from './utils/git.js';
import { log } from './utils/log.js';

function printUsage(): void {
log.info('Usage: volbrene-git-hooks <command>\n');
Expand All @@ -19,6 +20,12 @@ function printUsage(): void {
const [, , ...argv] = process.argv;
const command = (argv[0] || 'install') as Command;

if (!isGitRepository()) {
log.info('Not a git repository, skipping...');

process.exit(0);
}

switch (command) {
case 'init':
handleInit();
Expand Down
6 changes: 2 additions & 4 deletions src/commands/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { assertGitRepo, getHooksPath, resolveRepoRoot } from '../utils/git.js';
import { log } from '../utils/log.js';
import { fail } from '../utils/errors.js';
import { getHooksPath, resolveRepoRoot } from '../utils/git.js';
import { log } from '../utils/log.js';

/**
*
Expand Down Expand Up @@ -61,8 +61,6 @@ function addGitHook(hookName: string, sourceDir: string, targetDir: string): voi
* @returns void
*/
export function handleInstall(): void {
assertGitRepo();

log.step('Git Hooks Setup');

// Resolve repo root
Expand Down
6 changes: 2 additions & 4 deletions src/commands/resetHooks.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { assertGitRepo, getHooksPath, resetHooksPath } from '../utils/git.js';
import { log } from '../utils/log.js';
import { fail } from '../utils/errors.js';
import { getHooksPath, resetHooksPath } from '../utils/git.js';
import { log } from '../utils/log.js';

/**
* Handles the 'reset-hooks' command.
*/
export function handleResetHooks(): void {
assertGitRepo();

log.step('Resetting core.hooksPath to .git/hooks...');

try {
Expand Down
6 changes: 2 additions & 4 deletions src/commands/uninstall.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { assertGitRepo, removeHooksDirAndUnset } from '../utils/git.js';
import { log } from '../utils/log.js';
import { fail } from '../utils/errors.js';
import { removeHooksDirAndUnset } from '../utils/git.js';
import { log } from '../utils/log.js';

/**
* Handles the 'uninstall' command.
*/
export function handleUninstall(): void {
assertGitRepo();

log.link('Uninstalling hooks...');

try {
Expand Down
9 changes: 5 additions & 4 deletions src/utils/git.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import fs from 'node:fs';
import { sh, shGetOutput } from './exec.js';
import { fail } from './errors.js';
import path from 'node:path';
import { sh, shGetOutput } from './exec.js';

/** Ensure we are inside a git repository (cheap sanity check). */
export function assertGitRepo(): void {
export function isGitRepository(): boolean {
try {
shGetOutput('git rev-parse --is-inside-work-tree');
} catch (e) {
fail(e, 'Not a git repository');
return false;
}

return true;
}

/**
Expand Down
8 changes: 8 additions & 0 deletions tests/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ function runCLI(args: string[], cwd: string): string {
}

describe('volbrene-git-hooks CLI', () => {
test('should print a warning and skip execution when no git repository is present', () => {
const cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'pcm-'));

const out = runCLI([''], cwd);

expect(out).toMatch(/Not a git repository,/);
});

test('init writes prepare script into package.json (no install)', () => {
const { cwd } = setupGitRepo();

Expand Down