De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.

Unindo o subversion e o doxygen para um controle de configuração e uma boa documentação

Colaboração: Francisco José Alonso Ares

Data de Publicação: 07 de August de 2008

O subversion tem uma opção que permite a execução de qualquer programa em algumas etapas de seu trabalho de versionamento. São chamados "hooks", tem nomes padronizados para cada função disponível e devem ser instalados no diretório de mesmo nome dentro do repositório usado, ou seja:

  /caminho/para/seu/repositório/hooks

Apesar de seu poder, o subversion sozinho não faz o gerenciamento de configuração de um software, apenas o gerenciamento de versão - que já não é pouca coisa!

Para manter registro não apenas das versões de um software mas também das versões de suas dependências que estejam no mesmo repositório e ainda gerando automaticamente a documentação para cada nova versão atualizada, peguei umas idéias no manual do próprio subversion e do doxygen e bolei os scripts abaixo.

O primeiro é só um "wrapper" para o segundo, que pode ser colocado em outro diretório.

Este segundo script cria um diretório temporário no próprio servidor em que o seu repositório está rodando e faz um "checkout" do projeto que acabou de ter sua versão atualizada.

Como opção, ele verifica se existe um arquivo "geradoc*" (pode ser "geradoc.c", "geradoc.txt", qualquer coisa, até com comprimento nulo, basta ter a entrada); caso não exista, ele não faz mais nada, apenas limpa esse diretório temporário.

Caso o "geradoc*" exista, ele faz uma varredura nos arquivos *.c, *.h, *.cpp e *.hpp (outros podem ser adicionados livremente) em busca da diretiva "#include" que contenha uma referência a algum arquivo que esteja no formato abaixo:

  #include "../projeto/arquivo"

onde o "projeto" deve estar sob versionamento do subversion.

Após a extração dessas informações, ele gera um arquivo "depend.c" com umas poucas linhas que serão aproveitadas pelo doxygen. Estas linhas contém o número de versão de cada linha "#include" encontrada que aponte para um projeto externo ao projeto atual.

A seguir, ele remove qualquer prévia existência de um arquivo de configuração do doxygen e o substitui por um padrão, editando apenas o nome do projeto para que o documento final receba o nome do projeto de forma adequada.

O segmento seguinte executa o doxygen, move a documentação em HTML para um diretório onde um apache está rodando, também faz as mesmas tarefas que o "make pdf" faria, ou seja, finaliza a geração da documentação em PDF, que é uma das configurações usadas neste arquivo de configuração padrão do doxygen, copia este PDF para um diretório determinado e o envia por e-mail para o usuário que fez a atualização da versão. Só faltou encriptar via GPG, mas isto fica para outra oportunidade ;)

De quebra, ainda tem mais dois scripts: um encontra a versão do arquivo sendo documentado pelo doxygen dentro do repositório para que esta apareça na documentação gerada e outro que faz este mesmo arquivo passar pelo "astyle" antes de ser documentado, portanto garantindo uma formatação padronizada.

Seguem os arquivos:

arquivo post-commit

  #!/bin/bash
  
  /bin/echo _ _ _ _ `/bin/date` $1 $2 >> /var/log/svn/commit.log
  
  r=`/usr/bin/svnlook dirs-changed /desenv/svnroot | /bin/sed -n 2p`
  
  if [ "a" == "a"$r ]
  then
         r=`/usr/bin/svnlook dirs-changed /desenv/svnroot | /bin/sed -n 1p`
  fi
  
  /caminho/para/o/segundo/script/postco $r $2 &
  
  exit 0

