tags:

views:

60

answers:

2

Trying to make a php syntax check hook for a git repository. I was happy when I found a snipped 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?

+1  A: 

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);
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")

VonC
Yes, that's the code I'm talking about. In $output you get the list of files that are to be committed, correct. But I think you are wrong with your last sentence. It is the working copy version that is sent to php -l, not the staging area version. And that's an error. The hook linked by takeshin seems to do better.
zedoo
@zedoo: I have update my answer to reflect on the actual issue here (which is not `git diff-index`)
VonC
Yes, exactly. +1 ;)
zedoo
+2  A: 

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.

takeshin
+1 for a working hook.
VonC
Yes, this does it much better than the hook from the article.
zedoo