--- /dev/null
+#!/usr/bin/env python
+# -*- coding:utf-8 -*-
+# Copyright (C) 2010-2012 CEA/DEN
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# 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
+
+import re
+import os
+import pprint as PP
+
+import src
+import src.debug as DBG
+
+
+# Define all possible option for update command : sat update <options>
+parser = src.options.Options()
+parser.add_option(
+ "p",
+ "products",
+ "list2",
+ "products",
+ _("Optional: products to update. This option accepts a comma separated list."),
+)
+# parser.add_option('f', 'force', 'boolean', 'force',
+# _("Optional: force to update the products in development mode."))
+parser.add_option('', 'force_patch', 'boolean', 'force_patch',
+ _("Optional: force to apply patch to the products in development mode."))
+# parser.add_option('c', 'complete', 'boolean', 'complete',
+# _("Optional: completion mode, only update products not present in SOURCES dir."),
+# False)
+
+
+def find_products_already_prepared(l_products):
+ """function that returns the list of products that have an existing source
+ directory.
+
+ :param l_products List: The list of products to check
+ :return: The list of product configurations that have an existing source
+ directory.
+ :rtype: List
+ """
+ l_res = []
+ for p_name_p_cfg in l_products:
+ __, prod_cfg = p_name_p_cfg
+ if "source_dir" in prod_cfg and os.path.exists(prod_cfg.source_dir):
+ l_res.append(p_name_p_cfg)
+ return l_res
+
+def find_git_products(l_products):
+ """
+ function that returns the list of products that have an existing source
+ directory and a git configuration. Those products will be updated using :
+
+ git checkout TARGET_TAG
+ git pull origin TARGET_TAG --ff-only
+
+ Not committed dev or conflict with origin during pull will trigger an error.
+
+ :param l_products List: The list of products to check
+ :return: The list of product configurations that have an existing source
+ directory and a git history.
+ :rtype: List
+ """
+ l_res = []
+ for p_name_p_cfg in l_products:
+ __, prod_cfg = p_name_p_cfg
+ if "source_dir" in prod_cfg and os.path.exists(prod_cfg.source_dir):
+ if os.path.exists(prod_cfg.source_dir + "/.git"):
+ l_res.append(p_name_p_cfg)
+ return l_res
+
+
+def find_products_with_patchs(l_products):
+ """function that returns the list of products that have one or more patches.
+
+ :param l_products List: The list of products to check
+ :return: The list of product configurations that have one or more patches.
+ :rtype: List
+ """
+ l_res = []
+ for p_name_p_cfg in l_products:
+ __, prod_cfg = p_name_p_cfg
+ l_patchs = src.get_cfg_param(prod_cfg, "patches", [])
+ if len(l_patchs) > 0:
+ l_res.append(p_name_p_cfg)
+ return l_res
+
+
+def description():
+ """method that is called when salomeTools is called with --help option.
+
+ :return: The text to display for the update command description.
+ :rtype: str
+ """
+ return _(
+ "The update command gets the sources of "
+ "the application products and apply the patches if there is any."
+ "\n\nexample:\nsat update SALOME-master --products KERNEL,GUI"
+ )
+
+class UpdateOp:
+ """
+ This is an operation class. It is prepared though the init and launched
+ with the launch method.
+
+ This operation updates the products, meaning it get the missing ones, and
+ pull the TARGET_TAG for the already present ones. It prevents from erasing
+ everything, especially .git/ files.
+
+ In case you have uncommited work, the operation will stop.
+
+ In case the remote tracking branch can't be pulled fast-forward (after a
+ checkout to the matching local branch), the operation will stop.
+ """
+
+ def __init__(self, args, runner, logger):
+ """
+ Initialisation of the UpdateOp. The runner and the plateform are
+ checked.
+
+ :args: arguments passed to sat
+ :runner: Sat class instance
+ :logger: Current logger
+ """
+ # check that the command has been called with an application
+ src.check_config_has_application(runner.cfg)
+
+ # write warning if platform is not declared as supported
+ src.check_platform_is_supported(runner.cfg, logger)
+
+ # Parse the options
+ (options, args) = parser.parse_args(args)
+ self._list_of_products = options.products
+ self._force_patch = options.force_patch
+
+ self.runner = runner
+ self.logger = logger
+ self.products_infos = src.product.get_products_list(options, self.runner.cfg, self.logger)
+
+ # Construct the arguments to pass to the clean, source and patch commands
+ self.args_appli = runner.cfg.VARS.application + " " # useful whitespace
+
+ @property
+ def products(self):
+ if self._list_of_products:
+ return list(self._list_of_products)
+ return [name for name, tmp in self.products_infos]
+
+ def getProductsToPrepare(self):
+ """
+ Remove products that are already prepared and under git tracking so
+ that only new products (and not tracked ones) are prepared.
+ """
+ pi_already_prepared = find_git_products(self.products_infos)
+ l_already_prepared = [i for i, tmp in pi_already_prepared]
+ newList, removedList = removeInList(self.products, l_already_prepared)
+ if len(newList) == 0 and len(removedList) > 0:
+ msg = "\nAll the products are already installed, do nothing!\n"
+ self.logger.write(src.printcolors.printcWarning(msg), 1)
+ return 0
+ if len(removedList) > 0:
+ msg = (
+ "\nList of already prepared products that are skipped : %s\n"
+ % ",".join(removedList)
+ )
+ self.logger.write(msg, 3)
+ return newList
+
+ def getProductsToUpdate(self):
+ pi_already_prepared = find_git_products(self.products_infos)
+ productsToUpdate = [i for i, tmp in pi_already_prepared]
+ return productsToUpdate
+
+ def getProductsToClean(self, listProdToPrepare):
+ ldev_products = [p for p in self.products_infos if src.product.product_is_dev(p[1])]
+ productsToClean = listProdToPrepare # default
+ if len(ldev_products) > 0:
+ l_products_not_getted = find_products_already_prepared(ldev_products)
+ listNot = [i for i, tmp in l_products_not_getted]
+ productsToClean, removedList = removeInList(listProdToPrepare, listNot)
+ if len(removedList) > 0:
+ msg = _(
+ """
+ Do not get the source of the following products in
+ development mode.
+ """
+ )
+ msg += "\n%s\n" % ",".join(removedList)
+ self.logger.write(src.printcolors.printcWarning(msg), 1)
+ return productsToClean
+
+ def getProductsToPatch(self, listProdToPrepare):
+ productsToPatch = listProdToPrepare # default
+ ldev_products = [p for p in self.products_infos if src.product.product_is_dev(p[1])]
+ if not self._force_patch and len(ldev_products) > 0:
+ l_products_with_patchs = find_products_with_patchs(ldev_products)
+ listNot = [i for i, tmp in l_products_with_patchs]
+ productsToPatch, removedList = removeInList(listProdToPrepare, listNot)
+ if len(removedList) > 0:
+ msg = _(
+ """
+ Do not patch the following products in development mode.
+ Use the --force_patch option to overwrite it.
+ """
+ )
+ msg += "\n%s\n" % ",".join(removedList)
+ self.logger.write(src.printcolors.printcWarning(msg), 1)
+ return productsToPatch
+
+ def launch(self):
+ productsToPrepare = self.getProductsToPrepare()
+ args_product_to_prepare_opt = "--products " + ",".join(productsToPrepare)
+
+ productsToClean = self.getProductsToClean(productsToPrepare)
+ args_product_opt_clean = "--products " + ",".join(productsToClean)
+
+ productsToPatch = self.getProductsToPatch(productsToPrepare)
+ args_product_opt_patch = "--products " + ",".join(productsToPatch)
+
+
+ # Initialize the results to a running status
+ res_clean = 0
+ res_source = 0
+ res_patch = 0
+
+ # Call the commands using the API
+ if len(productsToClean) > 0:
+ msg = _("Clean the source directories ...")
+ self.logger.write(msg, 3)
+ self.logger.flush()
+ args_clean = self.args_appli + args_product_opt_clean + " --sources"
+ res_clean = self.runner.clean(args_clean, batch=True, verbose = 0, logger_add_link = self.logger)
+ if res_clean == 0:
+ self.logger.write('%s\n' % src.printcolors.printc(src.OK_STATUS), 3)
+ else:
+ self.logger.write('%s\n' % src.printcolors.printc(src.KO_STATUS), 3)
+ if len(productsToPrepare) > 0:
+ msg = _("Get the sources of the products ...")
+ self.logger.write(msg, 5)
+ args_source = self.args_appli + args_product_to_prepare_opt
+ res_source = self.runner.source(args_source, logger_add_link=self.logger)
+ if res_source == 0:
+ self.logger.write("%s\n" % src.printcolors.printc(src.OK_STATUS), 5)
+ else:
+ self.logger.write("%s\n" % src.printcolors.printc(src.KO_STATUS), 5)
+ if len(productsToPatch) > 0:
+ msg = _("Patch the product sources (if any) ...")
+ self.logger.write(msg, 5)
+ args_patch = self.args_appli + args_product_opt_patch
+ res_patch = self.runner.patch(args_patch, logger_add_link=self.logger)
+ if res_patch == 0:
+ self.logger.write("%s\n" % src.printcolors.printc(src.OK_STATUS), 5)
+ else:
+ self.logger.write("%s\n" % src.printcolors.printc(src.KO_STATUS), 5)
+ return res_clean + res_source + res_patch
+
+
+
+def run(args, runner, logger):
+ """method that is called when salomeTools is called with update parameter."""
+ updateOp = UpdateOp(args, runner, logger)
+ res = updateOp.launch()
+ return res
+
+
+def removeInList(aList, removeList):
+ """Removes elements of removeList list from aList
+
+ :param aList: (list) The list from which to remove elements
+ :param removeList: (list) The list which contains elements to remove
+ :return: (list, list) (list with elements removed, list of elements removed)
+ """
+ res1 = [i for i in aList if i not in removeList]
+ res2 = [i for i in aList if i in removeList]
+ return (res1, res2)