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
26 import src.debug as DBG
28 PACKAGE_EXT = ".tar.gz" # the extension we use for the packages
30 # Define all possible option for patch command : sat patch <options>
31 parser = src.options.Options()
38 "Optional: products from which to get the sources. This option accepts a comma separated list."
43 def get_binary_from_archive(config, product_name, product_info, install_dir, logger):
44 """The method get the binary of the product from an archive
46 :param config Config: The global configuration
47 :param product_name : The name of the product
48 :param product_info Config: The configuration specific to
49 the product to be prepared
50 :param install_dir Path: The Path instance corresponding to the
51 directory where to put the sources
52 :param logger Logger: The logger instance to use for the display and logging
53 :return: True if it succeed, else False
57 # check archive exists
59 # the expected name of the bin archive, as produced by sat package --bin_products
61 product_name + "-" + product_info.version + "-" + config.VARS.dist + PACKAGE_EXT
63 # we search this archive in bin directory
64 bin_arch_name = os.path.join("bin", archive_name)
65 # search in the config.PATHS.ARCHIVEPATH
66 arch_path = src.find_file_in_lpath(archive_name, config.PATHS.ARCHIVEPATH, "bin")
68 # bin archive was not found locally in ARCHIVEPATH
71 "\n The bin archive is not found on local file system, we try ftp\n", 3
73 ret = src.find_file_in_ftppath(
75 config.PATHS.ARCHIVEFTP,
76 config.LOCAL.archive_dir,
82 # archive was found on ftp and stored in ret
85 logger.write("%s " % src.printcolors.printc(src.OK_STATUS), 3, False)
87 _("Archive not found in ARCHIVEPATH, nor on ARCHIVEFTP: '%s'")
93 logger.write("arc:%s ... " % src.printcolors.printcInfo(archive_name), 3, False)
95 # Call the system function that do the extraction in archive mode
96 retcode, NameExtractedDirectory = src.system.archive_extract(
97 arch_path, install_dir.dir(), logger
100 # Rename the source directory if
101 # it does not match with product_info.source_dir
102 if NameExtractedDirectory.replace("/", "") != os.path.basename(
103 product_info.install_dir
107 os.path.dirname(product_info.install_dir), NameExtractedDirectory
109 product_info.install_dir,
115 def get_all_product_binaries(config, products, logger):
116 """Get all the product sources.
118 :param config Config: The global configuration
119 :param products List: The list of tuples (product name, product informations)
120 :param logger Logger: The logger instance to be used for the logging
121 :return: the tuple (number of success, dictionary product_name/success_fail)
125 # Initialize the variables that will count the fails and success
129 # Get the maximum name length in order to format the terminal display
130 max_product_name_len = 1
131 if len(products) > 0:
132 max_product_name_len = max(map(lambda l: len(l), products[0])) + 4
134 # The loop on all the products from which to get the binaries
135 for product_name, product_info in products:
137 logger.write("%s: " % src.printcolors.printcLabel(product_name), 3)
138 logger.write(" " * (max_product_name_len - len(product_name)), 3, False)
139 logger.write("\n", 4, False)
141 do_install_prod = True
142 # check if there is something to do!
143 if src.product.product_is_fixed(product_info):
144 do_install_prod = False
146 _("INFO : Not doing anything because the products %s is fixed\n")
149 elif src.product.product_is_native(product_info):
150 do_install_prod = False
152 _("INFO : Not doing anything because the products %s is native\n")
155 elif src.appli_test_property(
157 ) and src.product.product_test_property(product_info, "pip", "yes"):
158 do_install_prod = False
161 "INFO : Not doing anything because the products %s is managed by pip\n"
166 install_dir = src.Path(product_info.install_dir)
167 if install_dir.exists():
168 do_install_prod = False
171 "INFO : Not doing anything because the install directory already exists:\n %s\n"
176 if not do_install_prod:
177 logger.write("%s " % src.printcolors.printc(src.OK_STATUS), 3, False)
179 good_result = good_result + 1
180 # Do not get the binaries and go to next product
183 # we neeed to install binaries for the product
184 retcode = get_binary_from_archive(
185 config, product_name, product_info, install_dir, logger
188 # Check that the sources are correctly get using the files to be tested
189 # in product information
192 # CNC TODO check md5sum
193 # check_OK, wrong_path = check_sources(product_info, logger)
195 # # Print the missing file path
196 # msg = _("The required file %s does not exists. " % wrong_path)
197 # logger.write(src.printcolors.printcError("\nERROR: ") + msg, 3)
199 # does post install substitutions
200 # for f in $(grep -RIl -e /volatile/salome/jenkins/workspace/Salome_master_CO7/SALOME-9.7.0-CO7/INSTALL INSTALL); do
202 # s?/volatile/salome/jenkins/workspace/Salome_master_CO7/SALOME-9.7.0-CO7/INSTALL?$(pwd)/INSTALL?g
207 results[product_name] = retcode
209 # The case where it succeed
211 good_result = good_result + 1
213 # The case where it failed
218 logger.write("%s\n" % src.printcolors.printc(res), 3, False)
220 return good_result, results
223 def check_sources(product_info, logger):
224 """Check that the sources are correctly get, using the files to be tested
225 in product information
227 :param product_info Config: The configuration specific to
228 the product to be prepared
229 :return: True if the files exists (or no files to test is provided).
232 # Get the files to test if there is any
233 if "present_files" in product_info and "source" in product_info.present_files:
234 l_files_to_be_tested = product_info.present_files.source
235 for file_path in l_files_to_be_tested:
236 # The path to test is the source directory
237 # of the product joined the file path provided
238 path_to_test = os.path.join(product_info.source_dir, file_path)
239 logger.write(_("\nTesting existence of file: \n"), 5)
240 logger.write(path_to_test, 5)
241 if not os.path.exists(path_to_test):
242 return False, path_to_test
243 logger.write(src.printcolors.printcSuccess(" OK\n"), 5)
248 """method that is called when salomeTools is called with --help option.
250 :return: The text to display for the source command description.
254 "The install command gets the binaries of the application products "
255 "from local (ARCHIVEPATH) or ftp server.\n\nexample:"
256 "\nsat install SALOME-master --products GEOM,SMESH"
260 def run(args, runner, logger):
261 """method that is called when salomeTools is called with install parameter."""
262 DBG.write("install.run()", args)
264 (options, args) = parser.parse_args(args)
266 # check that the command has been called with an application
267 src.check_config_has_application(runner.cfg)
269 # Print some informations
271 _("Getting binaries of the application %s\n")
272 % src.printcolors.printcLabel(runner.cfg.VARS.application),
275 src.printcolors.print_value(logger, "workdir", runner.cfg.APPLICATION.workdir, 2)
276 logger.write("\n", 2, False)
278 # Get the list of all application products, and create its dependency graph
279 all_products_infos = src.product.get_products_infos(
280 runner.cfg.APPLICATION.products, runner.cfg
282 from compile import get_dependencies_graph, depth_search_graph
284 all_products_graph = get_dependencies_graph(all_products_infos)
285 # logger.write("Dependency graph of all application products : %s\n" % all_products_graph, 6)
286 DBG.write("Dependency graph of all application products : ", all_products_graph)
289 if options.products is None:
290 # implicit selection of all products
291 products_infos = all_products_infos
293 # a list of products is specified
294 products_list = options.products
295 # we evaluate the complete list including dependencies (~ to the --with-fathers of sat compile)
297 # Extend the list with all recursive dependencies of the given products
299 for p_name in products_list:
300 visited = depth_search_graph(all_products_graph, p_name, visited)
301 products_list = visited
303 "Product we have to compile (as specified by user) : %s\n" % products_list,
307 # Create a dict of all products to facilitate products_infos sorting
308 all_products_dict = {}
309 for (pname, pinfo) in all_products_infos:
310 all_products_dict[pname] = (pname, pinfo)
312 # build products_infos for the products we have to install
313 for product in products_list:
314 products_infos.append(all_products_dict[product])
316 # Call to the function that gets all the sources
317 good_result, results = get_all_product_binaries(runner.cfg, products_infos, logger)
319 # Display the results (how much passed, how much failed, etc...)
320 status = src.OK_STATUS
323 logger.write("\n", 2, False)
324 if good_result == len(products_infos):
325 res_count = "%d / %d" % (good_result, good_result)
327 status = src.KO_STATUS
328 res_count = "%d / %d" % (good_result, len(products_infos))
330 for product in results:
331 if results[product] == 0 or results[product] is None:
332 details.append(product)
334 result = len(products_infos) - good_result
337 logger.write(_("Getting binaries of the application:"), 1)
338 logger.write(" " + src.printcolors.printc(status), 1, False)
339 logger.write(" (%s)\n" % res_count, 1, False)
342 logger.write(_("Following binaries haven't been get:\n"), 2)
343 logger.write(" ".join(details), 2)
344 logger.write("\n", 2, False)