blog do Zé

 
 

26 de December, 2008

Usando git em seu projeto PHP, Perl, Python ou Ruby

Filed under: Dicas para Webmasters, Programação — jfonseca @ 2:26 pm

Git é o sistema de controle de versão criado por Linus Torvalds para substituir o Bit Keeper no desenvolvimento do kernel Linux. Suas principais metas eram criar um gerenciador de versões rápido mesmo quando o projeto se tornasse grande, com facilidades para desenvolvimento distribuido incluindo proteção contra corrupção de dados e vandalismo, e utilizando a filosofia UNIX de só fazer o que lhe é dito e fazer bem feito(sem efeitos colaterais ou “burocracia” excessiva).

Na minha opinião o git obteve sucesso em todos os quesitos acima. É rápido, prático e quem usa UNIX(MacOS X, Linux, *BSD, Solaris, etc) no dia a dia não terá qualquer problema para utilizá-lo. Existe versão para Windows, porém é realmente recomendando migrar para um sistema UNIX para trabalhar com desenvolvimento.

Git no escritório

Você pode usá-lo para trabalhos em planilhas ou documentos do office, mantendo controle das alterações e quem as efetuou. Imagine um trabalho acadêmico controlado por git, você pode cometer erros à vontade e voltar atrás quando percebê-los. Ou trabalhar num grupo com pessoas do mundo todo e depois juntar todos os pedaços no documento central do trabalho.

Git até mesmo para o Congresso Nacional!

O Congresso Nacional poderia utilizar o git em toda a legislação Brasileira, assim saberíamos o que mudou nas leis com apenas um comando, quem mudou, e, se necessário, voltar a uma versão anterior quando a nova lei falhasse. Também teríamos controle contra vandalismo e alterações sorrateiras na Lei que possam passar desapercebidas pelos olhos dos demais Congressistas. Afinal, acadêmicos afirmam categoricamente, e oferecem provas, de que Nelson Jobim alterou nossa Constituição Federal às escondidas. Se tivesse controle de versão com git, saberíamos quem alterou o texto e exatamente quais alterações foram efetuadas. Que tal? É esperar muito de nossos deputados e senadores? Deixo aí como sugestão que utilizem git em todo o trabalho legislativo. E admito que essa idéia não é minha, alguns hackers no exterior já sugerem isso ao Congresso dos Estados Unidos.

Git para projetos web

Vamos tratar de um uso mais simples e realista: controle de versão de um projeto web.

Normalmente é complicado usar controle de versão com projetos web baseados em scripts interpretados como Ruby, Perl ou PHP. Isso acontece porque o programa executável é o próprio script, enquanto que linguagens compiladas exigem que seja gerado um diretório à parte para compilação. Portanto, em linguagens como Java ou C, a compilação ocorre longe do código fonte, e este nunca é alterado pela compilação.

Com scripts a história é diferente.

O próprio código-fonte é o produto final, e o produto final costuma estar sob uma árvore debaixo de um diretório como htdocs ou c:\inetpub, etc. Os testes acontecem em tempo real, normalmente editando um fonte PHP ou ruby e simplesmente recarregando a página no navegador. Se você tivesse que buscar a nova árvore de dentro do sistema de controle de versões toda vez que alterasse um script, isso acrescentaria muito tempo ao processo, seria praticamente impossível trabalhar. Em determinado projeto, tive que abandonar o CVS por esse motivo - apesar de útil e importante, o controle de versão se tornou um problema maior que a solução.

Neste post apresento uma solução que resolve o problema acima, usando git. Git torna esta solução possível pois utiliza apenas um diretório central de controle(chamado .git) e não polui a árvore onde ele opera com arquivos ou diretórios ocultos por toda parte.

Este workflow tem se mostrado eficiente e não tive qualquer problema até o momento em diversos sites em produção, todos com bom tráfego. Usando esta estratégia, o git se tornou a ferramenta mais poderosa que acrescentei a meu trabalho com web de muito tempo para cá.

Automatizando para evitar erros

Todo este processo é automatizável e, de fato, recomendo que alguns passos sejam scriptados ao invés de rodá-los à mão. Quando estamos cansados as chances de cometer erros de digitação aumentam e às vezes causam problemas difíceis de detectar, como digitar hdocs ao invés de htdocs e enviar a árvore toda a um diretório remoto que não existe(isso não gera erro, apenas estamos atualizando uma outra pasta e o htdocs permanece lá como o último commit). Neste tutorial eu incluo os comandos individuais apenas para fins didáticos, faça o máximo possível em scripts quando trabalhando num projeto em produção. Atenção especial deve ser dada ao caso de usar a opção –delete do rsync. Caso erre o nome do diretório local, o rsync apagará tudo no diretório remoto para deixá-lo igual ao local. É bom executar o rsync sem –delete uma primeira vez, testar tudo, e depois, em caso de sucesso, copiá-lo para um script com a opção –delete

