3 # Copyright (C) 2010-2012 CEA/DEN
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.
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.
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
25 # Define all possible option for patch command : sat patch <options>
26 parser = src.options.Options()
27 parser.add_option('p', 'product', 'list2', 'products',
28 _('products from which to get the sources. This option can be'
29 ' passed several time to get the sources of several products.'))
30 parser.add_option('f', 'force', 'boolean', 'force',
31 _("force to remove the sources before getting them (in development mode only)."))
33 def get_source_for_dev(config, product_info, source_dir, force, logger, pad):
34 '''The method called if the product is in development mode
36 :param config Config: The global configuration
37 :param product_info Config: The configuration specific to
38 the product to be prepared
39 :param source_dir Path: The Path instance corresponding to the
40 directory where to put the sources
41 :param force boolean: True if the --force option was invoked
42 :param logger Logger: The logger instance to use for the display and logging
43 :param pad int: The gap to apply for the terminal display
44 :return: True if it succeed, else False
48 # if the product source directory does not exist,
49 # get it in checkout mode, else, do not do anything
50 # unless the force option is invoked
51 if not os.path.exists(product_info.source_dir) or force:
52 # If the source path exists (it means that force option is invoked)
53 # remove the source path
54 if source_dir.exists():
57 # Call the function corresponding to get the sources with True checkout
58 retcode = get_product_sources(config,
66 logger.write("\n", 3, False)
67 # +2 because product name is followed by ': '
68 logger.write(" " * (pad+2), 3, False)
70 logger.write('dev: %s ... ' %
71 src.printcolors.printcInfo(product_info.source_dir), 3, False)
76 def get_source_from_git(product_info, source_dir, logger, pad, is_dev=False):
77 '''The method called if the product is to be get in git mode
79 :param product_info Config: The configuration specific to
80 the product to be prepared
81 :param source_dir Path: The Path instance corresponding to the
82 directory where to put the sources
83 :param logger Logger: The logger instance to use for the display and logging
84 :param pad int: The gap to apply for the terminal display
85 :param is_dev boolean: True if the product is in development mode
86 :return: True if it succeed, else False
92 # Get the repository address. (from repo_dev key if the product is
94 if is_dev and 'repo_dev' in product_info.git_info:
95 coflag = src.printcolors.printcHighlight(coflag.upper())
96 repo_git = product_info.git_info.repo_dev
98 repo_git = product_info.git_info.repo
100 # Display informations
101 logger.write('%s:%s' % (coflag, src.printcolors.printcInfo(repo_git)), 3,
103 logger.write(' ' * (pad + 50 - len(repo_git)), 3, False)
104 logger.write(' tag:%s' % src.printcolors.printcInfo(
105 product_info.git_info.tag),
108 logger.write(' %s. ' % ('.' * (10 - len(product_info.git_info.tag))), 3,
111 logger.write('\n', 5, False)
112 # Call the system function that do the extraction in git mode
113 retcode = src.system.git_extract(repo_git,
114 product_info.git_info.tag,
118 def get_source_from_archive(product_info, source_dir, logger):
119 '''The method called if the product is to be get in archive mode
121 :param product_info Config: The configuration specific to
122 the product to be prepared
123 :param source_dir Path: The Path instance corresponding to the
124 directory where to put the sources
125 :param logger Logger: The logger instance to use for the display and logging
126 :return: True if it succeed, else False
129 # check archive exists
130 if not os.path.exists(product_info.archive_info.archive_name):
131 raise src.SatException(_("Archive not found: '%s'") %
132 product_info.archive_info.archive_name)
134 logger.write('arc:%s ... ' %
135 src.printcolors.printcInfo(product_info.archive_info.archive_name),
139 # Call the system function that do the extraction in archive mode
140 retcode, NameExtractedDirectory = src.system.archive_extract(
141 product_info.archive_info.archive_name,
142 source_dir.dir(), logger)
144 # Rename the source directory if
145 # it does not match with product_info.source_dir
146 if (NameExtractedDirectory.replace('/', '') !=
147 os.path.basename(product_info.source_dir)):
148 shutil.move(os.path.join(os.path.dirname(product_info.source_dir),
149 NameExtractedDirectory),
150 product_info.source_dir)
154 def get_source_from_cvs(user, product_info, source_dir, checkout, logger, pad):
155 '''The method called if the product is to be get in cvs mode
157 :param user str: The user to use in for the cvs command
158 :param product_info Config: The configuration specific to
159 the product to be prepared
160 :param source_dir Path: The Path instance corresponding to the
161 directory where to put the sources
162 :param checkout boolean: If True, get the source in checkout mode
163 :param logger Logger: The logger instance to use for the display and logging
164 :param pad int: The gap to apply for the terminal display
165 :return: True if it succeed, else False
168 # Get the protocol to use in the command
169 if "protocol" in product_info.cvs_info:
170 protocol = product_info.cvs_info.protocol
174 # Construct the line to display
175 if "protocol" in product_info.cvs_info:
176 cvs_line = "%s:%s@%s:%s" % \
177 (protocol, user, product_info.cvs_info.server,
178 product_info.cvs_info.product_base)
180 cvs_line = "%s / %s" % (product_info.cvs_info.server,
181 product_info.cvs_info.product_base)
184 if checkout: coflag = src.printcolors.printcHighlight(coflag.upper())
186 logger.write('%s:%s' % (coflag, src.printcolors.printcInfo(cvs_line)),
189 logger.write(' ' * (pad + 50 - len(cvs_line)), 3, False)
190 logger.write(' src:%s' %
191 src.printcolors.printcInfo(product_info.cvs_info.source),
194 logger.write(' ' * (pad + 1 - len(product_info.cvs_info.source)), 3, False)
195 logger.write(' tag:%s' %
196 src.printcolors.printcInfo(product_info.cvs_info.tag),
199 # at least one '.' is visible
200 logger.write(' %s. ' % ('.' * (10 - len(product_info.cvs_info.tag))),
204 logger.write('\n', 5, False)
206 # Call the system function that do the extraction in cvs mode
207 retcode = src.system.cvs_extract(protocol, user,
208 product_info.cvs_info.server,
209 product_info.cvs_info.product_base,
210 product_info.cvs_info.tag,
211 product_info.cvs_info.source,
212 source_dir, logger, checkout)
215 def get_source_from_svn(user, product_info, source_dir, checkout, logger):
216 '''The method called if the product is to be get in svn mode
218 :param user str: The user to use in for the svn command
219 :param product_info Config: The configuration specific to
220 the product to be prepared
221 :param source_dir Path: The Path instance corresponding to the
222 directory where to put the sources
223 :param checkout boolean: If True, get the source in checkout mode
224 :param logger Logger: The logger instance to use for the display and logging
225 :return: True if it succeed, else False
229 if checkout: coflag = src.printcolors.printcHighlight(coflag.upper())
231 logger.write('%s:%s ... ' % (coflag,
232 src.printcolors.printcInfo(
233 product_info.svn_info.repo)),
237 logger.write('\n', 5, False)
238 # Call the system function that do the extraction in svn mode
239 retcode = src.system.svn_extract(user,
240 product_info.svn_info.repo,
241 product_info.svn_info.tag,
247 def get_product_sources(config,
255 '''Get the product sources.
257 :param config Config: The global configuration
258 :param product_info Config: The configuration specific to
259 the product to be prepared
260 :param is_dev boolean: True if the product is in development mode
261 :param source_dir Path: The Path instance corresponding to the
262 directory where to put the sources
263 :param force boolean: True if the --force option was invoked
264 :param logger Logger: The logger instance to use for the display and logging
265 :param pad int: The gap to apply for the terminal display
266 :param checkout boolean: If True, get the source in checkout mode
267 :return: True if it succeed, else False
270 if not checkout and is_dev:
271 return get_source_for_dev(config,
278 if product_info.get_source == "git":
279 return get_source_from_git(product_info, source_dir, logger, pad,
282 if product_info.get_source == "archive":
283 return get_source_from_archive(product_info, source_dir, logger)
285 if product_info.get_source == "cvs":
286 cvs_user = config.USER.cvs_user
287 return get_source_from_cvs(cvs_user,
294 if product_info.get_source == "svn":
295 svn_user = config.USER.svn_user
296 return get_source_from_svn(svn_user, product_info, source_dir,
300 if product_info.get_source == "native":
302 logger.write('%s ...' % _("native (ignored)"), 3, False)
305 if product_info.get_source == "fixed":
307 logger.write('%s ...' % _("fixed (ignored)"), 3, False)
310 # if the get_source is not in [git, archive, cvs, svn, fixed, native]
311 logger.write(_("Unknown get source method \"%(get)s\" for product %(product)s") % \
312 { 'get': product_info.get_source, 'product': product_info.name }, 3, False)
313 logger.write(" ... ", 3, False)
317 def get_all_product_sources(config, products, force, logger):
318 '''Get all the product sources.
320 :param config Config: The global configuration
321 :param products List: The list of tuples (product name, product informations)
322 :param force boolean: True if the --force option was invoked
323 :param logger Logger: The logger instance to be used for the logging
324 :return: the tuple (number of success, dictionary product_name/success_fail)
328 # Initialize the variables that will count the fails and success
332 # Get the maximum name length in order to format the terminal display
333 max_product_name_len = 1
334 if len(products) > 0:
335 max_product_name_len = max(map(lambda l: len(l), products[0])) + 4
337 # The loop on all the products from which to get the sources
338 for product_name, product_info in products:
339 # get product name, product informations and the directory where to put
341 if (not (src.product.product_is_fixed(product_info) or
342 src.product.product_is_native(product_info))):
343 source_dir = src.Path(product_info.source_dir)
345 source_dir = src.Path('')
348 logger.write('%s: ' % src.printcolors.printcLabel(product_name), 3)
349 logger.write(' ' * (max_product_name_len - len(product_name)), 3, False)
350 logger.write("\n", 4, False)
352 # Remove the existing source directory if
353 # the product is not in development mode
354 is_dev = src.product.product_is_dev(product_info)
355 if source_dir.exists() and not is_dev:
356 logger.write(" " + _('remove %s') % source_dir, 4)
357 logger.write("\n ", 4, False)
360 # Call to the function that get the sources for one product
361 retcode = get_product_sources(config,
367 max_product_name_len,
371 if 'no_rpath' in product_info.keys():
372 if product_info.no_rpath:
373 hack_no_rpath(config, product_info, logger)
377 results[product_name] = retcode
379 # The case where the product was not prepared because it is
380 # in development mode
381 res =(src.printcolors.printc(src.OK_STATUS) +
382 src.printcolors.printcWarning(_(
383 ' source directory already exists')))
384 good_result = good_result + 1
386 # The case where it succeed
388 good_result = good_result + 1
390 # The case where it failed
394 logger.write('%s\n' % src.printcolors.printc(res), 3, False)
396 return good_result, results
399 '''method that is called when salomeTools is called with --help option.
401 :return: The text to display for the source command description.
404 return _("The source command gets the sources of the application products "
405 "from cvs, git, an archive or a directory..")
407 def run(args, runner, logger):
408 '''method that is called when salomeTools is called with source parameter.
411 (options, args) = parser.parse_args(args)
413 # check that the command has been called with an application
414 src.check_config_has_application( runner.cfg )
416 # Print some informations
417 logger.write(_('Getting sources of the application %s\n') %
418 src.printcolors.printcLabel(runner.cfg.VARS.application), 1)
419 src.printcolors.print_value(logger, 'workdir',
420 runner.cfg.APPLICATION.workdir, 2)
421 logger.write("\n", 2, False)
423 # Get the force option if it was passed
424 force = options.force
426 msg = _("Warning: the --force option has effect only "
427 "on products in development mode\n\n")
428 logger.write(src.printcolors.printcWarning(msg))
430 # Get the products list with products informations regarding the options
431 products_infos = prepare.get_products_list(options, runner.cfg, logger)
433 # Call to the function that gets all the sources
434 good_result, results = get_all_product_sources(runner.cfg,
439 # Display the results (how much passed, how much failed, etc...)
440 status = src.OK_STATUS
443 logger.write("\n", 2, False)
444 if good_result == len(products_infos):
445 res_count = "%d / %d" % (good_result, good_result)
447 status = src.KO_STATUS
448 res_count = "%d / %d" % (good_result, len(products_infos))
450 for product in results:
451 if results[product] == 0 or results[product] is None:
452 details.append(product)
454 result = len(products_infos) - good_result
457 logger.write(_("Getting sources of the application:"), 1)
458 logger.write(" " + src.printcolors.printc(status), 1, False)
459 logger.write(" (%s)\n" % res_count, 1, False)
462 logger.write(_("Following sources haven't been get:\n"), 2)
463 logger.write(" ".join(details), 2)
464 logger.write("\n", 2, False)