Введение
Определения Структура репозитория Тег для Набора проектов Редактор svn:externals Заключение Несколько слов о .NET-проектах |
Автор статьи Структура проектов на C++ с использованием Subversion и Mxx_ru выстраивал иерархию проектов на основе отношения «Проект – Подпроект». Проект содержит файлы, которые в свою очередь требуют наличия других файлов из других проектов.
Есть и несколько иной способ хранения в репозитории и работы со сложными проектами. За основу можно взять отношение «Проект – Набор проектов». Такое отношение применяется, например, в системе контроля версий Perforce. В терминах Perforce "Набор проектов" – это Workspace разработчика, а "Проектом" можно считать любую папку, которую пользователь хочет видеть у себя на компьютере, в своём client Workspace. Важный момент, на который хотелось бы обратить внимание: Workspace содержит не сами файлы и папки, а только ссылки на них. В нашем случае это будет именно так, за небольшим исключением.
Договоримся о терминах:
Проектом будем называть папку в репозитории и в рабочей копии, содержащую некоторые файлы. Это может быть, например, папка с исходными текстами проекта какой-нибудь библиотеки или исполняемого файла.
Набор проектов – это папка в репозитории, предназначение которой – хранить ссылки на проекты, обеспечивать их загрузку при операции checkout и формировать файловую структуру в рабочей копии.
В документации Subversion и TortoiseSVN говорится о двух моделях хранения проектов. Здесь мы воспользуемся одной, в которой папка проекта содержит подпапки trunk, branches и tags.
Далее, нам понадобится место для хранения Наборов проектов, в котором мы также создадим папки trunk, branches и tags.
В целом, дерево репозитория будет выглядеть так:
Projects common branches tags trunk project1 ... project2 ... ProjectSets ProjectSet1 branches tags 1.1 (svn:externals p1 –r 101 project1/trunk p2 –r 149 project2/trunk ) trunk (svn:externals: p1 project1/trunk p2 project2/trunk ) ProjectSet2 |
Такая структура репозитория позволяет делать теги и ветки для Наборов проектов.
Пометка делается следующим образом. Допустим, у нас есть рабочая копия Набора проектов. Тогда для свойств svn:externals мы просто укажем текущие номера версий для подпроектов и сохраним папку с изменённым свойством на сервер в качестве тега. Например, у нас есть каталог C:\ProjectSet1, полученный checkout-ом пути svn://localhost/ProjectSets/ProjectSet1/trunk. Изменим его externals таким образом:
p1 project1/trunk -> p1 –r 101 project1/trunk p2 project2/trunk -> p2 –r 101 project2/trunk. |
Вернем в репозиторий измененные файлы следующим образом (для TortoiseSVN): из контекстного меню вызываем команду Branch/Tag для WS, причем надо ОБЯЗАТЕЛЬНО СНЯТЬ галочку напротив Create the branch/tag directly on server.
После этих действий для каталога рабочей копии нужно сделать Revert, чтобы сбросить номера версий и работать дальше.
Единственным, но довольно существенным недостатком такого подхода является отсутствие на сегодняшний день удобного редактора для свойства svn:externals, позволяющего сравнивать версию в свойстве с версией, которой реально был сделан checkout (они могут и не совпадать, если вручную, не через externals, переключить проект в наборе с одной ветки на другую). Столкнувшись с этой проблемой, я, опять-таки в качестве эксперимента с .Net, разработал расширение контекстного меню Explorer’а, позволяющее более-менее удобно редактировать свойство svn:externals. Внешний вид этого расширения таков:
Как видим, задача отслеживания версий сложных проектов может быть решена с помощью Subversion и даже не одним способом. Надо признать, что способ, описанный в этой врезке является подмножеством способа, предложенного автором статьи, но с другой стороны, он несёт и больше смысловой нагрузки.
Конечно, хорошо, когда в твоих руках оказывается гибкий и бесплатный инструмент, который можно дорабатывать под свои нужды. Но было бы ещё приятнее, если бы нужная функциональность была встроена в него изначально, чтобы не приходилось ухищряться при решении, в принципе, рутинных и повседневных задач.
Предложенная автором схема не вполне пригодна для .NET-проектов, особенно если речь идет о проектах, разрабатываемых с использованием Visual Studio. Дело в том, что во время работы Visual Studio блокирует сборку, чтобы создавать экземпляры компонентов или получать метаинформацию о сборке. Если воспользоваться идеей автора о размещении всех исполняемых модулей в одном каталоге, то с большой вероятностью компиляция будет заканчиваться неудачей, т.к. компилятор будет наталкиваться на модули, заблокированные Visual Studio. Для решения этой проблемы в Visual Studio применяется механизм теневого копирования (shadow copy), который позволяет избежать блокировки сборок, но при этом помещает копии сопутствующих сборок в каталог основной сборки. Таким образом, выходные (output) каталоги проекта, ссылающегося на другие сборки, обычно содержат копии сопутствующих сборок. Это поведение не зависит от языка, и характерно для всех .NET-проектов.
Однако никаких проблем со структурой каталогов в .Net нет, так как .NET-проектам нет никакой необходимости ссылаться на исходные коды. Они могут ссылаться скомпилированные (бинарные) сборки, что значительно упрощает жизнь программиста. Автоматизировать сборку .NET-проекта на других платформах можно с помощью утилиты NANT (.NET-аналога ANT), для которого в сети можно найти средство преобразования формата проекта VS в его собственный формат. Эта пробема не стоит остро, так как скомпилированные на одной платформе модули могут переноситься на другие платформы в бинарном виде – лишь бы эти сборки не имели зависимостей от других native-модулей. Да и в этом случае, если использовался P/Invoke, разбираться придется исключительно с native-модулями.
После выхода VS 2005 сборка проектов еще более упростится, так как их можно будет собирать с помощью MS Build, аналога NANT от Microsoft, о котором можно прочитать в предыдущем номере нашего журнала.