Finalmente: Usando o Git em seu projeto WWW

Existem diversas maneiras de usar o git em seu projeto web. Você pode usar os comandos push e pull para enviar e receber, respectivamente, uma arvore git remota. Assim, é possível trabalhar a cópia local e enviar para um servidor remoto quando os testes passarem com sucesso. Há, inclusive, sugestões em alguns blogs para automatizar este processo através do crond, enviando sempre o último release de hora em hora, por exemplo. É uma solução válida para grandes sites com grandes equipes e workflow com releases frequentes, mas eu prefiro trabalhar de forma mais básica, principalmente por meus projetos terem, normalmente, apenas 1 ou 2 programadores. Trabalhar à mão cada release não significa muito tempo perdido no meu caso.

Portanto, substituo os recursos de push e pull com uma solução mais simples, que envolve outra ferramenta igualmente poderosa: o rsync. Como transporte seguro utilizo o ssh.

Vamos lá.

Para começar a trabalhar com git, é preciso tê-lo instalado em sua máquina. Eu não utilizo programas binários, portanto se desejar instalar via algum desses monstrinhos chamados “gerenciadores de pacotes”, ou “promotores de bagunça binária”, como RPM ou apt-get, vá em frente. Aqui explico apenas como usar pacotes como eu considero que devem ser usados: compilando do código fonte.

Passo 1 - Compilando o código fonte

1.1) Baixe a última versão do código fonte do git do endereço http://git.or.cz/
1.2) - No momento a última versão é v1.6.0.6 que você pode baixar clicando aqui. - Verifique a nova versão antes de baixar a 1.6.0.6
1.3) Execute

tar xjvf git-1.6.0.6.tar.bz2

para descompactar o tarball.
1.4) Acesse o diretório recém descompactado, neste caso com

cd git-1.6.0.6

1.5) Rode o “trio maravilha” do GNU

./configure --prefix=/usr
make
make install

E pronto. Se tudo correr bem, agora você tem o git instalado. Caso a compilação falhe, é sinal que você não costuma compilar pacotes do código fonte e talvez não tenha os cabeçalhos instalados. Nesse caso sugiro uma mudança de hábito, pesquise um pouco e passe a usar o fonte, é pra isso que ele existe. Repito: se você é desenvolvedor profissional, gerenciadores de pacotes são impróprios para uso, falham com frequência, geram mais problemas do que solucionam e todo desenvolvedor deve saber viver sem eles.

Os gerenciadores de pacotes existem apenas para usuários casuais instalarem software de uso caseiro. Profissionais trabalham com o código fonte quando ele está disponível.

Passo 2 - Inicializando o repositório git para seu projeto web

2.1) Vá até um diretório acima da raiz do site que deseja acompanhar com git, por exemplo:
Para um site em /usr/local/apache/htdocs/ digite

cd /usr/local/apache

2.2) Nesta pasta crie e edite um arquivo chamado .gitignore contendo todas as pastas que devem ser ignoradas como por exemplo imagens que não deseje monitorar, arquivos ou pastas temporárias ou de testes, etc. Você está abaixo do htdocs, então acrescente-o ao prefixo.
Exemplo de arquivo .gitignore :


htdocs/imagens
htdocs/forum/cache

Este arquivo diz ao git para ignorar o cache gerado pelo phpBB e para não monitorar o diretório de imagens do site.

2.3) Inicialize o repositório git nessa pasta. Lembre-se, é um diretório acima, não o faça DENTRO de htdocs.

git init

2.4) Adicione os seus documentos PHP, Ruby ou Perl ao indice git para inciar o controle.

git add .

Este comando adiciona recursivamente tudo sob o diretório atual, dentro do qual está o htdocs.
2.5) Agora você está pronto para seu primeiro commit! À partir do commit, seu projeto tem um ponto de referência à partir do qual o git inicia o processo de acompanhamento. Até o momento os dados de todos seus arquivos estão numa área temporária chamada “index”, e o git ainda não tem um ponto de referência no tempo. Vamos lá:

git commit -a

Agora o git abrirá seu editor de texto padrão e lhe pedirá que insira um resumo do que foi feito neste commit. Nesta tela é possível ver também um resumo do que está sendo cometido ao controle git para você não ter que lembrar tudo. A primeira linha normalmente aparece como o título da mudança em sites como GitHub ou no próprio cliente gráfico GTK gitk, então acostume-se a criar um resumo bem sucinto para a primeira linha e insira uma descrição mais elaborada em linhas abaixo. Quanto melhor documentado, melhor. Como é nosso primeiro commit, sejamos breves:

