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
32 ARCHIVE_DIR = "ARCHIVES"
33 PROJECT_DIR = "PROJECT"
35 PROJECT_TEMPLATE = """#!/usr/bin/env python
38 # The path to the archive root directory
39 root_path : $PWD + "/../"
41 project_path : $PWD + "/"
43 # Where to search the archives of the products
44 ARCHIVEPATH : $root_path + "ARCHIVES"
45 # Where to search the pyconf of the applications
46 APPLICATIONPATH : $project_path + "applications/"
47 # Where to search the pyconf of the products
48 PRODUCTPATH : $project_path + "products/"
49 # Where to search the pyconf of the jobs of the project
50 JOBPATH : $project_path + "jobs/"
51 # Where to search the pyconf of the machines of the project
52 MACHINEPATH : $project_path + "machines/"
55 SITE_TEMPLATE = ("""#!/usr/bin/env python
62 log_dir : $USER.workdir + "/LOGS"
65 tmp_dir_with_application : '/tmp' + $VARS.sep + $VARS.user + """
66 """$VARS.sep + $APPLICATION.name + $VARS.sep + 'test'
67 tmp_dir : '/tmp' + $VARS.sep + $VARS.user + $VARS.sep + 'test'
74 project_file_paths : [$VARS.salometoolsway + $VARS.sep + \"..\" + $VARS.sep"""
75 """ + \"""" + PROJECT_DIR + """\" + $VARS.sep + "project.pyconf"]
79 # Define all possible option for the package command : sat package <options>
80 parser = src.options.Options()
81 parser.add_option('b', 'binaries', 'boolean', 'binaries',
82 _('Produce a binary package.'), False)
83 parser.add_option('f', 'force_creation', 'boolean', 'force_creation',
84 _('Only binary package: produce the archive even if there are some missing '
86 parser.add_option('', 'with_sources', 'boolean', 'with_sources',
87 _('Only binary package: produce and and a source archive in the binary '
89 parser.add_option('s', 'sources', 'boolean', 'sources',
90 _('Produce a compilable archive of the sources of the application.'), False)
91 parser.add_option('', 'with_vcs', 'boolean', 'with_vcs',
92 _('Only source package: do not make archive of vcs products.'), False)
93 parser.add_option('p', 'project', 'string', 'project',
94 _('Produce an archive that contains a project.'), "")
95 parser.add_option('t', 'salometools', 'boolean', 'sat',
96 _('Produce an archive that contains salomeTools.'), False)
97 parser.add_option('n', 'name', 'string', 'name',
98 _('The name or full path of the archive.'), None)
100 def add_files(tar, name_archive, d_content, logger):
101 '''Create an archive containing all directories and files that are given in
102 the d_content argument.
104 :param tar tarfile: The tarfile instance used to make the archive.
105 :param name_archive str: The name of the archive to make.
106 :param d_content dict: The dictionary that contain all directories and files
107 to add in the archive.
109 (path_on_local_machine, path_in_archive)
110 :param logger Logger: the logging instance
111 :return: 0 if success, 1 if not.
114 # get the max length of the messages in order to make the display
115 max_len = len(max(d_content.keys(), key=len))
118 # loop over each directory or file stored in the d_content dictionary
119 for name in d_content.keys():
120 # display information
121 len_points = max_len - len(name)
122 logger.write(name + " " + len_points * "." + " ", 3)
123 # Get the local path and the path in archive
124 # of the directory or file to add
125 local_path, archive_path = d_content[name]
126 in_archive = os.path.join(name_archive, archive_path)
127 # Add it in the archive
129 tar.add(local_path, arcname=in_archive)
130 logger.write(src.printcolors.printcSuccess(_("OK")), 3)
131 except Exception as e:
132 logger.write(src.printcolors.printcError(_("KO ")), 3)
133 logger.write(str(e), 3)
135 logger.write("\n", 3)
138 def produce_relative_launcher(config,
143 '''Create a specific SALOME launcher for the binary package. This launcher
146 :param config Config: The global configuration.
147 :param logger Logger: the logging instance
148 :param file_dir str: the directory where to put the launcher
149 :param file_name str: The launcher name
150 :param binaries_dir_name str: the name of the repository where the binaries
152 :return: the path of the produced launcher
156 # Get the launcher template
157 profile_install_dir = os.path.join(binaries_dir_name,
158 config.APPLICATION.profile.product)
159 withProfile = src.fileEnviron.withProfile
160 withProfile = withProfile.replace(
161 "ABSOLUTE_APPLI_PATH'] = 'PROFILE_INSTALL_DIR'",
162 "ABSOLUTE_APPLI_PATH'] = out_dir_Path + '" + config.VARS.sep + profile_install_dir + "'")
163 withProfile = withProfile.replace(
164 "os.path.join( 'PROFILE_INSTALL_DIR'",
165 "os.path.join( out_dir_Path, '" + profile_install_dir + "'")
167 before, after = withProfile.split(
168 "# here your local standalone environment\n")
170 # create an environment file writer
171 writer = src.environment.FileEnvWriter(config,
176 filepath = os.path.join(file_dir, file_name)
177 # open the file and write into it
178 launch_file = open(filepath, "w")
179 launch_file.write(before)
181 writer.write_cfgForPy_file(launch_file, for_package = binaries_dir_name)
182 launch_file.write(after)
185 # Little hack to put out_dir_Path outside the strings
186 src.replace_in_file(filepath, 'r"out_dir_Path', 'out_dir_Path + r"' )
188 # change the rights in order to make the file executable for everybody
200 def binary_package(config, logger, options, tmp_working_dir):
201 '''Prepare a dictionary that stores all the needed directories and files to
202 add in a binary package.
204 :param config Config: The global configuration.
205 :param logger Logger: the logging instance
206 :param options OptResult: the options of the launched command
207 :param tmp_working_dir str: The temporary local directory containing some
208 specific directories or files needed in the
210 :return: the dictionary that stores all the needed directories and files to
211 add in a binary package.
212 {label : (path_on_local_machine, path_in_archive)}
216 # Get the list of product installation to add to the archive
217 l_products_name = config.APPLICATION.products.keys()
218 l_product_info = src.product.get_products_infos(l_products_name,
222 for prod_name, prod_info in l_product_info:
223 # ignore the native and fixed products
224 if (src.product.product_is_native(prod_info)
225 or src.product.product_is_fixed(prod_info)):
227 if src.product.check_installation(prod_info):
228 l_install_dir.append((prod_name, prod_info.install_dir))
230 l_not_installed.append(prod_name)
232 # Print warning or error if there are some missing products
233 if len(l_not_installed) > 0:
234 text_missing_prods = ""
235 for p_name in l_not_installed:
236 text_missing_prods += "-" + p_name + "\n"
237 if not options.force_creation:
238 msg = _("ERROR: there are missing products installations:")
239 logger.write("%s\n%s" % (src.printcolors.printcError(msg),
244 msg = _("WARNING: there are missing products installations:")
245 logger.write("%s\n%s" % (src.printcolors.printcWarning(msg),
249 # construct the name of the directory that will contain the binaries
250 binaries_dir_name = "BINARIES-" + config.VARS.dist
252 # construct the correlation table between the product names, there
253 # actual install directories and there install directory in archive
255 for prod_name, install_dir in l_install_dir:
256 path_in_archive = os.path.join(binaries_dir_name, prod_name)
257 d_products[prod_name] = (install_dir, path_in_archive)
259 # create the relative launcher and add it to the files to add
260 if "profile" in config.APPLICATION:
261 launcher_name = config.APPLICATION.profile.launcher_name
262 launcher_package = produce_relative_launcher(config,
268 d_products["launcher"] = (launcher_package, launcher_name)
272 def source_package(sat, config, logger, options, tmp_working_dir):
273 '''Prepare a dictionary that stores all the needed directories and files to
274 add in a source package.
276 :param config Config: The global configuration.
277 :param logger Logger: the logging instance
278 :param options OptResult: the options of the launched command
279 :param tmp_working_dir str: The temporary local directory containing some
280 specific directories or files needed in the
282 :return: the dictionary that stores all the needed directories and files to
283 add in a source package.
284 {label : (path_on_local_machine, path_in_archive)}
288 # Get all the products that are prepared using an archive
289 logger.write("Find archive products ... ")
290 d_archives, l_pinfo_vcs = get_archives(config, logger)
291 logger.write("Done\n")
293 if not options.with_vcs and len(l_pinfo_vcs) > 0:
294 # Make archives with the products that are not prepared using an archive
295 # (git, cvs, svn, etc)
296 logger.write("Construct archives for vcs products ... ")
297 d_archives_vcs = get_archives_vcs(l_pinfo_vcs,
302 logger.write("Done\n")
305 logger.write("Create the project ... ")
306 d_project = create_project_for_src_package(config,
309 logger.write("Done\n")
312 tmp_sat = add_salomeTools(config, tmp_working_dir)
313 d_sat = {"salomeTools" : (tmp_sat, "salomeTools")}
315 # Add a sat symbolic link
316 tmp_satlink_path = os.path.join(tmp_working_dir, 'sat')
318 os.chdir(tmp_working_dir)
319 if os.path.lexists(tmp_satlink_path):
320 os.remove(tmp_satlink_path)
321 os.symlink(os.path.join('salomeTools', 'sat'), 'sat')
324 d_sat["sat link"] = (tmp_satlink_path, "sat")
326 return src.merge_dicts(d_archives, d_archives_vcs, d_project, d_sat)
328 def get_archives(config, logger):
329 '''Find all the products that are get using an archive and all the products
330 that are get using a vcs (git, cvs, svn) repository.
332 :param config Config: The global configuration.
333 :param logger Logger: the logging instance
334 :return: the dictionary {name_product :
335 (local path of its archive, path in the package of its archive )}
336 and the list of specific configuration corresponding to the vcs
340 # Get the list of product informations
341 l_products_name = config.APPLICATION.products.keys()
342 l_product_info = src.product.get_products_infos(l_products_name,
346 for p_name, p_info in l_product_info:
347 # ignore the native and fixed products
348 if (src.product.product_is_native(p_info)
349 or src.product.product_is_fixed(p_info)):
351 if p_info.get_source == "archive":
352 archive_path = p_info.archive_info.archive_name
353 archive_name = os.path.basename(archive_path)
355 l_pinfo_vcs.append((p_name, p_info))
357 d_archives[p_name] = (archive_path,
358 os.path.join(ARCHIVE_DIR, archive_name))
359 return d_archives, l_pinfo_vcs
361 def add_salomeTools(config, tmp_working_dir):
362 '''Prepare a version of salomeTools that has a specific site.pyconf file
363 configured for a source package.
365 :param config Config: The global configuration.
366 :param tmp_working_dir str: The temporary local directory containing some
367 specific directories or files needed in the
369 :return: The path to the local salomeTools directory to add in the package
372 # Copy sat in the temporary working directory
373 sat_tmp_path = src.Path(os.path.join(tmp_working_dir, "salomeTools"))
374 sat_running_path = src.Path(config.VARS.salometoolsway)
375 sat_running_path.copy(sat_tmp_path)
377 # Update the site.pyconf file that contains the path to the project
378 site_pyconf_name = "site.pyconf"
379 site_pyconf_dir = os.path.join(tmp_working_dir, "salomeTools", "data")
380 site_pyconf_file = os.path.join(site_pyconf_dir, site_pyconf_name)
381 ff = open(site_pyconf_file, "w")
382 ff.write(SITE_TEMPLATE)
385 return sat_tmp_path.path
387 def get_archives_vcs(l_pinfo_vcs, sat, config, logger, tmp_working_dir):
388 '''For sources package that require that all products are get using an
389 archive, one has to create some archive for the vcs products.
390 So this method calls the clean and source command of sat and then create
393 :param l_pinfo_vcs List: The list of specific configuration corresponding to
395 :param sat Sat: The Sat instance that can be called to clean and source the
397 :param config Config: The global configuration.
398 :param logger Logger: the logging instance
399 :param tmp_working_dir str: The temporary local directory containing some
400 specific directories or files needed in the
402 :return: the dictionary that stores all the archives to add in the source
403 package. {label : (path_on_local_machine, path_in_archive)}
406 # clean the source directory of all the vcs products, then use the source
407 # command and thus construct an archive that will not contain the patches
408 l_prod_names = [pn for pn, __ in l_pinfo_vcs]
410 logger.write(_("clean sources\n"))
411 args_clean = config.VARS.application
412 args_clean += " --sources --products "
413 args_clean += ",".join(l_prod_names)
414 sat.clean(args_clean, batch=True, verbose=0, logger_add_link = logger)
416 logger.write(_("get sources"))
417 args_source = config.VARS.application
418 args_source += " --products "
419 args_source += ",".join(l_prod_names)
420 sat.source(args_source, batch=True, verbose=0, logger_add_link = logger)
422 # make the new archives
424 for pn, pinfo in l_pinfo_vcs:
425 path_archive = make_archive(pn, pinfo, tmp_working_dir)
426 d_archives_vcs[pn] = (path_archive,
427 os.path.join(ARCHIVE_DIR, pn + ".tgz"))
428 return d_archives_vcs
430 def make_archive(prod_name, prod_info, where):
431 '''Create an archive of a product by searching its source directory.
433 :param prod_name str: The name of the product.
434 :param prod_info Config: The specific configuration corresponding to the
436 :param where str: The path of the repository where to put the resulting
438 :return: The path of the resulting archive
441 path_targz_prod = os.path.join(where, prod_name + ".tgz")
442 tar_prod = tarfile.open(path_targz_prod, mode='w:gz')
443 local_path = prod_info.source_dir
444 tar_prod.add(local_path, arcname=prod_name)
446 return path_targz_prod
448 def create_project_for_src_package(config, tmp_working_dir, with_vcs):
449 '''Create a specific project for a source package.
451 :param config Config: The global configuration.
452 :param tmp_working_dir str: The temporary local directory containing some
453 specific directories or files needed in the
455 :param with_vcs boolean: True if the package is with vcs products (not
456 transformed into archive products)
457 :return: The dictionary
458 {"project" : (produced project, project path in the archive)}
462 # Create in the working temporary directory the full project tree
463 project_tmp_dir = os.path.join(tmp_working_dir, PROJECT_DIR)
464 products_pyconf_tmp_dir = os.path.join(project_tmp_dir,
466 compil_scripts_tmp_dir = os.path.join(project_tmp_dir,
469 env_scripts_tmp_dir = os.path.join(project_tmp_dir,
472 patches_tmp_dir = os.path.join(project_tmp_dir,
475 application_tmp_dir = os.path.join(project_tmp_dir,
477 for directory in [project_tmp_dir,
478 compil_scripts_tmp_dir,
481 application_tmp_dir]:
482 src.ensure_path_exists(directory)
484 # Create the pyconf that contains the information of the project
485 project_pyconf_name = "project.pyconf"
486 project_pyconf_file = os.path.join(project_tmp_dir, project_pyconf_name)
487 ff = open(project_pyconf_file, "w")
488 ff.write(PROJECT_TEMPLATE)
491 # Loop over the products to get there pyconf and all the scripts
492 # (compilation, environment, patches)
493 # and create the pyconf file to add to the project
494 lproducts_name = config.APPLICATION.products.keys()
495 l_products = src.product.get_products_infos(lproducts_name, config)
496 for p_name, p_info in l_products:
497 # ignore native and fixed products
498 if (src.product.product_is_native(p_info) or
499 src.product.product_is_fixed(p_info)):
501 find_product_scripts_and_pyconf(p_name,
505 compil_scripts_tmp_dir,
508 products_pyconf_tmp_dir)
510 find_application_pyconf(config, application_tmp_dir)
512 d_project = {"project" : (project_tmp_dir, PROJECT_DIR )}
515 def find_product_scripts_and_pyconf(p_name,
519 compil_scripts_tmp_dir,
522 products_pyconf_tmp_dir):
523 '''Create a specific pyconf file for a given product. Get its environment
524 script, its compilation script and patches and put it in the temporary
525 working directory. This method is used in the source package in order to
526 construct the specific project.
528 :param p_name str: The name of the product.
529 :param p_info Config: The specific configuration corresponding to the
531 :param config Config: The global configuration.
532 :param with_vcs boolean: True if the package is with vcs products (not
533 transformed into archive products)
534 :param compil_scripts_tmp_dir str: The path to the temporary compilation
535 scripts directory of the project.
536 :param env_scripts_tmp_dir str: The path to the temporary environment script
537 directory of the project.
538 :param patches_tmp_dir str: The path to the temporary patch scripts
539 directory of the project.
540 :param products_pyconf_tmp_dir str: The path to the temporary product
541 scripts directory of the project.
544 # read the pyconf of the product
545 product_pyconf_path = src.find_file_in_lpath(p_name + ".pyconf",
546 config.PATHS.PRODUCTPATH)
547 product_pyconf_cfg = src.pyconf.Config(product_pyconf_path)
549 # find the compilation script if any
550 if src.product.product_has_script(p_info):
551 compil_script_path = src.Path(p_info.compil_script)
552 compil_script_path.copy(compil_scripts_tmp_dir)
553 product_pyconf_cfg[p_info.section].compil_script = os.path.basename(
554 p_info.compil_script)
555 # find the environment script if any
556 if src.product.product_has_env_script(p_info):
557 env_script_path = src.Path(p_info.environ.env_script)
558 env_script_path.copy(env_scripts_tmp_dir)
559 product_pyconf_cfg[p_info.section].environ.env_script = os.path.basename(
560 p_info.environ.env_script)
561 # find the patches if any
562 if src.product.product_has_patches(p_info):
563 patches = src.pyconf.Sequence()
564 for patch_path in p_info.patches:
565 p_path = src.Path(patch_path)
566 p_path.copy(patches_tmp_dir)
567 patches.append(os.path.basename(patch_path), "")
569 product_pyconf_cfg[p_info.section].patches = patches
572 # put in the pyconf file the resolved values
573 for info in ["git_info", "cvs_info", "svn_info"]:
575 for key in p_info[info]:
576 product_pyconf_cfg[p_info.section][info][key] = p_info[
579 # if the product is not archive, then make it become archive.
580 if src.product.product_is_vcs(p_info):
581 product_pyconf_cfg[p_info.section].get_source = "archive"
582 if not "archive_info" in product_pyconf_cfg[p_info.section]:
583 product_pyconf_cfg[p_info.section].addMapping("archive_info",
584 src.pyconf.Mapping(product_pyconf_cfg),
586 product_pyconf_cfg[p_info.section
587 ].archive_info.archive_name = p_info.name + ".tgz"
589 # write the pyconf file to the temporary project location
590 product_tmp_pyconf_path = os.path.join(products_pyconf_tmp_dir,
592 ff = open(product_tmp_pyconf_path, 'w')
593 ff.write("#!/usr/bin/env python\n#-*- coding:utf-8 -*-\n\n")
594 product_pyconf_cfg.__save__(ff, 1)
597 def find_application_pyconf(config, application_tmp_dir):
598 '''Find the application pyconf file and put it in the specific temporary
599 directory containing the specific project of a source package.
601 :param config Config: The global configuration.
602 :param application_tmp_dir str: The path to the temporary application
603 scripts directory of the project.
605 # read the pyconf of the application
606 application_name = config.VARS.application
607 application_pyconf_path = src.find_file_in_lpath(
608 application_name + ".pyconf",
609 config.PATHS.APPLICATIONPATH)
610 application_pyconf_cfg = src.pyconf.Config(application_pyconf_path)
613 application_pyconf_cfg.APPLICATION.workdir = src.pyconf.Reference(
614 application_pyconf_cfg,
616 'VARS.salometoolsway + $VARS.sep + ".."')
618 # Prevent from compilation in base
619 application_pyconf_cfg.APPLICATION.no_base = "yes"
621 # write the pyconf file to the temporary application location
622 application_tmp_pyconf_path = os.path.join(application_tmp_dir,
623 application_name + ".pyconf")
624 ff = open(application_tmp_pyconf_path, 'w')
625 ff.write("#!/usr/bin/env python\n#-*- coding:utf-8 -*-\n\n")
626 application_pyconf_cfg.__save__(ff, 1)
629 def project_package(project_file_path, tmp_working_dir):
630 '''Prepare a dictionary that stores all the needed directories and files to
631 add in a project package.
633 :param project_file_path str: The path to the local project.
634 :param tmp_working_dir str: The temporary local directory containing some
635 specific directories or files needed in the
637 :return: the dictionary that stores all the needed directories and files to
638 add in a project package.
639 {label : (path_on_local_machine, path_in_archive)}
643 # Read the project file and get the directories to add to the package
644 project_pyconf_cfg = src.pyconf.Config(project_file_path)
645 paths = {"ARCHIVEPATH" : "archives",
646 "APPLICATIONPATH" : "applications",
647 "PRODUCTPATH" : "products",
649 "MACHINEPATH" : "machines"}
650 # Loop over the project paths and add it
652 if path not in project_pyconf_cfg:
654 # Add the directory to the files to add in the package
655 d_project[path] = (project_pyconf_cfg[path], paths[path])
656 # Modify the value of the path in the package
657 project_pyconf_cfg[path] = src.pyconf.Reference(
660 'project_path + "/' + paths[path] + '"')
663 if "project_path" not in project_pyconf_cfg:
664 project_pyconf_cfg.addMapping("project_path",
665 src.pyconf.Mapping(project_pyconf_cfg),
667 project_pyconf_cfg.project_path = src.pyconf.Reference(project_pyconf_cfg,
671 # Write the project pyconf file
672 project_file_name = os.path.basename(project_file_path)
673 project_pyconf_tmp_path = os.path.join(tmp_working_dir, project_file_name)
674 ff = open(project_pyconf_tmp_path, 'w')
675 ff.write("#!/usr/bin/env python\n#-*- coding:utf-8 -*-\n\n")
676 project_pyconf_cfg.__save__(ff, 1)
678 d_project["Project hat file"] = (project_pyconf_tmp_path, project_file_name)
682 def add_readme(config, package_type, where):
683 readme_path = os.path.join(where, "README")
684 f = open(readme_path, 'w')
685 # prepare substitution dictionary
687 if package_type == BINARY:
688 d['application'] = config.VARS.application
689 d['user'] = config.VARS.user
690 d['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
691 d['version'] = config.INTERNAL.sat_version
692 d['dist'] = config.VARS.dist
693 if 'profile' in config.APPLICATION:
694 d['launcher'] = config.APPLICATION.profile.launcher_name
695 readme_template_path = os.path.join(config.VARS.internal_dir,
696 "README_BIN.template")
697 if package_type == SOURCE:
698 d['application'] = config.VARS.application
699 d['user'] = config.VARS.user
700 d['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
701 d['version'] = config.INTERNAL.sat_version
702 if 'profile' in config.APPLICATION:
703 d['profile'] = config.APPLICATION.profile.product
704 d['launcher'] = config.APPLICATION.profile.launcher_name
705 readme_template_path = os.path.join(config.VARS.internal_dir,
706 "README_SRC.template")
708 if package_type == PROJECT:
709 d['user'] = config.VARS.user
710 d['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
711 d['version'] = config.INTERNAL.sat_version
712 readme_template_path = os.path.join(config.VARS.internal_dir,
713 "README_PROJECT.template")
715 if package_type == SAT:
716 d['user'] = config.VARS.user
717 d['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
718 d['version'] = config.INTERNAL.sat_version
719 readme_template_path = os.path.join(config.VARS.internal_dir,
720 "README_SAT.template")
722 f.write(src.template.substitute(readme_template_path, d))
728 '''method that is called when salomeTools is called with --help option.
730 :return: The text to display for the package command description.
733 return _("The package command creates an archive.\nThere are 4 kinds of "
734 "archive:\n 1- The binary archive. It contains all the product "
735 "installation directories and a launcher,\n 2- The sources archive."
736 " It contains the products archives, a project corresponding to "
737 "the application and salomeTools,\n 3- The project archive. It "
738 "contains a project (give the project file path as argument),\n 4-"
739 " The salomeTools archive. It contains salomeTools.")
741 def run(args, runner, logger):
742 '''method that is called when salomeTools is called with package parameter.
746 (options, args) = parser.parse_args(args)
748 # Check that a type of package is called, and only one
749 all_option_types = (options.binaries,
751 options.project not in ["", None],
754 # Check if no option for package type
755 if all_option_types.count(True) == 0:
756 msg = _("Error: Precise a type for the package\nUse one of the "
757 "following options: --binaries, --sources, --project or --sat")
758 logger.write(src.printcolors.printcError(msg), 1)
759 logger.write("\n", 1)
762 # Check for only one option for package type
763 if all_option_types.count(True) > 1:
764 msg = _("Error: You can use only one type for the package\nUse only one"
765 " of the following options: --binaries, --sources, --project or"
767 logger.write(src.printcolors.printcError(msg), 1)
768 logger.write("\n", 1)
771 # Get the package type
773 package_type = BINARY
775 package_type = SOURCE
777 package_type = PROJECT
781 # The repository where to put the package if not Binary or Source
782 package_default_path = runner.cfg.USER.workdir
784 if package_type in [BINARY, SOURCE]:
785 # Check that the command has been called with an application
786 src.check_config_has_application(runner.cfg)
788 # Display information
789 logger.write(_("Packaging application %s\n") % src.printcolors.printcLabel(
790 runner.cfg.VARS.application), 1)
792 # Get the default directory where to put the packages
793 package_default_path = os.path.join(runner.cfg.APPLICATION.workdir,
795 src.ensure_path_exists(package_default_path)
797 elif package_type == PROJECT:
798 # check that the project is visible by SAT
799 if options.project not in runner.cfg.PROJECTS.project_file_paths:
800 site_path = os.path.join(runner.cfg.VARS.salometoolsway,
803 msg = _("ERROR: the project %(proj)s is not visible by salomeTools."
804 "\nPlease add it in the %(site)s file." % {
805 "proj" : options.project, "site" : site_path})
806 logger.write(src.printcolors.printcError(msg), 1)
807 logger.write("\n", 1)
811 src.printcolors.print_value(logger, "Package type", package_type, 2)
813 # get the name of the archive or construct it
815 if os.path.basename(options.name) == options.name:
816 # only a name (not a path)
817 archive_name = options.name
818 dir_name = package_default_path
820 archive_name = os.path.basename(options.name)
821 dir_name = os.path.dirname(options.name)
824 if archive_name[-len(".tgz"):] == ".tgz":
825 archive_name = archive_name[:-len(".tgz")]
826 if archive_name[-len(".tar.gz"):] == ".tar.gz":
827 archive_name = archive_name[:-len(".tar.gz")]
830 dir_name = package_default_path
831 if package_type == BINARY:
832 archive_name = (runner.cfg.APPLICATION.name +
834 runner.cfg.VARS.dist)
836 if package_type == SOURCE:
837 archive_name = (runner.cfg.APPLICATION.name +
841 archive_name = (runner.cfg.APPLICATION.name +
847 if package_type == PROJECT:
848 project_name, __ = os.path.splitext(
849 os.path.basename(options.project))
850 archive_name = ("PROJECT" +
854 if package_type == SAT:
855 archive_name = ("salomeTools" +
857 runner.cfg.INTERNAL.sat_version)
859 path_targz = os.path.join(dir_name, archive_name + ".tgz")
861 # Print the path of the package
862 src.printcolors.print_value(logger, "Package path", path_targz, 2)
864 # Create a working directory for all files that are produced during the
865 # package creation and that will be removed at the end of the command
866 tmp_working_dir = os.path.join(runner.cfg.VARS.tmp_root,
867 runner.cfg.VARS.datehour)
868 src.ensure_path_exists(tmp_working_dir)
869 logger.write("\n", 5)
870 logger.write(_("The temporary working directory: %s\n" % tmp_working_dir),5)
872 logger.write("\n", 3)
874 msg = _("Preparation of files to add to the archive")
875 logger.write(src.printcolors.printcLabel(msg), 2)
876 logger.write("\n", 2)
878 if package_type == BINARY:
879 d_files_to_add = binary_package(runner.cfg,
883 if not(d_files_to_add):
886 # Create and add the source package
887 # if the option "with_sources" is called
888 if options.with_sources:
889 logger.write(_("Create a source archive (can be long) ... "), 3)
890 tmp_pkg_src_name = runner.cfg.APPLICATION.name + "-" + "SRC.tgz"
891 tmp_pkg_src_path = os.path.join(tmp_working_dir, tmp_pkg_src_name)
892 package_options = runner.cfg.VARS.application
893 package_options += " --sources --with_vcs --name "
894 package_options += tmp_pkg_src_path
895 # sat package <package_options>
896 runner.package(package_options,
899 logger_add_link = logger)
900 d_files_to_add["SOURCES PACKAGE"] = (tmp_pkg_src_path,
902 logger.write(src.printcolors.printc("OK"), 3)
903 logger.write("\n", 3)
905 if package_type == SOURCE:
906 d_files_to_add = source_package(runner,
912 if package_type == PROJECT:
913 d_files_to_add = project_package(options.project, tmp_working_dir)
915 if package_type == SAT:
916 d_files_to_add = {"salomeTools" : (runner.cfg.VARS.salometoolsway, "")}
918 # Add the README file in the package
919 local_readme_tmp_path = add_readme(runner.cfg,
922 d_files_to_add["README"] = (local_readme_tmp_path, "README")
924 logger.write("\n", 2)
926 logger.write(src.printcolors.printcLabel(_("Actually do the package")), 2)
927 logger.write("\n", 2)
930 # Creating the object tarfile
931 tar = tarfile.open(path_targz, mode='w:gz')
933 # Add the files to the tarfile object
934 res = add_files(tar, archive_name, d_files_to_add, logger)
936 except KeyboardInterrupt:
937 logger.write(src.printcolors.printcError("\nERROR: forced interruption\n"), 1)
938 logger.write(_("Removing the temporary working directory ... "), 1)
939 # remove the working directory
940 shutil.rmtree(tmp_working_dir)
941 logger.write(_("OK"), 1)
942 logger.write(_("\n"), 1)
945 # remove the working directory
946 shutil.rmtree(tmp_working_dir)
948 # Print again the path of the package
949 logger.write("\n", 2)
950 src.printcolors.print_value(logger, "Package path", path_targz, 2)