Иногда полезно иметь рабочую копию, собранную из разных источников. К примеру, может понадобиться, чтобы различные рабочие подкаталоги выгружались из разных каталогов хранилища, или даже из разных хранилищ. Безусловно, всё это можно сделать вручную, с помощью вызовов команды svn checkout создав рабочую копию с нужной структурой. Но, ели подобная структура требуется всем пользователям хранилища, каждому из них нужно будет повторить все те же операции по созданию рабочей копии, которые делали вы сами.
Чтобы этого избежать, Subversion обеспечивает поддержку
внешних зависимостей. Внешняя зависимость
является сопоставлением локального каталога к URL
версионированного каталога (или к его конкретной правке). Групповое
объявление внешних зависимостей делается в Subversion при помощи
свойства svn:externals
. Установка и редактирование
этого свойства выполняется с помощью команд
svn propset и svn propedit
(см. «Использование свойств»). Свойство может быть
установлено для любого версионированного каталога, значение свойства
представляет собой таблицу с путями к подкаталогам (относительно того
каталога, для которого это свойство устанавливается) и полными
абсолютными URL в Subversion-хранилище.
$ svn propget svn:externals calc third-party/sounds http://sounds.red-bean.com/repos third-party/skins http://skins.red-bean.com/repositories/skinproj third-party/skins/toolkit -r21 http://svn.red-bean.com/repos/skin-maker
Удобство свойства svn:external
заключается в том,
что после его задания для версионированного каталога все, кто будет
создавать рабочую копию с этим каталогом, получат возможность пользоваться
преимуществами внешней зависимости. Другими словами, после того как
кто-то из участников проекта обозначил необходимую структуру рабочей
копии, больше никому не придется об этом беспокоиться — при
создании рабочей копии Subversion, кроме оригинальных данных, сделает
рабочие копии данных, определенных как внешние зависимости.
Посмотрите на предыдущий пример с внешними зависимостями. Когда
кто-нибудь будет создавать рабочую копию каталога
calc
, Subversion создаст, в том числе, и копии
элементов, определенных как внешние зависимости.
$ svn checkout http://svn.example.com/repos/calc A calc A calc/Makefile A calc/integer.c A calc/button.c Checked out revision 148. Fetching external item into calc/third-party/sounds A calc/third-party/sounds/ding.ogg A calc/third-party/sounds/dong.ogg A calc/third-party/sounds/clang.ogg … A calc/third-party/sounds/bang.ogg A calc/third-party/sounds/twang.ogg Checked out revision 14. Fetching external item into calc/third-party/skins …
Если необходимо изменить внешние зависимости, сделать это можно с
помощью обычных команд редактирования свойств. После того как вы
зафиксируете изменения свойства svn:externals
,
при следующем запуске
svn update Subversion синхронизирует
существующие копии элементов в соответствии с внесенными во внешние
зависимости изменениями. Тоже самое произойдет и когда другие
участники проекта обновят свои рабочие копии и получат изменения во
внешних зависимостях.
Подсказка | |
---|---|
Учитывая, что свойство |
Подсказка | |
---|---|
Вам стоит всерьез подумать про использование явно указанного номера правки для всех внешних зависимостей. Поступая таким образом, вы сможете выбирать момент перехода на другой снимок внешней информации и явно указывать какой это будет снимок. Кроме того что это позволяет избежать получения неожиданных изменений из сторонних хранилищ, которые вы, возможно, никак не контролируете, явное указание номера правки означает, что откат вашей рабочей копии к более ранней правке приведет к откату и для внешних зависимостей, к тому состоянию, в котором они были в той, предыдущей, правке, то есть это значит, что внешние рабочие копии будут выглядеть так, как они выглядели на момент той правки вашего хранилища. Для программных проектов это может быть вопросом удачной или неудачной сборки старого снимка сложной и запутанной базы программного кода. |
Команда svn status умеет определять внешние
зависимости, показывая код статуса X
для
подкаталогов, выгруженных из внешних зависимостей, и рекурсивно
проходя по этим подкаталогам для отображения статуса самих внешних
элементов.
Вместе с тем, текущая реализация поддержки внешних зависимостей
в Subversion может вводить в заблуждение. Во-первых, внешние зависимости
могут указывать только на папки, но не на файлы. Во-вторых, внешние
зависимости не могут указывать на относительные пути (например,
такие как ../../skins/myskin
). В-третьих,
рабочие копии, созданные через внешние зависимости, являются оторванными от
первичной рабочей копии (от того каталога, для которого установлено
свойство svn:externals
). А Subversion полноценно
работает только на неотсоединенных рабочих копиях. Это означает, что
если вы захотите зафиксировать изменения, сделанные в одной или
нескольких таких рабочих копиях, вам придется принудительно выполнять
команду svn commit для этих рабочих копий —
фиксация в первичной рабочей копии не распространяется на внешние
зависимости.
Кроме того, поскольку зависимости используют абсолютные URL,
перемещение или копирование папки, к которой они присоединены, не
будет влиять на то, что будет выгружаться из хранилища в виде
внешней зависимости (при этом, локальные подкаталоги, назначенные
как целевые для внешних зависимостей, при переименовании родительского
каталога будут, естественно, перемещены вместе с ним).
В определенных ситуациях это может сбивать с толку и запутывать.
Например, у вас есть корневой каталог my-project
и для одного из его подкаталогов (my-project/some-dir
)
вы назначаете внешнюю зависимость, отслеживающую изменения другого
подкаталога (my-project/external-dir
).
$ svn co http://svn.example.com/projects . A my-project A my-project/some-dir A my-project/external-dir … Fetching external item into 'my-project/some-dir/subdir' Checked out external at revision 11. Checked out revision 11. $ svn pget svn:externals my-project/some-dir subdir http://svn.example.com/projects/my-project/external-dir $
Переименуем с помощью команды svn move
каталог my-project
. Теперь
внешние зависимости продолжают продолжают указывать на путь в каталоге
my-project
, а самого этого каталога уже не
существует.
$ svn mv -q my-project renamed-project $ svn ci -m "Rename my-project to renamed-project." Deleting my-project Adding my-renamed-project Committed revision 12. $ svn up Fetching external item into 'renamed-project/some-dir/subdir' svn: Target path does not exist $
Тот факт, что внешние зависимости используют абсолютные URL, может
вызвать проблемы при работе с хранилищами, доступными через несколько
URL-схем. Интересная проблема может возникнуть, если, например, сервер
Subversion позволяет любому пользователю создать рабочую копию, подключившись
через http://
или https://
, а
фиксации позволяет выполнять только через https://
.
Если внешние зависимости используют http://
вариант
URL хранилища, то для рабочих копий, созданных для этих внешних
зависимостей, нельзя будет выполнить фиксацию изменений. С другой
стороны, если использовался https://
вариант URL, то
пользователи, которые создают рабочую копию через
http://
потому, что их клиент не поддерживает
https://
, не смогут получить внешние элементы.
Обратите внимание и на то, что при переопределении рабочей копии
(с помощью команды svn --relocate) внешние
зависимости не будут переопределены.
Наконец, могут быть ситуации, в которых предпочтительно, чтобы
подкоманды svn не идентифицировали и не оперировали
рабочими копиями, созданными как внешние зависимости. Для таких
случаев при вызове подкоманды можно использовать параметр
--ignore-externals
.