import os
import stat
import shutil
+import datetime
import tarfile
+import codecs
+import string
import src
+from application import get_SALOME_modules
+
BINARY = "binary"
SOURCE = "Source"
PROJECT = "Project"
ARCHIVE_DIR = "ARCHIVES"
PROJECT_DIR = "PROJECT"
+IGNORED_DIRS = [".git", ".svn"]
+IGNORED_EXTENSIONS = []
+
PROJECT_TEMPLATE = """#!/usr/bin/env python
#-*- coding:utf-8 -*-
# The path to the archive root directory
-root_path : ""
+root_path : $PWD + "/../"
# path to the PROJECT
-project_path : $root_path + "PROJECT/"
+project_path : $PWD + "/"
# Where to search the archives of the products
ARCHIVEPATH : $root_path + "ARCHIVES"
MACHINEPATH : $project_path + "machines/"
"""
-SITE_TEMPLATE = ("""#!/usr/bin/env python
+LOCAL_TEMPLATE = ("""#!/usr/bin/env python
#-*- coding:utf-8 -*-
-SITE :
-{
- log :
- {
- log_dir : $USER.workdir + "/LOGS"
- }
- test :{
- tmp_dir_with_application : '/tmp' + $VARS.sep + $VARS.user + """
-"""$VARS.sep + $APPLICATION.name + $VARS.sep + 'test'
- tmp_dir : '/tmp' + $VARS.sep + $VARS.user + $VARS.sep + 'test'
- timeout : 150
- }
-}
+ LOCAL :
+ {
+ base : 'unknown'
+ workdir : 'unknown'
+ log_dir : 'unknown'
+ VCS : None
+ tag : None
+ }
PROJECTS :
{
# Define all possible option for the package command : sat package <options>
parser = src.options.Options()
parser.add_option('b', 'binaries', 'boolean', 'binaries',
- _('Produce a binary package.'), False)
+ _('Optional: Produce a binary package.'), False)
+parser.add_option('f', 'force_creation', 'boolean', 'force_creation',
+ _('Optional: Only binary package: produce the archive even if '
+ 'there are some missing products.'), False)
parser.add_option('s', 'sources', 'boolean', 'sources',
- _('Produce a compilable archive of the sources of the application.'), False)
+ _('Optional: Produce a compilable archive of the sources of the '
+ 'application.'), False)
+parser.add_option('', 'with_vcs', 'boolean', 'with_vcs',
+ _('Optional: Only source package: do not make archive of vcs products.'),
+ False)
parser.add_option('p', 'project', 'string', 'project',
- _('Produce an archive that contains a project.'), "")
-parser.add_option('', 'salometools', 'boolean', 'sat',
- _('Produce an archive that contains salomeTools.'), False)
+ _('Optional: Produce an archive that contains a project.'), "")
+parser.add_option('t', 'salometools', 'boolean', 'sat',
+ _('Optional: Produce an archive that contains salomeTools.'), False)
parser.add_option('n', 'name', 'string', 'name',
- _('The name or full path of the archive.'), None)
-parser.add_option('', 'with_vcs', 'boolean', 'with_vcs',
- _('Only source package: do not make archive of vcs products.'), False)
+ _('Optional: The name or full path of the archive.'), None)
+parser.add_option('', 'add_files', 'list2', 'add_files',
+ _('Optional: The list of additional files to add to the archive.'), [])
+parser.add_option('', 'without_commercial', 'boolean', 'without_commercial',
+ _('Optional: do not add commercial licence.'), False)
+parser.add_option('', 'without_property', 'string', 'without_property',
+ _('Optional: Filter the products by their properties.\n\tSyntax: '
+ '--without_property <property>:<value>'))
+
-def add_files(tar, name_archive, d_content, logger):
+def add_files(tar, name_archive, d_content, logger, f_exclude=None):
'''Create an archive containing all directories and files that are given in
the d_content argument.
d_content[label] =
(path_on_local_machine, path_in_archive)
:param logger Logger: the logging instance
+ :param f_exclude Function: the function that filters
:return: 0 if success, 1 if not.
:rtype: int
'''
in_archive = os.path.join(name_archive, archive_path)
# Add it in the archive
try:
- tar.add(local_path, arcname=in_archive)
+ tar.add(local_path, arcname=in_archive, exclude=f_exclude)
logger.write(src.printcolors.printcSuccess(_("OK")), 3)
except Exception as e:
logger.write(src.printcolors.printcError(_("KO ")), 3)
- logger.write(e, 3)
+ logger.write(str(e), 3)
success = 1
logger.write("\n", 3)
return success
+def exclude_VCS_and_extensions(filename):
+ ''' The function that is used to exclude from package the link to the
+ VCS repositories (like .git)
+
+ :param filename Str: The filname to exclude (or not).
+ :return: True if the file has to be exclude
+ :rtype: Boolean
+ '''
+ for dir_name in IGNORED_DIRS:
+ if dir_name in filename:
+ return True
+ for extension in IGNORED_EXTENSIONS:
+ if filename.endswith(extension):
+ return True
+ return False
+
def produce_relative_launcher(config,
logger,
file_dir,
file_name,
- binaries_dir_name):
+ binaries_dir_name,
+ with_commercial=True):
'''Create a specific SALOME launcher for the binary package. This launcher
uses relative paths.
# Get the launcher template
profile_install_dir = os.path.join(binaries_dir_name,
config.APPLICATION.profile.product)
- withProfile = src.fileEnviron.withProfile.replace( "PROFILE_INSTALL_DIR",
- profile_install_dir )
+ withProfile = src.fileEnviron.withProfile
+ withProfile = withProfile.replace(
+ "ABSOLUTE_APPLI_PATH'] = 'PROFILE_INSTALL_DIR'",
+ "ABSOLUTE_APPLI_PATH'] = out_dir_Path + '" + config.VARS.sep + profile_install_dir + "'")
+ withProfile = withProfile.replace(
+ "os.path.join( 'PROFILE_INSTALL_DIR'",
+ "os.path.join( out_dir_Path, '" + profile_install_dir + "'")
before, after = withProfile.split(
"# here your local standalone environment\n")
launch_file = open(filepath, "w")
launch_file.write(before)
# Write
- writer.write_cfgForPy_file(launch_file, for_package = binaries_dir_name)
+ writer.write_cfgForPy_file(launch_file,
+ for_package = binaries_dir_name,
+ with_commercial=with_commercial)
launch_file.write(after)
launch_file.close()
+ # Little hack to put out_dir_Path outside the strings
+ src.replace_in_file(filepath, 'r"out_dir_Path', 'out_dir_Path + r"' )
+
+ # A hack to put a call to a file for distene licence.
+ # It does nothing to an application that has no distene product
+ hack_for_distene_licence(filepath)
+
+ # change the rights in order to make the file executable for everybody
+ os.chmod(filepath,
+ stat.S_IRUSR |
+ stat.S_IRGRP |
+ stat.S_IROTH |
+ stat.S_IWUSR |
+ stat.S_IXUSR |
+ stat.S_IXGRP |
+ stat.S_IXOTH)
+
+ return filepath
+
+def hack_for_distene_licence(filepath):
+ '''Replace the distene licence env variable by a call to a file.
+
+ :param filepath Str: The path to the launcher to modify.
+ '''
+ shutil.move(filepath, filepath + "_old")
+ fileout= filepath
+ filein = filepath + "_old"
+ fin = open(filein, "r")
+ fout = open(fileout, "w")
+ text = fin.readlines()
+ # Find the Distene section
+ num_line = -1
+ for i,line in enumerate(text):
+ if "# Set DISTENE License" in line:
+ num_line = i
+ break
+ if num_line == -1:
+ # No distene product, there is nothing to do
+ fin.close()
+ for line in text:
+ fout.write(line)
+ fout.close()
+ return
+ del text[num_line +1]
+ del text[num_line +1]
+ text_to_insert =""" import imp
+ try:
+ distene = imp.load_source('distene_licence', '/data/tmpsalome/salome/prerequis/install/LICENSE/dlim8.var.py')
+ distene.set_distene_variables(context)
+ except:
+ pass\n"""
+ text.insert(num_line + 1, text_to_insert)
+ for line in text:
+ fout.write(line)
+ fin.close()
+ fout.close()
+ return
+
+def produce_relative_env_files(config,
+ logger,
+ file_dir,
+ binaries_dir_name):
+ '''Create some specific environment files for the binary package. These
+ files use relative paths.
+
+ :param config Config: The global configuration.
+ :param logger Logger: the logging instance
+ :param file_dir str: the directory where to put the files
+ :param binaries_dir_name str: the name of the repository where the binaries
+ are, in the archive.
+ :return: the list of path of the produced environment files
+ :rtype: List
+ '''
+ # create an environment file writer
+ writer = src.environment.FileEnvWriter(config,
+ logger,
+ file_dir,
+ src_root=None)
+
+ # Write
+ filepath = writer.write_env_file("env_launch.sh",
+ False, # for launch
+ "bash",
+ for_package = binaries_dir_name)
+
+ # Little hack to put out_dir_Path as environment variable
+ src.replace_in_file(filepath, '"out_dir_Path', '"${out_dir_Path}' )
+
# change the rights in order to make the file executable for everybody
os.chmod(filepath,
stat.S_IRUSR |
return filepath
+def produce_install_bin_file(config,
+ logger,
+ file_dir,
+ d_sub,
+ file_name):
+ '''Create a bash shell script which do substitutions in BIRARIES dir
+ in order to use it for extra compilations.
+
+ :param config Config: The global configuration.
+ :param logger Logger: the logging instance
+ :param file_dir str: the directory where to put the files
+ :param d_sub, dict: the dictionnary that contains the substitutions to be done
+ :param file_name str: the name of the install script file
+ :return: the produced file
+ :rtype: str
+ '''
+ # Write
+ filepath = os.path.join(file_dir, file_name)
+ # open the file and write into it
+ # use codec utf-8 as sat variables are in unicode
+ with codecs.open(filepath, "w", 'utf-8') as installbin_file:
+ installbin_template_path = os.path.join(config.VARS.internal_dir,
+ "INSTALL_BIN.template")
+
+ # build the name of the directory that will contain the binaries
+ binaries_dir_name = "BINARIES-" + config.VARS.dist
+ # build the substitution loop
+ loop_cmd = "for f in $(grep -RIl"
+ for key in d_sub:
+ loop_cmd += " -e "+ key
+ loop_cmd += ' INSTALL); do\n sed -i "\n'
+ for key in d_sub:
+ loop_cmd += " s?" + key + "?$(pwd)/" + d_sub[key] + "?g\n"
+ loop_cmd += ' " $f\ndone'
+
+ d={}
+ d["BINARIES_DIR"] = binaries_dir_name
+ d["SUBSTITUTION_LOOP"]=loop_cmd
+
+ # substitute the template and write it in file
+ content=src.template.substitute(installbin_template_path, d)
+ installbin_file.write(content)
+ # change the rights in order to make the file executable for everybody
+ os.chmod(filepath,
+ stat.S_IRUSR |
+ stat.S_IRGRP |
+ stat.S_IROTH |
+ stat.S_IWUSR |
+ stat.S_IXUSR |
+ stat.S_IXGRP |
+ stat.S_IXOTH)
+
+ return filepath
+
+def product_appli_creation_script(config,
+ logger,
+ file_dir,
+ binaries_dir_name):
+ '''Create a script that can produce an application (EDF style) in the binary
+ package.
+
+ :param config Config: The global configuration.
+ :param logger Logger: the logging instance
+ :param file_dir str: the directory where to put the file
+ :param binaries_dir_name str: the name of the repository where the binaries
+ are, in the archive.
+ :return: the path of the produced script file
+ :rtype: Str
+ '''
+ template_name = "create_appli.py.for_bin_packages.template"
+ template_path = os.path.join(config.VARS.internal_dir, template_name)
+ text_to_fill = open(template_path, "r").read()
+ text_to_fill = text_to_fill.replace("TO BE FILLED 1",
+ '"' + binaries_dir_name + '"')
+
+ text_to_add = ""
+ for product_name in get_SALOME_modules(config):
+ product_info = src.product.get_product_config(config, product_name)
+
+ if src.product.product_is_smesh_plugin(product_info):
+ continue
+
+ if 'install_dir' in product_info and bool(product_info.install_dir):
+ if src.product.product_is_cpp(product_info):
+ # cpp module
+ for cpp_name in src.product.get_product_components(product_info):
+ line_to_add = ("<module name=\"" +
+ cpp_name +
+ "\" gui=\"yes\" path=\"''' + "
+ "os.path.join(dir_bin_name, \"" +
+ cpp_name + "\") + '''\"/>")
+ else:
+ # regular module
+ line_to_add = ("<module name=\"" +
+ product_name +
+ "\" gui=\"yes\" path=\"''' + "
+ "os.path.join(dir_bin_name, \"" +
+ product_name + "\") + '''\"/>")
+ text_to_add += line_to_add + "\n"
+
+ filled_text = text_to_fill.replace("TO BE FILLED 2", text_to_add)
+
+ tmp_file_path = os.path.join(file_dir, "create_appli.py")
+ ff = open(tmp_file_path, "w")
+ ff.write(filled_text)
+ ff.close()
+
+ # change the rights in order to make the file executable for everybody
+ os.chmod(tmp_file_path,
+ stat.S_IRUSR |
+ stat.S_IRGRP |
+ stat.S_IROTH |
+ stat.S_IWUSR |
+ stat.S_IXUSR |
+ stat.S_IXGRP |
+ stat.S_IXOTH)
+
+ return tmp_file_path
+
def binary_package(config, logger, options, tmp_working_dir):
'''Prepare a dictionary that stores all the needed directories and files to
add in a binary package.
l_product_info = src.product.get_products_infos(l_products_name,
config)
l_install_dir = []
+ l_source_dir = []
l_not_installed = []
+ l_sources_not_present = []
for prod_name, prod_info in l_product_info:
- # ignore the native and fixed products
+
+ # Add the sources of the products that have the property
+ # sources_in_package : "yes"
+ if src.get_property_in_product_cfg(prod_info,
+ "sources_in_package") == "yes":
+ if os.path.exists(prod_info.source_dir):
+ l_source_dir.append((prod_name, prod_info.source_dir))
+ else:
+ l_sources_not_present.append(prod_name)
+
+ # ignore the native and fixed products for install directories
if (src.product.product_is_native(prod_info)
- or src.product.product_is_fixed(prod_info)):
+ or src.product.product_is_fixed(prod_info)
+ or not src.product.product_compiles(prod_info)):
continue
if src.product.check_installation(prod_info):
l_install_dir.append((prod_name, prod_info.install_dir))
else:
l_not_installed.append(prod_name)
-
+
+ # Add also the cpp generated modules (if any)
+ if src.product.product_is_cpp(prod_info):
+ # cpp module
+ for name_cpp in src.product.get_product_components(prod_info):
+ install_dir = os.path.join(config.APPLICATION.workdir,
+ "INSTALL", name_cpp)
+ if os.path.exists(install_dir):
+ l_install_dir.append((name_cpp, install_dir))
+ else:
+ l_not_installed.append(name_cpp)
+
# Print warning or error if there are some missing products
if len(l_not_installed) > 0:
text_missing_prods = ""
logger.write("%s\n%s" % (src.printcolors.printcWarning(msg),
text_missing_prods),
1)
-
+
+ # Do the same for sources
+ if len(l_sources_not_present) > 0:
+ text_missing_prods = ""
+ for p_name in l_sources_not_present:
+ text_missing_prods += "-" + p_name + "\n"
+ if not options.force_creation:
+ msg = _("ERROR: there are missing products sources:")
+ logger.write("%s\n%s" % (src.printcolors.printcError(msg),
+ text_missing_prods),
+ 1)
+ return None
+ else:
+ msg = _("WARNING: there are missing products sources:")
+ logger.write("%s\n%s" % (src.printcolors.printcWarning(msg),
+ text_missing_prods),
+ 1)
+
# construct the name of the directory that will contain the binaries
binaries_dir_name = "BINARIES-" + config.VARS.dist
d_products = {}
for prod_name, install_dir in l_install_dir:
path_in_archive = os.path.join(binaries_dir_name, prod_name)
- d_products[prod_name] = (install_dir, path_in_archive)
-
+ d_products[prod_name + " (bin)"] = (install_dir, path_in_archive)
+
+ for prod_name, source_dir in l_source_dir:
+ path_in_archive = os.path.join("SOURCES", prod_name)
+ d_products[prod_name + " (sources)"] = (source_dir, path_in_archive)
+
# create the relative launcher and add it to the files to add
- launcher_name = config.APPLICATION.profile.launcher_name
- launcher_package = produce_relative_launcher(config,
- logger,
- tmp_working_dir,
- launcher_name,
- binaries_dir_name)
-
- d_products["launcher"] = (launcher_package, launcher_name)
+ if ("profile" in config.APPLICATION and
+ "product" in config.APPLICATION.profile):
+ launcher_name = config.APPLICATION.profile.launcher_name
+ launcher_package = produce_relative_launcher(config,
+ logger,
+ tmp_working_dir,
+ launcher_name,
+ binaries_dir_name,
+ not(options.without_commercial))
+ d_products["launcher"] = (launcher_package, launcher_name)
+ if options.sources:
+ # if we mix binaries and sources, we add a copy of the launcher,
+ # prefixed with "bin",in order to avoid clashes
+ d_products["launcher (copy)"] = (launcher_package, "bin"+launcher_name)
+ else:
+ # Provide a script for the creation of an application EDF style
+ appli_script = product_appli_creation_script(config,
+ logger,
+ tmp_working_dir,
+ binaries_dir_name)
+
+ d_products["appli script"] = (appli_script, "create_appli.py")
+
+ # Put also the environment file
+ env_file = produce_relative_env_files(config,
+ logger,
+ tmp_working_dir,
+ binaries_dir_name)
+
+ d_products["environment file"] = (env_file, "env_launch.sh")
+
return d_products
def source_package(sat, config, logger, options, tmp_working_dir):
d_archives, l_pinfo_vcs = get_archives(config, logger)
logger.write("Done\n")
d_archives_vcs = {}
- if not options.with_vcs:
+ if not options.with_vcs and len(l_pinfo_vcs) > 0:
# Make archives with the products that are not prepared using an archive
# (git, cvs, svn, etc)
logger.write("Construct archives for vcs products ... ")
tmp_sat = add_salomeTools(config, tmp_working_dir)
d_sat = {"salomeTools" : (tmp_sat, "salomeTools")}
- # Add a sat symbolic link
- tmp_satlink_path = os.path.join(tmp_working_dir, 'sat')
- t = os.getcwd()
- os.chdir(tmp_working_dir)
- if os.path.lexists(tmp_satlink_path):
- os.remove(tmp_satlink_path)
- os.symlink(os.path.join('salomeTools', 'sat'), 'sat')
- os.chdir(t)
-
- d_sat["sat link"] = (tmp_satlink_path, "sat")
+ # Add a sat symbolic link if not win
+ if not src.architecture.is_windows():
+ tmp_satlink_path = os.path.join(tmp_working_dir, 'sat')
+ try:
+ t = os.getcwd()
+ except:
+ # In the jobs, os.getcwd() can fail
+ t = config.USER.workdir
+ os.chdir(tmp_working_dir)
+ if os.path.lexists(tmp_satlink_path):
+ os.remove(tmp_satlink_path)
+ os.symlink(os.path.join('salomeTools', 'sat'), 'sat')
+ os.chdir(t)
+
+ d_sat["sat link"] = (tmp_satlink_path, "sat")
- return src.merge_dicts(d_archives, d_archives_vcs, d_project, d_sat)
+ d_source = src.merge_dicts(d_archives, d_archives_vcs, d_project, d_sat)
+ return d_source
def get_archives(config, logger):
'''Find all the products that are get using an archive and all the products
return d_archives, l_pinfo_vcs
def add_salomeTools(config, tmp_working_dir):
- '''Prepare a version of salomeTools that has a specific site.pyconf file
+ '''Prepare a version of salomeTools that has a specific local.pyconf file
configured for a source package.
:param config Config: The global configuration.
sat_running_path = src.Path(config.VARS.salometoolsway)
sat_running_path.copy(sat_tmp_path)
- # Update the site.pyconf file that contains the path to the project
- site_pyconf_name = "site.pyconf"
- site_pyconf_dir = os.path.join(tmp_working_dir, "salomeTools", "data")
- site_pyconf_file = os.path.join(site_pyconf_dir, site_pyconf_name)
- ff = open(site_pyconf_file, "w")
- ff.write(SITE_TEMPLATE)
+ # Update the local.pyconf file that contains the path to the project
+ local_pyconf_name = "local.pyconf"
+ local_pyconf_dir = os.path.join(tmp_working_dir, "salomeTools", "data")
+ local_pyconf_file = os.path.join(local_pyconf_dir, local_pyconf_name)
+ # Remove the .pyconf file in the root directory of salomeTools if there is
+ # any. (For example when launching jobs, a pyconf file describing the jobs
+ # can be here and is not useful)
+ files_or_dir_SAT = os.listdir(os.path.join(tmp_working_dir, "salomeTools"))
+ for file_or_dir in files_or_dir_SAT:
+ if file_or_dir.endswith(".pyconf"):
+ file_path = os.path.join(tmp_working_dir,
+ "salomeTools",
+ file_or_dir)
+ os.remove(file_path)
+
+ ff = open(local_pyconf_file, "w")
+ ff.write(LOCAL_TEMPLATE)
ff.close()
return sat_tmp_path.path
path_targz_prod = os.path.join(where, prod_name + ".tgz")
tar_prod = tarfile.open(path_targz_prod, mode='w:gz')
local_path = prod_info.source_dir
- tar_prod.add(local_path, arcname=prod_name)
+ tar_prod.add(local_path,
+ arcname=prod_name,
+ exclude=exclude_VCS_and_extensions)
tar_prod.close()
return path_targz_prod
lproducts_name = config.APPLICATION.products.keys()
l_products = src.product.get_products_infos(lproducts_name, config)
for p_name, p_info in l_products:
- # ignore native and fixed products
- if (src.product.product_is_native(p_info) or
- src.product.product_is_fixed(p_info)):
- continue
find_product_scripts_and_pyconf(p_name,
p_info,
config,
project_pyconf_cfg.addMapping("project_path",
src.pyconf.Mapping(project_pyconf_cfg),
"")
- project_pyconf_cfg.project_path = ""
+ project_pyconf_cfg.project_path = src.pyconf.Reference(project_pyconf_cfg,
+ src.pyconf.DOLLAR,
+ 'PWD')
# Write the project pyconf file
project_file_name = os.path.basename(project_file_path)
return d_project
+def add_readme(config, options, where):
+ readme_path = os.path.join(where, "README")
+ with codecs.open(readme_path, "w", 'utf-8') as f:
+
+ # templates for building the header
+ readme_header="""
+# This package was generated with sat $version
+# Date: $date
+# User: $user
+# Distribution : $dist
+
+In the following, $$ROOT represents the directory where you have installed
+SALOME (the directory where this file is located).
+
+"""
+ readme_compilation_with_binaries="""
+
+compilation based on the binaries used as prerequisites
+=======================================================
+
+If you fail to compile the complete application (for example because
+you are not root on your system and cannot install missing packages), you
+may try a partial compilation based on the binaries.
+For that it is necessary to copy the binaries from BINARIES to INSTALL,
+and do some substitutions on cmake and .la files (replace the build directories
+with local paths).
+The procedure to do it is:
+ 1) Remove or rename INSTALL directory if it exists
+ 2) Execute the shell script install_bin.sh:
+ > cd $ROOT
+ > ./install_bin.sh
+ 3) Use SalomeTool (as explained in Sources section) and compile only the
+ modules you need to (with -p option)
+
+"""
+ readme_header_tpl=string.Template(readme_header)
+ readme_template_path_bin_prof = os.path.join(config.VARS.internal_dir,
+ "README_BIN.template")
+ readme_template_path_bin_noprof = os.path.join(config.VARS.internal_dir,
+ "README_BIN_NO_PROFILE.template")
+ readme_template_path_src = os.path.join(config.VARS.internal_dir,
+ "README_SRC.template")
+ readme_template_path_pro = os.path.join(config.VARS.internal_dir,
+ "README_PROJECT.template")
+ readme_template_path_sat = os.path.join(config.VARS.internal_dir,
+ "README_SAT.template")
+
+ # prepare substitution dictionary
+ d = dict()
+ d['user'] = config.VARS.user
+ d['date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
+ d['version'] = config.INTERNAL.sat_version
+ d['dist'] = config.VARS.dist
+ f.write(readme_header_tpl.substitute(d)) # write the general header (common)
+
+ if options.binaries or options.sources:
+ d['application'] = config.VARS.application
+ f.write("# Application: " + d['application'])
+ if 'profile' in config.APPLICATION:
+ d['launcher'] = config.APPLICATION.profile.launcher_name
+ d['launcher'] = config.APPLICATION.profile.launcher_name
+ else:
+ d['env_file'] = 'env_launch.sh'
+
+ # write the specific sections
+ if options.binaries:
+ if "env_file" in d:
+ f.write(src.template.substitute(readme_template_path_bin_noprof, d))
+ else:
+ f.write(src.template.substitute(readme_template_path_bin_prof, d))
+
+ if options.sources:
+ f.write(src.template.substitute(readme_template_path_src, d))
+
+ if options.binaries and options.sources:
+ f.write(readme_compilation_with_binaries)
+
+ if options.project:
+ f.write(src.template.substitute(readme_template_path_pro, d))
+
+ if options.sat:
+ f.write(src.template.substitute(readme_template_path_sat, d))
+
+ return readme_path
+
+def update_config(config, prop, value):
+ '''Remove from config.APPLICATION.products the products that have the property given as input.
+
+ :param config Config: The global config.
+ :param prop str: The property to filter
+ :param value str: The value of the property to filter
+ '''
+ src.check_config_has_application(config)
+ l_product_to_remove = []
+ for product_name in config.APPLICATION.products.keys():
+ prod_cfg = src.product.get_product_config(config, product_name)
+ if src.get_property_in_product_cfg(prod_cfg, prop) == value:
+ l_product_to_remove.append(product_name)
+ for product_name in l_product_to_remove:
+ config.APPLICATION.products.__delitem__(product_name)
+
def description():
'''method that is called when salomeTools is called with --help option.
:rtype: str
'''
return _("The package command creates an archive.\nThere are 4 kinds of "
- "archive:\n 1- The binary archive. It contains all the product "
+ "archive, which can be mixed:\n 1- The binary archive. It contains all the product "
"installation directories and a launcher,\n 2- The sources archive."
" It contains the products archives, a project corresponding to "
"the application and salomeTools,\n 3- The project archive. It "
"contains a project (give the project file path as argument),\n 4-"
- " The salomeTools archive. It contains salomeTools.")
+ " The salomeTools archive. It contains salomeTools.\n\nexample:"
+ "\nsat package SALOME-master --bineries --sources")
def run(args, runner, logger):
'''method that is called when salomeTools is called with package parameter.
# Check that a type of package is called, and only one
all_option_types = (options.binaries,
options.sources,
- options.project != "",
+ options.project not in ["", None],
options.sat)
# Check if no option for package type
if all_option_types.count(True) == 0:
msg = _("Error: Precise a type for the package\nUse one of the "
- "following options: --binaries, --sources, --project or --sat")
+ "following options: --binaries, --sources, --project or"
+ " --salometools")
logger.write(src.printcolors.printcError(msg), 1)
logger.write("\n", 1)
return 1
- # Check for only one option for package type
- if all_option_types.count(True) > 1:
- msg = _("Error: You can use only one type for the package\nUse only one"
- " of the following options: --binaries, --sources, --project or"
- " --sat")
- logger.write(src.printcolors.printcError(msg), 1)
- logger.write("\n", 1)
- return 1
-
- # Get the package type
- if options.binaries:
- package_type = BINARY
- if options.sources:
- package_type = SOURCE
- if options.project:
- package_type = PROJECT
- if options.sat:
- package_type = SAT
-
# The repository where to put the package if not Binary or Source
package_default_path = runner.cfg.USER.workdir
- if package_type in [BINARY, SOURCE]:
+ # if the package contains binaries or sources:
+ if options.binaries or options.sources:
# Check that the command has been called with an application
src.check_config_has_application(runner.cfg)
"PACKAGE")
src.ensure_path_exists(package_default_path)
- elif package_type == PROJECT:
+ # if the package contains a project:
+ if options.project:
# check that the project is visible by SAT
if options.project not in runner.cfg.PROJECTS.project_file_paths:
- site_path = os.path.join(runner.cfg.VARS.salometoolsway,
+ local_path = os.path.join(runner.cfg.VARS.salometoolsway,
"data",
- "site.pyconf")
+ "local.pyconf")
msg = _("ERROR: the project %(proj)s is not visible by salomeTools."
- "\nPlease add it in the %(site)s file." % {
- "proj" : options.project, "site" : site_path})
+ "\nPlease add it in the %(local)s file." % {
+ "proj" : options.project, "local" : local_path})
logger.write(src.printcolors.printcError(msg), 1)
logger.write("\n", 1)
return 1
- # Print
- src.printcolors.print_value(logger, "Package type", package_type, 2)
-
- # get the name of the archive or construct it
+ # Remove the products that are filtered by the --without_property option
+ if options.without_property:
+ [prop, value] = options.without_property.split(":")
+ update_config(runner.cfg, prop, value)
+
+ # get the name of the archive or build it
if options.name:
if os.path.basename(options.name) == options.name:
# only a name (not a path)
archive_name = archive_name[:-len(".tar.gz")]
else:
+ archive_name=""
dir_name = package_default_path
- if package_type == BINARY:
- archive_name = (runner.cfg.APPLICATION.name +
- "-" +
- runner.cfg.VARS.dist)
+ if options.binaries or options.sources:
+ archive_name = runner.cfg.APPLICATION.name
+
+ if options.binaries:
+ archive_name += "_"+runner.cfg.VARS.dist
- if package_type == SOURCE:
- archive_name = (runner.cfg.APPLICATION.name +
- "-" +
- "SRC")
+ if options.sources:
+ archive_name += "_SRC"
+ if options.with_vcs:
+ archive_name += "_VCS"
- if package_type == PROJECT:
+ if options.project:
project_name, __ = os.path.splitext(
os.path.basename(options.project))
- archive_name = ("PROJECT" +
- "-" +
- project_name)
+ archive_name += ("PROJECT_" + project_name)
- if package_type == SAT:
- archive_name = ("salomeTools" +
- "-" +
- runner.cfg.INTERNAL.sat_version)
+ if options.sat:
+ archive_name += ("salomeTools_" + runner.cfg.INTERNAL.sat_version)
+ if len(archive_name)==0: # no option worked
+ msg = _("Error: Cannot name the archive\n"
+ " check if at least one of the following options was "
+ "selected : --binaries, --sources, --project or"
+ " --salometools")
+ logger.write(src.printcolors.printcError(msg), 1)
+ logger.write("\n", 1)
+ return 1
path_targz = os.path.join(dir_name, archive_name + ".tgz")
- # Print the path of the package
src.printcolors.print_value(logger, "Package path", path_targz, 2)
# Create a working directory for all files that are produced during the
tmp_working_dir = os.path.join(runner.cfg.VARS.tmp_root,
runner.cfg.VARS.datehour)
src.ensure_path_exists(tmp_working_dir)
+ logger.write("\n", 5)
+ logger.write(_("The temporary working directory: %s\n" % tmp_working_dir),5)
logger.write("\n", 3)
logger.write(src.printcolors.printcLabel(msg), 2)
logger.write("\n", 2)
- if package_type == BINARY:
- d_files_to_add = binary_package(runner.cfg,
- logger,
- options,
- tmp_working_dir)
- if not(d_files_to_add):
- return 1
+ d_files_to_add={} # content of the archive
+
+ # a dict to hold paths that will need to be substitute for users recompilations
+ d_paths_to_substitute={}
+
+ if options.binaries:
+ d_bin_files_to_add = binary_package(runner.cfg,
+ logger,
+ options,
+ tmp_working_dir)
+ # for all binaries dir, store the substitution that will be required
+ # for extra compilations
+ for key in d_bin_files_to_add:
+ if key.endswith("(bin)"):
+ source_dir = d_bin_files_to_add[key][0]
+ path_in_archive = d_bin_files_to_add[key][1].replace("BINARIES-" + runner.cfg.VARS.dist,"INSTALL")
+ if os.path.basename(source_dir)==os.path.basename(path_in_archive):
+ # if basename is the same we will just substitute the dirname
+ d_paths_to_substitute[os.path.dirname(source_dir)]=\
+ os.path.dirname(path_in_archive)
+ else:
+ d_paths_to_substitute[source_dir]=path_in_archive
+
+ d_files_to_add.update(d_bin_files_to_add)
- if package_type == SOURCE:
- d_files_to_add = source_package(runner,
+ if options.sources:
+ d_files_to_add.update(source_package(runner,
runner.cfg,
logger,
options,
- tmp_working_dir)
+ tmp_working_dir))
+ if options.binaries:
+ # for archives with bin and sources we provide a shell script able to
+ # install binaries for compilation
+ file_install_bin=produce_install_bin_file(runner.cfg,logger,
+ tmp_working_dir,
+ d_paths_to_substitute,
+ "install_bin.sh")
+ d_files_to_add.update({"install_bin" : (file_install_bin, "install_bin.sh")})
+ logger.write("substitutions that need to be done later : \n", 5)
+ logger.write(str(d_paths_to_substitute), 5)
+ logger.write("\n", 5)
+ else:
+ # --salomeTool option is not considered when --sources is selected, as this option
+ # already brings salomeTool!
+ if options.sat:
+ d_files_to_add.update({"salomeTools" : (runner.cfg.VARS.salometoolsway, "")})
+
- if package_type == PROJECT:
- d_files_to_add = project_package(options.project, tmp_working_dir)
+ if options.project:
+ d_files_to_add.update(project_package(options.project, tmp_working_dir))
+
+ if not(d_files_to_add):
+ msg = _("Error: Empty dictionnary to build the archive!\n")
+ logger.write(src.printcolors.printcError(msg), 1)
+ logger.write("\n", 1)
+ return 1
+
+ # Add the README file in the package
+ local_readme_tmp_path = add_readme(runner.cfg,
+ options,
+ tmp_working_dir)
+ d_files_to_add["README"] = (local_readme_tmp_path, "README")
+
+ # Add the additional files of option add_files
+ if options.add_files:
+ for file_path in options.add_files:
+ if not os.path.exists(file_path):
+ msg = _("WARNING: the file %s is not accessible.\n" % file_path)
+ continue
+ file_name = os.path.basename(file_path)
+ d_files_to_add[file_name] = (file_path, file_name)
- if package_type == SAT:
- d_files_to_add = {"salomeTools" : (runner.cfg.VARS.salometoolsway, "")}
-
logger.write("\n", 2)
logger.write(src.printcolors.printcLabel(_("Actually do the package")), 2)
logger.write("\n", 2)
- # Creating the object tarfile
- tar = tarfile.open(path_targz, mode='w:gz')
-
- # Add the files to the tarfile object
- res = add_files(tar, archive_name, d_files_to_add, logger)
- tar.close()
+ try:
+ # Creating the object tarfile
+ tar = tarfile.open(path_targz, mode='w:gz')
+
+ # get the filtering function if needed
+ filter_function = exclude_VCS_and_extensions
+
+ # Add the files to the tarfile object
+ res = add_files(tar, archive_name, d_files_to_add, logger, f_exclude=filter_function)
+ tar.close()
+ except KeyboardInterrupt:
+ logger.write(src.printcolors.printcError("\nERROR: forced interruption\n"), 1)
+ logger.write(_("Removing the temporary working directory ... "), 1)
+ # remove the working directory
+ shutil.rmtree(tmp_working_dir)
+ logger.write(_("OK"), 1)
+ logger.write(_("\n"), 1)
+ return 1
- # remove the working directory
+ # remove the working directory
shutil.rmtree(tmp_working_dir)
# Print again the path of the package
logger.write("\n", 2)
src.printcolors.print_value(logger, "Package path", path_targz, 2)
- return res
\ No newline at end of file
+ return res