用Java编写预提交钩子吗?

11
我需要用Java编写一个Git pre commit hook,它可以在实际提交之前检查开发人员提交的代码是否按照特定的eclipse代码格式化程序进行格式化,如果不符合要求,则拒绝提交。是否可以用Java编写pre commit hook?
4个回答

9

这个想法是调用一个脚本,然后再调用你的Java程序(检查格式)。

你可以在这里看到一个用Python编写的示例,该示例调用了Java。

try:
    # call checkstyle and print output
    print call(['java', '-jar', checkstyle, '-c', checkstyle_config, '-r', tempdir])
except subprocess.CalledProcessError, ex:
    print ex.output  # print checkstyle messages
    exit(1)
finally:
    # remove temporary directory
    shutil.rmtree(tempdir)

这个另一个示例直接调用ant,以执行一个ant脚本(该脚本又调用Java JUnit测试套件)。

#!/bin/sh

# Run the test suite.
# It will exit with 0 if it everything compiled and tested fine.
ant test
if [ $? -eq 0 ]; then
  exit 0
else
  echo "Building your project or running the tests failed."
  echo "Aborting the commit. Run with --no-verify to ignore."
  exit 1
fi

5

从Java 11开始,您现在可以使用java命令运行未编译的主类文件。

$ java Hook.java

如果您使用的是基于Unix的操作系统(例如MacOS或Linux),您可以去掉 .java 扩展名并在顶行添加shebang,如下所示:

#!/your/path/to/bin/java --source 11
public class Hook {
    public static void main(String[] args) {
        System.out.println("No committing please.");
        System.exit(1);
    }
} 

那么你可以像处理其他脚本文件一样简单地执行它。

$ ./Hook

如果您将文件 pre-commit 重命名,然后将其移动到您的 .git/hooks 目录中,您现在拥有一个可用的 Java Git Hook。

注意:您可以尝试使用 Cygwin 或 Git Bash 等终端模拟器在 Windows 上运行此操作。但是,shebangs 不会处理空格问题。我通过将 Java 的副本移动到没有空格的目录中进行了测试,测试结果表明可以正常工作。


我已经更新了答案,因为似乎有些混淆。Shebang是Unix的一个特性。 - Rudi Kershaw

1

是的,您可以使用Java编写git钩子。

尝试的解决方案

我尝试了Rudi提供的解决方案来编写我的commit-msg钩子:

commit-msg文件

#!C:/Progra~1/Java/jdk-17.0.1/bin/java.exe --source 17
#Using Progra~1 to represent "Program Files" as escaping the space
#or surrounding the path in double quotes didn't work for me.
public class Hook {
    public static void main(String[] args) {
        System.out.println("No committing please.");
        System.exit(1);
    }
}

但是我收到了这个错误信息,并且在排查问题时遇到了困难。

$ git commit -m "Message"
Error: Could not find or load main class .git.hooks.commit-msg
Caused by: java.lang.ClassNotFoundException: /git/hooks/commit-msg

适合我的解决方案

后来我找到了一份提供另一种方式的资源。

https://dev.to/awwsmm/eliminate-unnecessary-builds-with-git-hooks-in-bash-java-and-scala-517n#writing-a-git-hook-in-java

commit-msg 钩子看起来像这样

#!bin/sh
DIR=$(dirname "$0")
exec java $DIR/commit-msg.java "$@"

这段内容是关于it技术的翻译:

该命令将当前目录(.git/hooks)保存到一个变量中,以帮助构建到java文件的路径。然后shell使用java文件的路径和一个参数(包含COMMIT_EDITMSG文件的路径)执行java命令。

接下来,您可以将上面定义的Hook类移动到自己的java文件中(在本例中为commit-msg.java),并将其放置在.git/hooks目录中。

现在,您可以运行git commit -m "Message",commit-msg钩子将阻止提交。


exec 会阻止后续的命令(例如在提交更改之前需要执行 git add 命令)。 - Ahmed Ashour

1

您可以使用任何能够被shell理解的语言编写钩子,例如已经配置好的解释器(bash、python、perl)等。

但是,为什么不用Java编写您的代码格式化程序,并从预提交钩子中调用它呢?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接