[英]Perl — commit-msg hook doesn't stop the commit when exiting 1
内容:
我正在使用一些git-hooks自动在Perl脚本上应用某些格式设置选项。 在预提交的钩子上,我使用perltidy清理并重新格式化了脚本。 我想检查用户在提交消息上放置了什么内容,如果它为空或等于“中止”,我们要阻止提交并撤消格式修改。
问题:
我删除了git hook的.sample扩展名,并使用chmod u+x .git/hooks/commit-msg
使它可执行,但是当我的脚本exit 1
,提交并没有像应该的那样停止。
提交-MSG
这个钩子由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
}
该脚本是可执行的并且有效! 如果在提交某些内容时输入“ abort”,它会显示“我们不应该提交所做的修改”,但提交时将放弃出口1 ...
希望有人能够提供帮助! 我是git-hook的新手,找不到解决方案。 也许我在Stackoverflow上错过了一些东西,但是我没有找到回答此问题的帖子。
最好,
安托万
编辑:我不承诺使用:-- --no-verify
当我第一次安装您的钩子时,我无法使其执行任何操作 ,但这是因为该钩子具有太多的底片。 您的语言老师提倡避免双重否定的警告也会在编写软件时帮助您。 钩子尝试通过负向测试来确定行是否良好,以寻找有效条件;如果是,则将$boolean
设置$boolean
1,然后仅在$boolean
为0时exit 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)使用shift
从@ARGV
提取参数。
(3)始终要 始终检查open
的返回值。 请注意,错误消息(如果确实失败)包含具有错误( $0
)的程序的名称,试图执行的操作( "open $commit_file"
)和错误( $!
)。 养成这个习惯。 有一天,它将为您节省很多挫败感。
(4)不是将线复制到数组中,而是将它们全部连接到一个标量中。 使用while (<$fh>) { ... }
查看$_
每一行,这是Perl的惯用语,会使代码混乱。
(5) next if /^#/;
则跳过注释行变得很简单next if /^#/;
。
(6)说出您的意思。 而不是机制( $boolean
)来指定您的意图。 您想知道一个提交消息在通过之前是有效的。 有效的提交消息必须满足两个条件:
abort
。 在Perl中渲染,这是
my $valid_commit_msg = $commit_msg ne "" && $commit_msg !~ /^abort$/m;
一些注意事项:
!~
运算符会反转正则表达式匹配的含义, 即 $commit_msg
不得包含abort
。 /m
开关用于多行模式。 它使^
和$
定位符在目标中的行的开头和结尾匹配,而不仅仅是最左边和最右边的字符。 (7) $valid_commit_msg
自然读取的方式将$valid_commit_msg
用作布尔值。
if ($valid_commit_msg) { ... }
比if ($valid_commit_msg == 0) { ... }
更可取,因为0值是一个错误的值,重复良好的值是多余的,并且结尾处的值很容易被忽略。
我认为您脚本中的逻辑是相反的,即单词abort
不会导致退出代码1。
我认为以下应该起作用:
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
my($commit_msg_file) = @ARGV
or die "usage: $0 <commit message file>\n";
open(my $fh, '<', $commit_msg_file);
my $do_commit;
while (<$fh>) {
# skip comment or empty lines
next if /^#/ || /^\s*$/;
# check for the word "abort" on its own line
last if (/^abort$/);
# at least one non-empty non-comment line detected
$do_commit++;
last;
}
close($fh);
if ($do_commit) {
print "We should commit the modifications\n";
exit 0; # Don't prevent commit
}
print "We shouldn't commit the modifications\n";
exit 1; # Prevent commit
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.