Phing PHP构建选择文件的Git预提交挂钩


Git Pre Commit Hook for Phing PHP Build Select Files

在将代码文件提交到git之前,我想使用预提交挂钩来检查代码文件。为了进行检查,我将使用Phing(一种PHP构建工具)。

这是我的pre_commit_hook(MacOS):

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

这是构建文件:

<?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>

目前git启动了构建过程,文件夹"app"的所有文件都将被检查(不仅仅是我想要提交的文件)。在这个过程之后,尽管会发现一些失败(即违反编码准则),但构建过程已经完成,文件将被提交(但在这种情况下,他们没有提交)。

以下是我的问题:

  1. 我如何告诉Phing只使用那些我想提交的文件。或者:如何将要提交的文件的信息从git传输到Phing?

  2. 如果构建过程必须失败,我如何"收集"构建过程目标中的失败(即错误的文件名或违反编码准则)并进行控制。

  3. 如果一个或多个目标失败,我如何向git发送返回值(1),以便git停止提交?

  4. 我如何在临时任务中定义它失败(我已经用${failure}属性尝试过了)?

非常感谢您的支持!

Stefan

关于"我只想提交什么":

在提交挂钩中,我们将文件签出到一个临时暂存区并检查这些文件。这是只验证阶段性更改的唯一方法。(也可以想想git add -p)。

返回值:让您的构建失败。phing以非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>

我用gitdiff索引过滤未收集的文件,并将结果存储到外部文件unmited_files.txt中。然后我将加载此文件,用我未提交的文件创建一个文件集。(当我将结果存储到属性中并使用include构建文件集时,这也会起作用。)

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