2010-03-31 17 views
10

Quiero tener un gancho Mercurial que se ejecutará antes de realizar una transacción que abortará la transacción si un archivo binario que se está confirmando es mayor que 1 megabyte. Encontré el siguiente código que funciona bien excepto por un problema. Si mi conjunto de cambios implica eliminar un archivo, este enlace generará una excepción.Gancho mercurial para no permitir archivos binarios grandes

El gancho (estoy usando 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 

La excepción:

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

No estoy familiarizado con la escritura de ganchos Mercurial, así que estoy bastante confundido acerca de lo que es pasando. ¿Por qué le importa al gancho que se elimine un archivo si hg ya lo conoce? ¿Hay alguna manera de arreglar este gancho para que funcione todo el tiempo?

Actualización (resuelta): Modifiqué el gancho para filtrar los archivos que se eliminaron en el conjunto de cambios.

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 

Respuesta

4

for f in ctx.files() archivos incluirá retirados, lo que necesita para filtrar aquellos cabo.

(y se puede sustituir por for rev in xrange(ctx.rev(), len(repo)):for rev in range(ctx.rev(), tip+1):, y quitar tip = ...)

Si estás utilizando un hg moderna, no se hace ctx = context.changectx(repo, node)ctx = repo[node] pero en su lugar.

+0

¿Cómo puedo filtrar los archivos eliminados de ctx.files()? – hekevintran

+0

No importa, pude descifrarlo. Gracias. – hekevintran

+0

capturar la excepción es suficiente;) – tonfa

5

Esto es realmente fácil de hacer en un gancho en la cáscara reciente Mercurial:

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

¿Qué está pasando aquí? Primero tenemos un conjunto de archivos para encontrar todos los archivos modificados que son problemáticos (consulte 'hg filesets de ayuda' en hg 1.9). El comando 'localizar' es como el estado, excepto que solo enumera los archivos y devuelve 0 si encuentra algo. Y especificamos '-r tip' para ver la confirmación pendiente.

Cuestiones relacionadas