Perl -- commit-msg 钩子在退出时不停止提交 1
Perl -- commit-msg hook doesn't stop the commit when exiting 1
上下文:
我正在使用一些 git-hooks 在 Perl 脚本上自动应用一些格式化选项。在预提交挂钩上,我使用 perltidy 清理并重新格式化我的脚本。我想检查用户在提交消息上放了什么,如果它是空的或者它等同于 "abort",我们想阻止提交并撤消格式修改。
问题:
我删除了 git 挂钩的 .sample 扩展名并使用 chmod u+x .git/hooks/commit-msg
使其可执行,但是当我的脚本 exit 1
提交没有像它应该的那样停止。
commit-msg
This hook is invoked by git-commit[1] and git-merge[1], and can be bypassed with the --no-verify option. It takes a single parameter, the name of the file that holds the proposed commit log message. Exiting with a non-zero status causes the command to abort.
来源: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" ,它会打印 "We shouldn't commit the modifications" 但提交它们会丢弃出口 1...
希望有人能够提供帮助!我是 git-hook 的新手,找不到解决方案。也许我在 Whosebug 上遗漏了一些东西,但我没有找到 post 回答这个问题。
最佳,
安托万
编辑:
我不承诺使用:--no-verify
当我第一次安装你的钩子时,我无法让它提交任何东西,但那是因为钩子有太多的底片。你的语言老师关于避免双重否定的警告也会帮助你编写软件。如果一行看起来不错,钩子会尝试通过在负面意义上进行测试来寻找有效条件,如果是这样,则将 $boolean
设置为 1,然后仅当 $boolean
时才将 exit 0
(表示成功)是 0.
非描述性名称 $boolean
可能部分负责。您可能已经忘记了设置它和您想要产生的退出状态之间的预期含义。此外,只要提交消息的最后一行有效,您的逻辑背后的意图就会失败。
下面的代码在 git 2.17.1.
中以您想要的方式运行
#! /usr/bin/perl -w
use strict;
use warnings;
die "Usage: [=10=] 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 "[=10=]: 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)总是,总是,总是检查return来自 open
的值。请注意,如果失败,错误消息包含出错程序的名称 ([=20=]
)、它试图执行的操作 ("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
开关用于多行模式。它使 ^
和 $
锚点匹配目标内行的开头和结尾,而不是仅匹配最左边和最右边的字符。
(7) 以自然阅读的方式使用 $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: [=10=] <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
上下文:
我正在使用一些 git-hooks 在 Perl 脚本上自动应用一些格式化选项。在预提交挂钩上,我使用 perltidy 清理并重新格式化我的脚本。我想检查用户在提交消息上放了什么,如果它是空的或者它等同于 "abort",我们想阻止提交并撤消格式修改。
问题:
我删除了 git 挂钩的 .sample 扩展名并使用 chmod u+x .git/hooks/commit-msg
使其可执行,但是当我的脚本 exit 1
提交没有像它应该的那样停止。
commit-msg
This hook is invoked by git-commit[1] and git-merge[1], and can be bypassed with the --no-verify option. It takes a single parameter, the name of the file that holds the proposed commit log message. Exiting with a non-zero status causes the command to abort.
来源: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" ,它会打印 "We shouldn't commit the modifications" 但提交它们会丢弃出口 1...
希望有人能够提供帮助!我是 git-hook 的新手,找不到解决方案。也许我在 Whosebug 上遗漏了一些东西,但我没有找到 post 回答这个问题。
最佳,
安托万
编辑:
我不承诺使用:--no-verify
当我第一次安装你的钩子时,我无法让它提交任何东西,但那是因为钩子有太多的底片。你的语言老师关于避免双重否定的警告也会帮助你编写软件。如果一行看起来不错,钩子会尝试通过在负面意义上进行测试来寻找有效条件,如果是这样,则将 $boolean
设置为 1,然后仅当 $boolean
时才将 exit 0
(表示成功)是 0.
非描述性名称 $boolean
可能部分负责。您可能已经忘记了设置它和您想要产生的退出状态之间的预期含义。此外,只要提交消息的最后一行有效,您的逻辑背后的意图就会失败。
下面的代码在 git 2.17.1.
中以您想要的方式运行#! /usr/bin/perl -w
use strict;
use warnings;
die "Usage: [=10=] 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 "[=10=]: 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)总是,总是,总是检查return来自 open
的值。请注意,如果失败,错误消息包含出错程序的名称 ([=20=]
)、它试图执行的操作 ("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
开关用于多行模式。它使^
和$
锚点匹配目标内行的开头和结尾,而不是仅匹配最左边和最右边的字符。
(7) 以自然阅读的方式使用 $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: [=10=] <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