diff --git a/.github/workflows/test-hooks.yml b/.github/workflows/test-hooks.yml index ed5df8d..07b14e7 100644 --- a/.github/workflows/test-hooks.yml +++ b/.github/workflows/test-hooks.yml @@ -7,12 +7,18 @@ on: jobs: test: - name: Test on ${{ matrix.os }} + name: Test on ${{ matrix.os }} with ${{ matrix.install-method }} runs-on: ${{ matrix.os }} + permissions: + contents: read strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] + install-method: ['install-hooks.py', 'install-hooks.sh'] + exclude: + - os: windows-latest + install-method: 'install-hooks.sh' steps: - name: Checkout repository @@ -47,3 +53,5 @@ jobs: - name: Run Python tests run: python test_hooks.py + env: + INSTALL_HOOKS_METHOD: ${{ matrix.install-method }} diff --git a/scripts/install-hooks.py b/scripts/install-hooks.py index f671d58..136a615 100644 --- a/scripts/install-hooks.py +++ b/scripts/install-hooks.py @@ -8,6 +8,9 @@ import sys import os + # Automatically detect the script directory (like the shell script does) + script_dir = os.path.dirname(os.path.abspath(__file__)) + def read_file(path): print("Reading file: " + path) with open(path, 'r') as content_file: @@ -48,9 +51,9 @@ def write_file(path, content): print("Reading hooks...") print() - post_checkout_commands = read_file("post-checkout") - post_merge_commands = read_file("post-merge") - pre_commit_commands = read_file("pre-commit") + post_checkout_commands = read_file(os.path.join(script_dir, "post-checkout")) + post_merge_commands = read_file(os.path.join(script_dir, "post-merge")) + pre_commit_commands = read_file(os.path.join(script_dir, "pre-commit")) print() print() @@ -71,6 +74,6 @@ def write_file(path, content): except Exception as ex: print() - print("Error occured: " + str(ex)) + print("Error occurred: " + str(ex)) input("Press any key to exit.") diff --git a/test_hooks.py b/test_hooks.py index efd98fe..ff118dd 100755 --- a/test_hooks.py +++ b/test_hooks.py @@ -99,7 +99,12 @@ def _install_hooks(self): """ Install git hooks into the test repository Hooks will be run automatically by git + + Uses the installation method specified by INSTALL_HOOKS_METHOD environment variable. + If not set, defaults to install-hooks.py. """ + install_method = os.environ.get('INSTALL_HOOKS_METHOD', 'install-hooks.py') + # Get the scripts directory script_dir = Path(__file__).parent / 'scripts' @@ -107,16 +112,68 @@ def _install_hooks(self): hooks_dir = os.path.join(self.repo_dir, '.git', 'hooks') os.makedirs(hooks_dir, exist_ok=True) - # Copy hook files - hooks = ['pre-commit', 'post-checkout', 'post-merge'] - for hook in hooks: - src = script_dir / hook - dst = os.path.join(hooks_dir, hook) - if src.exists(): - shutil.copy2(str(src), dst) - # Make executable on Unix systems - if platform.system() != 'Windows': - os.chmod(dst, 0o755) + if install_method == 'install-hooks.sh': + # Use the shell script to install hooks + install_script = script_dir / 'install-hooks.sh' + if platform.system() == 'Windows': + # On Windows, we need bash to run the shell script + # Try Git Bash first + bash_paths = [ + os.path.expandvars(r'%PROGRAMFILES%\Git\bin\bash.exe'), + os.path.expandvars(r'%PROGRAMFILES(X86)%\Git\bin\bash.exe'), + ] + bash_cmd = None + for bash_path in bash_paths: + if os.path.exists(bash_path): + bash_cmd = bash_path + break + + if not bash_cmd: + bash_cmd = shutil.which('bash') + + if bash_cmd: + subprocess.run( + [bash_cmd, str(install_script)], + cwd=self.repo_dir, + check=True + ) + else: + # Raise error if bash is not available on Windows + raise RuntimeError("Bash is required to run install-hooks.sh on Windows, but it was not found") + else: + subprocess.run( + [str(install_script)], + cwd=self.repo_dir, + check=True + ) + + elif install_method == 'install-hooks.py': + # Use the Python script to install hooks + install_script = script_dir / 'install-hooks.py' + # The install-hooks.py script now auto-detects its directory and can be run from anywhere. + # It still requires user input for the repo path and exit confirmation. + subprocess.run( + [sys.executable, str(install_script)], + input=self.repo_dir + '\n\n', # First for repo path, second for exit prompt + text=True, + check=True, + capture_output=True + ) + + # The install-hooks.py script doesn't set executable permissions + # We need to do this after installation on Unix systems + if platform.system() != 'Windows': + hooks = ['pre-commit', 'post-checkout', 'post-merge'] + for hook in hooks: + hook_path = os.path.join(hooks_dir, hook) + if os.path.exists(hook_path): + os.chmod(hook_path, 0o755) + + else: + # Unknown installation method + raise ValueError(f"Unknown installation method: {install_method}. " + f"Expected 'install-hooks.py' or 'install-hooks.sh'") + class TestPreCommitHook(GitHooksTestCase):