2010-03-31 11 views
10

Ich möchte einen Mercurial-Hook haben, der vor dem Commit einer Transaktion ausgeführt wird, die die Transaktion abbricht, wenn eine binäre Datei größer als 1 Megabyte ist. Ich habe den folgenden Code gefunden, der bis auf ein Problem funktioniert. Wenn mein Changeset das Entfernen einer Datei beinhaltet, löst dieser Hook eine Ausnahme aus.Mercurial-Hook, um die Übertragung großer Binärdateien zu verbieten

Der Haken (Ich verwende 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 

Die Ausnahme:

$ 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! 

ich mit dem Schreiben Mercurial Haken nicht vertraut bin, so bin ich ziemlich verwirrt über das, was geht weiter. Warum kümmert sich der Haken, dass eine Datei entfernt wurde, wenn hg schon davon weiß? Gibt es eine Möglichkeit, diesen Haken so zu reparieren, dass er immer funktioniert?

Update (gelöst): Ich habe den Hook modifiziert, um Dateien herauszufiltern, die im Änderungsset entfernt wurden.

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 

Antwort

4

for f in ctx.files() gehören entfernt Dateien, müssen Sie jene auszufiltern.

(und Sie können for rev in range(ctx.rev(), tip+1): durch for rev in xrange(ctx.rev(), len(repo)): ersetzen und entfernen tip = ...)

Wenn Sie einen modernen hg verwenden, Sie nicht tun ctx = context.changectx(repo, node) aber ctx = repo[node] statt.

+0

Wie filtere ich die entfernten Dateien aus ctx.files()? – hekevintran

+0

Macht nichts, ich konnte es herausfinden. Vielen Dank. – hekevintran

+0

das Abfangen der Ausnahme ist ausreichend;) – tonfa

5

Das ist einfach in einem Shell-Haken in der letzten Mercurial zu tun:

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

Was hier los ist? Zuerst haben wir eine Dateigruppe, um alle geänderten Dateien zu finden, die problematisch sind (siehe 'hg help filesets' in Hg 1.9). Der 'locate'-Befehl ist wie status, außer dass er nur Dateien auflistet und 0 zurückgibt, wenn er etwas findet. Und wir geben '-r Tipp' an, um die ausstehende Festschreibung zu betrachten.