Pregunta

Quiero tener un gancho Mercurial que se ejecutará antes de cometer una transacción que abortar la transacción si un archivo binario estar comprometida es mayor que 1 megabyte. He encontrado el siguiente código que funciona muy bien excepto por un problema. Si mi conjunto de cambios consiste en extraer un archivo, este gancho lanzará una excepción.

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/include_extends.py@bced6272d8f4: not found in manifest
transaction abort!
rollback completed
abort: apps/helpers/templatetags/include_extends.py@bced6272d8f4: not found in manifest!

No estoy familiarizado con la escritura de ganchos Mercurial, así que estoy bastante confundido acerca de lo que está pasando. ¿Por qué el cuidado de gancho que un archivo se elimina si Hg ya se sabe al respecto? ¿Hay una manera de solucionar este gancho para que funcione todo el tiempo?

Actualizar (resuelto): He modificado el gancho para filtrar los archivos que se han eliminado 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
¿Fue útil?

Solución

for f in ctx.files() incluirá los archivos eliminados, necesita filtrar ésos hacia fuera.

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

Si estás usando un hg moderna, que no hacen sino ctx = context.changectx(repo, node) ctx = repo[node] lugar.

Otros consejos

Esto es muy fácil de hacer en un gancho de cáscara en los últimos 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í? En primer lugar tenemos un conjunto de archivos para encontrar todos los archivos modificados que son problemáticos (véase 'conjuntos de archivos de ayuda hg' de Hg 1.9). El comando 'localizar' es como el estado, excepto que sólo enumera los archivos y devuelve 0 si encuentra cualquier cosa. Y especificamos 'punta -r' para mirar la pendiente de confirmación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top