Salome HOME
add logs to git retry functionality
[tools/sat.git] / src / system.py
1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3 #  Copyright (C) 2010-2013  CEA/DEN
4 #
5 #  This library is free software; you can redistribute it and/or
6 #  modify it under the terms of the GNU Lesser General Public
7 #  License as published by the Free Software Foundation; either
8 #  version 2.1 of the License.
9 #
10 #  This library is distributed in the hope that it will be useful,
11 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 #  Lesser General Public License for more details.
14 #
15 #  You should have received a copy of the GNU Lesser General Public
16 #  License along with this library; if not, write to the Free Software
17 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18
19 '''
20 In this file : all functions that do a system call, 
21 like open a browser or an editor, or call a git command
22 '''
23
24 import os
25 import subprocess
26 import time
27 import tarfile
28
29 import debug as DBG
30 import utilsSat as UTS
31
32 from . import printcolors
33
34 def show_in_editor(editor, filePath, logger):
35     '''open filePath using editor.
36     
37     :param editor str: The editor to use.
38     :param filePath str: The path to the file to open.
39     '''
40     # default editor is vi
41     if editor is None or len(editor) == 0:
42         editor = 'vi'
43     
44     if '%s' not in editor:
45         editor += ' %s'
46
47     try:
48         # launch cmd using subprocess.Popen
49         cmd = editor % filePath
50         logger.write('Launched command:\n' + cmd + '\n', 5)
51         p = subprocess.Popen(cmd, shell=True)
52         p.communicate()
53     except:
54         logger.write(printcolors.printcError(_("Unable to edit file %s\n") 
55                                              % filePath), 1)
56
57
58 def git_extract(from_what, tag, where, logger, environment=None):
59   '''Extracts sources from a git repository.
60
61   :param from_what str: The remote git repository.
62   :param tag str: The tag.
63   :param where str: The path where to extract.
64   :param logger Logger: The logger instance to use.
65   :param environment src.environment.Environ: The environment to source when extracting.
66   :return: True if the extraction is successful
67   :rtype: boolean
68   '''
69   DBG.write("git_extract", [from_what, tag, str(where)])
70   if not where.exists():
71     where.make()
72   if tag == "master" or tag == "HEAD":
73     cmd = r"""
74 set -x
75 git clone %(remote)s %(where)s
76 """
77     cmd = cmd % {'remote': from_what, 'tag': tag, 'where': str(where)}
78   else:
79     # NOTICE: this command only works with recent version of git
80     #         because --work-tree does not work with an absolute path
81     where_git = os.path.join(str(where), ".git")
82
83     cmd = r"""
84 set -x
85 rmdir %(where)s
86 git clone %(remote)s %(where)s && \
87 git --git-dir=%(where_git)s --work-tree=%(where)s checkout %(tag)s
88 """
89     cmd = cmd % {'remote': from_what,
90                  'tag': tag,
91                  'where': str(where),
92                  'where_git': where_git}
93
94
95   logger.logTxtFile.write("\n" + cmd + "\n")
96   logger.logTxtFile.flush()
97
98   DBG.write("cmd", cmd)
99
100   # git commands may fail sometimes for various raisons (big module, network troubles, tuleap maintenance)
101   # therefore we give several tries
102   i_try=0
103   max_number_of_tries=3
104   sleep_delay=30  # seconds
105   while (True):
106     i_try+=1
107     rc = UTS.Popen(cmd, cwd=str(where.dir()), env=environment.environ.environ, logger=logger)
108     if rc.isOk() or (i_try>=max_number_of_tries):
109         break
110     logger.write('\ngit command failed! Wait %d seconds and give an other try (%d/%d)\n' % (sleep_delay,i_try+1,max_number_of_tries), 3)
111     time.sleep(sleep_delay) # wait a little
112
113   return rc.isOk()
114
115   """
116   res = subprocess.call(command,
117                         cwd=str(where.dir()),
118                         env=environment.environ.environ,
119                         shell=True,
120                         stdout=logger.logTxtFile,
121                         stderr=subprocess.STDOUT)
122   return (res == 0)
123   """
124
125
126
127 def git_extract_sub_dir(from_what, tag, where, sub_dir, logger, environment=None):
128   '''Extracts sources from a subtree sub_dir of a git repository.
129
130   :param from_what str: The remote git repository.
131   :param tag str: The tag.
132   :param where str: The path where to extract.
133   :param sub_dir str: The relative path of subtree to extract.
134   :param logger Logger: The logger instance to use.
135   :param environment src.environment.Environ: The environment to source when extracting.
136   :return: True if the extraction is successful
137   :rtype: boolean
138   '''
139   strWhere = str(where)
140   tmpWhere = strWhere + '_tmp'
141   parentWhere = os.path.dirname(strWhere)
142   if not os.path.exists(parentWhere):
143     logger.error("not existing directory: %s" % parentWhere)
144     return False
145   if os.path.isdir(strWhere):
146     logger.error("do not override existing directory: %s" % strWhere)
147     return False
148   aDict = {'remote': from_what,
149            'tag': tag,
150            'sub_dir': sub_dir,
151            'where': strWhere,
152            'parentWhere': parentWhere,
153            'tmpWhere': tmpWhere,
154            }
155   DBG.write("git_extract_sub_dir", aDict)
156
157   cmd = r"""
158 set -x
159 export tmpDir=%(tmpWhere)s && \
160 rm -rf $tmpDir
161 git clone %(remote)s $tmpDir && \
162 cd $tmpDir && \
163 git checkout %(tag)s && \
164 mv %(sub_dir)s %(where)s && \
165 git log -1 > %(where)s/README_git_log.txt && \
166 rm -rf $tmpDir
167 """ % aDict
168   DBG.write("cmd", cmd)
169
170   for nbtry in range(0,3): # retries case of network problem
171     rc = UTS.Popen(cmd, cwd=parentWhere, env=environment.environ.environ, logger=logger)
172     if rc.isOk(): break
173     time.sleep(30) # wait a little
174
175   return rc.isOk()
176
177 def archive_extract(from_what, where, logger):
178     '''Extracts sources from an archive.
179     
180     :param from_what str: The path to the archive.
181     :param where str: The path where to extract.
182     :param logger Logger: The logger instance to use.
183     :return: True if the extraction is successful
184     :rtype: boolean
185     '''
186     try:
187         archive = tarfile.open(from_what)
188         for i in archive.getmembers():
189             archive.extract(i, path=str(where))
190         return True, os.path.commonprefix(archive.getnames())
191     except Exception as exc:
192         logger.write("archive_extract: %s\n" % exc)
193         return False, None
194
195 def cvs_extract(protocol, user, server, base, tag, product, where,
196                 logger, checkout=False, environment=None):
197     '''Extracts sources from a cvs repository.
198     
199     :param protocol str: The cvs protocol.
200     :param user str: The user to be used.
201     :param server str: The remote cvs server.
202     :param base str: .
203     :param tag str: The tag.
204     :param product str: The product.
205     :param where str: The path where to extract.
206     :param logger Logger: The logger instance to use.
207     :param checkout boolean: If true use checkout cvs.
208     :param environment src.environment.Environ: The environment to source when
209                                                 extracting.
210     :return: True if the extraction is successful
211     :rtype: boolean
212     '''
213
214     opttag = ''
215     if tag is not None and len(tag) > 0:
216         opttag = '-r ' + tag
217
218     cmd = 'export'
219     if checkout:
220         cmd = 'checkout'
221     elif len(opttag) == 0:
222         opttag = '-DNOW'
223     
224     if len(protocol) > 0:
225         root = "%s@%s:%s" % (user, server, base)
226         command = "cvs -d :%(protocol)s:%(root)s %(command)s -d %(where)s %(tag)s %(product)s" % \
227             { 'protocol': protocol, 'root': root, 'where': str(where.base()),
228               'tag': opttag, 'product': product, 'command': cmd }
229     else:
230         command = "cvs -d %(root)s %(command)s -d %(where)s %(tag)s %(base)s/%(product)s" % \
231             { 'root': server, 'base': base, 'where': str(where.base()),
232               'tag': opttag, 'product': product, 'command': cmd }
233
234     logger.write(command + "\n", 5)
235
236     if not where.dir().exists():
237         where.dir().make()
238
239     logger.logTxtFile.write("\n" + command + "\n")
240     logger.logTxtFile.flush()        
241     res = subprocess.call(command,
242                           cwd=str(where.dir()),
243                           env=environment.environ.environ,
244                           shell=True,
245                           stdout=logger.logTxtFile,
246                           stderr=subprocess.STDOUT)
247     return (res == 0)
248
249 def svn_extract(user,
250                 from_what,
251                 tag,
252                 where,
253                 logger,
254                 checkout=False,
255                 environment=None):
256     '''Extracts sources from a svn repository.
257     
258     :param user str: The user to be used.
259     :param from_what str: The remote git repository.
260     :param tag str: The tag.
261     :param where str: The path where to extract.
262     :param logger Logger: The logger instance to use.
263     :param checkout boolean: If true use checkout svn.
264     :param environment src.environment.Environ: The environment to source when
265                                                 extracting.
266     :return: True if the extraction is successful
267     :rtype: boolean
268     '''
269     if not where.exists():
270         where.make()
271
272     if checkout:
273         command = "svn checkout --username %(user)s %(remote)s %(where)s" % \
274             { 'remote': from_what, 'user' : user, 'where': str(where) }
275     else:
276         command = ""
277         if os.path.exists(str(where)):
278             command = "/bin/rm -rf %(where)s && " % \
279                 { 'remote': from_what, 'where': str(where) }
280         
281         if tag == "master":
282             command += "svn export --username %(user)s %(remote)s %(where)s" % \
283                 { 'remote': from_what, 'user' : user, 'where': str(where) }       
284         else:
285             command += "svn export -r %(tag)s --username %(user)s %(remote)s %(where)s" % \
286                 { 'tag' : tag, 'remote': from_what, 'user' : user, 'where': str(where) }
287     
288     logger.logTxtFile.write(command + "\n")
289     
290     logger.write(command + "\n", 5)
291     logger.logTxtFile.write("\n" + command + "\n")
292     logger.logTxtFile.flush()
293     res = subprocess.call(command,
294                           cwd=str(where.dir()),
295                           env=environment.environ.environ,
296                           shell=True,
297                           stdout=logger.logTxtFile,
298                           stderr=subprocess.STDOUT)
299     return (res == 0)