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
24 import src.debug as DBG
26 PROPERTY_EXPRESSION = "^.+:.+$"
28 # Define all possible option for prepare command : sat prepare <options>
29 parser = src.options.Options()
30 parser.add_option('p', 'products', 'list2', 'products',
31 _('Optional: products to prepare. This option can be'
32 ' passed several time to prepare several products.'))
33 parser.add_option('', 'properties', 'string', 'properties',
34 _('Optional: Filter the products by their properties.\n\tSyntax: '
35 '--properties <property>:<value>'))
36 parser.add_option('f', 'force', 'boolean', 'force',
37 _("Optional: force to prepare the products in development mode."))
38 parser.add_option('', 'force_patch', 'boolean', 'force_patch',
39 _("Optional: force to apply patch to the products in development mode."))
41 def get_products_list(options, cfg, logger):
42 '''method that gives the product list with their informations from
43 configuration regarding the passed options.
45 :param options Options: The Options instance that stores the commands
47 :param config Config: The global configuration
48 :param logger Logger: The logger instance to use for the display and logging
49 :return: The list of (product name, product_informations).
52 # Get the products to be prepared, regarding the options
53 if options.products is None:
54 # No options, get all products sources
55 products = cfg.APPLICATION.products
57 # if option --products, check that all products of the command line
58 # are present in the application.
59 products = options.products
61 if p not in cfg.APPLICATION.products:
62 raise src.SatException(_("Product %(product)s "
63 "not defined in application %(application)s") %
64 { 'product': p, 'application': cfg.VARS.application} )
66 # Construct the list of tuple containing
67 # the products name and their definition
68 products_infos = src.product.get_products_infos(products, cfg)
70 # if the property option was passed, filter the list
71 if options.properties:
72 [prop, value] = options.properties.split(":")
73 products_infos = [(p_name, p_info) for
74 (p_name, p_info) in products_infos
75 if "properties" in p_info and
76 prop in p_info.properties and
77 p_info.properties[prop] == value]
81 def find_products_already_getted(l_products):
82 '''function that returns the list of products that have an existing source
85 :param l_products List: The list of products to check
86 :return: The list of product configurations that have an existing source
91 for p_name_p_cfg in l_products:
92 __, prod_cfg = p_name_p_cfg
93 if os.path.exists(prod_cfg.source_dir):
94 l_res.append(p_name_p_cfg)
97 def find_products_with_patchs(l_products):
98 '''function that returns the list of products that have one or more patches.
100 :param l_products List: The list of products to check
101 :return: The list of product configurations that have one or more patches.
105 for p_name_p_cfg in l_products:
106 __, prod_cfg = p_name_p_cfg
107 l_patchs = src.get_cfg_param(prod_cfg, "patches", [])
109 l_res.append(p_name_p_cfg)
113 '''method that is called when salomeTools is called with --help option.
115 :return: The text to display for the prepare command description.
118 return _("The prepare command gets the sources of "
119 "the application products and apply the patches if there is any."
120 "\n\nexample:\nsat prepare SALOME-master --products KERNEL,GUI")
122 def run(args, runner, logger):
123 '''method that is called when salomeTools is called with prepare parameter.
127 (options, args) = parser.parse_args(args)
129 # check that the command has been called with an application
130 src.check_config_has_application( runner.cfg )
132 # Verify the --properties option
133 if options.properties:
134 oExpr = re.compile(PROPERTY_EXPRESSION)
135 if not oExpr.search(options.properties):
136 msg = _('WARNING: the "--properties" options must have the '
137 'following syntax:\n--properties <property>:<value>')
138 logger.write(src.printcolors.printcWarning(msg), 1)
139 logger.write("\n", 1)
140 options.properties = None
142 products_infos = get_products_list(options, runner.cfg, logger)
144 # Construct the arguments to pass to the clean, source and patch commands
145 args_appli = config.VARS.application + " " # useful whitespace
147 listProd = list(options.products)
148 else: # no product interpeted as all products
149 listProd = [name for name, tmp in products_infos]
151 DBG.write("prepare products", sorted(listProd))
152 args_product_opt = '--products ' + ",".join(listProd)
153 do_source = (len(listProd) > 0)
156 ldev_products = [p for p in products_infos if src.product.product_is_dev(p[1])]
157 newList = listProd # default
158 if not options.force and len(ldev_products) > 0:
159 l_products_not_getted = find_products_already_getted(ldev_products)
160 listNot = [i for i, tmp in l_products_not_getted]
161 newList, removedList = removeInList(listProd, listNot)
162 if len(removedList) > 0:
164 Do not get the source of the following products in development mode.
165 Use the --force option to overwrite it.
167 msg += "\n%s\n" % ",".join(removedList)
168 logger.write(src.printcolors.printcWarning(msg), 1)
170 args_product_opt_clean = '--products ' + ",".join(newList)
171 do_clean = (len(newList) > 0)
173 newList = listProd # default
174 if not options.force_patch and len(ldev_products) > 0:
175 l_products_with_patchs = find_products_with_patchs(ldev_products)
176 listNot = [i for i, tmp in l_products_with_patchs]
177 newList, removedList = removeInList(listProd, listNot)
178 if len(removedList) > 0:
180 Do not patch the following products in development mode.
181 Use the --force_patch option to overwrite it.
183 msg += "\n%s\n" % ",".join(removedList)
184 logger.write(src.printcolors.printcWarning(msg), 1)
186 args_product_opt_patch = '--products ' + ",".join(newList)
187 do_patch = (len(newList) > 0)
189 # Construct the final commands arguments
190 args_clean = args_appli + args_product_opt_clean + " --sources"
191 args_source = args_appli + args_product_opt
192 args_patch = args_appli + args_product_opt_patch
194 # Initialize the results to a failing status
199 # Call the commands using the API
201 msg = _("Clean the source directories ...")
204 res_clean = runner.clean(args_clean, batch=True, verbose = 0, logger_add_link = logger)
206 logger.write('%s\n' % src.printcolors.printc(src.OK_STATUS), 3)
208 logger.write('%s\n' % src.printcolors.printc(src.KO_STATUS), 3)
210 msg = _("Get the sources of the products ...")
212 res_source = runner.source(args_source, logger_add_link = logger)
214 logger.write('%s\n' % src.printcolors.printc(src.OK_STATUS), 5)
216 logger.write('%s\n' % src.printcolors.printc(src.KO_STATUS), 5)
218 msg = _("Patch the product sources (if any) ...")
220 res_patch = runner.patch(args_patch, logger_add_link = logger)
222 logger.write('%s\n' % src.printcolors.printc(src.OK_STATUS), 5)
224 logger.write('%s\n' % src.printcolors.printc(src.KO_STATUS), 5)
226 return res_clean + res_source + res_patch
229 def removeInList(aList, removeList):
230 """Removes elements of removeList list from aList
232 :param aList: (list) The list from which to remove elements
233 :param removeList: (list) The list which contains elements to remove
234 :return: (list, list) (list with elements removed, list of elements removed)
236 res1 = [i for i in aList if i not in removeList]
237 res2 = [i for i in aList if i in removeList]