git - Perl -- commit-msg 钩子在退出时不会停止提交 1
问题描述
语境 :
我正在使用一些 git-hooks 在 Perl 脚本上自动应用一些格式化选项。在预提交挂钩上,我使用 perltidy 清理并重新格式化我的脚本。我想检查用户在提交消息上放了什么,如果它是空的或者它相当于“中止”,我们想要阻止提交并撤消格式修改。
问题 :
我删除了 git 钩子的 .sample 扩展名并使用它使其可执行,chmod u+x .git/hooks/commit-msg
但是当我的脚本exit 1
没有像应有的那样停止时。
提交消息
这个钩子由 git-commit[1] 和 git-merge[1] 调用,并且可以用 --no-verify 选项绕过。它采用单个参数,即保存建议的提交日志消息的文件的名称。以非零状态退出会导致命令中止。
来源:https ://git-scm.com/docs/githooks#_commit_msg
#!/usr/bin/perl -w
use strict;
use warnings;
# Get the path to the files in which we have the commit message
my $commit_file = $ARGV[0];
# Read the file and extract the commit message (lines which don't start with #)
my @commit_msg;
open(my $fh, "<", "$commit_file");
while (my $line = <$fh>) {
if (substr($line, 0, 1) ne "#") {
push(@commit_msg, $line);
}
}
# Check the message isn't empty or we don't have a "abort" line
my $boolean = 0;
foreach my $line (@commit_msg) {
if ($line ne "abort" && $line ne "") {
$boolean = 1;
}
}
if ($boolean == 0) {
print "We should commit the modifications\n";
exit 0; # Don't prevent commit
}
else {
print "We shouldn't commit the modifications\n";
exit 1; # Prevent commit
}
该脚本是可执行的并且有效!如果我在提交某些内容时输入“中止”,它会打印“我们不应该提交修改”,但提交它们会丢弃退出 1...
我希望有人能提供帮助!我是 git-hook 的新手,找不到解决方案。也许我错过了 Stackoverflow 上的一些东西,但我没有找到回答这个问题的帖子。
最好的,
安托万
编辑:
我不承诺使用:--no-verify
解决方案
当我第一次安装你的钩子时,我无法让它提交任何东西,但那是因为钩子有太多的负面影响。您的语言老师避免双重否定的警告也会在您编写软件时帮助您。如果一行看起来不错,则挂钩尝试通过在否定意义上测试来寻找有效条件,如果是,则设置$boolean
为 1,但exit 0
仅当$boolean
为 0 时(表示成功)。
非描述性名称$boolean
可能部分负责。在设置它和想要产生的退出状态之间,您可能已经忘记了您的预期含义。此外,只要提交消息的最后一行有效,您在逻辑背后的意图就会失败。
下面的代码以您希望 git 2.17.1 的方式运行。
#! /usr/bin/perl -w
use strict;
use warnings;
die "Usage: $0 commit-log-message\n" unless @ARGV == 1; # (1)
# Get the path to the files in which we have the commit message
my $commit_file = shift; # (2)
# Read the file and extract the commit message (lines which don't start with #)
my $commit_msg = "";
open my $fh, "<", $commit_file or die "$0: open $commit_file: $!"; # (3)
while (<$fh>) { # (4)
next if /^#/; # (5)
$commit_msg .= $_;
}
# Check the message isn't empty or we don't have an "abort" line
my $valid_commit_msg = $commit_msg ne "" && $commit_msg !~ /^abort$/m; # (6)
if ($valid_commit_msg) { # (7)
print "We should commit the modifications\n";
exit 0; # Don't prevent commit
}
else {
print "We shouldn't commit the modifications\n";
exit 1; # Prevent commit
}
(1)是的,git 应该提供带有日志消息的文件名,但是如果代码被复制或以其他方式安装在错误的钩子中,请对其进行完整性检查。
(2)@ARGV
从with中提取论点shift
。
(3)总是,总是,总是检查来自 的返回值open
。请注意,如果确实失败了,则错误消息包含出现错误的程序的名称 ( $0
)、它尝试执行的操作 ( "open $commit_file"
) 和错误 ( $!
)。养成这个习惯。有一天它会为你省去很多挫败感。
(4)与其将行复制到数组中,不如将它们全部连接成一个标量。用于while (<$fh>) { ... }
查看 中的每一行$_
,这更符合 Perl 的习惯并且可以让您的代码更加整洁。
(5)跳过注释行变得很简单next if /^#/;
。
(6)说出你的意思。而不是机制($boolean
)命名你的意图。您想知道提交消息在通过之前是否有效。一个有效的提交信息必须满足两个条件:
- 提交消息是非空的。
- 提交消息没有任何行其唯一内容是
abort
.
在 Perl 中呈现,这是
my $valid_commit_msg = $commit_msg ne "" && $commit_msg !~ /^abort$/m;
几点注意事项:
- 运算符反转正则表达式匹配的含义
!~
,即,$commit_msg
不得包含。abort
/m
模式末尾的开关用于多线模式。它使^
and$
锚点匹配目标中行的开头和结尾,而不是只匹配最左边和最右边的字符。
(7)以自然阅读的方式$valid_commit_msg
用作布尔值。
if ($valid_commit_msg) { ... }
更可取,if ($valid_commit_msg == 0) { ... }
因为 0 值是错误的,重复好的值是多余的,最后挂出的值很容易被忽略。
推荐阅读
- php - 未存储在杂货店杂货中的 HTML 标签
- android - 有没有人对如何在反应原生的 Android 上调试应用程序购买有任何建议?
- bash - 排序或唯一命令 bash
- php - 从 PHP 中的字符串中提取数字时丢失小数
- unity3d - 将顶点数据相乘会导致轮廓不均匀(shaderlab unity3d)
- scala - 修改 via 以接受返回 Future 的方法
- python-3.x - 如何使用扩展用户模型类实现 django admin 查询集过滤器
- node.js - 更新 npm install npm@latest -g 时出现错误?
- javascript - Vue组件传递多个对象作为道具不起作用
- jhipster - 如何在不同的服务器中连接 Jhipster 前端和后端