Desenvolvimento

23 abr, 2010

Customizando o Subversion

Publicidade

O Subversion é um dos
mais conhecidos sistemas de controle de versão do mercado. É uma solução
open source que pode ser utilizada de forma viável no ambiente
corporativo. O seu maior problema é quanto à administração, porque as boas ferramentas de administração são pagas, não usando essas
ferramentas você tem que administrá-lo via linha de comando. Mas isso
não é o fim do mundo.

Eu sinto fala de processamento da working
copy do SVN, o Clear Case
de Rational/IBM já tem essa feature de maneira bem inteligente e
eficiente, quem sabe nas próximas versões eles colocam.

Existem
diversos clientes visuais para o Subversion, o melhor deles, que é o Tortoise, não existe para Linux, somente para Windos. O que é uma pena, pois esse é o melhor
client, e no Linux não existe nenhum que seja bom perto do Tortoise.

O
Tortoise é o nosso primeiro ponto de customização – você pode adicionar
scripts customizados que realizam determinados processamentos no
Tortoise, mas isso não é aconselhado porque o script teria que ser
configurado máquina a máquina de quem usa o Tortoise.

Qual o melhor
ponto de customização de Scripts?

Do lado do servidor, porque lá você coloca no repositório e pronto, todos os clientes estariam
usando esse script, que pode ser escrito em diversas linguagens,
como por exemplo Java, Bash, Python e outras.

Podemos manipular a
API do Subversion através dessas e outras linguagens que eu mencionei;
essa API é conhecida como Binding. Você só precisa achar um binding do
Subversion para a sua linguagem preferida.

Para criar scripts
para o SVN, acho que Python é uma
boa solução. Mas antes de falarmos dos scripts, vamos ver
como o SVN armazena esses scripts e que pontos de customização existem à
nossa disposição.

Nota:
Um binding para Python é o Pysvn.
Porém, é recomendado apenas para Windos, ele não funciona bem no Linux; para isso você deve usar os bindings dos próprios svn na sua
compilação.

Criando um
repositório

Para criar um repositório no SVN, basta usar o
comando abaixo.

svnadmin create nomeDoNovoRepositorio  

A localização dos Scripts (hooks)

Para
o Subversion, esses scripts são conhecidos como hooks, se você olha para
um repositório do Subversion 1.5.x, por exemplo, pode notar esta
estrutura de pastas:

  • conf:
    Configurações do repositório.
  • db: Banco de dados do SVN.
  • hooks: Onde você coloca os seus scripts.
  • locks: Controle interno de locks do
    SVN.
  • format: Layout
    do repositório.

OK. Mas para
que eu criaria um Script?

Por vários motivos. Que variam
muito, dependendo da sua utilização do Subverion. Veja alguns exemplos:

  • Controle de commits
  • Notificação
    de commits
  • Notificação de arquivos removidos/tagueados/mergiados
  • Realização
    de estatísticas
  • Controle de permissões de acesso a arquivos
  • Backup

Entre
tantas outras aplicações. No primeiro exemplo, que seria o controle de
comits, seria um script muito simples e muito útil. Por que? Porque o
svn, por default, deixa comentários em branco e pode ser que você não
deseje isso.

Comentários em
Branco

Essa, de fato, é uma péssima prática de gerência de
configurações. Porque na hora de fazer um merge ou mover arquivos não
se sabe o que aconteceu no arquivo, claro que você pode usar o
histórico. Mas o comentários facilitam horrores. Então você pode criar
um script para não deixar passar comentários em branco.

Pontos de customização

Traçando um paralelo com banco de dados, esses scripts hooks seriam como
triggers. Então, vamos aos hooks e quando eles são disparados.

  • start-commit
  • pre-commit
  • post-commit
  • pre-lock
  • post-lock
  • pre-unlock
  • post-unlock
  • pre-rev-prop-change
  • post-rev-prop-change

