Git预提交脚本不返回非零

时间:2013-05-30 19:58:44

标签: git hook githooks pre-commit-hook pre-commit

我有一个脚本,我正在尝试运行以检查最新提交中的文件编码。当我手动运行它时,它的行为与预期的一样,但是当我执行提交时,它没有。如果它们不在我的函数之内,我可以打印变量就好了,所以我怀疑它与我检索修改/添加文件的方式有关。有没有办法让Git能够更好地处理?

#!/usr/bin/env python

import chardetect, subprocess, os
from sys import stdin, exit
from chardet.universaldetector import UniversalDetector

confidenceLevel = 0.8
allowedEncoding = ('ascii', 'utf-8')

# Get the current path and modify it to be the path to the repo
filePath = os.path.dirname(os.path.realpath(__file__))
filePath = filePath.replace('.git/hooks', '')

# Get all files that have been added or modified (filter is missing 'D' so that deleted files don't come through)
pr = subprocess.Popen(['/usr/bin/git', 'diff', '--diff-filter=ACMRTUXB', '--cached', '--name-only'],                  
       cwd=os.path.dirname('../../'), 
       stdout=subprocess.PIPE, 
       stderr=subprocess.PIPE, 
       shell=False) # Take note: Using shell=True has significant security implications.
(out, error) = pr.communicate()

# Create a list of files to check
out = out.split('\n')
out = [item for item in out if item != '']
out = [filePath + item for item in out]

messageList = [] # Keep this global

# If no paths are provided, it takes its input from stdin.
def description_of(file, name='stdin'):
    #Return a string describing the probable encoding of a file.
    u = UniversalDetector()
    for line in file:
        u.feed(line)
    u.close()
    result = u.result
    if result['encoding']:
        itPasses = ''
        if result['encoding'] in allowedEncoding and result['confidence'] >= confidenceLevel:
            pass
        else:
            messageList.append('%s: FAILS encode test %s with confidence %s\nYou must convert it before committing.' % (name, result['encoding'], result['confidence']))
    else:
        return '%s: no result' % name


def main():
    if len(out) <= 0:
        exit()
    else:
        for path in out:
            description_of(open(path, 'rb'), path)
        for item in messageList:
            print item
    if len(messageList) == 0:
        exit()
    else:
        exit(1)

if __name__ == '__main__':
    main()

1 个答案:

答案 0 :(得分:1)

脚本中的问题是这一行:

cwd=os.path.dirname('../../'), 

挂钩在.git目录中运行,而不是在hooks目录中。因此,您将使用给定的行离开回购。有关详细信息,请访问in this answer。因此,您无需更改git diff --cached的cwd。

您可能想要更改cwd,以便将您输入UniversalDetector的路径有意义。但无论如何你在做什么都是错的。您不应该检查工作目录文件,而是检查索引中的文件,因为它们实际上是要提交的。

您应该使用git ls-files --stagedgit show来获取索引的内容。简写为git show :filename,但这可能会导致文件名出错。

同时将-z添加到git diff的参数中,以便处理更多文件名。