|
1 | 1 | #!/usr/bin/env bash |
2 | 2 |
|
| 3 | +ALLOW_ANALYSIS_VAR="BYPASS_PHP_ANALYSIS" |
| 4 | + |
| 5 | +if [ "${!ALLOW_ANALYSIS_VAR}" == "1" ]; then |
| 6 | + echo "BYPASS_PHP_ANALYSIS is set to 1. Skipping code quality checks." |
| 7 | + exit 0 |
| 8 | +fi |
| 9 | + |
3 | 10 | # Check if MERGE_HEAD exists |
4 | 11 | if [ -f "$GIT_DIR/MERGE_HEAD" ]; then |
5 | | - # Skip the hook during a merge |
| 12 | + echo "Merge in progress. Skipping pre-commit hook." |
6 | 13 | exit 0 |
7 | 14 | fi |
8 | 15 |
|
9 | 16 | ROOT=$(git rev-parse --show-toplevel) |
10 | 17 | runner="$ROOT/tools/runner.sh" |
11 | 18 |
|
12 | 19 | # Filter for only .php files (using grep) |
13 | | -STAGED_FILES=$(git diff --diff-filter=ACMR --cached --name-only -- . ":(exclude)vendor/*" ":(exclude)ecs.php" ":(exclude)rector.php" HEAD) |
14 | | -# Check if there are any staged PHP files |
15 | | -if ! echo "$STAGED_FILES" | grep '\.php$'; then |
16 | | - echo "No staged PHP files found. Skipping checks..." |
17 | | - exit 0 |
18 | | -fi |
| 20 | +STAGED_FILES=$(git diff --diff-filter=ACMR --cached --name-only -- . ":(exclude)vendor/*" HEAD) |
19 | 21 |
|
20 | | -echo "Checking PHP Lint..." |
| 22 | +# Filter for only PHP files and store in a new variable |
| 23 | +PHP_FILES="" |
21 | 24 | for FILE in $STAGED_FILES; do |
22 | | - if ! echo "$FILE" | grep '\.php$'; then |
23 | | - continue |
24 | | - fi |
25 | | - bash "$runner" php -l -d display_errors=0 "$FILE" |
26 | | - if [ $? != 0 ]; then |
27 | | - echo "Fix the error before commit." |
28 | | - exit 1 |
29 | | - fi |
30 | | - # Add the file to the FILES variable |
31 | | - FILES="$FILES $FILE" |
32 | | - # Ensure there are no trailing whitespaces in $FILES |
33 | | - FILES=$(echo "$FILES" | xargs) |
| 25 | + if [[ "$FILE" =~ \.php$ ]]; then |
| 26 | + PHP_FILES="$PHP_FILES $FILE" |
| 27 | + fi |
34 | 28 | done |
35 | 29 |
|
36 | | -if [ "$FILES" != "" ]; then |
37 | | - |
38 | | - if [ -f "$ROOT/vendor/bin/ecs" ]; then |
39 | | - echo "Pre-hook: Running EasyCodingStandard" |
40 | | - bash "$runner" ./vendor/bin/ecs check --fix $FILES |
| 30 | +# Trim whitespace from the list of PHP files |
| 31 | +PHP_FILES=$(echo "$PHP_FILES" | xargs) |
41 | 32 |
|
42 | | - bash "$runner" git add $FILES |
43 | | - fi |
| 33 | +# Check if there are any staged PHP files |
| 34 | +if [ -z "$PHP_FILES" ]; then |
| 35 | + echo "No staged PHP files found. Skipping PHP checks..." |
| 36 | + exit 0 |
| 37 | +fi |
44 | 38 |
|
45 | | - if [ -f "$ROOT/vendor/bin/rector" ]; then |
46 | | - echo "Pre-hook: Running Rector" |
47 | | - bash "$runner" ./vendor/bin/rector process -- $FILES |
| 39 | +echo "--- Running PHP Checks on Staged Files ---" |
48 | 40 |
|
49 | | - bash "$runner" git add $FILES |
| 41 | +# --- PHP Lint Check --- |
| 42 | +echo "Checking PHP Lint..." |
| 43 | +for FILE in $PHP_FILES; do |
| 44 | + bash "$runner" php -l -d display_errors=0 "$FILE" |
| 45 | + if [ $? -ne 0 ]; then |
| 46 | + echo "PHP Lint failed in $FILE. Please fix the error before commit." |
| 47 | + exit 1 # Always exit for basic lint errors, as they prevent code execution |
50 | 48 | fi |
| 49 | +done |
| 50 | +echo "PHP Lint check passed." |
51 | 51 |
|
52 | | - if [ -f "$ROOT/vendor/bin/ecs" ]; then |
53 | | - echo "Pre-hook: Running EasyCodingStandard" |
54 | | - bash "$runner" ./vendor/bin/ecs check --fix $FILES |
55 | | - |
56 | | - bash "$runner" git add $FILES |
57 | | - fi |
58 | 52 |
|
59 | | - if [ -f "$ROOT/vendor/bin/deptrac" ]; then |
60 | | - echo "Pre-hook: Running deptrac" |
61 | | - bash "$runner" composer deptrac |
62 | | - RESULT=$? |
63 | | - if [ $RESULT -ne 0 ]; then |
64 | | - echo "Deptrac failed. Please fix the issues before committing." |
65 | | - exit 1 |
66 | | - fi |
67 | | - bash "$runner" composer deptrac:image |
68 | | - |
69 | | - bash "$runner" git add $FILES deptrac.png |
70 | | - fi |
71 | 53 |
|
72 | | - if [ -f "$ROOT/vendor/bin/phpstan" ]; then |
73 | | - echo "Pre-hook: Running PHPStan" |
74 | | - bash "$runner" ./vendor/bin/phpstan analyse -c phpstan.neon.dist $FILES |
| 54 | +# --- Rector (Run FIRST among modifiers) --- |
| 55 | +if [ -f "$ROOT/vendor/bin/rector" ]; then |
| 56 | + echo "Running Rector..." |
| 57 | + # Run Rector on staged files and automatically fix issues |
| 58 | + bash "$runner" "./vendor/bin/rector" process -- $PHP_FILES |
| 59 | + # Re-add files to staging area after Rector might have modified them |
| 60 | + bash "$runner" git add $PHP_FILES |
| 61 | + echo "Rector finished. Files re-added to staging." |
| 62 | +fi |
75 | 63 |
|
76 | | - RESULT_CODE=$? |
77 | | - if [ $RESULT_CODE != 0 ]; then |
78 | | - echo "Fix the error(s) before commit." |
79 | | - exit $RESULT_CODE |
80 | | - fi |
| 64 | +# --- EasyCodingStandard (ECS) (Run SECOND among modifiers) --- |
| 65 | +if [ -f "$ROOT/vendor/bin/ecs" ]; then |
| 66 | + echo "Running EasyCodingStandard..." |
| 67 | + # Run ECS on staged files and automatically fix issues |
| 68 | + bash "$runner" "./vendor/bin/ecs" check --fix $PHP_FILES |
| 69 | + # Re-add files to staging area after ECS might have modified them |
| 70 | + bash "$runner" git add $PHP_FILES |
| 71 | + echo "EasyCodingStandard finished. Files re-added to staging." |
| 72 | +fi |
81 | 73 |
|
82 | | - bash "$runner" git add $FILES |
| 74 | +if [ -f "$ROOT/vendor/bin/deptrac" ]; then |
| 75 | + echo "Running Deptrac..." |
| 76 | + # Run Deptrac on the relevant code paths (often the whole src directory) |
| 77 | + bash "$runner" composer deptrac |
| 78 | + DEPTRAC_RESULT=$? |
| 79 | + if [ $DEPTRAC_RESULT -ne 0 ]; then |
| 80 | + echo "Deptrac failed. Please fix the architectural issues before committing." |
| 81 | + exit $DEPTRAC_RESULT # Usually, deptrac failures should block commits |
83 | 82 | fi |
| 83 | + # Optional: Generate and add deptrac image if configured |
| 84 | + bash "$runner" composer deptrac:image |
| 85 | + bash "$runner" git add deptrac.png # Add generated image if applicable |
| 86 | + echo "Deptrac check passed." |
| 87 | +fi |
84 | 88 |
|
85 | | - if [ -f "$ROOT/vendor/bin/psalm.phar" ]; then |
86 | | - echo "Pre-hook: Running Psalm Phar" |
87 | | - bash "$runner" ./vendor/bin/psalm.phar --show-info=false $FILES |
88 | | - |
89 | | - RESULT_CODE=$? |
90 | | - if [ $RESULT_CODE != 0 ]; then |
91 | | - echo "Fix the error(s) before commit." |
92 | | - exit $RESULT_CODE |
93 | | - fi |
94 | | - |
95 | | - bash "$runner" git add $FILES |
| 89 | +# --- PHPStan --- |
| 90 | +if [ -f "$ROOT/vendor/bin/phpstan" ]; then |
| 91 | + echo "Running PHPStan..." |
| 92 | + # Run PHPStan analysis on staged files |
| 93 | + bash "$runner" "vendor/bin/phpstan" analyse -c phpstan.neon.dist $PHP_FILES |
| 94 | + PHPSTAN_RESULT=$? |
| 95 | + if [ $PHPSTAN_RESULT -ne 0 ]; then |
| 96 | + echo "PHPStan failed. Please fix the issues before commit." |
| 97 | + exit $PHPSTAN_RESULT # Exit if errors and bypass is not enabled |
96 | 98 | fi |
| 99 | + echo "PHPStan check passed." |
| 100 | +fi |
97 | 101 |
|
98 | | - if [ -f "$ROOT/vendor/bin/psalm" ]; then |
99 | | - echo "Pre-hook: Running Psalm" |
100 | | - bash "$runner" ./vendor/bin/psalm --show-info=false $FILES |
| 102 | +# --- Psalm --- |
| 103 | +# Check for psalm first, then psalm.phar |
| 104 | +PSALM_BIN="vendor/bin/psalm" |
| 105 | +if [ ! -f "$ROOT/vendor/bin/psalm" ]; then |
| 106 | + PSALM_BIN="vendor/bin/psalm.phar" |
| 107 | +fi |
101 | 108 |
|
102 | | - RESULT_CODE=$? |
103 | | - if [ $RESULT_CODE != 0 ]; then |
104 | | - echo "Fix the error(s) before commit." |
105 | | - exit $RESULT_CODE |
106 | | - fi |
| 109 | +if [ -f "$PSALM_BIN" ]; then |
| 110 | + echo "Running Psalm..." |
| 111 | + # Run Psalm analysis on staged files |
| 112 | + bash "$runner" "$PSALM_BIN" --show-info=false $PHP_FILES |
| 113 | + PSALM_RESULT=$? |
107 | 114 |
|
108 | | - bash "$runner" git add $FILES |
| 115 | + if [ $PSALM_RESULT -ne 0 ]; then |
| 116 | + echo "Psalm failed. Please fix the issues before commit." |
| 117 | + exit $PSALM_RESULT # Exit if errors and bypass is not enabled |
109 | 118 | fi |
| 119 | + echo "Psalm check passed." |
110 | 120 | fi |
| 121 | + |
| 122 | +echo "--- All staged PHP file checks completed. ---" |
111 | 123 | exit 0 |
0 commit comments