[1174] | 1 | #!/usr/bin/python |
---|
| 2 | # -*- coding: utf-8 -*- |
---|
| 3 | |
---|
| 4 | import os, popen2, fcntl, select, sys, os, pysvn, time |
---|
| 5 | # Prerequisitos: cliente do subversion instalado, e pysvn mais o python-dialog instalado no python. |
---|
| 6 | from dialog import * |
---|
| 7 | |
---|
| 8 | #Função para solicitar ao usuario o tipo de distribuicao |
---|
| 9 | def mostra(d,escolhas): |
---|
| 10 | return d.menu("Selecione o tipo de distrbuicao desejada:",height=0,choices=escolhas) |
---|
| 11 | |
---|
| 12 | def msg_box_info(d,msg): |
---|
| 13 | d.infobox(msg,height=19,width=60) |
---|
| 14 | time.sleep(2) |
---|
| 15 | return |
---|
| 16 | |
---|
| 17 | def msg_box_sim_nao(d,msg): |
---|
| 18 | return d.yesno(msg,height=18,width=80) |
---|
| 19 | |
---|
| 20 | |
---|
| 21 | #As duas funcoes, a seguir, executam comandos e retornam resultado. |
---|
| 22 | def makeNonBlocking(fd): |
---|
| 23 | fl = fcntl.fcntl(fd, fcntl.F_GETFL) |
---|
| 24 | try: |
---|
| 25 | fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NDELAY) |
---|
| 26 | except AttributeError: |
---|
| 27 | fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.FNDELAY) |
---|
| 28 | |
---|
| 29 | def getCommandOutput(command): |
---|
| 30 | f=sys.stdout |
---|
| 31 | child = popen2.Popen3(command, 1) # Captura stdout e stderr do comando |
---|
| 32 | child.tochild.close( ) # nao necessitamos escrever para a stdin do processo iniciado pelo comando |
---|
| 33 | outfile = child.fromchild |
---|
| 34 | outfd = outfile.fileno( ) |
---|
| 35 | errfile = child.childerr |
---|
| 36 | errfd = errfile.fileno( ) |
---|
| 37 | makeNonBlocking(outfd) # Evitamos deadlocks tornando fd's nonblock. |
---|
| 38 | makeNonBlocking(errfd) |
---|
| 39 | outdata, errdata = [ ], [ ] |
---|
| 40 | outeof = erreof = False |
---|
| 41 | while True: |
---|
| 42 | f.write('.') |
---|
| 43 | f.flush() |
---|
| 44 | to_check = [outfd]*(not outeof) + [errfd]*(not erreof) |
---|
| 45 | ready = select.select(to_check, [ ], [ ]) # Espera por dados... |
---|
| 46 | if outfd in ready[0]: |
---|
| 47 | outchunk = outfile.read( ) |
---|
| 48 | if outchunk == '': |
---|
| 49 | outeof = True |
---|
| 50 | else: |
---|
| 51 | outdata.append(outchunk) |
---|
| 52 | if errfd in ready[0]: |
---|
| 53 | errchunk = errfile.read( ) |
---|
| 54 | if errchunk == '': |
---|
| 55 | erreof = True |
---|
| 56 | else: |
---|
| 57 | errdata.append(errchunk) |
---|
| 58 | if outeof and erreof: |
---|
| 59 | break |
---|
| 60 | select.select([ ],[ ],[ ],.1) # Seta um intervalo de tempo bem curto para os buffers serem preenchidos. |
---|
| 61 | err = child.wait( ) |
---|
| 62 | if err != 0: |
---|
| 63 | raise RuntimeError, '%r falhou com codigo %d\n%s' % ( |
---|
| 64 | command, err, ''.join(errdata)) |
---|
| 65 | return ''.join(outdata) |
---|
| 66 | |
---|
| 67 | |
---|
| 68 | #Callback para login no svn |
---|
| 69 | def Login_no_svn( realm, username, may_save ): |
---|
| 70 | from getpass import getpass |
---|
| 71 | global flag |
---|
| 72 | print 'Por favor, identifique-se' |
---|
| 73 | usuario = raw_input('Usuario:').strip() |
---|
| 74 | senha = getpass('Senha:').strip() |
---|
| 75 | if not flag: |
---|
| 76 | flag = True |
---|
| 77 | else: |
---|
| 78 | flag = False |
---|
| 79 | print 'Falhou acesso ao Subversion...\n' |
---|
| 80 | sys.exit(92) |
---|
| 81 | return True, usuario, senha, True |
---|
| 82 | |
---|
| 83 | #Rotina para recuperar dados do svn sobre as revisoes e gerar arquivo html |
---|
| 84 | def r_svn_to_html(): |
---|
| 85 | global projeto, caminho,rev |
---|
| 86 | arq_sai = caminho + os.sep + 'revisoes-svn.php' |
---|
| 87 | saida='' |
---|
| 88 | cor ='' |
---|
| 89 | linha = 0 |
---|
| 90 | |
---|
| 91 | try: |
---|
| 92 | cliente = pysvn.Client() |
---|
| 93 | cliente.callback_get_login = Login_no_svn |
---|
| 94 | logs = cliente.log( projeto, revision_start=pysvn.Revision( pysvn.opt_revision_kind.number,rev), |
---|
| 95 | revision_end=pysvn.Revision( pysvn.opt_revision_kind.number, 0 ), |
---|
| 96 | discover_changed_paths=True,strict_node_history=True,limit=0 ) |
---|
| 97 | except: |
---|
| 98 | print 'Erro Obtendo dados do svn para gerar revisoes-svn.php' |
---|
| 99 | sys.exit(93) |
---|
| 100 | |
---|
| 101 | fd = open(arq_sai, 'w') |
---|
| 102 | saida += '<?php ?>\n' |
---|
| 103 | saida += '<div>\n' |
---|
| 104 | saida += '<h3 align="center" style="color: #0000FF;margin-bottom: 0 ">Expresso - Subversion</h3>\n' |
---|
| 105 | saida += '<table border="1" witdh="100%">\n' |
---|
| 106 | saida += '<tr bgcolor="#D3DCE3">\n' |
---|
| 107 | saida += '<td>Revisão</td><td><font color="#000066">Data</font></td><td><font color="#000066">Implementação</font></td></tr>\n' |
---|
| 108 | for revisao in logs: |
---|
| 109 | linha += 1 |
---|
| 110 | if linha%2: |
---|
| 111 | cor = '#DDDDDD' |
---|
| 112 | else: |
---|
| 113 | cor = '#EEEEEE' |
---|
| 114 | saida += '<tr bgcolor="'+cor+'">\n' |
---|
| 115 | saida += '<td valign="top">'+str(revisao['revision'].number)+'</td>\n' |
---|
| 116 | saida += '<td valign="top">'+time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(revisao['date']))+'</td>\n' |
---|
| 117 | try: |
---|
| 118 | aux = revisao['message'] |
---|
| 119 | saida += '<td valign="top">'+aux+'</td>\n' |
---|
| 120 | except: |
---|
| 121 | saida += '<td valign="top">Nao foi possivel obter a msg no subversion. Falha no encode...</td>\n' |
---|
| 122 | saida += '</tr>\n' |
---|
| 123 | saida += '</table>\n' |
---|
| 124 | saida += '</div>\n' |
---|
| 125 | fd.write(saida.encode('iso8859','replace')) |
---|
| 126 | |
---|
| 127 | fd.close() |
---|
| 128 | |
---|
| 129 | # ########################################################################################## |
---|
| 130 | # INICIO |
---|
| 131 | # ########################################################################################## |
---|
| 132 | |
---|
| 133 | #Carrega arquivo com dados que configuram as distribuiçoes possÃveis... |
---|
| 134 | from gerador_conf import * |
---|
| 135 | |
---|
| 136 | |
---|
| 137 | # Pega identificador de cada distribuicao configurada... |
---|
| 138 | aux_tipo_distribuicao = parametros.keys() |
---|
| 139 | |
---|
| 140 | # Ordena |
---|
| 141 | aux_tipo_distribuicao.sort() |
---|
| 142 | |
---|
| 143 | tipo_distribuicao = {} |
---|
| 144 | |
---|
| 145 | # Tipo de distribuicao: uma entrada para distribuicao configurada... |
---|
| 146 | for i in range(0,len(aux_tipo_distribuicao)): |
---|
| 147 | tipo_distribuicao[str(i+1)] = aux_tipo_distribuicao[i] |
---|
| 148 | |
---|
| 149 | |
---|
| 150 | # ordena pelo enumerador..... |
---|
| 151 | Ks = tipo_distribuicao.keys() |
---|
| 152 | Ks.sort() |
---|
| 153 | escolhas = [] |
---|
| 154 | |
---|
| 155 | # COnstruindo itens do menu, uma entrada para cada distribuicao configurada... |
---|
| 156 | for t in Ks: |
---|
| 157 | escolhas.append([t,tipo_distribuicao[t]]) |
---|
| 158 | |
---|
| 159 | flag = False |
---|
| 160 | rev='' |
---|
| 161 | params={} |
---|
| 162 | |
---|
| 163 | d=Dialog() |
---|
| 164 | # Seta titulo geral.... |
---|
| 165 | d.add_persistent_args(["--backtitle", "Gera distribuicao"]) |
---|
| 166 | |
---|
| 167 | # Usuario seleciona a distribuição desejada. |
---|
| 168 | # cod = 0 , usuario selecionou um item, ver valor em opc... |
---|
| 169 | # cod = 1 , usuario selecionou cancelar, valor em opc é vazio |
---|
| 170 | # cod = 2 , usurio usou a tecla esc, valor em opc é vazio |
---|
| 171 | [cod,opc] = mostra(d,escolhas) |
---|
| 172 | |
---|
| 173 | # Se opc for vazio o usuario pediu para cancelar, ou usou a tecla esc... |
---|
| 174 | if opc == '': |
---|
| 175 | sys.exit(98) |
---|
| 176 | |
---|
| 177 | # Com base na selecao do usuario, carrega variaveis com valÃŽres configurados.... |
---|
| 178 | projeto = parametros[tipo_distribuicao[opc]]['projeto'] |
---|
| 179 | caminho = parametros[tipo_distribuicao[opc]]['caminho'] |
---|
| 180 | s_ftp = parametros[tipo_distribuicao[opc]]['s_ftp'] |
---|
| 181 | s_path = parametros[tipo_distribuicao[opc]]['s_path'] |
---|
| 182 | sufixo = parametros[tipo_distribuicao[opc]]['sufixo'] |
---|
| 183 | pasta_do_produto = parametros[tipo_distribuicao[opc]]['pasta_do_produto'] |
---|
| 184 | script = parametros[tipo_distribuicao[opc]]['script'] |
---|
| 185 | |
---|
| 186 | # Seta titulo da distribuicao que sera efetuada... |
---|
| 187 | d.add_persistent_args(["--title", 'Distribuição ' +tipo_distribuicao[opc]]) |
---|
| 188 | |
---|
| 189 | # Pega lista de parametros, se houver.... |
---|
| 190 | if len(sys.argv)>1: |
---|
| 191 | for parametro in sys.argv: |
---|
| 192 | aux=parametro.split('=') |
---|
| 193 | if len(aux)==2: |
---|
| 194 | params[aux[0]] = aux[1] |
---|
| 195 | if 'url' in params.keys(): |
---|
| 196 | projeto = params['url'] |
---|
| 197 | #Se existir o parametro projeto usar o ultimo elemento para compor o caminho no dir corrente.
|
---|
| 198 | aux = projeto.split(os.sep) |
---|
| 199 | caminho=os.getcwd()+os.sep+aux[-1] |
---|
| 200 | if 'caminho' in params.keys(): |
---|
| 201 | caminho = params['caminho'] |
---|
| 202 | if 'rev' in params.keys(): |
---|
| 203 | try: |
---|
| 204 | rev = int(params['rev']) |
---|
| 205 | except: |
---|
| 206 | msg_box_info(d,"Revisao invalida.") |
---|
| 207 | sys.exit(99) |
---|
| 208 | |
---|
| 209 | |
---|
| 210 | # Prepara alerta ao usuario, para confirmar execução... |
---|
| 211 | if len(params)<2: |
---|
| 212 | msg = "\nExemplo: ."+os.sep+"gerador.py url=http://xxx/bbb/yyyy caminho="+os.sep+"xxxx"+os.sep+"pasta rev=xxx\n" |
---|
| 213 | msg = msg + " url : Aponta projeto no svn\n" |
---|
| 214 | msg = msg + " caminho : Aponta o destino dos arquivo do projeto.\n" |
---|
| 215 | msg = msg + " rev : Informa o num. da revisao que sera tratada. Se vazio trata a mais recente.\n" |
---|
| 216 | msg = msg + "\nAssumindo valores default para esta execucao." |
---|
| 217 | msg = msg + "Sera processado o projeto apontado pela url " + projeto + "\n" |
---|
| 218 | if rev != '': |
---|
| 219 | msg = msg + "Posicionado na revisao " + str(rev) + ".\n\n" |
---|
| 220 | else: |
---|
| 221 | msg = msg + "\n\n" |
---|
| 222 | msg = msg + "Os arquivos do projeto serao armazenados no caminho " + caminho + "\n\n" |
---|
| 223 | msg = msg + "Continuar?" |
---|
| 224 | |
---|
| 225 | # Envia msg ao usuario e agurada resposta.... |
---|
| 226 | if msg_box_sim_nao(d,msg) != d.DIALOG_OK: |
---|
| 227 | sys.exit(98) |
---|
| 228 | |
---|
| 229 | |
---|
| 230 | # Iniciando o processamento... |
---|
| 231 | caminho1 = trabalho + os.sep + caminho |
---|
| 232 | caminho = trabalho + os.sep + caminho + os.sep + pasta_do_produto |
---|
| 233 | |
---|
| 234 | # Verifica a existencia de uma pasta de trabalho. |
---|
| 235 | # Nesta pasta serao gerados subdiretorios que vao conter as distribuiçoes. |
---|
| 236 | if not os.path.isdir(trabalho): |
---|
| 237 | os.makedirs(trabalho) |
---|
| 238 | |
---|
| 239 | if os.path.isdir(caminho1): |
---|
| 240 | retorno = getCommandOutput('rm -fR ' + caminho1) |
---|
| 241 | else: |
---|
| 242 | retorno = getCommandOutput('mkdir ' + caminho1) |
---|
| 243 | |
---|
| 244 | try: |
---|
| 245 | cliente = pysvn.Client() |
---|
| 246 | cliente.callback_get_login = Login_no_svn |
---|
| 247 | except:
|
---|
| 248 | msg_box_info(d,'\nErro gerando cliente do subversion.')
|
---|
| 249 | sys.exit(97) |
---|
| 250 |
|
---|
| 251 |
|
---|
| 252 | if rev == '':
|
---|
| 253 | try:
|
---|
| 254 | msg_box_info(d,'\nAguarde.\nVerificando qual a revisao mais recente do projeto no Subversion.\n')
|
---|
| 255 | logs = cliente.log( projeto, discover_changed_paths=True,strict_node_history=True,limit=1) |
---|
| 256 | rev = logs[0]['revision'].number |
---|
| 257 | except:
|
---|
| 258 | msg_box_info(d,'\nErro determinando qual he a revisao mais recente no subversion.')
|
---|
| 259 | sys.exit(96)
|
---|
| 260 |
|
---|
| 261 | msg = '\nBuscando os arquivos da revisao ' + str(rev) + '.\n\n'
|
---|
| 262 | msg = msg + 'Esta atividade pode demorar alguns minutos. \nAguarde.\n' |
---|
| 263 | msg_box_info(d,msg) |
---|
| 264 |
|
---|
| 265 | try:
|
---|
| 266 | revisao = cliente.export( projeto,
|
---|
| 267 | caminho,
|
---|
| 268 | force=False,
|
---|
| 269 | revision=pysvn.Revision(pysvn.opt_revision_kind.number,rev),
|
---|
| 270 | native_eol=None,
|
---|
| 271 | ignore_externals=False,
|
---|
| 272 | recurse=True,
|
---|
| 273 | peg_revision=pysvn.Revision(pysvn.opt_revision_kind.number, rev))
|
---|
| 274 | |
---|
| 275 | except:
|
---|
| 276 | msg_box_info(d,'\nErro buscando arquivos no subversion.') |
---|
| 277 | sys.exit(95)
|
---|
| 278 |
|
---|
| 279 | #Gera arqivo com infrmacoes do Subversion
|
---|
| 280 | r_svn_to_html()
|
---|
| 281 | |
---|
| 282 | # Se existir um nome de script no arquivo de configuração, vai tentar executar... |
---|
| 283 | if script != '': |
---|
| 284 | msg = msg + "\nExecutando o script ." + os.sep + script + " \n"
|
---|
| 285 | msg_box_info(d,msg) |
---|
| 286 | retorno = getCommandOutput('.' + os.sep + script) |
---|
| 287 | |
---|
| 288 | #Solicita execucao do comando de compactaçao |
---|
| 289 | path_corrente = os.getcwd() |
---|
| 290 | os.chdir(caminho1) |
---|
| 291 | retorno = getCommandOutput("tar -zcf " + sufixo + str(rev) + ".tgz ./expresso") |
---|
| 292 | os.chdir(path_corrente) |
---|
| 293 | msg = ''
|
---|
| 294 | msg = msg + "\nFoi gerado o arquivo " + sufixo + str(rev) + ".tgz \n"
|
---|
| 295 | msg_box_info(d,msg) |
---|
| 296 |
|
---|
| 297 | #Faz ftp para a maquina de distribuicao...
|
---|
| 298 | msg = msg + 'Iniciando copia do arquivo gerado para a maquina de distribuicao(FTP)\n' |
---|
| 299 | msg_box_info(d,msg)
|
---|
| 300 | from ftplib import FTP
|
---|
| 301 | servidor_ftp = s_ftp
|
---|
| 302 | try:
|
---|
| 303 | ftp = FTP(servidor_ftp,'anonymous','')
|
---|
| 304 | except: |
---|
| 305 | msg = msg + '\nErro ao conectar no servidor FTP.'
|
---|
| 306 | msg_box_info(d,msg) |
---|
| 307 | sys.exit(94)
|
---|
| 308 |
|
---|
| 309 | resp = ftp.cwd(s_path)
|
---|
| 310 | msg = msg + resp + '\n' |
---|
| 311 | msg_box_info(d,msg)
|
---|
| 312 | lista = ftp.nlst()
|
---|
| 313 | if 'R'+str(rev) in lista:
|
---|
| 314 | ftp.cwd('R'+str(rev)) |
---|
| 315 | # pode existir a pasta mas nao o arquivo.... |
---|
| 316 | try: |
---|
| 317 | resp = ftp.delete(sufixo+str(rev)+'.tgz') |
---|
| 318 | except: |
---|
| 319 | pass
|
---|
| 320 | msg = msg + resp + '\n' |
---|
| 321 | msg_box_info(d,msg)
|
---|
| 322 | resp = ftp.cwd('../')
|
---|
| 323 | msg = msg + resp + '\n' |
---|
| 324 | msg_box_info(d,msg)
|
---|
| 325 | else:
|
---|
| 326 | resp = ftp.mkd('R'+str(rev))
|
---|
| 327 | msg = msg + resp + '\n' |
---|
| 328 | msg_box_info(d,msg)
|
---|
| 329 | resp = ftp.cwd('R'+str(rev))
|
---|
| 330 | msg = msg + resp + '\n' |
---|
| 331 | msg_box_info(d,msg)
|
---|
| 332 | f = open(caminho1 + os.sep + sufixo+str(rev)+'.tgz','rb')
|
---|
| 333 | resp = ftp.storbinary('STOR ' + sufixo + str(rev) + '.tgz',f)
|
---|
| 334 | msg = msg + resp + '\n' |
---|
| 335 | msg_box_info(d,msg)
|
---|
| 336 | msg = msg + 'Verifique os dados abaixo:\n' |
---|
| 337 | msg_box_info(d,msg)
|
---|
| 338 | resp = ftp.pwd()
|
---|
| 339 | msg = msg + 'Diretorio de distribuicao R'+str(rev)+' gerado em '+servidor_ftp+' : '+resp |
---|
| 340 | msg_box_info(d,msg)
|
---|
| 341 | resp = ftp.retrlines('LIST')
|
---|
| 342 | msg = msg + '\nConteudo gerado no diretorio acima : \n'+resp+'\n' |
---|
| 343 | msg_box_info(d,msg)
|
---|
| 344 | ftp.close() |
---|
| 345 | msg = msg + '\nProcessamento concluido.\n' |
---|
| 346 | msg_box_info(d,msg) |
---|
| 347 | |
---|
| 348 | |
---|
| 349 | |
---|
| 350 | |
---|