Python 如何检查有效的Git分支名称?
我正在开发一个新的。数据在Python 如何检查有效的Git分支名称?,python,regex,git,githooks,Python,Regex,Git,Githooks,我正在开发一个新的。数据在stdin上提供,行与 ef4d4037f8568e386629457d4d960915a85da2ae 61a4033ccf9159ae69f951f709d9c987d3c9f580 refs/heads/master 第一个散列是旧的ref,第二个散列是新的ref,第三列是正在更新的引用 我想把它分成3个变量,同时验证输入如何验证分支名称? 我目前正在使用以下正则表达式 ^([0-9a-f]{40}) ([0-9a-f]{40}) refs/heads/([0-
stdin
上提供,行与
ef4d4037f8568e386629457d4d960915a85da2ae 61a4033ccf9159ae69f951f709d9c987d3c9f580 refs/heads/master
第一个散列是旧的ref,第二个散列是新的ref,第三列是正在更新的引用
我想把它分成3个变量,同时验证输入如何验证分支名称?
我目前正在使用以下正则表达式
^([0-9a-f]{40}) ([0-9a-f]{40}) refs/heads/([0-9a-zA-Z]+)$
这不接受中列出的所有可能的分支名称。例如,它排除了名为buildmaster
的分支,这是有效的
奖金分数
我实际上想排除任何以“build-”开头的分支。这可以在同一个正则表达式中完成吗
测验
根据下面的答案,我写了一些测试,可以在
状态:下面的所有正则表达式都无法编译。这可能表明我的脚本或不兼容的语法有问题。让我们剖析各种规则并从中构建正则表达式部分:
/
,但斜杠分隔的组件不能以点
开头或以序列.lock
结尾
# must not contain /.
(?!.*/\.)
# must not end with .lock
(?<!\.lock)$
(?!.*\.\.)
[^\000-\037\177 ~^:]+ # pattern for allowed characters
\040
或\177 DEL
的字节)、空格、波浪号~
、插入符号^
或冒号:
(?!.*\.\.)
[^\000-\037\177 ~^:]+ # pattern for allowed characters
?
、星号*
或开括号[
。有关此规则的例外情况,请参阅下面的--refspec pattern
选项
[^\000-\037\177 ~^:?*[]+ # new pattern for allowed characters
/
,也不能包含多个连续的斜杠(有关此规则的例外情况,请参阅下面的--normalize
选项)
@{
(?!.*@\{)
\
(?!.*\\)
^(?!.*/\.)(?!.*\.\.)(?!/)(?!.*//)(?!.*@\{)(?!.*\\)[^\000-\037\177 ~^:?*[]+/[^\000-\037\177 ~^:?*[]+(?<!\.lock)(?<!/)(?<!\.)$
这也可以通过合并一些寻找通用模式的东西来进行优化:
^(?!@$|build-|/|.*([/.]\.|//|@\{|\\))[^\000-\037\177 ~^:?*[]+/[^\000-\037\177 ~^:?*[]+(?<!\.lock|[/.])$
^(?!$| build-|/|*([/.]\.[/.]\/.[^\000-\037\177~^:?*[]+/[^\000-\037\177~:?*[]+(?直接从链接页获取规则,以下正则表达式应仅匹配引用/heads
中的有效分支名称,而不是以“build-”开头:
这将对分支名称的每一部分应用基本相同的规则,但只检查最后一个分支名称是否以build-
开头。对于遇到此问题并希望PCRE正则表达式与有效的Git分支名称匹配的人,如下所示:
^(?!/|.*([/.]\.|//|@\{|\\\\))[^\040\177 ~^:?*\[]+(?<!\.lock|[/.])$
^(?!/.*([/.]\.[/.\/.\\\\\)[^\040\177~ ^:?*\[]+(?)?
这是作者编写的正则表达式的修订版本。但是,在此版本中,不需要斜线(用于匹配branchName
,而不是refs/heads/branchName
)
请参考他的正确答案。
他提供了正则表达式每个部分的完整分解,以及它与上指定的每个需求的关系。没有必要用Perl编写monstrosities。只需使用/x:
# RegExp rules based on git-check-ref-format
my $valid_ref_name = qr%
^
(?!
# begins with
/| # (from #6) cannot begin with /
# contains
.*(?:
[/.]\.| # (from #1,3) cannot contain /. or ..
//| # (from #6) cannot contain multiple consecutive slashes
@\{| # (from #8) cannot contain a sequence @{
\\ # (from #9) cannot contain a \
)
)
# (from #2) (waiving this rule; too strict)
[^\040\177 ~^:?*[]+ # (from #4-5) valid character rules
# ends with
(?<!\.lock) # (from #1) cannot end with .lock
(?<![/.]) # (from #6-7) cannot end with / or .
$
%x;
foreach my $branch (qw(
master
.master
build/master
ref/HEAD/blah
/HEAD/blah
HEAD/blah/
master.lock
head/@{block}
master.
build//master
build\master
build\\master
),
'master blaster',
) {
print "$branch --> ".($branch =~ $valid_ref_name)."\n";
}
#基于git check ref格式的RegExp规则
我的$valid\u ref\u name=qr%
^
(?!
#开始于
/|#(from#6)不能以开头/
#包含
.*(?:
[/.]\.|#(from#1,3)不能包含/。或。。
//|#(从#6开始)不能包含多个连续的斜杠
@\{|#(来自#8)不能包含序列@{
\\#(from#9)不能包含\
)
)
#(从#2开始)(放弃此规则;过于严格)
[^\040\177~^:?*[]+#(来自#4-5)有效字符规则
#以
(?
Joey++对一些代码进行了修改。git check ref format
带有子流程。Popen
是一种可能性:
import subprocess
process = subprocess.Popen(["git", "check-ref-format", ref])
exit_status = process.wait()
优点:
- 如果算法发生变化,检查将自动更新
- 你一定会做对的,这对于一个怪物正则表达式来说要困难得多
缺点:
- 因为子流程而变慢。但过早优化是万恶之源
- 需要Git作为二进制依赖项。但在钩子的情况下,它将始终存在
,它使用C绑定到,如果check ref format
在那里公开,则可能性更大,因为它将比Popen
快,但我还没有找到它。如果您想检查引用是否有效,可以像该函数()那样做:
我猜猫比它们看起来更聪明。它们没有愚弄我!我很确定和@{
的负面外观必须与每个字符匹配,因为外观只检查紧接着的下一个字符,而不是字符串的其余部分(根据)。这就是为什么对Hanks@Joey来说,构建的前瞻功能正如您所期望的那样工作。请参见上面的编辑。我正在尝试测试正则表达式,但它们没有编译atm。@dregad:两者都已修复。我只需在Java中实现上面的正则表达式,也许它对其他人也会有用:“^(?。**/\”(?!。\\\\。(?!!/)(?!*/)(?!*/)(?!*/)(?!!*/)(?!!!*/)(?!!*)(?!)(?!!)(?!!)(?)(?!.\\\\)[^\000-\037\177~^:?*\[]+/[^\000-\037\177~^:?*\[]+(?谢谢@murgatroid99。请参见上面的编辑。我正在尝试测试正则表达式,但它们不是在编译atm。是否在包含正则表达式的字符串前面加上r
(如r“regex”
)前缀?对于包含转义序列的正则表达式,您必须这样做(使用“`”)否则它们将不正确。谢谢…略有改进…@Joey的前2个正在编译,但不是你的,也不是他的第3个。你的报告是不平衡的括号。我将开始调查。我很确定我已经修复了
(?!.)((?!\.\.)(?!@{)[^\cA-\cZ ~^:?*[\\])+))(/(?!.)((?!\.\.)(?!@{)[^\cA-\cZ ~^:?*[\\])+)))*?/(?!.)(?!build-)((?!\.\.)(?!@{)[^\cA-\cZ ~^:?*[\\])+))(?<!\.)(?<!\.lock)
^(?!/|.*([/.]\.|//|@\{|\\\\))[^\040\177 ~^:?*\[]+(?<!\.lock|[/.])$
# RegExp rules based on git-check-ref-format
my $valid_ref_name = qr%
^
(?!
# begins with
/| # (from #6) cannot begin with /
# contains
.*(?:
[/.]\.| # (from #1,3) cannot contain /. or ..
//| # (from #6) cannot contain multiple consecutive slashes
@\{| # (from #8) cannot contain a sequence @{
\\ # (from #9) cannot contain a \
)
)
# (from #2) (waiving this rule; too strict)
[^\040\177 ~^:?*[]+ # (from #4-5) valid character rules
# ends with
(?<!\.lock) # (from #1) cannot end with .lock
(?<![/.]) # (from #6-7) cannot end with / or .
$
%x;
foreach my $branch (qw(
master
.master
build/master
ref/HEAD/blah
/HEAD/blah
HEAD/blah/
master.lock
head/@{block}
master.
build//master
build\master
build\\master
),
'master blaster',
) {
print "$branch --> ".($branch =~ $valid_ref_name)."\n";
}
import subprocess
process = subprocess.Popen(["git", "check-ref-format", ref])
exit_status = process.wait()
from pygit2 import reference_is_valid_name
reference_is_valid_name("refs/heads/master")