Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

git hook syntax check

Tags:

git

Trying to make a php syntax check hook for a git repository. I was happy when I found a code snippet that does exactly this.

But it seems that the snippet script has a flaw. It executes

git diff-index --cached --name-only HEAD

to get a list of files in the index. Now it runs php -l for each file on that list. The flaw is that a file might differ between the working copy and the staging area. If the staging area php has a syntax error, but the working copy version doesnt, no syntax error is found and the committ succeeds which was the thing to prevent.

Is this a nontrivial problem to solve, or is there some way to run php -l on the staging-version of each file?

like image 738
zedoo Avatar asked Sep 15 '10 16:09

zedoo


People also ask

How do I see my git hooks?

The hooks are all stored in the hooks subdirectory of the Git directory. In most projects, that's . git/hooks .

How do I manually run a git hook?

If you want to manually run all pre-commit hooks on a repository, run pre-commit run --all-files . To run individual hooks use pre-commit run <hook_id> . The first time pre-commit runs on a file it will automatically download, install, and run the hook.

Where are git hooks configured?

Conceptual Overview. All Git hooks are ordinary scripts that Git executes when certain events occur in the repository. This makes them very easy to install and configure. Hooks can reside in either local or server-side repositories, and they are only executed in response to actions in that repository.


2 Answers

I'm very happy using this php syntax validation hook. Hope it will fit your needs too.

It uses git diff-index --cached --full-index.

like image 160
takeshin Avatar answered Sep 24 '22 14:09

takeshin


I am not sure if there is a problem here.

The snippet you mention probably comes from the blog post Don’t Commit That Error.
And it includes:

Next, we call git diff-index with a few parameters.
First, we add --cached to tell Git we only want files that are going to be committed.
Then, we add --name-only to tell Git to only output the name of the files that are being committed.

It seems the files which are about to be committed are precisely the ones a pre-commit hook would want to inspect.
Even if they differ from the files in the working directory, it is their version (in the index) which is to be committed. And it is that same version which will be send to the php -l process.


Actually, the problem is not in the git diff-index itself (with or without --full-index) is in the way you will read the file content in the index

  • The "PHP Advent 2008" hook will simply try to access the file from its name (with the risk of accessing the working copy)
exec("php -l " . escapeshellarg($file), $lint_output, $return);
  • The "phpbb3" hook (mentioned by takeshkin in his answer) will ask Git for the actual content:
result=$(git cat-file -p $sha | /usr/bin/env $PHP_BIN -l 2>/dev/null)

Using git cat-file is the key here, to access an object in the Git repo (i.e. not in the "working directory")

like image 37
VonC Avatar answered Sep 26 '22 14:09

VonC