Introdução ao CVS
Utilize o CVS e livre-se das dores de cabeça que uma equipe de desenvolvedores pode enfrentar
O desenvolvimento de grandes projetos possui como principal fator limitante a concorrência. Ela se deve ao fato de diversas pessoas estarem trabalhando no mesmo projeto ao mesmo tempo, e impede o total aproveitamento dos recursos disponíveis, causando a perda de oportunidades de paralelização. Quanto maior o projeto, mais provável é que duas ou mais pessoas estejam editando um único programa simultaneamente, gerando conflitos e aumentando as chances do aparecimento de inconsistências.
Talvez o método mais utilizado para contornar este problema seja a concordância mútua entre desenvolvedores: somente uma pessoa trabalhando em um módulo por vez, o que não é eficiente. Em primeiro lugar, não é pouco freqüente a situação em que duas pessoas precisam urgentemente modificar o mesmo módulo - sobretudo quando ocorrem erros críticos. Mais ainda, em se tratando de um ambiente de desenvolvimento distribuído, parte da equipe pode estar isolada do resto do grupo, retardando a liberação do módulo para edição.
utro método é empregar uma ferramenta de controle de versão. Esta gerencia o acesso aos módulos e fontes que compõem um sistema, registrando todas as alterações realizadas e permitindo a recuperação segura de qualquer versão armazenada. Servem para controlar quaisquer tipos de arquivos, e não somente fontes. Este artigo, por exemplo, foi escrito com o suporte do CVS.
No entanto, a maioria dessas ferramentas emprega a técnica de "locking", que tenta controlar, de forma automatizada os problemas descritos acima, sem, no entanto, conseguir: Imagine que alguém necessite editar um arquivo. Utilizando-se do "lock", ela o adquire e, confiante na exclusividade de acesso que lhe oferece, começa a editá-lo. A partir desta situação, surgem algumas questões: 1. ninguém obterá acesso ao arquivo até que o "lock" seja liberado (e não há garantia de que isto algum dia ocorra); 2. são freqüentes os casos em que é necessário mais de um arquivo em um projeto. "Locks" múltiplos não são raros e tendem a manter ocioso o restante da equipe de desenvolvimento durante a sua existência; e 3. qual a vantagem de se ter uma equipe, se somente uma pessoa pode trabalhar por vez?
O CVS (Concurrent Versions System) é um sistema Open Source que permite que várias pessoas trabalhem nos mesmos projetos ao mesmo tempo. Utilizando técnicas que permitem identificação de modificações, ele pode controlar a atualização de arquivos, sem restringir o acesso a eles. Esta prática está de acordo com as metodologias de desenvolvimento do tipo agile, como Extreme Programming e Adaptive Software Development, nas quais comumente emprega-se a técnica de Collective Code Ownership, ou seja, não há restrições de acesso ao código do projeto para seus participantes.
Dessa forma, todos os arquivos estão disponíveis para edição a qualquer hora. Trechos distintos, modificados por várias pessoas, são combinados automaticamente, sem a necessidade de intervenção humana. No caso da detecção de mudanças no mesmo trecho de código, um alerta é emitido, e os responsáveis pela edição, imediatamente notificados.
Utilizado por grande parte dos projetos de software de código aberto (open source), nos quais trabalham centenas ou milhares de desenvolvedores distribuídos geograficamente pelo mundo, o CVS é responsável pelo gerenciamento de inúmeros produtos, entre os quais destacamos:
~U O servidor HTTP Apache
~U O Kernel do Linux
~U Gnome
~U KDE
~U Kylix (Delphi para Linux)
~U Mozilla (versão aberta do Netscape)
~U CVS (o próprio)
Conceitos
Antes de passarmos para a parte prática, precisamos definir alguns termos e conceitos:
~U Projeto - conjunto de arquivos-fontes e documentos que compõem um produto, organizados através de estrutura hierárquica (diretórios).
~U Repositório - conjunto lógico de projetos. Todo projeto deve estar associado a um repositório. Não há regras bem estabelecidas sobre como agrupar os projetos. Alguns desenvolvedores criam um repositório por projeto, enquanto outros preferem agrupá-los em alguns repositórios e outros, ainda, utilizam um único repositório para todos os projetos.
~U Versão - identificação de um momento bem definido no tempo de um projeto e dos arquivos que o compõem naquele instante.
Criando o repositório
O nosso ponto de partida será um sistema criado para demonstrar o uso do CVS e que é composto pelos arquivos representados na árvore de diretório abaixo:
|~W Makefile
|~W prog1.c
|~W prog2.cpp
|~W prog.tex
|~W testes
|~W teste1.c
|~W Makefile
O primeiro passo no uso do CVS é a criação de um repositório para armazenar nosso projeto. Para fazê-lo, devemos definir um diretório que servirá como raiz do repositório. Neste artigo, escolhemos /home/user/cvsroot, mas qualquer outro serviria igualmente. A seguir, executamos o comando de criação:
cvs -d /home/user/cvsroot init
Com o repositório criado, poderíamos começar a utilizar o CVS. Antes disso, porém, é conveniente apontar a variável CVSROOT para o diretório raiz, a fim de não precisarmos digitar o seu caminho a cada comando entrado:
export CVSROOT=/home/user/cvsroot
Importando os fontes do projeto
Criado o repositório, devemos importar os fontes do nosso projeto. Isto significa incluí-los no repositório, para que possam ser controlados pelo CVS. Devemos, primeiro, entrar no diretório onde se encontram os fontes e, depois, digitar o comando:
cvs import -m "Projeto 1 - Revista do Linux" teste_cvs rdl start
A opção -m permite passar uma breve descrição do projeto. Caso não a utilizemos, o CVS abrirá um editor de textos para que possamos fazê-lo. teste_cvs e rdl identificam, respectivamente, o projeto e a empresa que o desenvolveu. Procure escolher bem o nome do projeto, dando preferência a palavras de fácil memorização, pois é através dele que referenciaremos o projeto nos demais comandos do CVS.
Se não houve erros na execução do comando, podemos remover os arquivos locais, para garantir que não existam cópias desatualizadas dos mesmos.
Obtendo os fontes do projeto
Para modificar os fontes de um projeto que se encontra no repositório, devemos usar o comando cvs checkout. Este comando permite baixar todos os arquivos e sub-diretórios do projeto para um diretório local, chamado de working directory ou diretório de trabalho. É neste diretório que serão realizados o desenvolvimento e/ou modificações nos fontes.
OBS: Repare que vários usuários podem trabalhar no mesmo projeto, simultaneamente. Basta que cada um realize o checkout para um diretório distinto.
É nosso hábito manter um diretório para receber os fontes baixados para o CVS. Neste artigo, usaremos /home/user/src.
cd /home/user/src
cd /home/user/src
Se tudo ocorreu normalmente, o CVS criou um sub-diretório (teste_cvs) a partir de onde estávamos (/home/user/src) e copiou para ele toda a estrutura do projeto, ou seja, seus arquivos e sub-diretórios:
home
|~W user
|~W src
|~W teste_cvs
|~W Makefile
|~W prog1.c
|~W prog2.cpp
|~W prog.tex
|~W testes
|~W teste1.c
|~W Makefile
A partir de agora, basta entrarmos no diretório /home/teste_cvs e editar os arquivos normalmente.
Adicionando e removendo arquivos
Se durante o desenvolvimento, necessitarmos criar ou eliminar arquivos, devemos informar ao CVS, para que este possa adicioná-los ou removê-los do repositório. Para isso, usamos dois comandos: cvs add e cvs remove.
Suponha que criamos o arquivo prog3.cpp e desejamos apagar o arquivo prog2.cpp. Devemos informar ao CVS através dos comandos:
cvs add prog3.cpp
cvs remove prog2.cpp
rm prog2.cpp
Repare que nenhuma alteração entrará em vigor até que tenhamos executado o commit, como veremos adiante. Por isso, sinta-se à vontade para experimentar.
Para adicionar ou remover um diretório, procedemos da mesma forma que para um arquivo, usando os comandos descritos acima.
Verificando as alterações realizadas
Durante o desenvolvimento, é bastante provável que sintamos a necessidade de comparar a versão que está sofrendo manutenção com a que se encontra no repositório. Para isso, o CVS disponibiliza o comando cvs diff.
Este comando executa o utilitário diff em cada um dos fontes do projeto e mostra o resultado. Assim, podemos verificar todas as linhas que sofreram alteração. Para visualizar as alterações sofridas pelo arquivo progl.c, usamos:
cvs diff prog1.c
Atualizando fontes antigos
Quando o diretório de trabalho fica muito tempo sem sofrer atualizações, os fontes que ele contém podem não mais refletir o estado atual do repositório. Nestes casos, devemos executar o comando cvs update, que combina as atualizações sofridas pelos fontes que se encontram no repositório, com as que efetuamos no diretório local.
Aconselhamos que você se habitue, contudo, a somente realizar o checkout quando souber o que modificar, e só então realizar o commit e o release. Não mantenha versões antigas no seu diretório de trabalho. Elas podem ser uma fonte de inconsistências no projeto. Para realizar o update, utilizamos o comando cvs update.
O CVS atualizará os fontes do nosso diretório de trabalho para que estes reflitam as últimas alterações que nós e outros desenvolvedores impingimos ao projeto.
Gravando as alterações no repositório
Após todas as alterações terem sido feitas nos fontes do projeto, devemos sinalizar ao CVS que desejamos torná-las permanentes, através do comando cvs commit.
Este comando pesquisa todos os fontes do projeto e os compara com os que se encontram no repositório, verificando os arquivos que foram removidos, criados ou alterados, e faz com que essas alterações sejam refletidas no repositório, tornando-as permanentes.
Imediatamente antes da gravação, o CVS abrirá um editor de textos, para que possamos informar o que foi alterado. Esta é uma ótima forma de manter um histórico do projeto. Procure informar fatos relevantes sobre a nova versão, tais como mudanças nas interfaces das funções (quantidade ou tipos de parâmetros), no funcionamento dos programas, etc. Evite digitar informações que o CVS fornece de forma automática, como por exemplo, arquivos removidos ou criados, ou o usuário que realizou as alterações.
Liberando o diretório de trabalho
Em qualquer momento, durante o desenvolvimento ou após o commit, podemos liberar o diretório de trabalho, através do comando:
cd /home/user/src
cvs release -d teste_cvs
Este comando possui duas finalidades distintas:
~U Antes do commit, serve para descartar todas as alterações realizadas.
~U Depois do commit, serve para eliminar o diretório de trabalho, uma vez que este não deverá mais ser utilizado.
~U Repare que, para executarmos este comando, devemos estar no diretório imediatamente acima do diretório de trabalho. Esta é a função do comando cd acima.
O CVS listará as alterações que serão abandonadas (se houver) e perguntará se desejamos continuar. Caso confirmemos, o diretório de trabalho do projeto será removido.
Outros comandos
O CVS possui diversos outros comandos cuja descrição não caberia neste artigo. Verifique o box Para saber mais, onde listamos as principais fontes de informação sobre o produto. Existem, além disso, diversos tutoriais e ferramentas de auxílio, que tornam a manipulação dos fontes mais fácil. Visite a página oficial do CVS para maiores informações.
É natural do ser humano ser reticente às mudanças, ainda que estas comprovadamente nos promovam vantagens. Como a maioria dos desenvolvedores com anos de experiência, nos opusemos inicialmente a idéia. Hoje em dia, não conseguimos imaginar a criação de um simples shell ou de um documento sem o suporte que o CVS oferece.
Além disso, ele oferece uma flexibilidade antes inimaginável: em qualquer máquina devidamente configurada, temos acesso imediato aos fontes de um projeto. Ou seja, os fontes que antes se localizavam fisicamente em um só ponto, estão, agora, acessíveis logicamente em toda a rede, desde que a configuração e as permissões de acesso estejam de acordo.
Para saber mais:
CVS Homepage: www.cvshome.org
Blandy Jim - Introduction to CVS
Per Cederqvist - Version Management with CVS. (Considerado o manual oficial do CVS).
Karl Fogel - Open Source Development with CVS. The Coriolis Group; ISBN: 1576104907; 1st edition
Controle de Versão - Sem medo de aprimorar. Lisiane Sztoltz. Revista do Linux, Edição 25 - www.revistadolinux.com.br/ed/025/assinantes/documentacao.php3
Eduardo Aguiar - eduardo.oliveira@sondabrasil.com.br