воскресенье, 14 августа 2011 г.

Inside .bzr: что внутри служебного каталога .bzr: Часть 2: shared repository

В первой части мы рассмотрели как внутри выглядит ветка и отметили, что у самостоятельных веток (standalone branch) репозиторий свой. Посмотрим, что изменится при работе с shared repository.
(Далее)

Копия ветки без использования shared repository

Но для начала давайте проанализируем, что происходит при создании копии самостоятельной ветки.

C:\work\bzr-day\Inside>bzr branch  branch copy
Branched 1 revision(s).

Заходим в копию нашей первой ветки и смотрим вывод bzr info -v:

C:\work\bzr-day\Inside\copy>bzr info -v
Standalone tree (format: 2a)
Location:
  branch root: .


Related branches:
  parent branch: C:/work/bzr-day/Inside/branch


Format:
       control: Meta directory format 1
  working tree: Working tree format 6
        branch: Branch format 7
    repository: Repository format 2a - rich roots, group compression and chk inventories
...

Интересными для нас являются следующие секции: Related branches и Format.

Секция Related branches показывает нам путь к родительской ветке (т.е. к нашей первой ветке). Как уже отмечалось ранее в 1й части, эти данные хранятся в конфигурационном файле .bzr/branch/branch.conf в чем легко можно убедиться:

parent_location = ../branch/

(Путь сохранен в относительном виде, относительно корневого каталога ветки-копии).

Секция Format показывает, что у текущей ветки есть свой репозиторий. В этом также легко убедиться, заглянув в /bzr/repository. Имя пакетированного файла в клонированном репозитории скорее всего будет отличаться от первого репозитория, поскольку bzr осуществил не просто копирование репозитория, а еще и выполнил перепаковку данных.
Кстати говоря, если мы просто скопируем каталог с оригинальной веткой как новый каталог, то получим вполне рабочую новую ветку, но очевидно, что при этом значение parent_location в branch.conf останется старым.
Для только что созданных веток, с малой историей, время клонирования репозитория будет сравнительно невелико, да и занимаемый размер весьма мал. Однако с течением времени репозиторий будет расти, и подобное дублирование репозиториев окажется весьма накладным.

Поэтому для оптимизации времени создания новой ветки и для уменьшения требуемого дискового пространства для копий веток, рекомендуется использовать разделяемый/общий репозиторий (shared repository). Как следует из названия он служит общим хранилищем для нескольких веток (располагающихся внутри).

Анатомия shared repository

Создадим новый общий репозиторий и посмотрим, что находится внутри его служебного каталога.

C:\work\bzr-day\Inside>bzr init-repo shared-repo
Shared repository with trees (format: 2a)
Location:
  shared repository: shared-repo

Мы создали общий репозиторий, в котором по умолчанию для веток будут создаваться рабочее дерево (Shared repository with trees). Для работы с ветками на локальном компьютере это ожидаемая конфигурация.

Заглянем внутрь .bzr:

branch-lock/
repository/
branch-format
readme

Как мы видим в отличие от ветки, в общем репозитории присутствует только компонент .bzr/repository, другие служебные файлы и каталоги на своих местах. Что нам покажет bzr info -v:

C:\work\bzr-day\Inside\shared-repo\.bzr>bzr info -v
Shared repository with trees (format: 2a)
Location:
  shared repository: C:/work/bzr-day/Inside/shared-repo

Format:
       control: Meta directory format 1
    repository: Repository format 2a - rich roots, group compression and chk inventories

Create working tree for new branches inside the repository.

Repository:
         0 revisions

Хотя этот общий репозиторий пока пустой (0 revisions), однако внутри каталога .bzr/repository есть на что посмотреть:

indices/
lock/
obsolete_packs/
packs/
upload/
format
pack-names
shared-storage

Очень похоже на содержимое .bzr/repository для обычной ветки, но добавился файл shared-storage (нулевой длины). Этот файл является маркером общего репозитория. Если его удалить, то наш объект перестанет быть shared repository.

Ветки внутри общего репозитория

Теперь посмотрим, что происходит при клонировании ветки внутрь общего репозитория:

C:\work\bzr-day\Inside\shared-repo>bzr branch ../branch a_branch
Branched 1 revision(s).

Посмотрим внутрь служебного каталога новой копии a_branch:

branch/
branch-lock/
checkout/
branch-format
readme

Как мы видим компонент .bzr/repository отсутствует. Что нам покажет bzr info -v:

C:\work\bzr-day\Inside\shared-repo\a_branch>bzr info -v
Repository tree (format: 2a)
Location:
  shared repository: C:/work/bzr-day/Inside/shared-repo
  repository branch: .

Related branches:
  parent branch: C:/work/bzr-day/Inside/branch

Format:
       control: Meta directory format 1
  working tree: Working tree format 6
        branch: Branch format 7
    repository: Repository format 2a - rich roots, group compression and chk inventories
...

