mercurial server hooks


Понадобилось сделать mercurial hook для проверки json файлов на валидность. К сожалению, документация mercurial оставляет желать лучшего, поэтому напишу, как я реализовал эту задачу.

Так, у нас есть сервер с репозиторием, мы хотим сделать так, чтобы при изменении, добавлении невалидного json в репозиторий, push отваливался с ошибкой.

Для начала, напишем сам hook. Было решено написать его на python.

# -*- coding: utf-8 -*-
import os

try:
    import simplejson as json
except ImportError:
    import json

check_extension = 'json'

# colors
BLUE = '\033[94m'
GREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'

# mercurial passes ui, repo, hooktype and node as parameters
# node is a revision
def run(ui, repo, hooktype, node, **kwargs):
    fileSet = set()
# we analyze each change
    for change_id in xrange(repo[node].rev(), len(repo)):
        for currentFile in repo[change_id].files():
# check each changed file, if it is json then validate it
            if currentFile.endswith('.%s' % check_extension):
                fileSet.add(currentFile)
    for currentFile in fileSet:
        ctx = repo['tip']
# do not check removed files
        if currentFile not in ctx:
            continue
        fctx = ctx[currentFile]
        try:
            json_object = json.loads(fctx.data())
        except Exception, e:
            ui.write('JSON parsing of {0} {1} {2} FAILED: {3}\n'.format(
                GREEN, currentFile, FAIL, ENDC))
            ui.write(e.message + '\n')
            return True
    return False

Думаю, что код с комментариями достаточно понятный. Еще раз замечу, что внутренности mercurial очень плохо документированы, зачастую приходится смотреть в код mercurial, чтоб понять с какими параметрами вызывать объекты.

Вот статья про хуки из документации: https://www.mercurial-scm.org/wiki/Hook Как видите, информации совсем мало, правда внизу страницы есть ссылка на более подробное описание.

Теперь, когда хук готов, нужно добавить его в секцию [hooks] в hgrc репозитория. На сервере репы лежат в /var/hg/repos, репозиторий называется projects. Меняем файл /var/hg/repos/projects/.hg/hgrc

[hooks]
pretxnchangegroup.syntax_check = python:/usr/local/share/hg-hooks/validate_json.py:run

/usr/local/share/hg-hooks/validate_json.py — это наш хук, run — это имя функции. которую мы вызвали.

Если функция возвращает True, это как бы exit code 1, значит валидация не прошла и push откатит изменения, выдав предупреждение.

Cтатья, которую я взял за основу.