Que o Subversion é uma ótima ferramenta, todo mundo sabe. Mas muitos – assim como eu – acabam não a utilizando por completo, por falta de conhecimento.
Descobri o svn:externals (External Definitions é o nome correto) da pior forma possível: tendo mais trabalho que o necessário para manter dependências em projetos.
Mas em que o svn:externals facilita?
Estou recomeçando um projeto (PHPCashControl) que já estava parado há um bom tempo (e que não tinha nada além de um ‘hello world’). Decidi então utilizar o Zend Framework.
Seguindo a sugestão de estrutura de diretórios, precisava incluir o ZF dentro do meu projeto. Para isso, tinha algumas opções:
- Baixar a biblioteca compactada, descompactá-la em um diretório qualquer e copiar os arquivos para meu projeto, depois fazer o commit para atualizar meu projeto com a versão mais nova do ZF baixado.
- Criar um diretório qualquer, e nele fazer o checkout do trunk do ZF. Fazer um export desse diretório para dentro do meu projeto e, depois disso, fazer o commit para atualizar o repositório do meu projeto.
Consegue perceber os contratempos?
- Tenho que estar sempre preocupado em verificar se existem novas versões para as bibliotecas externas que utilizo, principalmente correções críticas. No meu caso é o Zend Framework, mas pode ser qualquer outra, como por exemplo a Smarty Template, PHPMailer, dentre outras.
- Além disso, tenho o trabalho de sempre baixar a última versão do seu repositório (ou baixar sua respectiva versão compactada) e enviar para o repositório do meu projeto.
Entra em cena a propriedade svn:externals
Ela permite utilizar recursos de diferentes repositórios, ou de diferentes lugares (diretórios) de um repositório no seu projeto. Basicamente, é um tipo de link para outro repositório SVN. Usando-a, você adiciona código de (vários) repositórios dentro de um único working copy.
Definindo a propriedade em nosso projeto
Vamos utilizar a mesma idéia do PHPCashControl. Temos um projeto e queremos adicionar a biblioteca ZF nele.
No raiz de nosso projeto temos os seguintes diretórios:
1 2 3 4 | app data library public |
É dentro de library que adicionaremos o ZF. Estando no diretório raiz do projeto, basta executar no terminal:
1 2 3 | svn propedit svn:externals library http://framework.zend.com/svn/framework/standard/trunk/library/Zend/ svn commit -m "Adicionado recurso externo do Zend Framework" svn update |
Na linha 1 definimos o diretório Zend (e seus subdiretórios) de seu repositório para ser importado dentro da pasta library de nosso working copy. Na linha de baixo, fazemos o commit para gravar essa alteração no repositório, com o comentário para descrever o motivo desse commit. Só depois do terceiro comando que você receberá os arquivos do repositório do ZF.
Importante: o diretório Zend não pode existir dentro do diretório library. Ele será criado automaticamente.
Externals Definitions no Eclipse PDT com Subclipse
Utilizando o plugin Subclipse para o Eclipse PDT também é muito fácil de definir recursos externos.
Para adicionar o ZF em nosso projeto pelo Eclipse:
- Clique com o botão direito na pasta library;
- Depois clique em Team, e em seguida Set Property;
- Em Property name, selecione svn:externals na combo;
- Na caixa de texto abaixo – deixe a opção Enter a text property marcada – informe o caminho do repositório. No nosso caso: http://framework.zend.com/svn/framework/standard/trunk/library/Zend/
- Clique em OK;
- Clique com o botão direito no diretório raiz do projeto, depois clique em Team e Commit;
- Na caixa de texto coloque o motivo do commit: Adicionado recurso externo do Zend Framework e clique em OK;
- Depois clique novamente com o botão direito no diretório raiz do projeto e, por fim clique em Team, depois Update;
Atenção com as revisions
Se definirmos a propriedade svn:externals conforme demonstrado nos exemplos acima, podemos ter um grande problema, caso esse não seja o comportamento esperado. Explico.
Criamos uma tag de nosso projeto na revision 10. No momento da criação da nossa tag, a revision do ZF era 15060, por exemplo. O ZF continua recebendo commits em seu repositório, e digamos que depois de 10 dias da nossa tag, a revision do ZF seja 16000. Ao fazermos o checkout da tag de nosso projeto, ao invés de termos a revision 15060 do ZF dentro do diretório library, teremos a versão 16000. É exatamente esse o problema, principalmente se há uma grande mudança no projeto do qual o teu projeto depende.
Para evitar esse tipo de problema, é recomendado que você crie dependências (svn:externals) apenas de tags de outros projetos, ou então, que se especifique a revision da qual se pretende criar a dependência.
Para criar uma dependência de uma tag, basta informar seu caminho. Exatamente como nos exemplos anteriores. O que muda nesse caso é apenas o endereço do repositório:
1 2 3 | svn propedit svn:externals library http://framework.zend.com/svn/framework/standard/tags/release-1.7.8/library/Zend/ svn commit -m "Adicionado recurso externo da tag 1.7.8 do Zend Framework" svn update |
Para criar uma dependência da revision 15000 do trunk do ZF:
1 2 3 | svn propedit svn:externals library -r15000 http://framework.zend.com/svn/framework/standard/trunk/library/Zend/ svn commit -m "Adicionado recurso externo da revision 15000 do trunk do Zend Framework" svn update |
Perceba o parâmetro -r15000 na linha 1 acima.
Versões utilizadas no post
- Subversion 1.6.1 Build 16129 – 64 Bit
- Eclipse Platform 3.4.2 Build id: M20090211-1700
- PDT 2.0.0.v20081229-1135
Referências:
Posts relacionados:
Muito boa a dica, vou utilizar…
Parabéns.
Cara, fantástico! Mas é sempre bom monitorar os changelogs das bibliotecas para não ver se precisamos mudar alguma coisa em nossos códigos.