Commit inicial. Projeto agora rastreado pelo git.

Salve o arquivo. Você deve saber como trabalhar com o editor padrão de seu sistema, normalmente o vi.

Pronto! Agora você tem controle de versão de seu projeto web. Vamos usar este commit inicial como exemplo de uso do git.

Passo 3 - Trabalhando no projeto com git

Agora você entenderá porque deixamos o git um diretório acima do htdocs, e veremos como trabalhar com este arranjo sem acrescentar problemas demais ao projeto web ao usar controle de versão.

3.1) Edite um arquivo do projeto como teste. Neste caso vamos criar um arquivo meuteste.php não ligado ao resto do sistema para podermos cometer erros sem prejuízos ao site em produção. Em situação real, este seria um arquivo real do sistema.

vi meuteste.php
Contem:

funcao_inexistente();

Salve o arquivo (:wq) e saia do editor.

git add .  # para adicionar o novo arquivo ao index
git commit -a -m "Criei um arquivo de testes e inseri um erro proposital."
# Repare que acima ja inserimos a mensagem do commit com o parametro -m - assim fica mais rápido trabalhar quando o commit não exige muita explicação.

3.2) Agora enviaremos o projeto ao servidor de produção para testes. No seu workflow real é sempre bom utilizar um terceiro servidor para testes antes do lançamento final do sistema. Aqui, novamente, simplificamos as coisas enviando direto ao servidor de produção.

rsync -ave ssh /usr/local/apache/htdocs/ 1.2.3.4:/usr/local/apache/htdocs/

Perceba que o diretório de controle do git(.git) está acima do htdocs. Portanto ele não será enviado no procedimento com rsync.

Duas observações: a) a barra após htdocs/ é essencial para o rsync, tanto na pasta local quanto na remota. Para o rsync htdocs e htdocs/ significam 2 coisas distintas: a pasta htdocs e o conteúdo da pasta, respectivamente e b) caso deseje que o rsync trabalhe em silêncio, retire a opção ‘v’ de -ave.

3.3) Teste o script. Acesse seusite.com/meuteste.php e confira ao erro. Ops! Precisamos devolver o projeto ao estágio anterior quando não havia erro! É claro que, na vida real, este erro poderia ser muito mais sério, sendo preciso reverter dezenas de arquivos. O passo à seguir resolveria isso de forma simples.

3.4) Procure a última versão que funcionou utilizando o comando

git log

(Na pasta /usr/local/apache, ou a pasta equivalente em seu projeto acima de htdocs/)

O resultado será algo parecido a

commit 69534e728e54d98b17ff350bb233962f7505ac3c
Author: root
Date:   Fri Dec 26 13:50:15 2008 -0200

    Criei um arquivo de testes e inseri um erro proposital.

commit 9526238e43b5a767608ab4e24539d611e904ed91
Author: root
Date:   Sun Dec 14 19:28:56 2008 -0200

    Commit inicial. Projeto agora rastreado pelo git.

Repare alguns detalhes aqui: o nome do commit é um hash de 40 bytes gerado por uma função segura(SHA1). É claro que ninguém desejaria decorar tudo isso, portanto o git permite que os primeiros caracteres sejam usados. Desde que não tenha algum outro commit com os mesmos caracteres iniciais você pode se referir a ele usando apenas o início. Aqui por exemplo temos o commit inicial chamado 9526238e43b5a767608ab4e24539d611e904ed91 e o commit do nosso erro proposital chamado 69534e728e54d98b17ff350bb233962f7505ac3c. Os dois commit’s iniciam com números distintos, portanto podemos apenas chamá-los de 9526 e 6953 respectivamente. Em projetos maiores haverão prefixos parecidos, então é boa prática usar 6 ou 8 caracteres, ou quantos forem necessários para referir-se a um commit sem ambiguidade.

Percebemos que a revisão que funcionava era aquela do commit chamado 9526238e43b5a767608ab4e24539d611e904ed91 efetuado no dia 14 de Dezembro. Doze dias depois, dia 26, efetuamos novo commit causando problemas no sistema. Este commit ocorreu às 13:50 horas. Quem cometeu o erro foi ninguém menos que o root. É bom chamar root para uma conversa e discutir o problema no sistema.

Observações: neste caso trabalhar como root foi apenas um experimento. Nunca é recomendado trabalhar como root. Também não é bom passar tanto tempo sem efetuar commit’s intermediários, pois no caso de precisar voltar atrás perderia-se muito trabalho em outros arquivos que talvez não tenham problemas. A quantidade de commits e peridiocidade dos mesmos depende apenas do desenvolvedor, mas é bom considerar efetuar diversos commits por sessão visando um histórico mais “granular” do projeto.


