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 launcher_name = config.APPLICATION.profile.launcher_name
261 launcher_package = produce_relative_launcher(config,
267 d_products["launcher"] = (launcher_package, launcher_name)
271 def source_package(sat, config, logger, options, tmp_working_dir):
272 '''Prepare a dictionary that stores all the needed directories and files to
273 add in a source package.
275 :param config Config: The global configuration.
276 :param logger Logger: the logging instance
277 :param options OptResult: the options of the launched command
278 :param tmp_working_dir str: The temporary local directory containing some
279 specific directories or files needed in the
281 :return: the dictionary that stores all the needed directories and files to
282 add in a source package.
283 {label : (path_on_local_machine, path_in_archive)}
287 # Get all the products that are prepared using an archive
288 logger.write("Find archive products ... ")
289 d_archives, l_pinfo_vcs = get_archives(config, logger)
290 logger.write("Done\n")
292 if not options.with_vcs:
293 # Make archives with the products that are not prepared using an archive
294 # (git, cvs, svn, etc)
295 logger.write("Construct archives for vcs products ... ")
296 d_archives_vcs = get_archives_vcs(l_pinfo_vcs,
301 logger.write("Done\n")
304 logger.write("Create the project ... ")
305 d_project = create_project_for_src_package(config,
308 logger.write("Done\n")
311 tmp_sat = add_salomeTools(config, tmp_working_dir)
312 d_sat = {"salomeTools" : (tmp_sat, "salomeTools")}
314 # Add a sat symbolic link
315 tmp_satlink_path = os.path.join(tmp_working_dir, 'sat')
317 os.chdir(tmp_working_dir)
318 if os.path.lexists(tmp_satlink_path):
319 os.remove(tmp_satlink_path)
320 os.symlink(os.path.join('salomeTools', 'sat'), 'sat')
323 d_sat["sat link"] = (tmp_satlink_path, "sat")
325 return src.merge_dicts(d_archives, d_archives_vcs, d_project, d_sat)
327 def get_archives(config, logger):
328 '''Find all the products that are get using an archive and all the products
329 that are get using a vcs (git, cvs, svn) repository.
331 :param config Config: The global configuration.
332 :param logger Logger: the logging instance
333 :return: the dictionary {name_product :
334 (local path of its archive, path in the package of its archive )}
335 and the list of specific configuration corresponding to the vcs
339 # Get the list of product informations
340 l_products_name = config.APPLICATION.products.keys()
341 l_product_info = src.product.get_products_infos(l_products_name,
345 for p_name, p_info in l_product_info:
346 # ignore the native and fixed products
347 if (src.product.product_is_native(p_info)
348 or src.product.product_is_fixed(p_info)):
350 if p_info.get_source == "archive":
351 archive_path = p_info.archive_info.archive_name
352 archive_name = os.path.basename(archive_path)
354 l_pinfo_vcs.append((p_name, p_info))
356 d_archives[p_name] = (archive_path,
357 os.path.join(ARCHIVE_DIR, archive_name))
358 return d_archives, l_pinfo_vcs
360 def add_salomeTools(config, tmp_working_dir):
361 '''Prepare a version of salomeTools that has a specific site.pyconf file
362 configured for a source package.
364 :param config Config: The global configuration.
365 :param tmp_working_dir str: The temporary local directory containing some
366 specific directories or files needed in the
368 :return: The path to the local salomeTools directory to add in the package
371 # Copy sat in the temporary working directory
372 sat_tmp_path = src.Path(os.path.join(tmp_working_dir, "salomeTools"))
373 sat_running_path = src.Path(config.VARS.salometoolsway)
374 sat_running_path.copy(sat_tmp_path)
376 # Update the site.pyconf file that contains the path to the project
377 site_pyconf_name = "site.pyconf"
378 site_pyconf_dir = os.path.join(tmp_working_dir, "salomeTools", "data")
379 site_pyconf_file = os.path.join(site_pyconf_dir, site_pyconf_name)
380 ff = open(site_pyconf_file, "w")
381 ff.write(SITE_TEMPLATE)
384 return sat_tmp_path.path
386 def get_archives_vcs(l_pinfo_vcs, sat, config, logger, tmp_working_dir):
387 '''For sources package that require that all products are get using an
388 archive, one has to create some archive for the vcs products.
389 So this method calls the clean and source command of sat and then create
392 :param l_pinfo_vcs List: The list of specific configuration corresponding to
394 :param sat Sat: The Sat instance that can be called to clean and source the
396 :param config Config: The global configuration.
397 :param logger Logger: the logging instance
398 :param tmp_working_dir str: The temporary local directory containing some
399 specific directories or files needed in the
401 :return: the dictionary that stores all the archives to add in the source
402 package. {label : (path_on_local_machine, path_in_archive)}
405 # clean the source directory of all the vcs products, then use the source
406 # command and thus construct an archive that will not contain the patches
407 l_prod_names = [pn for pn, __ in l_pinfo_vcs]
409 logger.write(_("clean sources\n"))
410 args_clean = config.VARS.application
411 args_clean += " --sources --products "
412 args_clean += ",".join(l_prod_names)
413 sat.clean(args_clean, batch=True, verbose=0, logger_add_link = logger)
415 logger.write(_("get sources"))
416 args_source = config.VARS.application
417 args_source += " --products "
418 args_source += ",".join(l_prod_names)
419 sat.source(args_source, batch=True, verbose=0, logger_add_link = logger)
421 # make the new archives
423 for pn, pinfo in l_pinfo_vcs:
424 path_archive = make_archive(pn, pinfo, tmp_working_dir)
425 d_archives_vcs[pn] = (path_archive,
426 os.path.join(ARCHIVE_DIR, pn + ".tgz"))
427 return d_archives_vcs
429 def make_archive(prod_name, prod_info, where):
430 '''Create an archive of a product by searching its source directory.
432 :param prod_name str: The name of the product.
433 :param prod_info Config: The specific configuration corresponding to the
435 :param where str: The path of the repository where to put the resulting
437 :return: The path of the resulting archive
440 path_targz_prod = os.path.join(where, prod_name + ".tgz")
441 tar_prod = tarfile.open(path_targz_prod, mode='w:gz')
442 local_path = prod_info.source_dir
443 tar_prod.add(local_path, arcname=prod_name)
445 return path_targz_prod
447 def create_project_for_src_package(config, tmp_working_dir, with_vcs):
448 '''Create a specific project for a source package.
450 :param config Config: The global configuration.
451 :param tmp_working_dir str: The temporary local directory containing some
452 specific directories or files needed in the
454 :param with_vcs boolean: True if the package is with vcs products (not
455 transformed into archive products)
456 :return: The dictionary
457 {"project" : (produced project, project path in the archive)}
461 # Create in the working temporary directory the full project tree
462 project_tmp_dir = os.path.join(tmp_working_dir, PROJECT_DIR)
463 products_pyconf_tmp_dir = os.path.join(project_tmp_dir,
465 compil_scripts_tmp_dir = os.path.join(project_tmp_dir,
468 env_scripts_tmp_dir = os.path.join(project_tmp_dir,
471 patches_tmp_dir = os.path.join(project_tmp_dir,
474 application_tmp_dir = os.path.join(project_tmp_dir,
476 for directory in [project_tmp_dir,
477 compil_scripts_tmp_dir,
480 application_tmp_dir]:
481 src.ensure_path_exists(directory)
483 # Create the pyconf that contains the information of the project
484 project_pyconf_name = "project.pyconf"
485 project_pyconf_file = os.path.join(project_tmp_dir, project_pyconf_name)
486 ff = open(project_pyconf_file, "w")
487 ff.write(PROJECT_TEMPLATE)
490 # Loop over the products to get there pyconf and all the scripts
491 # (compilation, environment, patches)
492 # and create the pyconf file to add to the project
493 lproducts_name = config.APPLICATION.products.keys()
494 l_products = src.product.get_products_infos(lproducts_name, config)
495 for p_name, p_info in l_products:
496 # ignore native and fixed products
497 if (src.product.product_is_native(p_info) or
498 src.product.product_is_fixed(p_info)):
500 find_product_scripts_and_pyconf(p_name,
504 compil_scripts_tmp_dir,
507 products_pyconf_tmp_dir)
509 find_application_pyconf(config, application_tmp_dir)
511 d_project = {"project" : (project_tmp_dir, PROJECT_DIR )}
514 def find_product_scripts_and_pyconf(p_name,
518 compil_scripts_tmp_dir,
521 products_pyconf_tmp_dir):
522 '''Create a specific pyconf file for a given product. Get its environment
523 script, its compilation script and patches and put it in the temporary
524 working directory. This method is used in the source package in order to
525 construct the specific project.
527 :param p_name str: The name of the product.
528 :param p_info Config: The specific configuration corresponding to the
530 :param config Config: The global configuration.
531 :param with_vcs boolean: True if the package is with vcs products (not
532 transformed into archive products)
533 :param compil_scripts_tmp_dir str: The path to the temporary compilation
534 scripts directory of the project.
535 :param env_scripts_tmp_dir str: The path to the temporary environment script
536 directory of the project.
537 :param patches_tmp_dir str: The path to the temporary patch scripts
538 directory of the project.
539 :param products_pyconf_tmp_dir str: The path to the temporary product
540 scripts directory of the project.
543 # read the pyconf of the product
544 product_pyconf_path = src.find_file_in_lpath(p_name + ".pyconf",
545 config.PATHS.PRODUCTPATH)
546 product_pyconf_cfg = src.pyconf.Config(product_pyconf_path)
548 # find the compilation script if any
549 if src.product.product_has_script(p_info):
550 compil_script_path = src.Path(p_info.compil_script)
551 compil_script_path.copy(compil_scripts_tmp_dir)
552 product_pyconf_cfg[p_info.section].compil_script = os.path.basename(
553 p_info.compil_script)
554 # find the environment script if any
555 if src.product.product_has_env_script(p_info):
556 env_script_path = src.Path(p_info.environ.env_script)
557 env_script_path.copy(env_scripts_tmp_dir)
558 product_pyconf_cfg[p_info.section].environ.env_script = os.path.basename(
559 p_info.environ.env_script)
560 # find the patches if any
561 if src.product.product_has_patches(p_info):
562 patches = src.pyconf.Sequence()
563 for patch_path in p_info.patches:
564 p_path = src.Path(patch_path)
565 p_path.copy(patches_tmp_dir)
566 patches.append(os.path.basename(patch_path), "")
568 product_pyconf_cfg[p_info.section].patches = patches
571 # put in the pyconf file the resolved values
572 for info in ["git_info", "cvs_info", "svn_info"]:
574 for key in p_info[info]:
575 product_pyconf_cfg[p_info.section][info][key] = p_info[
578 # if the product is not archive, then make it become archive.
579 if src.product.product_is_vcs(p_info):
580 product_pyconf_cfg[p_info.section].get_source = "archive"
581 if not "archive_info" in product_pyconf_cfg[p_info.section]:
582 product_pyconf_cfg[p_info.section].addMapping("archive_info",
583 src.pyconf.Mapping(product_pyconf_cfg),
585 product_pyconf_cfg[p_info.section
586 ].archive_info.archive_name = p_info.name + ".tgz"
588 # write the pyconf file to the temporary project location
589 product_tmp_pyconf_path = os.path.join(products_pyconf_tmp_dir,
591 ff = open(product_tmp_pyconf_path, 'w')
592 ff.write("#!/usr/bin/env python\n#-*- coding:utf-8 -*-\n\n")
593 product_pyconf_cfg.__save__(ff, 1)
596 def find_application_pyconf(config, application_tmp_dir):
597 '''Find the application pyconf file and put it in the specific temporary
598 directory containing the specific project of a source package.
600 :param config Config: The global configuration.
601 :param application_tmp_dir str: The path to the temporary application
602 scripts directory of the project.
604 # read the pyconf of the application
605 application_name = config.VARS.application
606 application_pyconf_path = src.find_file_in_lpath(
607 application_name + ".pyconf",
608 config.PATHS.APPLICATIONPATH)
609 application_pyconf_cfg = src.pyconf.Config(application_pyconf_path)
612 application_pyconf_cfg.APPLICATION.workdir = src.pyconf.Reference(
613 application_pyconf_cfg,
615 'VARS.salometoolsway + $VARS.sep + ".."')
617 # Prevent from compilation in base
618 application_pyconf_cfg.APPLICATION.no_base = "yes"
620 # write the pyconf file to the temporary application location
621 application_tmp_pyconf_path = os.path.join(application_tmp_dir,
622 application_name + ".pyconf")
623 ff = open(application_tmp_pyconf_path, 'w')
624 ff.write("#!/usr/bin/env python\n#-*- coding:utf-8 -*-\n\n")
625 application_pyconf_cfg.__save__(ff, 1)
628 def project_package(project_file_path, tmp_working_dir):
629 '''Prepare a dictionary that stores all the needed directories and files to
630 add in a project package.
632 :param project_file_path str: The path to the local project.
633 :param tmp_working_dir str: The temporary local directory containing some
634 specific directories or files needed in the
636 :return: the dictionary that stores all the needed directories and files to
637 add in a project package.
638 {label : (path_on_local_machine, path_in_archive)}
642 # Read the project file and get the directories to add to the package
643 project_pyconf_cfg = src.pyconf.Config(project_file_path)
644 paths = {"ARCHIVEPATH" : "archives",
645 "APPLICATIONPATH" : "applications",
646 "PRODUCTPATH" : "products",
648 "MACHINEPATH" : "machines"}
649 # Loop over the project paths and add it
651 if path not in project_pyconf_cfg:
653 # Add the directory to the files to add in the package
654 d_project[path] = (project_pyconf_cfg[path], paths[path])
655 # Modify the value of the path in the package
656 project_pyconf_cfg[path] = src.pyconf.Reference(
659 'project_path + "/' + paths[path] + '"')
662 if "project_path" not in project_pyconf_cfg:
663 project_pyconf_cfg.addMapping("project_path",
664 src.pyconf.Mapping(project_pyconf_cfg),
666 project_pyconf_cfg.project_path = src.pyconf.Reference(project_pyconf_cfg,
670 # Write the project pyconf file
671 project_file_name = os.path.basename(project_file_path)
672 project_pyconf_tmp_path = os.path.join(tmp_working_dir, project_file_name)
673 ff = open(project_pyconf_tmp_path, 'w')
674 ff.write("#!/usr/bin/env python\n#-*- coding:utf-8 -*-\n\n")
675 project_pyconf_cfg.__save__(ff, 1)
677 d_project["Project hat file"] = (project_pyconf_tmp_path, project_file_name)
681 def add_readme(config, package_type, where):
682 readme_path = os.path.join(where, "README")
683 f = open(readme_path, 'w')
684 # prepare substitution dictionary
686 if package_type == BINARY:
687 d['application'] = config.VARS.application
688 d['user'] = config.VARS.user
689 d['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
690 d['version'] = config.INTERNAL.sat_version
691 d['dist'] = config.VARS.dist
692 if 'profile' in config.APPLICATION:
693 d['launcher'] = config.APPLICATION.profile.launcher_name
694 readme_template_path = os.path.join(config.VARS.internal_dir,
695 "README_BIN.template")
696 if package_type == SOURCE:
697 d['application'] = config.VARS.application
698 d['user'] = config.VARS.user
699 d['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
700 d['version'] = config.INTERNAL.sat_version
701 if 'profile' in config.APPLICATION:
702 d['profile'] = config.APPLICATION.profile.product
703 d['launcher'] = config.APPLICATION.profile.launcher_name
704 readme_template_path = os.path.join(config.VARS.internal_dir,
705 "README_SRC.template")
707 if package_type == PROJECT:
708 d['user'] = config.VARS.user
709 d['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
710 d['version'] = config.INTERNAL.sat_version
711 readme_template_path = os.path.join(config.VARS.internal_dir,
712 "README_PROJECT.template")
714 if package_type == SAT:
715 d['user'] = config.VARS.user
716 d['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
717 d['version'] = config.INTERNAL.sat_version
718 readme_template_path = os.path.join(config.VARS.internal_dir,
719 "README_SAT.template")
721 f.write(src.template.substitute(readme_template_path, d))
727 '''method that is called when salomeTools is called with --help option.
729 :return: The text to display for the package command description.
732 return _("The package command creates an archive.\nThere are 4 kinds of "
733 "archive:\n 1- The binary archive. It contains all the product "
734 "installation directories and a launcher,\n 2- The sources archive."
735 " It contains the products archives, a project corresponding to "
736 "the application and salomeTools,\n 3- The project archive. It "
737 "contains a project (give the project file path as argument),\n 4-"
738 " The salomeTools archive. It contains salomeTools.")
740 def run(args, runner, logger):
741 '''method that is called when salomeTools is called with package parameter.
745 (options, args) = parser.parse_args(args)
747 # Check that a type of package is called, and only one
748 all_option_types = (options.binaries,
750 options.project not in ["", None],
753 # Check if no option for package type
754 if all_option_types.count(True) == 0:
755 msg = _("Error: Precise a type for the package\nUse one of the "
756 "following options: --binaries, --sources, --project or --sat")
757 logger.write(src.printcolors.printcError(msg), 1)
758 logger.write("\n", 1)
761 # Check for only one option for package type
762 if all_option_types.count(True) > 1:
763 msg = _("Error: You can use only one type for the package\nUse only one"
764 " of the following options: --binaries, --sources, --project or"
766 logger.write(src.printcolors.printcError(msg), 1)
767 logger.write("\n", 1)
770 # Get the package type
772 package_type = BINARY
774 package_type = SOURCE
776 package_type = PROJECT
780 # The repository where to put the package if not Binary or Source
781 package_default_path = runner.cfg.USER.workdir
783 if package_type in [BINARY, SOURCE]:
784 # Check that the command has been called with an application
785 src.check_config_has_application(runner.cfg)
787 # Display information
788 logger.write(_("Packaging application %s\n") % src.printcolors.printcLabel(
789 runner.cfg.VARS.application), 1)
791 # Get the default directory where to put the packages
792 package_default_path = os.path.join(runner.cfg.APPLICATION.workdir,
794 src.ensure_path_exists(package_default_path)
796 elif package_type == PROJECT:
797 # check that the project is visible by SAT
798 if options.project not in runner.cfg.PROJECTS.project_file_paths:
799 site_path = os.path.join(runner.cfg.VARS.salometoolsway,
802 msg = _("ERROR: the project %(proj)s is not visible by salomeTools."
803 "\nPlease add it in the %(site)s file." % {
804 "proj" : options.project, "site" : site_path})
805 logger.write(src.printcolors.printcError(msg), 1)
806 logger.write("\n", 1)
810 src.printcolors.print_value(logger, "Package type", package_type, 2)
812 # get the name of the archive or construct it
814 if os.path.basename(options.name) == options.name:
815 # only a name (not a path)
816 archive_name = options.name
817 dir_name = package_default_path
819 archive_name = os.path.basename(options.name)
820 dir_name = os.path.dirname(options.name)
823 if archive_name[-len(".tgz"):] == ".tgz":
824 archive_name = archive_name[:-len(".tgz")]
825 if archive_name[-len(".tar.gz"):] == ".tar.gz":
826 archive_name = archive_name[:-len(".tar.gz")]
829 dir_name = package_default_path
830 if package_type == BINARY:
831 archive_name = (runner.cfg.APPLICATION.name +
833 runner.cfg.VARS.dist)
835 if package_type == SOURCE:
836 archive_name = (runner.cfg.APPLICATION.name +
840 archive_name = (runner.cfg.APPLICATION.name +
846 if package_type == PROJECT:
847 project_name, __ = os.path.splitext(
848 os.path.basename(options.project))
849 archive_name = ("PROJECT" +
853 if package_type == SAT:
854 archive_name = ("salomeTools" +
856 runner.cfg.INTERNAL.sat_version)
858 path_targz = os.path.join(dir_name, archive_name + ".tgz")
860 # Print the path of the package
861 src.printcolors.print_value(logger, "Package path", path_targz, 2)
863 # Create a working directory for all files that are produced during the
864 # package creation and that will be removed at the end of the command
865 tmp_working_dir = os.path.join(runner.cfg.VARS.tmp_root,
866 runner.cfg.VARS.datehour)
867 src.ensure_path_exists(tmp_working_dir)
868 logger.write("\n", 5)
869 logger.write(_("The temporary working directory: %s\n" % tmp_working_dir),5)
871 logger.write("\n", 3)
873 msg = _("Preparation of files to add to the archive")
874 logger.write(src.printcolors.printcLabel(msg), 2)
875 logger.write("\n", 2)
877 if package_type == BINARY:
878 d_files_to_add = binary_package(runner.cfg,
882 if not(d_files_to_add):
885 # Create and add the source package
886 # if the option "with_sources" is called
887 if options.with_sources:
888 logger.write(_("Create a source archive (can be long) ... "), 3)
889 tmp_pkg_src_name = runner.cfg.APPLICATION.name + "-" + "SRC.tgz"
890 tmp_pkg_src_path = os.path.join(tmp_working_dir, tmp_pkg_src_name)
891 package_options = runner.cfg.VARS.application
892 package_options += " --sources --with_vcs --name "
893 package_options += tmp_pkg_src_path
894 # sat package <package_options>
895 runner.package(package_options,
898 logger_add_link = logger)
899 d_files_to_add["SOURCES PACKAGE"] = (tmp_pkg_src_path,
901 logger.write(src.printcolors.printc("OK"), 3)
902 logger.write("\n", 3)
904 if package_type == SOURCE:
905 d_files_to_add = source_package(runner,
911 if package_type == PROJECT:
912 d_files_to_add = project_package(options.project, tmp_working_dir)
914 if package_type == SAT:
915 d_files_to_add = {"salomeTools" : (runner.cfg.VARS.salometoolsway, "")}
917 # Add the README file in the package
918 local_readme_tmp_path = add_readme(runner.cfg,
921 d_files_to_add["README"] = (local_readme_tmp_path, "README")
923 logger.write("\n", 2)
925 logger.write(src.printcolors.printcLabel(_("Actually do the package")), 2)
926 logger.write("\n", 2)
929 # Creating the object tarfile
930 tar = tarfile.open(path_targz, mode='w:gz')
932 # Add the files to the tarfile object
933 res = add_files(tar, archive_name, d_files_to_add, logger)
935 except KeyboardInterrupt:
936 logger.write(src.printcolors.printcError("\nERROR: forced interruption\n"), 1)
937 logger.write(_("Removing the temporary working directory ... "), 1)
938 # remove the working directory
939 shutil.rmtree(tmp_working_dir)
940 logger.write(_("OK"), 1)
941 logger.write(_("\n"), 1)
944 # remove the working directory
945 shutil.rmtree(tmp_working_dir)
947 # Print again the path of the package
948 logger.write("\n", 2)
949 src.printcolors.print_value(logger, "Package path", path_targz, 2)