Question

Je veux avoir un crochet Mercurial qui se déroulera avant d'engager une transaction qui annulerait la transaction si un fichier binaire commis est supérieur à 1 méga-octet. J'ai trouvé le code suivant qui fonctionne très bien sauf un problème. Si mon changeset implique la suppression d'un fichier, ce crochet lancera une exception.

Le crochet (j'utilise 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'exception:

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

Je ne suis pas familier avec l'écriture des crochets Mercurial, donc je suis assez confus au sujet de ce qui se passe. Pourquoi le soin de crochet qui a été supprimé un fichier si hg sait déjà à ce sujet? Est-il possible de fixer ce crochet pour qu'il fonctionne tout le temps?

Mise à jour (résolu): J'ai modifié le crochet pour filtrer les fichiers qui ont été supprimés dans le 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
Était-ce utile?

La solution

for f in ctx.files() comprendra les fichiers supprimés, vous devez filtrer ceux sur.

(et vous pouvez remplacer par for rev in range(ctx.rev(), tip+1): for rev in xrange(ctx.rev(), len(repo)): et supprimer tip = ...)

Si vous utilisez un hg moderne, vous ne faites pas ctx = context.changectx(repo, node) mais ctx = repo[node] à la place.

Autres conseils

Ceci est vraiment facile à faire dans un crochet shell au cours des dernières 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-ce qui se passe ici? Tout d'abord, nous avons un ensemble de fichiers pour trouver tous les fichiers modifiés qui sont problématiques (voir « hg aider filesets » dans hg 1.9). La commande « localiser » est comme l'état, sauf qu'il énumère simplement les fichiers et renvoie 0 si elle trouve quelque chose. Et nous précisons « astuce -r » regarder INCIDENT commettre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top