Меркурийные скрипты с питоном
Я пытаюсь получить номер версии /id меркурийной версии (это хэш не число) программно в python.
Причина в том, что я хочу добавить его в файлы css/js на нашем веб-сайте так:
<link rel="stylesheet" href="example.css?{% mercurial_revision "example.css" %}" />
Итак, всякий раз, когда в таблицу стилей делается изменение, он получит новый url и больше не будет использовать старую кешированную версию.
ИЛИ, если вы знаете, где найти хорошую документацию для модуля python , это также было бы полезно. Кажется, я ничего не могу найти.
Мое решение
Я закончил использование подпроцесса, чтобы просто запустить команду, которая получает hg node. Я выбрал это решение, потому что api не гарантирует, что он останется прежним, но интерфейс bash, вероятно, будет:
import subprocess
def get_hg_rev(file_path):
pipe = subprocess.Popen(
["hg", "log", "-l", "1", "--template", "{node}", file_path],
stdout=subprocess.PIPE
)
return pipe.stdout.read()
пример использования:
> path_to_file = "/home/jim/workspace/lgr/pinax/projects/lgr/site_media/base.css"
> get_hg_rev(path_to_file)
'0ed525cf38a7b7f4f1321763d964a39327db97c4'
Ответы
Ответ 1
Правда, нет официального API, но вы можете получить представление о лучших практиках, прочитав другие расширения, особенно те, которые связаны с hg. Для этой конкретной задачи я бы сделал следующее:
from mercurial import ui, hg
from mercurial.node import hex
repo = hg.repository('/path/to/repo/root', ui.ui())
fctx = repo.filectx('/path/to/file', 'tip')
hexnode = hex(fctx.node())
Обновление В какой-то момент порядок параметров изменился, теперь он выглядит так:
repo = hg.repository(ui.ui(), '/path/to/repo/root' )
Ответ 2
Вы имеете в виду эту документацию?
Обратите внимание, что, как указано на этой странице, нет официального API, поскольку они по-прежнему оставляют за собой право изменить его в любое время. Но вы можете увидеть список изменений в последних версиях, он не очень обширен.
Ответ 3
Обновленная, более чистая версия подпроцесса (использует .check_output()
, добавлена в Python 2.7/3.1), которую я использую в своем файле настроек Django для грубой сквозной проверки развертывания (я выкидываю ее в комментарий HTML):
import subprocess
HG_REV = subprocess.check_output(['hg', 'id', '--id']).strip()
Вы можете обернуть его в try
, если не хотите, чтобы какой-то странный сбой предотвращал запуск:
try:
HG_REV = subprocess.check_output(['hg', 'id', '--id']).strip()
except OSError:
HG_REV = "? (Couldn't find hg)"
except subprocess.CalledProcessError as e:
HG_REV = "? (Error {})".format(e.returncode)
except Exception: # don't use bare 'except', mis-catches Ctrl-C and more
# should never have to deal with a hangup
HG_REV = "???"
Ответ 4
попробуйте расширение ключевого слова
Ответ 5
Если вы используете Python 2, вы хотите использовать hglib
.
Я не знаю, что использовать, если вы используете Python 3, извините. Вероятно, hgapi
.
Содержание этого ответа
- Mercurial API
- Как использовать hglib
- Почему hglib - лучший выбор для пользователей Python 2.
- Если вы пишете крючок, этот отвратительный внутренний интерфейс очень удобен.
API-интерфейсы Mercurial
Mercurial имеет два официальных API.
- Сервер команд Mercurial. Вы можете поговорить с ним из Python 2, используя
hglib
(wiki, PyPI), который поддерживается командой Mercurial.
- Интерфейс командной строки Mercurial. Вы можете поговорить с ним через
subprocess
или hgapi
или somesuch.
Как использовать hglib
Установка:
pip install python-hglib
Использование:
import hglib
client = hglib.open("/path/to/repo")
commit = client.log("tip")
print commit.author
Дополнительная информация об использовании на странице hglib wiki.
Почему hglib - лучший выбор для пользователей Python 2
Потому что он поддерживается командой Mercurial, и это то, что команда Mercurial рекомендует для взаимодействия с Mercurial.
Из Mercurial wiki, следующее выражение о взаимодействии с Mercurial:
Для подавляющего большинства стороннего кода наилучшим подходом является использование опубликованного, документированного и стабильного API Mercurial: интерфейса командной строки. В качестве альтернативы используйте CommandServer или библиотеки, основанные на нем, чтобы получить быстрый, стабильный, нечувствительный к языку интерфейс.
На странице сервера команд:
[Командный сервер позволяет] сторонним приложениям и библиотекам связываться с Mercurial по каналу, что устраняет накладные расходы для каждой команды. Библиотеки могут затем инкапсулировать генерацию команд и синтаксический анализ, чтобы представить API, соответствующий языку, этим командам.
Интерфейс Python для командного сервера Mercurial, как сказано, hglib
.
Накладные расходы командной строки интерфейса командной строки, кстати, не шутка. Я когда-то построил очень маленький набор тестов (всего около 5 тестов), который использовал hg
через subprocess
для создания, фиксации посредством фиксации нескольких репозиториев, например. слияния. В течение всего проекта время выполнения пакета оставалось от 5 до 30 секунд, причем почти все время, затрачиваемое на вызовы hg
.
Если вы пишете крючок, этот неудобный внутренний интерфейс очень удобен
Подпись функции крючка Python выглядит так:
# In the hgrc:
# [hooks]
# preupdate.my_hook = python:/path/to/file.py:my_hook
def my_hook(
ui, repo, hooktype,
... hook-specific args, find them in `hg help config` ...,
**kwargs)
ui
и repo
являются частью вышеупомянутого обескураженного неофициального внутреннего API. Тот факт, что они находятся прямо в вашей функции args, делает их чрезвычайно удобными в использовании, например, в этом примере крюка preupdate
, который запрещает слияния между определенными ветвями.
def check_if_merge_is_allowed(ui, repo, hooktype, parent1, parent2, **kwargs):
from_ = repo[parent2].branch()
to_ = repo[parent1].branch()
...
# return True if the hook fails and the merge should not proceed.
Если ваш код перехвата не так важен, и вы его не публикуете, вы можете использовать обескураженный неофициальный внутренний API. Если ваш крючок является частью расширения, которое вы публикуете, лучше используйте hglib
.
Ответ 6
FWIW, чтобы избежать получения этого значения на каждой странице/представлении рендеринга, я просто хочу, чтобы мое развертывание помещало его в файл settings.py
. Тогда я могу ссылаться на settings.REVISION
без всех накладных расходов на доступ к ртутью и/или другому процессу. У вас когда-либо было это изменение стоимости без перезагрузки сервера?
Ответ 7
Я хотел сделать то же самое, что хотел сделать OP, получить hg id -i
из script (получить отзыв о ревизии всего REPOSITORY, а не одного FILE в этом репо), но я не хотел использовать popen, а код из brendan
начал меня, но я этого не хотел.
Итак, я написал это... Комментарии/критика приветствуются. Это получает вершину rev в шестнадцатеричном виде как строку.
from mercurial import ui, hg, revlog
# from mercurial.node import hex # should I have used this?
def getrepohex(reporoot):
repo = hg.repository(ui.ui(), reporoot)
revs = repo.revs('tip')
if len(revs)==1:
return str(repo.changectx(revs[0]))
else:
raise Exception("Internal failure in getrepohex")