arquivo postco

  #!/bin/bash
  
  # evita que traduções afetem comandos de "strings" como o sed , o cut e o grep
  export LC_ALL="C"
  
  R="$1"
  #REV="$2"
  
  
  u=`/usr/bin/svn info file:///caminho/do/repositório/$R | /bin/grep Author | /bin/cut -d" " -f4`
  n=`/bin/cat /etc/postfix/aliases | /bin/grep $u | /bin/cut -f2`
  g=`/bin/cat /etc/hosts | grep $u | cut -d" " -f1`
  f="refman.pdf"
  t=`/bin/echo $R | /bin/cut -d"/" -f2`
  
  #cd /tmp/
  #if [ -s post_commit ]
  #then
  #   /bin/rm -fR post_commit
  #fi
  
  d=`/bin/tempfile -d /tmp/ -p postcommit`
  /bin/rm -f $d
  /bin/mkdir $d
  cd $d
  
  /bin/echo = = = = `/bin/date` $R $u $n $g $t $d>> /var/log/svn/commit.log
  
  /usr/bin/svn co file:///caminho/do/repositório/$R ./ > /dev/null
  
  if [ -f geradoc* ]
  then
  
  #código de verificação e documentação de dependências
  
     LC_ALL="C"
     touch depend.c
     echo "/*! " > depend.c
     echo " * \\file depend.c " >> depend.c
     echo " * \\author "$u >> depend.c
     echo " * \\brief Lista de dependências para controle de configuração." >> depend.c
     echo " *" >> depend.c
  
     for h in "*.c" "*.h" "*.cpp" "*.hpp"
     do
         for i in $h
         do
             if [ "$h" != "$i" ]
             then
                 m=`/bin/tempfile -d /tmp/ -p postcommit`
                 fgrep "#include \"" $i | grep [\/\\] | sed s#\\\\#\/#g > $m
                 a=`cat $m`
                 rm -f $m
                 if [ "$a" != "" ]
                 then
                     for j in $a
                     do
                         if [ "$j" != "#include" ]
                         then
                             d=`echo $j | cut -d "\"" -f2`
                             b=`basename $d`
                             d=`echo $d | sed s/$b//`
                             l=`echo $d | cut -d "/" -f2`
                             k=`svn info file:///caminho/do/repositório/trunk/$l 2>/dev/null | grep "Changed Rev:" | cut -d " " -f4`
                             if [ "$k" != "" ]
                             then
                                 echo " * \""$i"\"" depende do projeto "\""`echo $j | cut -d "/" -f2`"\", que está na versão " $k >> depend.c
                             else
                                 echo " * \""$i"\"" depende do projeto "\""`echo $j | cut -d "/" -f2`"\", <b>que não está no repositório! </b>" >> depend.c
                             fi
                             echo " *" >> depend.c
                         fi
                     done
                 fi
             fi
         done
     done
     echo -e " */\n">> depend.c
  
  #fim do código de verificação e documentação de dependências
  
     if [ -f Doxyfile ]
     then
         /bin/rm -f Doxyfile
     fi
  
     /bin/cat /caminho/do/arquivo/padrão/Doxyfile.post_commit | /bin/sed -e s/ProjectName/$t/ -e "s%/post_commit_dir/%"`/bin/pwd`/"%" > ./Doxyfile
  
     /usr/bin/doxygen > /dev/null 2> /dev/null
  
     cd doc
     if [ -d html ]
     then
         if [ -d /var/www/localhost/htdocs/docs/$t ]
         then
         /bin/rm -fR /var/www/localhost/htdocs/docs/$t
         fi
  
             /bin/mkdir /var/www/localhost/htdocs/docs/$t
  
         cd html
         /bin/mv * /var/www/localhost/htdocs/docs/$t/
         cd ..
     fi
  
     cd latex
  
     /usr/bin/pdflatex refman.tex > /dev/null 2> /dev/null
     /usr/bin/makeindex refman.idx > /dev/null 2> /dev/null
     /usr/bin/pdflatex refman.tex > /dev/null 2> /dev/null
  
     latex_count=5
  
     E=0
  
     while [ $E == 0 ]
     do
         /usr/bin/pdflatex refman.tex > /dev/null 2> /dev/null
         /bin/egrep -s 'Rerun (LaTeX|to get cross-references right)' refman.log
         E=$?
         if [ $E == 0 ]
         then
             latex_count=`expr $$latex_count - 1`
             if [ $latex_count == 0 ]
             then
                 E=1
             fi
         fi
     done
  
     /bin/cp refman.pdf ../..
     /bin/mv refman.pdf /caminho/da/pasta/de/documentação/"$t"_"$2"_refman.pdf
  
     cd ../..
  
     /usr/sbin/sendmail -f admin@srv.com.br -r admin@srv.com.br $n << EOF
  Bcc: Administrador <admin@srv.com.br>
  Subject: Projeto $1 na v$2 .
  From: "root @ desenv" <admin@srv.com.br>
  To: $u <$n>
  Reply-to: "root @ serv" <admin@srv.com.br>
  X-Mailer: postfix in $HOSTNAME
  
  Seu projeto $1 foi efetivado no repositorio na v$2 .
  
  Os documentos podem ser encontrados em:
  
  http://desenv/docs/$t
  
  O PDF se encontra na pasta "caminho da pasta de documentação" deste servidor e anexo a esta mensagem.
  
  
  --
  servidor "desenv"
  
  `uuencode $f $f`
  
  EOF
  
     cd ..
  fi
  
  /bin/rm -fR $d

