Мы разрабатываем .NET Enterprise Software на С#. Мы стремимся улучшить нашу систему контроля версий. Раньше я использовал ртуть и экспериментировал с ней в нашей компании. Однако, поскольку мы разрабатываем корпоративные продукты, мы уделяем большое внимание многократно используемым компонентам или модулям. Я пытаюсь использовать mercurial sub-repos для управления компонентами и зависимостями, но у меня есть некоторые трудности. Вот основные требования для управления версиями/управления зависимостями:
- Многоразовые компоненты
- Общие сведения об источнике (для отладки)
- Имеют зависимости от сторонних двоичных файлов и других компонентов многократного использования.
- Может быть разработано и поручено контролю источника в контексте потребляющего продукта
- Зависимости
- Продукты имеют зависимости от сторонних двоичных файлов и других компонентов многократного использования.
- Зависимости имеют свои зависимости
- Разработчики должны быть уведомлены о конфликтах версий в зависимостях
Вот структура в mercurial, которую я использовал:
Компонент многократного использования:
SHARED1_SLN-+-docs
|
+-libs----NLOG
|
+-misc----KEY
|
+-src-----SHARED1-+-proj1
| +-proj2
|
+-tools---NANT
Второй компонент многократного использования, потребляющий первый:
SHARED2_SLN-+-docs
|
+-libs--+-SHARED1-+-proj1
| | +-proj2
| |
| +-NLOG
|
+-misc----KEY
|
+-src-----SHARED2-+-proj3
| +-proj4
|
+-tools---NANT
Продукт, который потребляет оба компонента:
PROD_SLN----+-docs
|
+-libs--+-SHARED1-+-proj1
| | +-proj2
| |
| +-SHARED2-+-proj3
| | +-proj4
| |
| +-NLOG
|
+-misc----KEY
|
+-src-----prod----+-proj5
| +-proj6
|
+-tools---NANT
Примечания
- Репо находятся в CAPS
- Все дочерние репозитории считаются подчиненными
- Сторонние (двоичные) библиотеки и внутренние (исходные) компоненты - это все подпосылки, расположенные в папке libs
- 3-сторонние библиотеки хранятся в отдельных меркуриальных репозиториях, так что потребляющие проекты могут ссылаться на конкретные версии libs (то есть старый проект может ссылаться на NLog v1.0, а более новый проект может ссылаться на NLog v2.0).
- Все файлы Visual Studio.csproj находятся на 4-м уровне (proj * folders), что позволяет относить ссылки на зависимости (то есть.. /../../libs/NLog/NLog.dll для всех проектов Visual Studio, которые ссылаются NLog)
- Все файлы Visual Studio.sln находятся на 2-м уровне (папки src), чтобы они не включались при "совместном использовании" компонента в потребляющем компоненте или продукте.
- Разработчики могут свободно организовывать свои исходные файлы по своему усмотрению, пока исходные файлы являются дочерними страницами проекта proj * в проекте потребляющего Visual Studio (т.е. в папках proj * могут быть n детей, содержащих различные источники/ресурсы)
- Если Боб разрабатывает компонент SHARED2 и продукт PROD1, для него совершенно законно вносить изменения в источник SHARED2 (скажем, источники, принадлежащие proj3) в репозитории PROD1_SLN, и фиксировать эти изменения. Мы не против, если кто-то разрабатывает библиотеку в контексте потребляющего проекта.
- Внутренне разработанные компоненты (SHARED1 и SHARED2) обычно включаются источником в проект потребления (в Visual Studio добавление ссылки на проект, а не просмотр ссылки на dll). Это позволяет усилить отладку (вступая в библиотечный код), позволяет Visual Studio управлять, когда ему нужно перестраивать проекты (при изменении зависимостей), и позволяет при необходимости модифицировать библиотеки (как описано в примечании выше).
Вопросы
-
Если Боб работает над PROD1, и Алиса работает над SHARED1, как Боб может узнать, когда Алиса вносит изменения в SHARED1. В настоящее время с Mercurial, Боб вынужден вручную вытягивать и обновлять в каждом подпоре. Если он выталкивает/вытаскивает сервер из PROD_SLN-репо, он никогда не знает об обновлениях для subrepos. Это описано в Mercurial wiki. Как Боб может быть уведомлен об обновлениях в subrepos, когда он вытаскивает последнюю версию PROD_SLN с сервера? В идеале, он должен быть уведомлен (предпочтительнее во время вытаскивания), а затем должен вручную решить, какие субрепоты он хочет обновить.
-
Предположим, что ссылки SHARED1 NLog v1.0 (commit/rev abc in mercurial) и ссылки SHARED2 Nlog v2.0 (commit/rev xyz в mercurial). Если Боб поглощает эти два компонента в PROD1, он должен быть осведомлен об этом несоответствии. Хотя технически Visual Studio/.NET позволяла двум сборкам ссылаться на разные версии зависимостей, моя структура не позволяет этого, потому что путь к NLog фиксирован для всех .NET-проектов, которые зависят от NLog. Как Боб знает, что у двух его зависимостей есть конфликты версий?
-
Если Боб настраивает структуру репозитория для PROD1 и хочет включить SHARED2, как он может знать, какие зависимости необходимы для SHARED2? В моей структуре ему придется вручную клонировать (или просматривать на сервере) репозиторий SHARED2_SLN и либо искать в папке libs, либо пик в файле .hgsub, чтобы определить, какие зависимости он должен включать. В идеале это было бы автоматизировано. Если я включаю SHARED2 в свой продукт, SHARED1 и NLog тоже автоматически включаются, уведомляя меня, если конфликт версий с какой-либо другой зависимостью (см. Вопрос 2 выше).
Большие вопросы
-
Является ли mercurial правильным решением?
-
Есть ли лучшая структура ртути?
-
Является ли это допустимым использованием для subrepos (т.е. разработчики Mercurial отметили subrepos как особенность последнего средства)?
-
Имеет ли смысл использовать mercurial для управления зависимостями? Мы могли бы использовать еще один инструмент управления зависимостями (возможно, внутренний фид NuGet?). Хотя это будет хорошо работать для сторонних зависимостей, это действительно создаст проблему для внутренних компонентов (т.е. Если они будут активно развиваться, разработчикам придется постоянно обновлять фид, нам придется обслуживать их внутренне, и это не позволит компоненты, которые должны быть изменены потребляющим проектом (Примечание 8 и Вопрос 2).
-
У вас есть лучшее решение для программных проектов Enterprise.NET?
Ссылки
Я прочитал несколько вопросов SO и нашел этот, чтобы помочь, но принятый ответ предлагает используя специальный инструмент для зависимостей. Хотя мне нравятся функции такого инструмента, он не позволяет изменять зависимостей и совершенствовать их из проекта потребления (см. Большой вопрос 4).