Acho
que os hooks dispensam explicações mas, basicamente, aqui temos três tipos de hooks: os de antes, os de depois e os do início. E temos
três operações distintas, que seriam o commit, o lock e as mudanças de
propriedades. Para cada uma, temos esses tipos, mas com nomes diferentes.

Agora, veremos como ficariam esses scripts com o Python. Veremos como é possível modificar o comportamento do Subversion através de um Scrip Python, de forma que não deixe o usuário
realizar um commit sem um comentário.

A importância dos comentários nos commits

Além de
uma ótima prática de gerência de configurações, utilizar comentários no
commit do svn nos ajuda na hora de realizar merges, para acompanhar mudanças e também quando você está procurando um versão
antiga de um artefato.

Você vai precisar de um Binding

A API do Subversion para alguma
linguagem como Java, Python, PHP etc é chamada de Binding. Então
precisamos de um binding para Python. Vamos utilizar o binding do
próprio site do subversion, chamado de pysvn.

Você precisa instalar o Python e o Subversion, bem como o pysvn. Uma vez tudo isso instalado, vamos ao script.

Esse
script é construído utilizando os recursos de expressões regulares do
Python. Sinta-se à  vontade para modificá-lo de acordo com as suas
necessidades.

Vamos utilizar o hook de pre-commit, logo, se esse
script retornar 1, o svn não irá fazer o commit; nesse caso é justamente o
que queremos, pois não queremos commitar sem comentários.

#
# pre-commit.py
#
# @Autor Diego Pacheco
# @since 26/04/2009
# @Version 1.0
#
# Codigo Python que utiliza o pysvn para manipular o controle de versão afim de
# nao deixar passar commit sem comentários apropriados. Sinta-se a vontade para modifica-lo.
#

import os
import os.path
import sys
from datetime import date
import re

import svn
import svn.fs
import svn.repos
import svn.core

#
# Método que loga as exception em arquivo de log de erros.
# @Parameter e eh a exception que foi levantada
#
def _handleException(e):
try:
f = open('C:/log.pysvn..commits.txt', 'w+')
now = date.today()
dataFormated = now.strftime("%m-%d-%Y")
f.write("[" + dataFormated + "] " + str(e))
f.close()
_trace(str(e),"FATAL")
except:
print sys.exc_info()

#
# Método que valida se a mensagem de commit eh apropriada.
#
# @Parameter commitMessage eh a mensagem do commit
# @Return 0 para mensagem OK. 1 Para mensagem impróprias
#
def _validateCommitComment(commitMessage=None):
mat = None
if commitMessage:
try:
mat = re.search('[\w]{5}[_0-9]?', commitMessage)
print str(mat.group(0))
except AttributeError:
_handleException("Você não digitou um comentário valido. Digite um comentário apropriado!")
return 1
else:
_handleException("Você não pode commitar um arquivo em branco. Digite um comentário apropriado!")
return 1

#
# Metodo Main
#
def main(argv):
try:
txn_name = None
repos_path = None
log_message = None
txn = None
fs = None

# Obtem a messagem de commit que o usuario digitou
repos_path = svn.core.svn_path_canonicalize(argv[1])
fs = svn.repos.svn_repos_fs(svn.repos.svn_repos_open(repos_path))
txn_name = argv[2]
txn = svn.fs.svn_fs_open_txn(fs, txn_name)
log_message = svn.fs.svn_fs_txn_prop(txn, "svn:log")

return _validateCommitComment(log_message)

except:
_handleException(sys.exc_info())
return 1

#
# Execucao do metodo Main.
#
if __name__ == '__main__':
sys.exit(main(sys.argv))

Se você for usar esse script hook no Windows, precisa criar um script .bat para chamar o seu script python; isso é
necessário porque o svn do Windows só executa hooks com as extensões
bat e exe.

Você precisa colocar esse script na pasta hooks do
repositório do seu SVN.

Espero que tenham gostado. Abraços.