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()
32 parser.add_option('p', 'products', 'list2', 'products',
33 _('Optional: products from which to get the sources. This option accepts a comma separated list.'))
36 def get_binary_from_archive(config, product_name, product_info, install_dir, logger):
37 '''The method get the binary of the product from an archive
39 :param config Config: The global configuration
40 :param product_name : The name of the product
41 :param product_info Config: The configuration specific to
42 the product to be prepared
43 :param install_dir Path: The Path instance corresponding to the
44 directory where to put the sources
45 :param logger Logger: The logger instance to use for the display and logging
46 :return: True if it succeed, else False
51 # check archive exists
53 # the expected name of the bin archive, as produced by sat package --bin_products
54 archive_name = product_name + '-' + product_info.version + "-" + config.VARS.dist + PACKAGE_EXT
55 # we search this archive in bin directory
56 bin_arch_name = os.path.join("bin",archive_name)
57 # search in the config.PATHS.ARCHIVEPATH
58 arch_path = src.find_file_in_lpath(archive_name, config.PATHS.ARCHIVEPATH, "bin")
60 # bin archive was not found locally in ARCHIVEPATH
62 logger.write("\n The bin archive is not found on local file system, we try ftp\n", 3)
63 ret=src.find_file_in_ftppath(archive_name, config.PATHS.ARCHIVEFTP,
64 config.LOCAL.archive_dir, logger, "bin")
67 # archive was found on ftp and stored in ret
70 logger.write('%s ' % src.printcolors.printc(src.OK_STATUS), 3, False)
71 msg = _("Archive not found in ARCHIVEPATH, nor on ARCHIVEFTP: '%s'") % bin_arch_name
75 logger.write('arc:%s ... ' %
76 src.printcolors.printcInfo(archive_name),
80 # Call the system function that do the extraction in archive mode
81 retcode, NameExtractedDirectory = src.system.archive_extract(arch_path,
82 install_dir.dir(), logger)
84 # Rename the source directory if
85 # it does not match with product_info.source_dir
86 if (NameExtractedDirectory.replace('/', '') !=
87 os.path.basename(product_info.install_dir)):
88 shutil.move(os.path.join(os.path.dirname(product_info.install_dir),
89 NameExtractedDirectory),
90 product_info.install_dir)
96 def get_all_product_binaries(config, products, logger):
97 '''Get all the product sources.
99 :param config Config: The global configuration
100 :param products List: The list of tuples (product name, product informations)
101 :param logger Logger: The logger instance to be used for the logging
102 :return: the tuple (number of success, dictionary product_name/success_fail)
106 # Initialize the variables that will count the fails and success
110 # Get the maximum name length in order to format the terminal display
111 max_product_name_len = 1
112 if len(products) > 0:
113 max_product_name_len = max(map(lambda l: len(l), products[0])) + 4
115 # The loop on all the products from which to get the binaries
116 for product_name, product_info in products:
118 logger.write('%s: ' % src.printcolors.printcLabel(product_name), 3)
119 logger.write(' ' * (max_product_name_len - len(product_name)), 3, False)
120 logger.write("\n", 4, False)
123 # check if there is something to do!
124 if src.product.product_is_fixed(product_info):
125 do_install_prod=False
126 msg = _("INFO : Not doing anything because the products %s is fixed\n") % product_name
127 elif src.product.product_is_native(product_info):
128 do_install_prod=False
129 msg = _("INFO : Not doing anything because the products %s is native\n") % product_name
130 elif src.appli_test_property(config,"pip", "yes") and \
131 src.product.product_test_property(product_info,"pip", "yes"):
132 do_install_prod=False
133 msg = _("INFO : Not doing anything because the products %s is managed by pip\n") % product_name
135 install_dir=src.Path(product_info.install_dir)
136 if install_dir.exists():
137 do_install_prod=False
138 msg = _("INFO : Not doing anything because the install directory already exists:\n %s\n") % install_dir
140 if not do_install_prod:
141 logger.write('%s ' % src.printcolors.printc(src.OK_STATUS), 3, False)
143 good_result = good_result + 1
144 # Do not get the binaries and go to next product
147 # we neeed to install binaries for the product
148 retcode = get_binary_from_archive(config, product_name, product_info, install_dir, logger)
150 # Check that the sources are correctly get using the files to be tested
151 # in product information
154 # CNC TODO check md5sum
155 #check_OK, wrong_path = check_sources(product_info, logger)
157 # # Print the missing file path
158 # msg = _("The required file %s does not exists. " % wrong_path)
159 # logger.write(src.printcolors.printcError("\nERROR: ") + msg, 3)
161 # does post install substitutions
162 #for f in $(grep -RIl -e /volatile/salome/jenkins/workspace/Salome_master_CO7/SALOME-9.7.0-CO7/INSTALL INSTALL); do
164 # s?/volatile/salome/jenkins/workspace/Salome_master_CO7/SALOME-9.7.0-CO7/INSTALL?$(pwd)/INSTALL?g
170 results[product_name] = retcode
172 # The case where it succeed
174 good_result = good_result + 1
176 # The case where it failed
181 logger.write('%s\n' % src.printcolors.printc(res), 3, False)
183 return good_result, results
185 def check_sources(product_info, logger):
186 '''Check that the sources are correctly get, using the files to be tested
187 in product information
189 :param product_info Config: The configuration specific to
190 the product to be prepared
191 :return: True if the files exists (or no files to test is provided).
194 # Get the files to test if there is any
195 if ("present_files" in product_info and
196 "source" in product_info.present_files):
197 l_files_to_be_tested = product_info.present_files.source
198 for file_path in l_files_to_be_tested:
199 # The path to test is the source directory
200 # of the product joined the file path provided
201 path_to_test = os.path.join(product_info.source_dir, file_path)
202 logger.write(_("\nTesting existence of file: \n"), 5)
203 logger.write(path_to_test, 5)
204 if not os.path.exists(path_to_test):
205 return False, path_to_test
206 logger.write(src.printcolors.printcSuccess(" OK\n"), 5)
210 '''method that is called when salomeTools is called with --help option.
212 :return: The text to display for the source command description.
215 return _("The install command gets the binaries of the application products "
216 "from local (ARCHIVEPATH) or ftp server.\n\nexample:"
217 "\nsat install SALOME-master --products GEOM,SMESH")
219 def run(args, runner, logger):
220 '''method that is called when salomeTools is called with install parameter.
222 DBG.write("install.run()", args)
224 (options, args) = parser.parse_args(args)
226 # check that the command has been called with an application
227 src.check_config_has_application( runner.cfg )
229 # Print some informations
230 logger.write(_('Getting binaries of the application %s\n') %
231 src.printcolors.printcLabel(runner.cfg.VARS.application), 1)
232 src.printcolors.print_value(logger, 'workdir',
233 runner.cfg.APPLICATION.workdir, 2)
234 logger.write("\n", 2, False)
237 # Get the list of all application products, and create its dependency graph
238 all_products_infos = src.product.get_products_infos(runner.cfg.APPLICATION.products,
240 from compile import get_dependencies_graph,depth_search_graph
241 all_products_graph=get_dependencies_graph(all_products_infos)
242 #logger.write("Dependency graph of all application products : %s\n" % all_products_graph, 6)
243 DBG.write("Dependency graph of all application products : ", all_products_graph)
246 if options.products is None:
247 #implicit selection of all products
248 products_infos = all_products_infos
250 # a list of products is specified
251 products_list=options.products
252 # we evaluate the complete list including dependencies (~ to the --with-fathers of sat compile)
254 # Extend the list with all recursive dependencies of the given products
256 for p_name in products_list:
257 visited=depth_search_graph(all_products_graph, p_name, visited)
258 products_list = visited
259 logger.write("Product we have to compile (as specified by user) : %s\n" % products_list, 5)
261 # Create a dict of all products to facilitate products_infos sorting
263 for (pname,pinfo) in all_products_infos:
264 all_products_dict[pname]=(pname,pinfo)
266 # build products_infos for the products we have to install
267 for product in products_list:
268 products_infos.append(all_products_dict[product])
272 # Call to the function that gets all the sources
273 good_result, results = get_all_product_binaries(runner.cfg,
277 # Display the results (how much passed, how much failed, etc...)
278 status = src.OK_STATUS
281 logger.write("\n", 2, False)
282 if good_result == len(products_infos):
283 res_count = "%d / %d" % (good_result, good_result)
285 status = src.KO_STATUS
286 res_count = "%d / %d" % (good_result, len(products_infos))
288 for product in results:
289 if results[product] == 0 or results[product] is None:
290 details.append(product)
292 result = len(products_infos) - good_result
295 logger.write(_("Getting binaries of the application:"), 1)
296 logger.write(" " + src.printcolors.printc(status), 1, False)
297 logger.write(" (%s)\n" % res_count, 1, False)
300 logger.write(_("Following binaries haven't been get:\n"), 2)
301 logger.write(" ".join(details), 2)
302 logger.write("\n", 2, False)