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 | |
---|