From 66db44e7e1c5a668bc34649b8cb7950dbf2583cb Mon Sep 17 00:00:00 2001 From: Alexander Lichter Date: Wed, 20 May 2026 21:25:49 +0200 Subject: [PATCH] fix(cli): add managed bin to hook path --- .../migration-add-git-hooks/snap.txt | 9 +++ .../snap.txt | 9 +++ .../cli/src/config/__tests__/hooks.spec.ts | 63 ++++++++++++++++++- packages/cli/src/config/hooks.ts | 9 +++ 4 files changed, 89 insertions(+), 1 deletion(-) diff --git a/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt b/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt index c98f4e9d51..5eefd42a6b 100644 --- a/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt +++ b/packages/cli/snap-tests-global/migration-add-git-hooks/snap.txt @@ -59,6 +59,15 @@ i="${XDG_CONFIG_HOME:-$HOME/.config}/vite-plus/hooks-init.sh" { [ "${HUSKY-}" = "0" ] || [ "${VITE_GIT_HOOKS-}" = "0" ]; } && exit 0 +if [ -n "${VP_HOME-}" ]; then + __vp_bin="$VP_HOME/bin" +elif [ -n "${HOME-}" ]; then + __vp_bin="$HOME/.vite-plus/bin" +else + __vp_bin="" +fi +[ -n "$__vp_bin" ] && [ -d "$__vp_bin" ] && export PATH="$__vp_bin:$PATH" + d="$(dirname "$(dirname "$(dirname "$0")")")" export PATH="$d/node_modules/.bin:$PATH" sh -e "$s" "$@" diff --git a/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt b/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt index 27fed7c01c..e05a6ebe92 100644 --- a/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt +++ b/packages/cli/snap-tests-global/migration-composed-husky-custom-dir/snap.txt @@ -51,6 +51,15 @@ i="${XDG_CONFIG_HOME:-$HOME/.config}/vite-plus/hooks-init.sh" { [ "${HUSKY-}" = "0" ] || [ "${VITE_GIT_HOOKS-}" = "0" ]; } && exit 0 +if [ -n "${VP_HOME-}" ]; then + __vp_bin="$VP_HOME/bin" +elif [ -n "${HOME-}" ]; then + __vp_bin="$HOME/.vite-plus/bin" +else + __vp_bin="" +fi +[ -n "$__vp_bin" ] && [ -d "$__vp_bin" ] && export PATH="$__vp_bin:$PATH" + d="$(dirname "$(dirname "$(dirname "$(dirname "$0")")")")" export PATH="$d/node_modules/.bin:$PATH" sh -e "$s" "$@" diff --git a/packages/cli/src/config/__tests__/hooks.spec.ts b/packages/cli/src/config/__tests__/hooks.spec.ts index 8ec28d8f3f..80abee1c97 100644 --- a/packages/cli/src/config/__tests__/hooks.spec.ts +++ b/packages/cli/src/config/__tests__/hooks.spec.ts @@ -1,5 +1,5 @@ import { execSync } from 'node:child_process'; -import { existsSync, mkdtempSync, rmSync } from 'node:fs'; +import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; @@ -73,4 +73,65 @@ describe('hookScript', () => { expect(countDirnameCalls(withDot)).toBe(countDirnameCalls(withoutDot)); expect(countDirnameCalls(withDot)).toBe(3); }); + + it.skipIf(process.platform === 'win32')( + 'should add Vite+ managed bin to PATH before running user hook', + () => { + const tmp = mkdtempSync(join(tmpdir(), 'hooks-path-test-')); + try { + const hooksDir = join(tmp, '.vite-hooks'); + const internalHooksDir = join(hooksDir, '_'); + const nodeModulesBin = join(tmp, 'node_modules', '.bin'); + const vpHomeBin = join(tmp, 'vp-home', 'bin'); + const systemBin = join(tmp, 'system-bin'); + + mkdirSync(internalHooksDir, { recursive: true }); + mkdirSync(nodeModulesBin, { recursive: true }); + mkdirSync(vpHomeBin, { recursive: true }); + mkdirSync(systemBin, { recursive: true }); + + writeFileSync(join(internalHooksDir, 'h'), hookScript('.vite-hooks'), { mode: 0o755 }); + writeFileSync( + join(internalHooksDir, 'pre-commit'), + '#!/usr/bin/env sh\n. "$(dirname "$0")/h"', + { mode: 0o755 }, + ); + writeFileSync(join(hooksDir, 'pre-commit'), 'vp staged\n'); + + writeFileSync( + join(nodeModulesBin, 'vp'), + '#!/bin/sh\nbasedir=$(dirname "$0")\nexec node "$basedir/../vite-plus/bin/vp" "$@"\n', + { mode: 0o755 }, + ); + writeFileSync( + join(vpHomeBin, 'node'), + '#!/bin/sh\necho "fake-node $*" > "$VP_HOME/node-used"\n', + { mode: 0o755 }, + ); + + writeFileSync(join(systemBin, 'sh'), '#!/bin/sh\nexec /bin/sh "$@"\n', { + mode: 0o755, + }); + writeFileSync(join(systemBin, 'dirname'), '#!/bin/sh\nexec /usr/bin/dirname "$@"\n', { + mode: 0o755, + }); + writeFileSync(join(systemBin, 'basename'), '#!/bin/sh\nexec /usr/bin/basename "$@"\n', { + mode: 0o755, + }); + + execSync('sh .vite-hooks/_/pre-commit', { + cwd: tmp, + env: { + HOME: join(tmp, 'home'), + PATH: systemBin, + VP_HOME: join(tmp, 'vp-home'), + }, + }); + + expect(existsSync(join(tmp, 'vp-home', 'node-used'))).toBe(true); + } finally { + rmSync(tmp, { recursive: true, force: true }); + } + }, + ); }); diff --git a/packages/cli/src/config/hooks.ts b/packages/cli/src/config/hooks.ts index df0866dcbb..33e5778d19 100644 --- a/packages/cli/src/config/hooks.ts +++ b/packages/cli/src/config/hooks.ts @@ -49,6 +49,15 @@ i="\${XDG_CONFIG_HOME:-$HOME/.config}/vite-plus/hooks-init.sh" { [ "\${HUSKY-}" = "0" ] || [ "\${VITE_GIT_HOOKS-}" = "0" ]; } && exit 0 +if [ -n "\${VP_HOME-}" ]; then + __vp_bin="$VP_HOME/bin" +elif [ -n "\${HOME-}" ]; then + __vp_bin="$HOME/.vite-plus/bin" +else + __vp_bin="" +fi +[ -n "$__vp_bin" ] && [ -d "$__vp_bin" ] && export PATH="$__vp_bin:$PATH" + d=${rootExpr} export PATH="$d/node_modules/.bin:$PATH" sh -e "$s" "$@"