Тем не менее, мы видим, что в секции форматов компонент repository присутствует. А в секции Location появилось упоминание shared repository. Наша новая ветка автоматически использует общий репозиторий вместо создания своего собственного. Если мы посмотрим внутрь .bzr/repository общего репозитория, то увидим, что туда добавлен новый пакетированный файл для нашей ветки.

Если мы посмотрим на branch.conf нашей новой ветки, то не увидим там никаких упоминаний общего репозитория и его расположения. И вообще нигде нет таких упоминаний. В том числе в структурах самого общего репозитория нет никаких указаний на расположение нашей ветки.

Bazaar осуществляет поиск общего репозитория для ветки просто просматривая все родительские каталоги вверх по дереву файловой системы пока не найдет один.

Из этого следует два вывода:
  1. Вы можете как угодно перемещать ветки внутри общего репозитория, внутрь подкаталогов, между подкаталогами, просто переименовывать ветки/каталоги -- и всё будет работать.
  2. Если вы просто скопируете или перенесете ветку из общего репозитория наружу, в другой каталог, то работа с такой веткой станет невозможна, поскольку bzr не сможет найти требуемый общий репозиторий. Вместо этого вам нужно использовать команду bzr branch, которая позаботится о том, чтобы восстановить репозиторий для ветки, если нужно.
Теперь посмотрим, что происходит при создании новой копии ветки внутри общего репозитория:

C:\work\bzr-day\Inside\shared-repo>bzr branch a_branch a_copy
Branched 1 revision(s).

Новая ветка a_copy также использует общий репозиторий для хранения ревизий. Как следствие время создания новой ветки будет заметно меньше для веток с большой историей. В остальном новая копия работает точно также.

Дополнительные сведения про общие репозитории

1. Общий репозиторий ничего не знает про ветки внутри него

Общий репозиторий является максимально общим хранилищем для ревизий. Настолько, что он ничего не знает о содержащихся внутри ветках. Их там даже может и не быть. С другой стороны  вы можете иметь внутри репозитория ветки не имеющие ни одной общей ревизии, не имеющие общей истории, и все будет работать, поскольку каждая ревизия имеет внутри себя указатель на последнюю зафиксированную ревизию (файл last-revision).

2. Общий репозиторий на сервере

Если у вас есть центральный сервер,  на котором вы храните свои ветки, то в большинстве случаев имеет смысл заводить общий репозиторий и на сервере, для получения тех же преимуществ: экономия места и ускорение клонирования веток. Однако чаще всего на сервере вашим веткам не нужно иметь рабочее дерево (компонент .bzr/checkout). Поэтому на сервере общий репозиторий имеет смысл создавать с опцией --no-trees:

C:\work\bzr-day\Inside>bzr init-repo --no-trees shared-no-trees
Shared repository (format: 2a)
Location:
  shared repository: shared-no-trees


C:\work\bzr-day\Inside\shared-no-trees>bzr info -v
Shared repository (format: 2a)
Location:
  shared repository: .


Format:
       control: Meta directory format 1
    repository: Repository format 2a - rich roots, group compression and chk inventories


Repository:
         0 revisions

При данной опции внутри каталога .bzr/repository создается дополнительный файл-флаг нулевой длины no-working-trees. Этот флаг влияет только на создание новых веток. В существующих ветках вы всегда можете создать или удалить рабочее дерево при помощи команд bzr checkout и bzr remove-tree.

В существующем общем репозитории можно переключаться между режимами --no-trees и --trees при помощи команд:

bzr reconfigure --with-no-trees
bzr reconfigure --with-trees

3. Переход от самостоятельной ветки к использованию общего репозитория и обратно

Если мы скопируем обычным образом (как просто каталог с файлами) нашу оригинальную самостоятельную ветку внутрь общего репозитория, то она все так же останется веткой со своим собственным репозиторием и не перейдет автоматически на использование общего репозитория. Но мы можем попросить bzr сделать это для нас при помощи команды

bzr reconfigure --use-shared

Это полезная команда еще и в тех случаях, когда у нас была просто самостоятельная ветка или две, а потом мы решили, что неплохо было бы, чтобы эта ветка или две были внутри общего репозитория. Тогда мы просто создаем в родительском каталоге общий репозиторий, и для всех веток запускаем команду bzr reconfigure --use-shared

Существует и обратное преобразование: ветку, использующую общий репозиторий мы можем превратить в ветку со своим собственным репозиторием командой

bzr reconfigure --standalone

Также, если вам нужно создать копию ветки извне внутри вашего общего репозитория и вы хотите, чтобы новая копия не использовала этот общий репозиторий, то вместо двух команд

bzr branch URL a_copy
bzr reconfigure --stadalone a_copy

целесообразно использовать одну команду:

bzr branch --standalone URL a_copy

Особенно, если формат ветки и общего репозитория не совпадают.

4. Замечание касательно форматов репозиториев

Лучше всего если все ваши ветки используют один и тот же формат. Тем более, что формат в bzr не менялся уже 2 года.

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

Поэтому я настоятельно рекомендую вам держать все свои рабочие ветки в одинаковом формате.

Комментариев нет:

Отправить комментарий