arquivo Doxyfile.post_commit

  PROJECT_NAME           = ProjectName
  PROJECT_NUMBER         =
  OUTPUT_DIRECTORY       = ./doc
  CREATE_SUBDIRS         = NO
  OUTPUT_LANGUAGE        = Brazilian
  USE_WINDOWS_ENCODING   = YES
  BRIEF_MEMBER_DESC      = YES
  REPEAT_BRIEF           = YES
  ABBREVIATE_BRIEF       =
  ALWAYS_DETAILED_SEC    = YES
  INLINE_INHERITED_MEMB  = YES
  FULL_PATH_NAMES        = YES
  STRIP_FROM_PATH        = /post_commit_dir/
  STRIP_FROM_INC_PATH    =
  SHORT_NAMES            = NO
  JAVADOC_AUTOBRIEF      = NO
  MULTILINE_CPP_IS_BRIEF = NO
  DETAILS_AT_TOP         = YES
  INHERIT_DOCS           = YES
  DISTRIBUTE_GROUP_DOC   = NO
  SEPARATE_MEMBER_PAGES  = NO
  TAB_SIZE               = 4
  ALIASES                =
  OPTIMIZE_OUTPUT_FOR_C  = NO
  OPTIMIZE_OUTPUT_JAVA   = NO
  SUBGROUPING            = YES
  EXTRACT_ALL            = YES
  EXTRACT_PRIVATE        = YES
  EXTRACT_STATIC         = YES
  EXTRACT_LOCAL_CLASSES  = YES
  EXTRACT_LOCAL_METHODS  = YES
  HIDE_UNDOC_MEMBERS     = NO
  HIDE_UNDOC_CLASSES     = NO
  HIDE_FRIEND_COMPOUNDS  = NO
  HIDE_IN_BODY_DOCS      = NO
  INTERNAL_DOCS          = YES
  CASE_SENSE_NAMES       = YES
  HIDE_SCOPE_NAMES       = NO
  SHOW_INCLUDE_FILES     = YES
  INLINE_INFO            = YES
  SORT_MEMBER_DOCS       = YES
  SORT_BRIEF_DOCS        = YES
  SORT_BY_SCOPE_NAME     = YES
  GENERATE_TODOLIST      = YES
  GENERATE_TESTLIST      = YES
  GENERATE_BUGLIST       = YES
  GENERATE_DEPRECATEDLIST= YES
  ENABLED_SECTIONS       =
  MAX_INITIALIZER_LINES  = 30
  SHOW_USED_FILES        = YES
  SHOW_DIRECTORIES       = YES
  FILE_VERSION_FILTER    = "/caminho/auxiliares/versionfilter.sh"
  QUIET                  = YES
  WARNINGS               = YES
  WARN_IF_UNDOCUMENTED   = YES
  WARN_IF_DOC_ERROR      = YES
  WARN_NO_PARAMDOC       = YES
  WARN_FORMAT            = "$file:$line: $text"
  WARN_LOGFILE           =
  INPUT                  =
  FILE_PATTERNS          = *.c \
  RECURSIVE              = YES
  EXCLUDE                = .* */teste/*
  EXCLUDE_SYMLINKS       = NO
  EXCLUDE_PATTERNS       =
  EXAMPLE_PATH           =
  EXAMPLE_PATTERNS       =
  EXAMPLE_RECURSIVE      = NO
  IMAGE_PATH             =
  INPUT_FILTER           =
  FILTER_PATTERNS        = *.c="/caminho/auxiliares/beautyfier.sh"        \
                          *.h="/caminho/auxiliares/beautyfier.sh"        \
                          *.cpp="/caminho/auxiliares/beautyfier.sh"      \
                          *.hpp="/caminho/auxiliares/beautyfier.sh"      \
                          *.c++="/caminho/auxiliares/beautyfier.sh"      \
                          *.h++="/caminho/auxiliares/beautyfier.sh"
  FILTER_SOURCE_FILES    = NO
  SOURCE_BROWSER         = YES
  INLINE_SOURCES         = YES
  STRIP_CODE_COMMENTS    = YES
  REFERENCED_BY_RELATION = YES
  REFERENCES_RELATION    = YES
  VERBATIM_HEADERS       = YES
  ALPHABETICAL_INDEX     = YES
  COLS_IN_ALPHA_INDEX    = 5
  IGNORE_PREFIX          =
  GENERATE_HTML          = YES
  HTML_OUTPUT            = html
  HTML_FILE_EXTENSION    = .html
  HTML_HEADER            =
  HTML_FOOTER            =
  HTML_STYLESHEET        =
  HTML_ALIGN_MEMBERS     = YES
  GENERATE_HTMLHELP      = NO
  CHM_FILE               =
  HHC_LOCATION           =
  GENERATE_CHI           = NO
  BINARY_TOC             = NO
  TOC_EXPAND             = NO
  DISABLE_INDEX          = NO
  ENUM_VALUES_PER_LINE   = 4
  GENERATE_TREEVIEW      = YES
  TREEVIEW_WIDTH         = 250
  GENERATE_LATEX         = YES
  LATEX_OUTPUT           = latex
  LATEX_CMD_NAME         = latex
  MAKEINDEX_CMD_NAME     = makeindex
  COMPACT_LATEX          = YES
  PAPER_TYPE             = a4wide
  EXTRA_PACKAGES         =
  LATEX_HEADER           =
  PDF_HYPERLINKS         = YES
  USE_PDFLATEX           = YES
  LATEX_BATCHMODE        = YES
  LATEX_HIDE_INDICES     = NO
  GENERATE_RTF           = NO
  RTF_OUTPUT             =
  COMPACT_RTF            = YES
  RTF_HYPERLINKS         = YES
  RTF_STYLESHEET_FILE    =
  RTF_EXTENSIONS_FILE    =
  GENERATE_MAN           = NO
  MAN_OUTPUT             = man
  MAN_EXTENSION          = .3
  MAN_LINKS              = NO
  GENERATE_XML           = NO
  XML_OUTPUT             = xml
  XML_SCHEMA             =
  XML_DTD                =
  XML_PROGRAMLISTING     = YES
  GENERATE_AUTOGEN_DEF   = NO
  GENERATE_PERLMOD       = NO
  PERLMOD_LATEX          = NO
  PERLMOD_PRETTY         = YES
  PERLMOD_MAKEVAR_PREFIX =
  ENABLE_PREPROCESSING   = YES
  MACRO_EXPANSION        = YES
  EXPAND_ONLY_PREDEF     = NO
  SEARCH_INCLUDES        = YES
  INCLUDE_PATH           =
  INCLUDE_FILE_PATTERNS  =
  PREDEFINED             =
  EXPAND_AS_DEFINED      =
  SKIP_FUNCTION_MACROS   = YES
  TAGFILES               =
  GENERATE_TAGFILE       =
  ALLEXTERNALS           = NO
  EXTERNAL_GROUPS        = YES
  PERL_PATH              = /usr/bin/perl
  CLASS_DIAGRAMS         = YES
  HIDE_UNDOC_RELATIONS   = YES
  HAVE_DOT               = YES
  CLASS_GRAPH            = YES
  COLLABORATION_GRAPH    = YES
  GROUP_GRAPHS           = YES
  UML_LOOK               = YES
  TEMPLATE_RELATIONS     = YES
  INCLUDE_GRAPH          = YES
  INCLUDED_BY_GRAPH      = YES
  CALL_GRAPH             = YES
  GRAPHICAL_HIERARCHY    = YES
  DIRECTORY_GRAPH        = YES
  DOT_IMAGE_FORMAT       = png
  DOT_PATH               =
  DOTFILE_DIRS           =
  MAX_DOT_GRAPH_WIDTH    = 1024
  MAX_DOT_GRAPH_HEIGHT   = 1024
  MAX_DOT_GRAPH_DEPTH    = 0
  DOT_TRANSPARENT        = NO
  DOT_MULTI_TARGETS      = YES
  GENERATE_LEGEND        = YES
  DOT_CLEANUP            = YES
  SEARCHENGINE           = YES

arquivo versionfilter.sh

  #!/bin/sh
  PTH=`pwd`
  if [ -d CVS ] ; then
         cvs status `echo $1 | sed s%$PTH\/%%` | sed -n 's/^[ \]*Working revision:[ \t]*\([0-9][0-9\.]*\).*/\1/p'
  elif [ -d .svn ] ; then
         svn stat -v `echo $1 | sed s%$PTH\/%%` | sed -n 's/^[ A-Z?\*|!]\{1,15\}/r/;s/ \{1,15\}/\/r/;s/ .*//p'
         #F=`echo $1 | sed s%$PTH\/%%`
         #E=`svn stat -v $F | sed -n 's/^[ A-Z?\*|!]\{1,15\}/r/;s/ \{1,15\}/\/r/;s/ .*//p'`
  fi

arquivo beautyfier.sh

  #!/bin/sh
  /usr/bin/astyle --break-blocks --min-conditional-indent=0 --style=linux -CSKNPT4 $1
  rm $1.orig
  cat $1

Agora chega ;)

Adicionar comentário

* Campos obrigatórios
5000
Powered by Commentics

Comentários

Nenhum comentário ainda. Seja o primeiro!


Veja a relação completa dos artigos de Francisco José Alonso Ares