如何在.hgignore中模拟语言补充运算符?

时间:2009-07-03 13:22:56

标签: python regex mercurial

我有一个与一组文件名匹配的Python正则表达式。如何更改它以便我可以在Mercurial的.hgignore文件中使用它来忽略匹配表达式的文件?

全文: 我有一个很大的源代码树,其中*.ml个文件散布在各处。我想把它们放到一个新的存储库中。还有其他不太重要的文件太重,无法包含在存储库中。我正在尝试找到.hgignore文件的相应表达式。

第一次观察:Python没有常规语言补语操作符(AFAIK它只能补充一组字符)。 (顺便说一句,为什么?)

第二次观察: Python中的以下正则表达式:

re.compile("^.*(?<!\.ml)$")

按预期工作:

abcabc - match  
abc.ml - no match  
x/abcabc - match  
x/abc.ml - no match

但是,当我在.hgignore文件中放置完全相同的表达式时,我得到了这个:

$ hg st --all  
?  abc.ml  
I .hgignore  
I abcabc  
I x/xabc  
I x/xabc.ml  

根据.hgignore联机帮助页,Mercurial只使用普通的Python正则表达式。那我怎么得到不同的结果呢? Mercurial如何找到匹配x/xabc.ml

是否有人知道缺乏常规语言补语操作员的方式不那么丑陋?

3 个答案:

答案 0 :(得分:1)

正则表达式依次应用于每个子目录组件以及文件名,而不是一次性应用于整个相对路径。因此,如果我的仓库中有/ b / c / d,则每个正则表达式将应用于a,a / b,a / b / c以及a / b / c / d。如果任何组件匹配,则将忽略该文件。 (您可以通过使用bar / foo尝试^bar$来判断这是行为 - 您会看到bar / foo被忽略。)

^.*(?<!\.ml)$忽略x / xabc.ml,因为模式匹配x(即子目录。)

这意味着没有可以帮助您的正则表达式,因为您的模式必须与第一个子目录组件匹配。

答案 1 :(得分:0)

通过一些测试,找到了两种似乎有效的解决方案。第一个根到一个子目录,显然这很重要。第二个是脆的,因为它只允许使用一个后缀。我正在使用Mercurial 1.2.1在Windows XP上运行这些测试(自定义工作更加单一)。

(我在# message添加了评论。)

$ hg --version
Mercurial Distributed SCM (version 1.2.1)

$ cat .hgignore
syntax: regexp
^x/.+(?<!\.ml)$       # rooted to x/ subdir
#^.+[^.][^m][^l]$

$ hg status --all
? .hgignore           # not affected by x/ regex
? abc.ml              # not affected by x/ regex
? abcabc              # not affected by x/ regex
? x\saveme.ml         # versioned, is *.ml
I x\abcabc            # ignored, is not *.ml
I x\ignoreme.txt      # ignored, is not *.ml

第二个:

$ cat .hgignore
syntax: regexp
#^x/.+(?<!\.ml)$
^.+[^.][^m][^l]$      # brittle, can only use one suffix

$ hg status --all
? abc.ml              # versioned, is *.ml
? x\saveme.ml         # versioned, is *.ml
I .hgignore           # ignored, is not *.ml
I abcabc              # ignored, is not *.ml
I x\abcabc            # ignored, is not *.ml
I x\ignoreme.txt      # ignored, is not *.ml

第二个完全预期的行为,因为我理解OP。第一个只在子目录中有预期的行为,但更灵活。

答案 2 :(得分:0)

问题特别出现在子目录中的匹配与根目录不同。请注意以下事项:

$ hg --version
Mercurial Distributed SCM (version 1.1.2)

这是一个旧版本,但它的行为方式相同。我的项目有以下文件:

$ find . -name 'abc*' -print
./x/abcabc
./x/abc.ml
./abcabc
./abc.ml

这是我的.hgignore:

$ cat .hgignore
^.*(?<!\.ml)$

现在,当我运行stat时:

$ hg stat
? abc.ml

因此,hg无法接听x/abc.ml。但这是正则表达式的问题吗?也许不是:

$ python
Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) 
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import mercurial.ignore
>>> import os
>>> root = os.getcwd()
>>> ignorefunc = mercurial.ignore.ignore(root, ['.hgignore'], lambda msg: None)
>>> 
>>> ignorefunc("abc.ml") # No match - this is correct
>>> ignorefunc("abcabc") # Match - this is correct, we want to ignore this
<_sre.SRE_Match object at 0xb7c765d0>
>>> ignorefunc("abcabc").span() 
(0, 6)
>>> ignorefunc("x/abcabc").span() # Match - this is correct, we want to ignore this
(0, 8)
>>> ignorefunc("x/abc.ml") # No match - this is correct!
>>> 

请注意,ignorefunc处理abcabcx/abcabc相同(匹配 - 即忽略),而abc.mlx/abc.ml也处理相同(不匹配) - 即不要忽视)。

所以,也许逻辑错误在Mercurial的其他地方,或者我正在考虑Mercurial的错误位置(尽管如果是这样的话我会感到惊讶)。除非我错过了什么,否则可能需要向Mercurial提交一个错误(而不是Martin Geisler指出的RFE)。