Mercurial钩子禁止提交大型二进制文件 [英] Mercurial hook to disallow committing large binary files

查看:82
本文介绍了Mercurial钩子禁止提交大型二进制文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在提交事务之前运行一个Mercurial挂钩,如果提交的二进制文件大于1 MB,它将中止该事务.我发现以下代码可以正常工作,除了一个问题.如果我的变更集涉及删除文件,则此挂钩将引发异常.

I want to have a Mercurial hook that will run before committing a transaction that will abort the transaction if a binary file being committed is greater than 1 megabyte. I found the following code which works fine except for one problem. If my changeset involves removing a file, this hook will throw an exception.

挂钩(我正在使用pretxncommit = python:checksize.newbinsize):

The hook (I'm using pretxncommit = python:checksize.newbinsize):

from mercurial import context, util
from mercurial.i18n import _
import mercurial.node as dpynode

'''hooks to forbid adding binary file over a given size

Ensure the PYTHONPATH is pointing where hg_checksize.py is and setup your
repo .hg/hgrc like this:

[hooks]
pretxncommit = python:checksize.newbinsize
pretxnchangegroup = python:checksize.newbinsize
preoutgoing = python:checksize.nopull

[limits]
maxnewbinsize = 10240
'''

def newbinsize(ui, repo, node=None, **kwargs):
    '''forbid to add binary files over a given size'''
    forbid = False
    # default limit is 10 MB
    limit = int(ui.config('limits', 'maxnewbinsize', 10000000))
    tip = context.changectx(repo, 'tip').rev()
    ctx = context.changectx(repo, node)
    for rev in range(ctx.rev(), tip+1):
        ctx = context.changectx(repo, rev)
        print ctx.files()
        for f in ctx.files():
            fctx = ctx.filectx(f)
            filecontent = fctx.data()
            # check only for new files
            if not fctx.parents():
                if len(filecontent) > limit and util.binary(filecontent):
                    msg = 'new binary file %s of %s is too large: %ld > %ld\n'
                    hname = dpynode.short(ctx.node())
                    ui.write(_(msg) % (f, hname, len(filecontent), limit))
                    forbid = True
    return forbid

例外:

$  hg commit -m 'commit message'
error: pretxncommit hook raised an exception: apps/helpers/templatetags/include_extends.py@bced6272d8f4: not found in manifest
transaction abort!
rollback completed
abort: apps/helpers/templatetags/include_extends.py@bced6272d8f4: not found in manifest!

我对编写Mercurial钩子不熟悉,因此我对所发生的事情感到非常困惑.如果hg已经知道,钩子为什么会关心删除文件?有没有办法修复此挂钩,使其始终有效?

I'm not familiar with writing Mercurial hooks, so I'm pretty confused about what's going on. Why does the hook care that a file was removed if hg already knows about it? Is there a way to fix this hook so that it works all the time?

更新(已解决): 我修改了挂钩,以过滤掉变更集中已删除的文件.

Update (solved): I modified the hook to filter out files that were removed in the changeset.

def newbinsize(ui, repo, node=None, **kwargs):
    '''forbid to add binary files over a given size'''
    forbid = False
    # default limit is 10 MB
    limit = int(ui.config('limits', 'maxnewbinsize', 10000000))
    ctx = repo[node]
    for rev in xrange(ctx.rev(), len(repo)):
        ctx = context.changectx(repo, rev)

        # do not check the size of files that have been removed
        # files that have been removed do not have filecontexts
        # to test for whether a file was removed, test for the existence of a filecontext
        filecontexts = list(ctx)
        def file_was_removed(f):
            """Returns True if the file was removed"""
            if f not in filecontexts:
                return True
            else:
                return False

        for f in itertools.ifilterfalse(file_was_removed, ctx.files()):
            fctx = ctx.filectx(f)
            filecontent = fctx.data()
            # check only for new files
            if not fctx.parents():
                if len(filecontent) > limit and util.binary(filecontent):
                    msg = 'new binary file %s of %s is too large: %ld > %ld\n'
                    hname = dpynode.short(ctx.node())
                    ui.write(_(msg) % (f, hname, len(filecontent), limit))
                    forbid = True
    return forbid

推荐答案

for f in ctx.files()将包括已删除的文件,您需要将这些文件过滤掉.

for f in ctx.files() will include removed files, you need to filter those out.

(您可以将for rev in range(ctx.rev(), tip+1):替换为for rev in xrange(ctx.rev(), len(repo)):,然后删除tip = ...)

(and you can replace for rev in range(ctx.rev(), tip+1): by for rev in xrange(ctx.rev(), len(repo)):, and remove tip = ...)

如果您使用的是现代汞灯,则不执行ctx = context.changectx(repo, node),而是执行ctx = repo[node].

If you're using a modern hg, you don't do ctx = context.changectx(repo, node) but ctx = repo[node] instead.

这篇关于Mercurial钩子禁止提交大型二进制文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