X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2Fproduct.py;h=81ad048a261fc04f14236e95b431a40b0b7298bc;hb=31892e4d1e769f1c8fb38121529adea099253dfb;hp=007e2ce13ed91485cd84822adc9cb7d268914b30;hpb=cfa9edfb956345c69090469b519a94dcc55ba382;p=tools%2Fsat.git diff --git a/src/product.py b/src/product.py index 007e2ce..81ad048 100644 --- a/src/product.py +++ b/src/product.py @@ -15,21 +15,27 @@ # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -'''In this file are implemented the classes and methods +'''In this file are implemented the methods relative to the product notion of salomeTools ''' import os +import re import src AVAILABLE_VCS = ['git', 'svn', 'cvs'] +config_expression = "^config-\d+$" +VERSION_DELIMITER = "_to_" -def get_product_config(config, product_name): +def get_product_config(config, product_name, with_install_dir=True): '''Get the specific configuration of a product from the global configuration :param config Config: The global configuration :param product_name str: The name of the product + :param with_install_dir boolean: If false, do not provide an install + directory (at false only for internal use + of the function check_config_exists) :return: the specific configuration of the product :rtype: Config ''' @@ -46,6 +52,7 @@ def get_product_config(config, product_name): debug = 'no' dev = 'no' base = 'maybe' + section = None if isinstance(version, src.pyconf.Mapping): dic_version = version # Get the version/tag @@ -62,9 +69,13 @@ def get_product_config(config, product_name): if 'dev' in dic_version: dev = dic_version.dev - # Get the dev if any + # Get the base if any if 'base' in dic_version: base = dic_version.base + + # Get the section if any + if 'section' in dic_version: + section = dic_version.section vv = version # substitute some character with _ in order to get the correct definition @@ -74,19 +85,13 @@ def get_product_config(config, product_name): prod_info = None if product_name in config.PRODUCTS: - # If it exists, get the information of the product_version - if "version_" + vv in config.PRODUCTS[product_name]: - # returns specific information for the given version - prod_info = config.PRODUCTS[product_name]["version_" + vv] - # Get the standard informations - elif "default" in config.PRODUCTS[product_name]: - # returns the generic information (given version not found) - prod_info = config.PRODUCTS[product_name].default + # Search for the product description in the configuration + prod_info = get_product_section(config, product_name, vv, section) # merge opt_depend in depend if prod_info is not None and 'opt_depend' in prod_info: for depend in prod_info.opt_depend: - if depend in config.PRODUCTS: + if depend in config.APPLICATION.products: prod_info.depend.append(depend,'') # In case of a product get with a vcs, @@ -104,8 +109,9 @@ def get_product_config(config, product_name): # In case of a fixed product, # define the install_dir (equal to the version) - if prod_info is not None and prod_info.get_source=="fixed": + if prod_info is not None and os.path.isdir(version): prod_info.install_dir = version + prod_info.get_source = "fixed" # Check if the product is defined as native in the application if prod_info is not None: @@ -123,12 +129,34 @@ def get_product_config(config, product_name): prod_info = src.pyconf.Config() prod_info.name = product_name prod_info.get_source = "native" - + + # If there is no definition but the product is fixed, + # construct a new definition containing only the product name + if prod_info is None and os.path.isdir(version): + prod_info = src.pyconf.Config() + prod_info.name = product_name + prod_info.get_source = "fixed" + prod_info.addMapping("environ", src.pyconf.Mapping(prod_info), "") + + # If prod_info is still None, it means that there is no product definition # in the config. The user has to provide it. if prod_info is None: - msg = _("No definition found for the product %s\n" - "Please create a %s.pyconf file." % (product_name, product_name)) + prod_pyconf_path = src.find_file_in_lpath(product_name + ".pyconf", + config.PATHS.PRODUCTPATH) + if not prod_pyconf_path: + msg = _("""\ +No definition found for the product %(1)s. +Please create a %(2)s.pyconf file somewhere in: +%(3)s""") % { + "1": product_name, + "2": product_name, + "3": config.PATHS.PRODUCTPATH } + else: + msg = _("""\ +No definition corresponding to the version %(1)s was found in the file: + %(2)s. +Please add a section in it.""") % {"1" : vv, "2" : prod_pyconf_path} raise src.SatException(msg) # Set the debug, dev and version keys @@ -147,54 +175,31 @@ def get_product_config(config, product_name): arch_path = src.find_file_in_lpath(arch_name, config.PATHS.ARCHIVEPATH) if not arch_path: - msg = _("Archive %(arch_name)s for %(prod_name)s not found:" - "\n" % {"arch_name" : arch_name, - "prod_name" : prod_info.name}) + msg = _("Archive %(1)s for %(2)s not found.\n") % \ + {"1" : arch_name, "2" : prod_info.name} raise src.SatException(msg) prod_info.archive_info.archive_name = arch_path else: if (os.path.basename(prod_info.archive_info.archive_name) == prod_info.archive_info.archive_name): - + arch_name = prod_info.archive_info.archive_name arch_path = src.find_file_in_lpath( - prod_info.archive_info.archive_name, + arch_name, config.PATHS.ARCHIVEPATH) if not arch_path: - msg = _("Archive %(arch_name)s for %(prod_name)s not found:" - "\n" % {"arch_name" : arch_name, - "prod_name" : prod_info.name}) + msg = _("Archive %(1)s for %(2)s not found:\n") % \ + {"1" : arch_name, "2" : prod_info.name} raise src.SatException(msg) prod_info.archive_info.archive_name = arch_path - - # Set the install_dir key - if "no_base" in config.APPLICATION and config.APPLICATION.no_base == "yes": - # Set it to the default value (in application directory) - prod_info.install_dir = os.path.join(config.APPLICATION.workdir, - "INSTALL", - prod_info.name) - else: - if base == "yes": - prod_info.install_dir = "base" - if "install_dir" not in prod_info: - # Set it to the default value (in application directory) - prod_info.install_dir = os.path.join(config.APPLICATION.workdir, - "INSTALL", - prod_info.name) - else: - if prod_info.install_dir == "base": - # Get the product base of the application - base_path = src.get_base_path(config) - prod_info.install_dir = os.path.join(base_path, - prod_info.name + "-" + version) - + # If the product compiles with a script, check the script existence # and if it is executable if product_has_script(prod_info): # Check the compil_script key existence if "compil_script" not in prod_info: - msg = _("No compilation script found for the product %s\n" - "Please provide a \"compil_script\" key in its definition." - % (product_name)) + msg = _("""\ +No compilation script found for the product %s. +Please provide a 'compil_script' key in its definition.""") % product_name raise src.SatException(msg) # Get the path of the script @@ -205,21 +210,22 @@ def get_product_config(config, product_name): script_path = src.find_file_in_lpath(script_name, config.PATHS.PRODUCTPATH, "compil_scripts") + if not script_path: + raise src.SatException( + _("Compilation script not found: %s") % script_name) prod_info.compil_script = script_path - - # Check script existence - if not os.path.exists(prod_info.compil_script): - raise src.SatException(_("Compilation script not found: %s") % - prod_info.compil_script) - + if src.architecture.is_windows(): + prod_info.compil_script = prod_info.compil_script[:-len(".sh")] + ".bat" + # Check that the script is executable if not os.access(prod_info.compil_script, os.X_OK): - raise src.SatException( - _("Compilation script cannot be executed: %s") % - prod_info.compil_script) + #raise src.SatException( + # _("Compilation script cannot be executed: %s") % + # prod_info.compil_script) + print("WARNING: Compilation script cannot be executed:\n %s" % prod_info.compil_script) # Get the full paths of all the patches - if "patches" in prod_info: + if product_has_patches(prod_info): patches = [] for patch in prod_info.patches: patch_path = patch @@ -238,7 +244,7 @@ def get_product_config(config, product_name): prod_info.patches = patches # Get the full paths of the environment scripts - if "environ" in prod_info and "env_script" in prod_info.environ: + if product_has_env_script(prod_info): env_script_path = prod_info.environ.env_script # If only a filename, then search for the environment script # in the PRODUCTPATH/env_scripts @@ -255,9 +261,214 @@ def get_product_config(config, product_name): raise src.SatException(msg) prod_info.environ.env_script = env_script_path - + + if with_install_dir: + # The variable with_install_dir is at false only for internal use + # of the function get_install_dir + + # Save the install_dir key if there is any + if "install_dir" in prod_info and not "install_dir_save" in prod_info: + prod_info.install_dir_save = prod_info.install_dir + + # if it is not the first time the install_dir is computed, it means + # that install_dir_save exists and it has to be taken into account. + if "install_dir_save" in prod_info: + prod_info.install_dir = prod_info.install_dir_save + + # Set the install_dir key + prod_info.install_dir = get_install_dir(config, base, version, prod_info) + return prod_info +def get_product_section(config, product_name, version, section=None): + '''Get the product description from the configuration + + :param config Config: The global configuration + :param product_name str: The product name + :param version str: The version of the product + :param section str: The searched section (if not None, the section is + explicitly given + :return: The product description + :rtype: Config + ''' + + # if section is not None, try to get the corresponding section + if section: + if section not in config.PRODUCTS[product_name]: + return None + # returns specific information for the given version + prod_info = config.PRODUCTS[product_name][section] + prod_info.section = section + prod_info.from_file = config.PRODUCTS[product_name].from_file + return prod_info + + # If it exists, get the information of the product_version + if "version_" + version in config.PRODUCTS[product_name]: + # returns specific information for the given version + prod_info = config.PRODUCTS[product_name]["version_" + version] + prod_info.section = "version_" + version + prod_info.from_file = config.PRODUCTS[product_name].from_file + return prod_info + + # Else, check if there is a description for multiple versions + l_section_name = config.PRODUCTS[product_name].keys() + l_section_ranges = [section_name for section_name in l_section_name + if VERSION_DELIMITER in section_name] + for section_range in l_section_ranges: + minimum, maximum = section_range.split(VERSION_DELIMITER) + if (src.only_numbers(version) >= src.only_numbers(minimum) + and src.only_numbers(version) <= src.only_numbers(maximum)): + # returns specific information for the versions + prod_info = config.PRODUCTS[product_name][section_range] + prod_info.section = section_range + prod_info.from_file = config.PRODUCTS[product_name].from_file + return prod_info + + # Else, get the standard informations + if "default" in config.PRODUCTS[product_name]: + # returns the generic information (given version not found) + prod_info = config.PRODUCTS[product_name].default + prod_info.section = "default" + prod_info.from_file = config.PRODUCTS[product_name].from_file + return prod_info + + # if noting was found, return None + return None + +def get_install_dir(config, base, version, prod_info): + '''Compute the installation directory of a given product + + :param config Config: The global configuration + :param base str: This corresponds to the value given by user in its + application.pyconf for the specific product. If "yes", the + user wants the product to be in base. If "no", he wants the + product to be in the application workdir + :param version str: The version of the product + :param product_info Config: The configuration specific to + the product + + :return: The path of the product installation + :rtype: str + ''' + install_dir = "" + in_base = False + if (("install_dir" in prod_info and prod_info.install_dir == "base") + or base == "yes"): + in_base = True + if (base == "no" or ("no_base" in config.APPLICATION + and config.APPLICATION.no_base == "yes")): + in_base = False + + if in_base: + install_dir = get_base_install_dir(config, prod_info, version) + else: + if "install_dir" not in prod_info or prod_info.install_dir == "base": + # Set it to the default value (in application directory) + install_dir = os.path.join(config.APPLICATION.workdir, + "INSTALL", + prod_info.name) + else: + install_dir = prod_info.install_dir + + return install_dir + +def get_base_install_dir(config, prod_info, version): + '''Compute the installation directory of a product in base + + :param config Config: The global configuration + :param product_info Config: The configuration specific to + the product + :param version str: The version of the product + :return: The path of the product installation + :rtype: str + ''' + base_path = src.get_base_path(config) + prod_dir = os.path.join(base_path, prod_info.name + "-" + version) + if not os.path.exists(prod_dir): + return os.path.join(prod_dir, "config-1") + + exists, install_dir = check_config_exists(config, prod_dir, prod_info) + if exists: + return install_dir + + # Find the first config- directory that is available in the product + # directory + found = False + label = 1 + while not found: + install_dir = os.path.join(prod_dir, "config-%i" % label) + if os.path.exists(install_dir): + label+=1 + else: + found = True + + return install_dir + +def check_config_exists(config, prod_dir, prod_info): + '''Verify that the installation directory of a product in a base exists + Check all the config- directory and verify the sat-config.pyconf file + that is in it + + :param config Config: The global configuration + :param prod_dir str: The product installation directory path + (without config-) + :param product_info Config: The configuration specific to + the product + :return: True or false is the installation is found or not + and if it is found, the path of the found installation + :rtype: (boolean, str) + ''' + # check if the directories or files of the directory corresponds to the + # directory installation of the product + l_dir_and_files = os.listdir(prod_dir) + for dir_or_file in l_dir_and_files: + oExpr = re.compile(config_expression) + if not(oExpr.search(dir_or_file)): + # not config-, not interesting + continue + # check if there is the file sat-config.pyconf file in the installation + # directory + config_file = os.path.join(prod_dir, dir_or_file, src.CONFIG_FILENAME) + if not os.path.exists(config_file): + continue + + # If there is no dependency, it is the right path + if len(prod_info.depend)==0: + compile_cfg = src.pyconf.Config(config_file) + if len(compile_cfg) == 0: + return True, os.path.join(prod_dir, dir_or_file) + continue + + # check if there is the config described in the file corresponds the + # dependencies of the product + config_corresponds = True + compile_cfg = src.pyconf.Config(config_file) + for prod_dep in prod_info.depend: + # if the dependency is not in the config, + # the config does not correspond + if prod_dep not in compile_cfg: + config_corresponds = False + break + else: + prod_dep_info = get_product_config(config, prod_dep, False) + # If the version of the dependency does not correspond, + # the config does not correspond + if prod_dep_info.version != compile_cfg[prod_dep]: + config_corresponds = False + break + + for prod_name in compile_cfg: + if prod_name not in prod_info.depend: + config_corresponds = False + break + + if config_corresponds: + return True, os.path.join(prod_dir, dir_or_file) + + return False, None + + + def get_products_infos(lproducts, config): '''Get the specific configuration of a list of products @@ -294,6 +505,8 @@ def get_product_dependencies(config, product_info): return [] res = [] for prod in product_info.depend: + if prod == product_info.name: + continue if prod not in res: res.append(prod) prod_info = get_product_config(config, prod) @@ -312,6 +525,8 @@ def check_installation(product_info): :return: True if it is well installed :rtype: boolean ''' + if not product_compiles(product_info): + return True install_dir = product_info.install_dir if not os.path.exists(install_dir): return False @@ -338,18 +553,16 @@ def product_is_sample(product_info): return False def product_is_salome(product_info): - '''Know if a product is of type salome + '''Know if a product is a SALOME module :param product_info Config: The configuration specific to the product - :return: True if the product is salome, else False + :return: True if the product is a SALOME module, else False :rtype: boolean ''' - if 'type' in product_info: - ptype = product_info.type - return ptype.lower() == 'salome' - else: - return False + return ("properties" in product_info and + "is_SALOME_module" in product_info.properties and + product_info.properties.is_SALOME_module == "yes") def product_is_fixed(product_info): '''Know if a product is fixed @@ -417,6 +630,53 @@ def product_is_cmake(product_info): build_src = product_info.build_source return build_src.lower() == 'cmake' +def product_is_vcs(product_info): + '''Know if a product is download using git, svn or cvs (not archive) + + :param product_info Config: The configuration specific to + the product + :return: True if the product is vcs, else False + :rtype: boolean + ''' + return product_info.get_source in AVAILABLE_VCS + +def product_is_smesh_plugin(product_info): + '''Know if a product is a SMESH plugin + + :param product_info Config: The configuration specific to + the product + :return: True if the product is a SMESH plugin, else False + :rtype: boolean + ''' + return ("properties" in product_info and + "smesh_plugin" in product_info.properties and + product_info.properties.smesh_plugin == "yes") + +def product_is_cpp(product_info): + '''Know if a product is cpp + + :param product_info Config: The configuration specific to + the product + :return: True if the product is a cpp, else False + :rtype: boolean + ''' + return ("properties" in product_info and + "cpp" in product_info.properties and + product_info.properties.cpp == "yes") + +def product_compiles(product_info): + '''Know if a product compiles or not (some products do not have a + compilation procedure) + + :param product_info Config: The configuration specific to + the product + :return: True if the product compiles, else False + :rtype: boolean + ''' + return not("properties" in product_info and + "compilation" in product_info.properties and + product_info.properties.compilation == "no") + def product_has_script(product_info): '''Know if a product has a compilation script @@ -429,4 +689,93 @@ def product_has_script(product_info): # Native case return False build_src = product_info.build_source - return build_src.lower() == 'script' \ No newline at end of file + return build_src.lower() == 'script' + +def product_has_env_script(product_info): + '''Know if a product has an environment script + + :param product_info Config: The configuration specific to + the product + :return: True if the product it has an environment script, else False + :rtype: boolean + ''' + return "environ" in product_info and "env_script" in product_info.environ + +def product_has_patches(product_info): + '''Know if a product has one or more patches + + :param product_info Config: The configuration specific to + the product + :return: True if the product has one or more patches + :rtype: boolean + ''' + return "patches" in product_info and len(product_info.patches) > 0 + +def product_has_logo(product_info): + '''Know if a product has a logo (YACSGEN generate) + + :param product_info Config: The configuration specific to + the product + :return: The path of the logo if the product has a logo, else False + :rtype: Str + ''' + if ("properties" in product_info and + "logo" in product_info.properties): + return product_info.properties.logo + else: + return False + +def product_has_salome_gui(product_info): + '''Know if a product has a SALOME gui + + :param product_info Config: The configuration specific to + the product + :return: True if the product has a SALOME gui, else False + :rtype: Boolean + ''' + return ("properties" in product_info and + "has_salome_gui" in product_info.properties and + product_info.properties.has_salome_gui == "yes") + +def product_is_mpi(product_info): + '''Know if a product has openmpi in its dependencies + + :param product_info Config: The configuration specific to + the product + :return: True if the product has openmpi inits dependencies + :rtype: boolean + ''' + return "openmpi" in product_info.depend + +def product_is_generated(product_info): + '''Know if a product is generated (YACSGEN) + + :param product_info Config: The configuration specific to + the product + :return: True if the product is generated + :rtype: boolean + ''' + return ("properties" in product_info and + "generate" in product_info.properties and + product_info.properties.generate == "yes") + +def get_product_components(product_info): + '''Get the component list to generate with the product + + :param product_info Config: The configuration specific to + the product + :return: The list of names of the components + :rtype: List + + ''' + if not product_is_generated(product_info): + return [] + + compo_list = [] + if "component_name" in product_info: + compo_list = product_info.component_name + + if isinstance(compo_list, str): + compo_list = [ compo_list ] + + return compo_list