вторник, 6 апреля 2010 г.

Использование bzr-externals или компонентный подход

При работе над крупными проектами часто возникает потребность выделить часть проекта в отдельный подпроект, как самостоятельную сущность. Такой подпроект может представлять собой некоторую библиотеку, которая используется в разных проектах. Для работы с составными проектами, которые включают в себя дополнительные библиотеки, в bzr задумана функция под названием nested trees (в git для этого есть submodules, а в hg — subrepos). К сожалению разработка функции nested trees пока не завершена, поэтому вместо нее можно использовать плагины bzr-externals или bzr-scmproj. Я попросил автора плагина bzr-externals Евгения Тарасенко рассказать про работу с плагином. В данной статье описывается работа с плагином версии 1.3.
Автор: Евгений Тарасенко

Если ваш проект использует общие библиотеки или компоненты, то самым правильным решением будет подключить их как вложенные подпроекты (или компоненты), а не тупо копировать внутрь проекта.

В Bazaar работа с общими компонентами пока еще не доведена до ума, поэтому пришлось написать небольшой плагин bzr-externals. Надо отметить, что существует еще один похожий плагин bzr-scmproj, но в отличие от первого, в нем для работы с компонентами используются отдельные команды, а это означает, что работа возможна только из консоли и такие инструменты как Bazaar Explorer, QBzr и TortoizeBzr остаются не у дел.

Основная же идея bzr-externals — использование только стандартных команд, чтобы пользователю не нужно было делать лишних телодвижений для работы с компонентами.

Итак, нам понадобится плагин bzr-externals, который можно скачать с http://launchpad.net/bzr-externals или взять прямо из репозитория lp:bzr-externals, о том как это сделать можно узнать из этой статьи.

Проектом может быть любая ветка. Для добавления нового компонента в проект как внешней ссылки нам все же понадобится консоль, но так как это делается только один раз, то я думаю ничего страшного. Формат команды добавления компонента следующий:
bzr externals-add URL  DIRECTORY [--revision REVISIONSPEC]
Здесь URL может быть относительным, так же как и в svn:externals. Например, следующие команды делают почти одно и тоже, но разными способами, не считая использования конкретной ревизии в первом варианте (eadd — встроенный псевдоним команды):
bzr eadd bzr://example.com/repos/common/foo  common/foo -r revno:100
Если доступ к хранилищу возможен по разным протоколам (например, http или bzr+http), то для компонента имя протокола можно опустить, будет использоваться тот же протокол, по которому вы получите главный проект
bzr eadd //example.com/repos/common/foo  common/foo
Если ваш проект хостится на разных серверах, но с одинаковой структурой каталогов, то имя сервера также можно опустить, будет использовать сервер главного проекта
bzr eadd /repos/common/foo  common/foo
И наконец возможен доступ относительно каталога главного проекта в репозитории
bzr eadd ../../common/foo  common/foo
Каталог, в котором должен размещаться компонент, DIRECTORY указывается относительно корня проекта. Если такого компонента еще нет в рабочей папке проекта, то будет выполнен branch/checkout, в зависимости от типа главного проекта, иначе pull/update.
REVISIONSPEC — необязательный параметр, и должен использоваться, только если вам нужна конкретная версия компонента.

В результате выполнения команды externals-add будет добавлен компонент в рабочую директорию, а также в корне проекта появятся конфигурационные файлы:
.bzrmeta/externals
.bzrmeta/externals-snapshot
Первый файл используется для хранения параметров всех компонентов и может быть отредактирован пользователем; например, чтобы привязать компонент к конкретной версии или просто удалить компонент из проекта. Второй файл создается автоматически при каждом commit в проекте и предназначен для создания "снимка" используемых ревизий компонентов, чтобы впоследствии, при откате на какую-либо ревизию, можно было точно восстановить все дерево проекта (чего, кстати, не умеет делать subversion).

Формат обоих конфигурационных файлов одинаков и незатейлив:
URL DIRECTORY REVISIONSPEC
Итак, компонент добавлен в ваш проект, и теперь, казалось бы, надо описать, как нам работать с ним, но тут вступает в силу главный принцип плагина – никаких дополнительных команд. Поэтому всё, что вы делаете с основным проектом, будет повторяться и для всех компонентов. Вот список поддерживаемых команд для версии 1.3:
  • branch [--revision]
  • checkout [--revision]
  • commit
  • pull
  • push
  • update.
Однако, если вам все же не хватает этих команд, то есть два пути: первый — просто зайти в директорию с компонентом и делать с ним что угодно, так как по сути это обыкновенная ветка Bazaar. И второй путь — использовать вторую дополнительную команду externals-cmd или кратко ecmd, чтобы выполнить любую команду Bazaar для всех компонентов проекта и для самого проекта тоже. Например, посмотреть последнюю ревизию для всех:
bzr ecmd -- log -r -1
Работа с Bazaar может быть организована различными способами, в том числе с использованием feature branch, когда сначала делается локальная копия удаленного репозитория, а уже от нее делается ветка для конкретной фичи, плагин поддерживает и такой режим работы.

Рассмотрение плагина подошло к концу, дополнительную информацию можно получить с помощью:
bzr help externals