2010-03-31 4 views
10

커밋중인 바이너리 파일이 1 메가 바이트보다 큰 경우 트랜잭션을 커밋하기 전에 실행될 Mercurial 훅을 갖고 싶습니다. 한 문제를 제외하고는 잘 작동하는 다음 코드를 발견했습니다. 내 changeset에 파일을 제거하는 것이 포함 된 경우이 훅은 예외를 throw합니다.큰 이진 파일을 커밋하지 못하도록하는 Mercurial hook

(I는 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/[email protected]: not found in manifest 
transaction abort! 
rollback completed 
abort: apps/helpers/templatetags/[email protected]: not found in manifest! 

나는 의욕 후크를 쓰기에 익숙하지 않은, 그래서 내가 무엇에 대해 꽤 혼란 스러워요 계속. hg가 이미 파일을 알고있는 경우 파일이 제거되었다는 것을 후크가 신경 써야하는 이유는 무엇입니까? 이 훅을 수정하여 항상 작동하도록하는 방법이 있습니까?

변경됨 (해결 된) : 변경 세트에서 제거 된 파일을 걸러 내기 위해 훅을 수정했습니다.

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 

답변

4

for f in ctx.files() 포함 제거 파일, 당신은 사람들을 필터링 할 필요가있다.

(당신이 for rev in xrange(ctx.rev(), len(repo)):에 의해 for rev in range(ctx.rev(), tip+1):을 교체하고 tip = ... 제거 할 수 있습니다) 당신이 현대 HG를 사용하는 경우, 당신은 ctx = context.changectx(repo, node)하지만 ctx = repo[node] 대신하지 않는다

.

+0

ctx.files()에서 제거 된 파일을 어떻게 필터링합니까? – hekevintran

+0

신경 쓰지 마라, 나는 그것을 알아낼 수 있었다. 감사. – hekevintran

+0

예외를 catch하는 것으로 충분합니다.) – tonfa

5

이 최근 의욕에 쉘 후크에서 할 정말 쉽습니다 : 여기 무슨 일이야

if hg locate -r tip "set:(added() or modified()) and binary() and size('>100k')"; then 
    echo "bad files!" 
    exit 1 
else 
    exit 0 
fi 

? 먼저 문제가있는 모든 변경된 파일을 찾을 수있는 파일 세트가 있습니다 (hg 1.9의 'hg help filesets'참조). 'locate'명령은 상태와 비슷하지만 파일을 나열하고 아무것도 찾으면 0을 반환합니다. 그리고 우리는 '-r tip'을 지정하여 보류중인 커밋을 봅니다.

관련 문제