Como usar subrepositos mercurial para componentes compartilhados e dependências?
Desenvolvemos o .NET Enterprise Software em C #. Estamos procurando melhorar nosso sistema de controle de versão. Eu usei mercurial antes e tenho experimentado usá-lo em nossa empresa. No entanto, desde que desenvolvemos produtos corporativos, temos um grande foco em componentes ou módulos reutilizáveis. Eu tenho tentado usar sub-repositórios do mercurial para gerenciar componentes e dependências, mas estou tendo algumas dificuldades. Aqui estão os requisitos básicos para gerenciamento de controle / dependência de origem:
Componentes reutilizáveisCompartilhado por fonte (para depuração)Tem dependências de binários de terceiros e outros componentes reutilizáveisPode ser desenvolvido e comprometido com o controle de origem no contexto de um produto consumidorDependênciasOs produtos têm dependências de binários de terceiros e outros componentes reutilizáveisDependências têm suas próprias dependênciasOs desenvolvedores devem ser notificados sobre conflitos de versão nas dependênciasAqui está a estrutura no mercurial que tenho usado:
Um componente reutilizável:SHARED1_SLN-+-docs
|
+-libs----NLOG
|
+-misc----KEY
|
+-src-----SHARED1-+-proj1
| +-proj2
|
+-tools---NANT
Um segundo componente reutilizável, consumindo o primeiro:SHARED2_SLN-+-docs
|
+-libs--+-SHARED1-+-proj1
| | +-proj2
| |
| +-NLOG
|
+-misc----KEY
|
+-src-----SHARED2-+-proj3
| +-proj4
|
+-tools---NANT
Um produto que consome os dois componentes:PROD_SLN----+-docs
|
+-libs--+-SHARED1-+-proj1
| | +-proj2
| |
| +-SHARED2-+-proj3
| | +-proj4
| |
| +-NLOG
|
+-misc----KEY
|
+-src-----prod----+-proj5
| +-proj6
|
+-tools---NANT
NotasRepos estão no CAPSTodas as reposições de crianças são consideradas sub-posiçõesAs bibliotecas de terceiros (binárias) e os componentes internos (de origem) são todos subrepositos localizados na pasta libsAs bibliotecas de terceira parte são mantidas em repositórios individuais de mercurial, para que os projetos de consumo possam fazer referência a versões específicas das libs (por exemplo, um projeto antigo pode fazer referência a NLog v1.0 e um projeto mais recente pode fazer referência a NLog v2.0).Todos os arquivos .csproj do Visual Studio estão no nível 4 (pastas proj *), permitindo referências relativas a dependências (por exemplo, ../../../libs/NLog/NLog.dll para todos os projetos do Visual Studio que fazem referência ao NLog)Todos os arquivos .sln do Visual Studio estão no segundo nível (pastas src) para que eles não sejam incluídos ao "compartilhar" um componente em um componente ou produto consumidorOs desenvolvedores são livres para organizar seus arquivos de origem da maneira que acharem melhor, contanto que as fontes sejam filhos da pasta proj * do projeto consumidor do Visual Studio (ou seja, pode haver n filhos para as pastas proj *, contendo várias fontes / recursos)Se Bob estiver desenvolvendo o componente SHARED2 e o produto PROD1, é perfeitamente legal que ele faça alterações na fonte SHARED2 (digamos, origens pertencentes a proj3) dentro do repositório PROD1_SLN e confirme essas alterações. Não nos importamos se alguém desenvolve uma biblioteca no contexto de um projeto consumidor.Componentes desenvolvidos internamente (SHARED1 e SHARED2) são geralmente incluídos pela fonte no projeto consumidor (no Visual Studio adicionando uma referência a um projeto ao invés de navegar para uma referência dll). Isso permite uma depuração aprimorada (revisão no código da biblioteca), permite que o Visual Studio gerencie quando precisa recriar projetos (quando as dependências são modificadas) e permite a modificação de bibliotecas quando necessário (conforme descrito na nota acima).QuestõesSe Bob estiver trabalhando no PROD1 e Alice estiver trabalhando no SHARED1, como o Bob saberá quando o Alice confirmar alterações no SHARED1. Atualmente com o Mercurial, Bob é forçado a puxar e atualizar manualmente dentro de cada sub-repo. Se ele empurra / puxa para o servidor do repositório PROD_SLN, ele nunca sabe sobre atualizações de sub-inscrições. Isso é descrito emWiki Mercurial. Como Bob pode ser notificado de atualizações para sub-repos quando ele retira o mais recente do PROD_SLN do servidor? Idealmente, ele deve ser notificado (preferível durante o pull) e depois ter que decidir manualmente quais sub-posições ele deseja atualizar.
Suponha que o SHARED1 faça referência ao NLog v1.0 (commit / rev abc no mercurial) e SHARED2 faça referência ao Nlog v2.0 (commit / rev xyz no mercurial). Se Bob estiver absorvendo esses dois componentes no PROD1, ele deve estar ciente dessa discrepância. Embora tecnicamente o Visual Studio / .NET permita que 2 assemblies consultem diferentes versões de dependências, minha estrutura não permite isso porque o caminho para o NLog é fixo para todos os projetos .NET que dependem do NLog. Como pode Bob saber que duas de suas dependências têm conflitos de versão?
Se Bob estiver configurando a estrutura de repositório para PROD1 e quiser incluir SHARED2, como ele poderá saber quais dependências são necessárias para SHARED2? Com minha estrutura, ele precisaria clonar manualmente (ou procurar no servidor) o repositório SHARED2_SLN e procurar na pasta libs ou no arquivo .hgsub para determinar quais dependências ele precisa incluir. Idealmente isso seria automatizado. Se eu incluir SHARED2 em meu produto, SHARED1 e NLog também serão incluídos automaticamente, notificando-me se houver conflito de versões com alguma outra dependência (consulte a pergunta 2 acima).
Perguntas maioresA solução correta é mercurial?
Existe uma estrutura mercurial melhor?
Este é um uso válido para sub-propostas (ou seja, desenvolvedores do Mercurial marcadossub-posições como uma característica do último recurso)?
Faz sentido usar mercurial para gerenciamento de dependências? Poderíamos usar ainda outra ferramenta para gerenciamento de dependências (talvez um feed interno do NuGet?). Embora isso funcionasse bem para dependências de terceiros, isso realmente criaria um incômodo para componentes desenvolvidos internamente (ou seja, se eles estivessem ativamente desenvolvidos, os desenvolvedores teriam que atualizar constantemente o feed, teríamos que atendê-los internamente, e isso não permitiria componentes a serem modificados por um projeto consumidor (Nota 8 e Pergunta 2).
Você tem uma solução melhor para projetos de software Enterprise .NET?
ReferênciasEu li várias perguntas do SO e encontreieste para ser útil, mas oresposta aceita sugere o uso de uma ferramenta dedicada para dependências. Embora eu goste dos recursos de tal ferramenta, não é permitido que as dependências sejam modificadas e comprometidas a partir de um projeto consumidor (veja a pergunta maior 4).