Библиотека сайта rus-linux.net
Архитектура Mercurial
Глава 12 из книги "Архитектура приложений с открытым исходным кодом", том 1.
Оригинал: "Mercurial".
Автор: Dirkjan Ochtman
Перевод: Vlad http://vlad8.com/
12.4. Общая структура
Mercurial почти полностью написан на Python, только некоторые части написаны на C (там, где критична производительность всего приложения). Python оказался наиболее подходящим для большей части кода, потому что гораздо легче выражать высокоуровневые концепции на динамическом языке, вроде Python. Так как для большей части кода быстродействие не слишком критично, мы не против того, что нас будут критиковать за то, что мы кое-где упростили себя процесс разрабоки в ущерб производительности.
Модуль в Python находится в одном файле кода. Модули могут содержать столько кода, сколько необходимо, и поэтому являются важным способ организации программы. Модули могут использовать типы или вызывать функции из других модулей путем явного импорта других модулей. Директория, содержая файл __init__.py, является пакетом, и все модули пакета будут доступны интерпретатору Python.
По умолчанию Mercurial устанавливает два пакета в окружение Python: mercurial и hgext. Пакет mercurial содержит ядро, необходимое для запуска Mercurial, в то время как hgext содержит некоторые расширения, которые считаются достаточно полезными и поэтому распространяются вместе с ядром. Однако, если они нужны, их все же нужно вручную включить в конфигурационном файле (это будет описано позже).
Для простоты Mercurial является консольным приложением. Это означает, что у него простой интерфейс: пользователь вызывает скрипт hg и команду. Эта команда (например, log, diff или commit) может принимать несколько опций или аргументов; некоторые опции подходят для всех команд. В том, что касается интерфейса, есть три нюанса:
- hg часто выводит информацию, которую запросил пользователь, или показывет сообщения о статусе
- hg может запросить дальнейшую информацию через консоль
- hg может запускать внешнюю программу (редактор для создания сообщения о коммите изменения или программу, для улаживания конфликтов в коде при слиянии)
Рис.12.3: Граф импорта
Начало этого процесса можно удобно наблюдать с помощью графа импорта на рисунке 3. Все аргументы командной строки передаются в функцию в модуль-диспетчер (dispatch). Первое что происходит: создается экземпляр объекта ui. Класс ui попытается найти конфигурационные файлы в нескольких хорошо известных местах (таких, как ваша домашняя папка) и сохранить параметры конфигурации в объекте ui. Конфигурационные файлы могут содержать пути к расширениям, которые также должны быть загружены в этот момент. Любой глобальный параметр, переданный через командую строку, также сохраняется в объекте ui на этом этапе.
После того, как все это будет выполнено, нам нужно решить, нужно ли создавать объект репозитория. В то время, как большинство команд требуют наличия локального репозитория (представлен классом localrepo из модуля localrepo), некоторые команды могут работать с удаленными репозиториями (через HTTP, SSH или каким-либо другим зарегистрированным образом), а некоторые команды могут выполнять свою работу вообще без обращения к репозиторию. Последняя категория включает команду init, которая используется для инициализации нового репозитория.
Все ключевые команды ядра представлены одной функцией в модуле commands; это дает возможность очень легко находить код каждой функции. Модуль команд также содержит хэшированную таблицу, которая хранит соответствие между именем команды, функцией и принимаемыми ей параметрами. То, как это выполнено, дает возможность наличия общего набора параметров у разных опций (например, у многих команд параметры аналогичны команде log). Описания параметров позволяют модулю-диспетчеру проверять конкретную опцию для любой из команд и конвертировать любые значения в тип, ожидаемый функцией команды. Практически каждая функция также получает доступ к объекту ui и объекту repository.
Продолжение статьи: Расширяемость.