1

I want to use a pre-commit hook to check my codefiles before commit them to git. For checking I will use Phing (a PHP build tool).

Here is my pre_commit_hook (MacOS):

#!/bin/sh
echo "Checking files before commit!"
phing -f pre_commit_build.xml || exit 1

And here is the build file:

<?xml version="1.0" encoding="UTF-8"?>
<project name="MyApplication" default="main" basedir=".">

    <fileset id="php_project_files" dir="app">
        <include name="*.php" />
        <include name="**/*.php" />
    </fileset>

    <target name="main">

        <echo message="+------------------------------------------+"/>
        <echo message="|                                          |"/>
        <echo message="| Pre_Commit_Build                         |"/>
        <echo message="|                                          |"/>
        <echo message="+------------------------------------------+"/>

        <phingcall target="check_file_names" />
        <phingcall target="check_syntax" />
        <phingcall target="check_coding_guideline" />
        <phingcall target="unit_test" />

    </target>

    ...

    <target name="check_file_names">

        <property name="failure" value="0" />

        <adhoc-task name="check_filename"><![CDATA[
            class CheckFileName extends Task {

            /** Any filesets of files that should be appended. */
            private $filesets = array();

            /**
             * Nested creator, adds a set of files (nested <fileset> attribute).
             * This is for when you don't care what order files get appended.
             * @return FileSet
             */
             function createFileSet() {
                 $num = array_push($this->filesets, new FileSet());
                 return $this->filesets[$num-1];
             }

             function main() {

                 // append any files in filesets
                 foreach($this->filesets as $fs) {
                     try {
                         $files = $fs->getDirectoryScanner($this->project)->getIncludedFiles();
                         foreach ($files as $file) {

                             if (preg_match('/^[a-z0-9-._]+$/', $file)) {
                                 $this->log("Checked: " . $file);
                             } else {
                                 $this->log("Error: " . $file . " : Allowed are only a-z 0-9 . - _", Project::MSG_ERR);
                                 $this->project->setProperty('failure', '1');
                             }
                          }
                      } catch (BuildException $be) {
                          $this->log($be->getMessage(), Project::MSG_WARN);
                      }
                  }    
              }
          }

      ]]></adhoc-task>

      <echo message="+------------------------------------------+"/>
      <echo message="|                                          |"/>
      <echo message="| Check PHP Filenames                      |"/>
      <echo message="|                                          |"/>
      <echo message="+------------------------------------------+"/>

          <check_filename>
              <fileset refid="php_project_files" />
          </check_filename>

          <echo message="Failure ${failure}" />

    ...

    <target name="check_syntax">

        <phplint level="verbose" haltonfailure="false">
            <fileset refid="php_project_files" />
        </phplint>

    </target>

    ...

</project>

Currently git starts the build process and ALL files of the folder 'app' will be checked (not only those I want to commit). After the process although there will found some fails (i.e. violation of coding guideline) the build process finished and the files will be committed (but they haven't to in this case).

Here are my questions:

  1. How can I tell Phing to use only those files which I want to commit. Or: How can I transfer the information about the files to commit from git to Phing?

  2. How can I "collect" the fails in the targets of the build process (i.e. wrong filenames or violation of a coding guideline) and control, if the build process has to fail.

  3. If one or more target fails, how can I send a return value (1) to git, so that git stops the commit?

  4. How can I define in an adhoc-task that it fails (I have tried it with the property ${failure}?

Thanks a lot for your support!

Stefan

4

2 回答 2

0

返回值:

如果我的任务失败,我会将其存储在属性 ${task_failed} (failed=1) 中。

比我让构建失败

<if>
    <equals arg1="${task_failed}" arg2="1" />
    <then> 
        <fail message="Task failed" />
    </then>
</if>

收集未提交的文件:

感谢@cweiske,我创建了一个任务来收集我未提交的文件:

<target name="collect_uncommited_files">
    <exec command="git diff-index --name-only --cached --diff-filter=ACMR HEAD" output="uncommitted_files.txt" />
    <fileset id="uncommitted_files" dir="./" includesfiles="uncommited_files.txt">
    </fileset>
</target>

我使用 git diff-index 过滤未收集的文件并将结果存储到外部文件 uncommited_files.txt 中。然后我将加载这个文件来创建一个包含我未提交文件的文件集。(当我将结果存储到属性中并使用包含构建我的文件集时,这也可以。)

在我的情况下,这似乎是一种更好的方法,而不是将所有未提交的文件复制到一个单独的目录中,就像在@cweiske:checkout the files中所做的那样,因为我不想移动一些 MB(我必须提交一些非常大的文件)。

于 2013-09-05T08:51:04.797 回答
0

关于“仅我想提交的内容”:

我们的提交钩子中,我们将文件签出到临时暂存区并检查它们。这是仅验证分阶段更改的唯一方法。(也想想git add -p)。

返回值:让你的构建失败。phing 以非 0 状态码存在。

于 2013-09-02T11:19:08.527 回答