Domanda

Voglio avere un gancio Mercurial che verrà eseguito prima di commettere una transazione che interrompere la transazione se un file binario essere impegnati è maggiore di 1 megabyte. Ho trovato il seguente codice che funziona bene, tranne per un problema. Se il mio gruppo di modifiche comporta la rimozione di un file, questo libro sarà un'eccezione.

Il gancio (sto 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

L'eccezione:

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

Non ho dimestichezza con la scrittura ganci Mercurial, quindi sono abbastanza confuso su ciò che sta succedendo. Perché la cura gancio che un file è stato rimosso se hg sa già su di esso? C'è un modo per risolvere questo problema gancio in modo che funziona per tutto il tempo?

Aggiorna (risolto): Ho modificato il gancio per filtrare i file che sono stati rimossi nel 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
È stato utile?

Soluzione

for f in ctx.files() includerà i file rimossi, è necessario filtrare quelli fuori.

(e si può sostituire for rev in range(ctx.rev(), tip+1): da for rev in xrange(ctx.rev(), len(repo)):, e rimuovere tip = ...)

Se stai usando un hg moderno, è non fare ctx = context.changectx(repo, node) ma ctx = repo[node] invece.

Altri suggerimenti

Questa è davvero facile da fare in un gancio guscio di recente 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

Che cosa sta succedendo qui? In primo luogo abbiamo un set di file per trovare tutti i file modificati che sono problematici (vedi 'hg aiutano serie di file' in hg 1.9). Il comando 'individuare' è come lo stato, tranne che semplicemente elenca i file e restituisce 0 se trova qualche cosa. E specifichiamo 'punta -r' a guardare il commit in attesa.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top