Salome HOME
sat #13318 : test et debug de paquets salome et projet
[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 def git_describe(repo_path):
58     '''Use git describe --tags command to return tag description of the git repository"
59     :param repo_path str: The git repository to describe
60     '''
61     git_cmd="cd %s;git describe --tags" % repo_path
62     p = subprocess.Popen(git_cmd, shell=True,
63                     stdin=subprocess.PIPE,
64                     stdout=subprocess.PIPE,
65                     stderr=subprocess.PIPE)
66     p.wait()
67     if p.returncode != 0:
68         return False
69     else:
70         return p.stdout.readlines()[0].strip()
71
72
73 def git_extract(from_what, tag, where, logger, environment=None):
74   '''Extracts sources from a git repository.
75
76   :param from_what str: The remote git repository.
77   :param tag str: The tag.
78   :param where str: The path where to extract.
79   :param logger Logger: The logger instance to use.
80   :param environment src.environment.Environ: The environment to source when extracting.
81   :return: True if the extraction is successful
82   :rtype: boolean
83   '''
84   DBG.write("git_extract", [from_what, tag, str(where)])
85   if not where.exists():
86     where.make()
87   if tag == "master" or tag == "HEAD":
88     cmd = r"""
89 set -x
90 git clone %(remote)s %(where)s
91 """
92     cmd = cmd % {'remote': from_what, 'tag': tag, 'where': str(where)}
93   else:
94     # NOTICE: this command only works with recent version of git
95     #         because --work-tree does not work with an absolute path
96     where_git = os.path.join(str(where), ".git")
97
98     cmd = r"""
99 set -x
100 rmdir %(where)s
101 git clone %(remote)s %(where)s && \
102 git --git-dir=%(where_git)s --work-tree=%(where)s checkout %(tag)s
103 """
104     cmd = cmd % {'remote': from_what,
105                  'tag': tag,
106                  'where': str(where),
107                  'where_git': where_git}
108
109
110   logger.logTxtFile.write("\n" + cmd + "\n")
111   logger.logTxtFile.flush()
112
113   DBG.write("cmd", cmd)
114
115   # git commands may fail sometimes for various raisons 
116   # (big module, network troubles, tuleap maintenance)
117   # therefore we give several tries
118   i_try = 0
119   max_number_of_tries = 3
120   sleep_delay = 30  # seconds
121   while (True):
122     i_try += 1
123     rc = UTS.Popen(cmd, cwd=str(where.dir()), env=environment.environ.environ, logger=logger)
124     if rc.isOk() or (i_try>=max_number_of_tries):
125       break
126     logger.write('\ngit command failed! Wait %d seconds and give an other try (%d/%d)\n' % \
127                  (sleep_delay, i_try + 1, max_number_of_tries), 3)
128     time.sleep(sleep_delay) # wait a little
129
130   return rc.isOk()
131
132
133 def git_extract_sub_dir(from_what, tag, where, sub_dir, logger, environment=None):
134   '''Extracts sources from a subtree sub_dir of a git repository.
135
136   :param from_what str: The remote git repository.
137   :param tag str: The tag.
138   :param where str: The path where to extract.
139   :param sub_dir str: The relative path of subtree to extract.
140   :param logger Logger: The logger instance to use.
141   :param environment src.environment.Environ: The environment to source when extracting.
142   :return: True if the extraction is successful
143   :rtype: boolean
144   '''
145   strWhere = str(where)
146   tmpWhere = strWhere + '_tmp'
147   parentWhere = os.path.dirname(strWhere)
148   if not os.path.exists(parentWhere):
149     logger.error("not existing directory: %s" % parentWhere)
150     return False
151   if os.path.isdir(strWhere):
152     logger.error("do not override existing directory: %s" % strWhere)
153     return False
154   aDict = {'remote': from_what,
155            'tag': tag,
156            'sub_dir': sub_dir,
157            'where': strWhere,
158            'parentWhere': parentWhere,
159            'tmpWhere': tmpWhere,
160            }
161   DBG.write("git_extract_sub_dir", aDict)
162
163   cmd = r"""
164 set -x
165 export tmpDir=%(tmpWhere)s && \
166 rm -rf $tmpDir
167 git clone %(remote)s $tmpDir && \
168 cd $tmpDir && \
169 git checkout %(tag)s && \
170 mv %(sub_dir)s %(where)s && \
171 git log -1 > %(where)s/README_git_log.txt && \
172 rm -rf $tmpDir
173 """ % aDict
174   DBG.write("cmd", cmd)
175
176   for nbtry in range(0,3): # retries case of network problem
177     rc = UTS.Popen(cmd, cwd=parentWhere, env=environment.environ.environ, logger=logger)
178     if rc.isOk(): break
179     time.sleep(30) # wait a little
180
181   return rc.isOk()
182
183 def archive_extract(from_what, where, logger):
184     '''Extracts sources from an archive.
185     
186     :param from_what str: The path to the archive.
187     :param where str: The path where to extract.
188     :param logger Logger: The logger instance to use.
189     :return: True if the extraction is successful
190     :rtype: boolean
191     '''
192     try:
193         archive = tarfile.open(from_what)
194         for i in archive.getmembers():
195             archive.extract(i, path=str(where))
196         return True, os.path.commonprefix(archive.getnames())
197     except Exception as exc:
198         logger.write("archive_extract: %s\n" % exc)
199         return False, None
200
201 def cvs_extract(protocol, user, server, base, tag, product, where,
202                 logger, checkout=False, environment=None):
203     '''Extracts sources from a cvs repository.
204     
205     :param protocol str: The cvs protocol.
206     :param user str: The user to be used.
207     :param server str: The remote cvs server.
208     :param base str: .
209     :param tag str: The tag.
210     :param product str: The product.
211     :param where str: The path where to extract.
212     :param logger Logger: The logger instance to use.
213     :param checkout boolean: If true use checkout cvs.
214     :param environment src.environment.Environ: The environment to source when
215                                                 extracting.
216     :return: True if the extraction is successful
217     :rtype: boolean
218     '''
219
220     opttag = ''
221     if tag is not None and len(tag) > 0:
222         opttag = '-r ' + tag
223
224     cmd = 'export'
225     if checkout:
226         cmd = 'checkout'
227     elif len(opttag) == 0:
228         opttag = '-DNOW'
229     
230     if len(protocol) > 0:
231         root = "%s@%s:%s" % (user, server, base)
232         command = "cvs -d :%(protocol)s:%(root)s %(command)s -d %(where)s %(tag)s %(product)s" % \
233             { 'protocol': protocol, 'root': root, 'where': str(where.base()),
234               'tag': opttag, 'product': product, 'command': cmd }
235     else:
236         command = "cvs -d %(root)s %(command)s -d %(where)s %(tag)s %(base)s/%(product)s" % \
237             { 'root': server, 'base': base, 'where': str(where.base()),
238               'tag': opttag, 'product': product, 'command': cmd }
239
240     logger.write(command + "\n", 5)
241
242     if not where.dir().exists():
243         where.dir().make()
244
245     logger.logTxtFile.write("\n" + command + "\n")
246     logger.logTxtFile.flush()        
247     res = subprocess.call(command,
248                           cwd=str(where.dir()),
249                           env=environment.environ.environ,
250                           shell=True,
251                           stdout=logger.logTxtFile,
252                           stderr=subprocess.STDOUT)
253     return (res == 0)
254
255 def svn_extract(user,
256                 from_what,
257                 tag,
258                 where,
259                 logger,
260                 checkout=False,
261                 environment=None):
262     '''Extracts sources from a svn repository.
263     
264     :param user str: The user to be used.
265     :param from_what str: The remote git repository.
266     :param tag str: The tag.
267     :param where str: The path where to extract.
268     :param logger Logger: The logger instance to use.
269     :param checkout boolean: If true use checkout svn.
270     :param environment src.environment.Environ: The environment to source when
271                                                 extracting.
272     :return: True if the extraction is successful
273     :rtype: boolean
274     '''
275     if not where.exists():
276         where.make()
277
278     if checkout:
279         command = "svn checkout --username %(user)s %(remote)s %(where)s" % \
280             { 'remote': from_what, 'user' : user, 'where': str(where) }
281     else:
282         command = ""
283         if os.path.exists(str(where)):
284             command = "/bin/rm -rf %(where)s && " % \
285                 { 'remote': from_what, 'where': str(where) }
286         
287         if tag == "master":
288             command += "svn export --username %(user)s %(remote)s %(where)s" % \
289                 { 'remote': from_what, 'user' : user, 'where': str(where) }       
290         else:
291             command += "svn export -r %(tag)s --username %(user)s %(remote)s %(where)s" % \
292                 { 'tag' : tag, 'remote': from_what, 'user' : user, 'where': str(where) }
293     
294     logger.logTxtFile.write(command + "\n")
295     
296     logger.write(command + "\n", 5)
297     logger.logTxtFile.write("\n" + command + "\n")
298     logger.logTxtFile.flush()
299     res = subprocess.call(command,
300                           cwd=str(where.dir()),
301                           env=environment.environ.environ,
302                           shell=True,
303                           stdout=logger.logTxtFile,
304                           stderr=subprocess.STDOUT)
305     return (res == 0)