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 log command : sat log <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('', 'no_sample', 'boolean', 'no_sample',
31 _("do not get sources from sample products."))
32 parser.add_option('f', 'force', 'boolean', 'force',
33 _("force to get the sources of the products in development mode."))
35 def get_source_for_dev(config, product_info, source_dir, force, logger, pad):
36 '''The method called if the product is in development mode
38 :param config Config: The global configuration
39 :param product_info Config: The configuration specific to
40 the product to be prepared
41 :param source_dir Path: The Path instance corresponding to the
42 directory where to put the sources
43 :param force boolean: True if the --force option was invoked
44 :param logger Logger: The logger instance to use for the display and logging
45 :param pad int: The gap to apply for the terminal display
46 :return: True if it succeed, else False
50 # if the product source directory does not exist,
51 # get it in checkout mode, else, do not do anything
52 # unless the force option is invoked
53 if not os.path.exists(product_info.source_dir) or force:
54 # If the source path exists (it means that force option is invoked)
55 # remove the source path
56 if source_dir.exists():
59 # Call the function corresponding to get the sources with True checkout
60 retcode = get_product_sources(config,
68 logger.write("\n", 3, False)
69 # +2 because product name is followed by ': '
70 logger.write(" " * (pad+2), 3, False)
72 logger.write('dev: %s ... ' %
73 src.printcolors.printcInfo(product_info.source_dir), 3, False)
78 def get_source_from_git(product_info, source_dir, logger, pad, is_dev=False):
79 '''The method called if the product is to be get in git mode
81 :param product_info Config: The configuration specific to
82 the product to be prepared
83 :param source_dir Path: The Path instance corresponding to the
84 directory where to put the sources
85 :param logger Logger: The logger instance to use for the display and logging
86 :param pad int: The gap to apply for the terminal display
87 :param is_dev boolean: True if the product is in development mode
88 :return: True if it succeed, else False
94 # Get the repository address. (from repo_dev key if the product is
96 if is_dev and 'repo_dev' in product_info.git_info:
97 coflag = src.printcolors.printcHighlight(coflag.upper())
98 repo_git = product_info.git_info.repo_dev
100 repo_git = product_info.git_info.repo
102 # Display informations
103 logger.write('%s:%s' % (coflag, src.printcolors.printcInfo(repo_git)), 3,
105 logger.write(' ' * (pad + 50 - len(repo_git)), 3, False)
106 logger.write(' tag:%s' % src.printcolors.printcInfo(
107 product_info.git_info.tag),
110 logger.write(' %s. ' % ('.' * (10 - len(product_info.git_info.tag))), 3,
113 logger.write('\n', 5, False)
114 # Call the system function that do the extraction in git mode
115 retcode = src.system.git_extract(repo_git,
116 product_info.git_info.tag,
120 def get_source_from_archive(product_info, source_dir, logger):
121 '''The method called if the product is to be get in archive mode
123 :param product_info Config: The configuration specific to
124 the product to be prepared
125 :param source_dir Path: The Path instance corresponding to the
126 directory where to put the sources
127 :param logger Logger: The logger instance to use for the display and logging
128 :return: True if it succeed, else False
131 # check archive exists
132 if not os.path.exists(product_info.archive_info.archive_name):
133 raise src.SatException(_("Archive not found: '%s'") %
134 product_info.archive_info.archive_name)
136 logger.write('arc:%s ... ' %
137 src.printcolors.printcInfo(product_info.archive_info.archive_name),
141 # Call the system function that do the extraction in archive mode
142 retcode, NameExtractedDirectory = src.system.archive_extract(
143 product_info.archive_info.archive_name,
144 source_dir.dir(), logger)
146 # Rename the source directory if
147 # it does not match with product_info.source_dir
148 if (NameExtractedDirectory.replace('/', '') !=
149 os.path.basename(product_info.source_dir)):
150 shutil.move(os.path.join(os.path.dirname(product_info.source_dir),
151 NameExtractedDirectory),
152 product_info.source_dir)
156 def get_source_from_cvs(user, product_info, source_dir, checkout, logger, pad):
157 '''The method called if the product is to be get in cvs mode
159 :param user str: The user to use in for the cvs command
160 :param product_info Config: The configuration specific to
161 the product to be prepared
162 :param source_dir Path: The Path instance corresponding to the
163 directory where to put the sources
164 :param checkout boolean: If True, get the source in checkout mode
165 :param logger Logger: The logger instance to use for the display and logging
166 :param pad int: The gap to apply for the terminal display
167 :return: True if it succeed, else False
170 # Get the protocol to use in the command
171 if "protocol" in product_info.cvs_info:
172 protocol = product_info.cvs_info.protocol
176 # Construct the line to display
177 if "protocol" in product_info.cvs_info:
178 cvs_line = "%s:%s@%s:%s" % \
179 (protocol, user, product_info.cvs_info.server,
180 product_info.cvs_info.product_base)
182 cvs_line = "%s / %s" % (product_info.cvs_info.server,
183 product_info.cvs_info.product_base)
186 if checkout: coflag = src.printcolors.printcHighlight(coflag.upper())
188 logger.write('%s:%s' % (coflag, src.printcolors.printcInfo(cvs_line)),
191 logger.write(' ' * (pad + 50 - len(cvs_line)), 3, False)
192 logger.write(' src:%s' %
193 src.printcolors.printcInfo(product_info.cvs_info.source),
196 logger.write(' ' * (pad + 1 - len(product_info.cvs_info.source)), 3, False)
197 logger.write(' tag:%s' %
198 src.printcolors.printcInfo(product_info.cvs_info.tag),
201 # at least one '.' is visible
202 logger.write(' %s. ' % ('.' * (10 - len(product_info.cvs_info.tag))),
206 logger.write('\n', 5, False)
208 # Call the system function that do the extraction in cvs mode
209 retcode = src.system.cvs_extract(protocol, user,
210 product_info.cvs_info.server,
211 product_info.cvs_info.product_base,
212 product_info.cvs_info.tag,
213 product_info.cvs_info.source,
214 source_dir, logger, checkout)
217 def get_source_from_svn(user, product_info, source_dir, checkout, logger):
218 '''The method called if the product is to be get in svn mode
220 :param user str: The user to use in for the svn command
221 :param product_info Config: The configuration specific to
222 the product to be prepared
223 :param source_dir Path: The Path instance corresponding to the
224 directory where to put the sources
225 :param checkout boolean: If True, get the source in checkout mode
226 :param logger Logger: The logger instance to use for the display and logging
227 :return: True if it succeed, else False
231 if checkout: coflag = src.printcolors.printcHighlight(coflag.upper())
233 logger.write('%s:%s ... ' % (coflag,
234 src.printcolors.printcInfo(
235 product_info.svn_info.repo)),
239 logger.write('\n', 5, False)
240 # Call the system function that do the extraction in svn mode
241 retcode = src.system.svn_extract(user,
242 product_info.svn_info.repo,
243 product_info.svn_info.tag,
249 def get_product_sources(config,
257 '''Get the product sources.
259 :param config Config: The global configuration
260 :param product_info Config: The configuration specific to
261 the product to be prepared
262 :param is_dev boolean: True if the product is in development mode
263 :param source_dir Path: The Path instance corresponding to the
264 directory where to put the sources
265 :param force boolean: True if the --force option was invoked
266 :param logger Logger: The logger instance to use for the display and logging
267 :param pad int: The gap to apply for the terminal display
268 :param checkout boolean: If True, get the source in checkout mode
269 :return: True if it succeed, else False
272 if not checkout and is_dev:
273 return get_source_for_dev(config,
280 if product_info.get_source == "git":
281 return get_source_from_git(product_info, source_dir, logger, pad,
284 if product_info.get_source == "archive":
285 return get_source_from_archive(product_info, source_dir, logger)
287 if product_info.get_source == "cvs":
288 cvs_user = config.USER.cvs_user
289 return get_source_from_cvs(cvs_user,
296 if product_info.get_source == "svn":
297 svn_user = config.USER.svn_user
298 return get_source_from_svn(svn_user, product_info, source_dir,
302 if product_info.get_source == "native":
304 logger.write('%s ...' % _("native (ignored)"), 3, False)
307 if product_info.get_source == "fixed":
309 logger.write('%s ...' % _("fixed (ignored)"), 3, False)
312 # if the get_source is not in [git, archive, cvs, svn, fixed, native]
313 logger.write(_("Unknown get source method \"%(get)s\" for product %(product)s") % \
314 { 'get': product_info.get_source, 'product': product_info.name }, 3, False)
315 logger.write(" ... ", 3, False)
319 def get_all_product_sources(config, products, force, logger):
320 '''Get all the product sources.
322 :param config Config: The global configuration
323 :param products List: The list of tuples (product name, product informations)
324 :param force boolean: True if the --force option was invoked
325 :param logger Logger: The logger instance to be used for the logging
326 :return: the tuple (number of success, dictionary product_name/success_fail)
330 # Initialize the variables that will count the fails and success
334 # Get the maximum name length in order to format the terminal display
335 max_product_name_len = 1
336 if len(products) > 0:
337 max_product_name_len = max(map(lambda l: len(l), products[0])) + 4
339 # The loop on all the products from which to get the sources
340 for product_name, product_info in products:
341 # get product name, product informations and the directory where to put
343 if (not (src.product.product_is_fixed(product_info) or
344 src.product.product_is_native(product_info))):
345 source_dir = src.Path(product_info.source_dir)
347 source_dir = src.Path('')
350 logger.write('%s: ' % src.printcolors.printcLabel(product_name), 3)
351 logger.write(' ' * (max_product_name_len - len(product_name)), 3, False)
352 logger.write("\n", 4, False)
354 # Remove the existing source directory if
355 # the product is not in development mode
356 is_dev = src.product.product_is_dev(product_info)
357 if source_dir.exists() and not is_dev:
358 logger.write(" " + _('remove %s') % source_dir, 4)
359 logger.write("\n ", 4, False)
362 # Call to the function that get the sources for one product
363 retcode = get_product_sources(config,
369 max_product_name_len,
373 if 'no_rpath' in product_info.keys():
374 if product_info.no_rpath:
375 hack_no_rpath(config, product_info, logger)
379 results[product_name] = retcode
381 # The case where the product was not prepared because it is
382 # in development mode
383 res =(src.printcolors.printc(src.OK_STATUS) +
384 src.printcolors.printcWarning(_(
385 ' source directory already exists')))
386 good_result = good_result + 1
388 # The case where it succeed
390 good_result = good_result + 1
392 # The case where it failed
396 logger.write('%s\n' % src.printcolors.printc(res), 3, False)
398 return good_result, results
401 '''method that is called when salomeTools is called with --help option.
403 :return: The text to display for the source command description.
406 return _("The source command gets the sources of the application products "
407 "from cvs, git, an archive or a directory..")
409 def run(args, runner, logger):
410 '''method that is called when salomeTools is called with source parameter.
413 (options, args) = parser.parse_args(args)
415 # check that the command has been called with an application
416 src.check_config_has_application( runner.cfg )
418 # Print some informations
419 logger.write(_('Getting sources of the application %s\n') %
420 src.printcolors.printcLabel(runner.cfg.VARS.application), 1)
421 src.printcolors.print_value(logger, 'out_dir',
422 runner.cfg.APPLICATION.out_dir, 2)
423 logger.write("\n", 2, False)
425 # Get the force option if it was passed
426 force = options.force
428 msg = _("Warning: the --force option has effect only "
429 "on products in development mode\n\n")
430 logger.write(src.printcolors.printcWarning(msg))
432 # Get the products list with products informations regarding the options
433 products_infos = prepare.get_products_list(options, runner.cfg, logger)
435 # Call to the function that gets all the sources
436 good_result, results = get_all_product_sources(runner.cfg,
441 # Display the results (how much passed, how much failed, etc...)
442 status = src.OK_STATUS
445 logger.write("\n", 2, False)
446 if good_result == len(products_infos):
447 res_count = "%d / %d" % (good_result, good_result)
449 status = src.KO_STATUS
450 res_count = "%d / %d" % (good_result, len(products_infos))
452 for product in results:
453 if results[product] == 0 or results[product] is None:
454 details.append(product)
456 result = len(products_infos) - good_result
459 logger.write(_("Getting sources of the application:"), 1)
460 logger.write(" " + src.printcolors.printc(status), 1, False)
461 logger.write(" (%s)\n" % res_count, 1, False)
464 logger.write(_("Following sources haven't been get:\n"), 2)
465 logger.write(" ".join(details), 2)
466 logger.write("\n", 2, False)