Nota sobre tags e releases no git

Quando uma versão estiver estável e contenha as funções desejadas, crie uma ‘tag’ para marcar esse estado do sistema no tempo. No kernel do Linux, por exemplo, os tags são os números de releases. O atual tag é 2.6.27. Aprenda mais sobre tags no site do git. Também é possível baixar projetos completos git, como o kernel Linux, e ver toda a história desse projeto e a forma de trabalho dos desenvolvedores desse projeto dentro do git, em especial usando um cliente gráfico como gitk. É a maravilha do Software Livre, aproveite!

3.5) Bem, vamos ver o que foi que root fez que causou problemas no sistema:

git diff 9526238e4

O resultado é um diff entre a versão atual e aquela em 9526238e4… É preciso entender um pouco do idioma do diff e patch, mas deixo esse exercício para o leitor. Enfim, sabendo ler a saída de diff é possível ver o que foi modificado e qual exatamente foi o erro.

3.6) Agora que sabemos o que deu errado, e determinamos que devemos mesmo voltar atrás, execute

git revert 9526238e4

E pronto! O arquivo meuteste.php desaparecerá do sistema, e tudo estará exatamente como voce congelou em 14 de Dezembro.

3.7) Agora é preciso enviar o sistema novamente ao servidor, repetindo o passo 3.2.

Aqui você perceberá um outro problema: o rsync não apaga arquivos remotos à não ser que comandado para isso. O motivo é claro: evitar apagamentos acidentais. Neste caso nos convém dizer ao rsync quais diretórios ignorar e mandá-lo apagar os arquivos que tenham sido apagados na arvore local com o comando:

rsync -ave ssh --delete --exclude 'imagens/*' --exclude 'forum/cache/*' /usr/local/apache/htdocs/ 1.2.3.4:/usr/local/apache/htdocs/

A opção –delete removerá os arquivos remotos não existentes localmente e os parâmetros –exclude impedirão que arquivos nesses diretórios sejam considerados remotamente.

Aviso: muito cuidado com a opção –delete do rsync! Não me responsabilizo pelos imensos prejuízos que voce pode causar se errar a pasta local e excluir tudo no site remoto. Lembre-se: se a pasta local estiver vazia, você apagará tudo no site remoto.

O git tem uma quantidade enorme de comandos. Neste post vimos apenas alguns deles pois usamos apenas seus recursos mais básicos. Entre outros que você talvez queira se aprofundar estão tags para marcar versões e releases(tags são como momentos congelados no tempo que refletem algo importante, como um release ou uma modificação importante).

Espero que este artigo lhe tenha sido útil. Acredito que o git é a ferramenta de controle de versão mais prática e veloz na atualidade. Vale a pena você pesquisar um pouco mais e ler a extensa documentação do git no site git.or.cz.

• • •
 

23 de October, 2008

A linguagem Python subiu no telhado

Filed under: Programação — jfonseca @ 12:01 pm

Logotipo da linguagem PythonA linguagem Python subiu no telhado. Antes que me acusem de parcialidade, contra Python, deixem que eu faça isso por vocês: eu não gosto de Python.

Mesmo assim, tentarei ser imparcial nesta crítica.

Dia 15 deste mês o criador da linguagem Python, Guido Van Rossum, divulgou a versão 3.0 da mesma. A principal diferença? Python 3.0 não rodará programas escritos em Python. Dá pra acreditar?

Traduzindo: Van Rossum basicamente criou uma nova linguagem cujo nome é Python 3.0.

O raciocínio por trás dessa decisão é desprovido de lógica : segundo Van Rossum, “haviam formas demais de resolver o mesmo problema, e muitas formas de não resolver problema algum”.

Parece delírio, visto que o sonho de todo designer de linguagens é que ela seja flexível o suficiente para oferecer mais de uma forma de resolver um problema. Perdoem o vício aqui, TMTOWTDI “There’s More Than One Way To Do It” é um dos lemas da linguagem Perl.

Afinal, nas linguagens humanas existem praticamente infinitas formas de se dizer algo. Às vezes, dado o contexto, nem é preciso falar a frase toda.

Por esse, e outros motivos(como espaços em branco como delimitadores sintáticos) afirmo: Python subiu no telhado. Se preferirem, não acreditem neste programador Perl. A própria comunidade Python já começa a pular fora:

“Python is pretty much determined to remove itself from consideration from various kinds of international projects like the one I work on. We’re already catching flak from people due to a few things that were valid in 2.2 that are not valid in 2.3,” bemoaned one developer in the comp.lang.python newsgroup.

Leia mais(link em inglês).

• • •