Salome HOME
spns #40779: implement git multiserver approach: github, gitpub, tuleap
[tools/sat.git] / commands / prepare.py
1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3 #  Copyright (C) 2010-2012  CEA/DEN
4 #
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.
9 #
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.
14 #
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
18
19 import re
20 import os
21 import pprint as PP
22
23 import src
24 import src.debug as DBG
25
26
27 # Define all possible option for prepare command :  sat prepare <options>
28 parser = src.options.Options()
29 parser.add_option('p', 'products', 'list2', 'products',
30     _('Optional: products to prepare. This option accepts a comma separated list.'))
31 parser.add_option('f', 'force', 'boolean', 'force',
32     _("Optional: force to prepare the products in development mode."))
33 parser.add_option('', 'force_patch', 'boolean', 'force_patch', 
34     _("Optional: force to apply patch to the products in development mode."))
35 parser.add_option('c', 'complete', 'boolean', 'complete',
36     _("Optional: completion mode, only prepare products not present in SOURCES dir."),
37     False)
38
39 def find_products_already_prepared(l_products):
40     '''function that returns the list of products that have an existing source 
41        directory.
42     
43     :param l_products List: The list of products to check
44     :return: The list of product configurations that have an existing source 
45              directory.
46     :rtype: List
47     '''
48     l_res = []
49     for p_name_p_cfg in l_products:
50         __, prod_cfg = p_name_p_cfg
51         if "source_dir" in prod_cfg and os.path.exists(prod_cfg.source_dir):
52             l_res.append(p_name_p_cfg)
53     return l_res
54
55 def find_products_with_patchs(l_products):
56     '''function that returns the list of products that have one or more patches.
57     
58     :param l_products List: The list of products to check
59     :return: The list of product configurations that have one or more patches.
60     :rtype: List
61     '''
62     l_res = []
63     for p_name_p_cfg in l_products:
64         __, prod_cfg = p_name_p_cfg
65         l_patchs = src.get_cfg_param(prod_cfg, "patches", [])
66         if len(l_patchs)>0:
67             l_res.append(p_name_p_cfg)
68     return l_res
69
70 def description():
71     '''method that is called when salomeTools is called with --help option.
72     
73     :return: The text to display for the prepare command description.
74     :rtype: str
75     '''
76     return _("The prepare command gets the sources of "
77              "the application products and apply the patches if there is any."
78              "\n\nexample:\nsat prepare SALOME-master --products KERNEL,GUI")
79   
80 def run(args, runner, logger):
81     '''method that is called when salomeTools is called with prepare parameter.
82     '''
83     
84     # Parse the options
85     (options, args) = parser.parse_args(args)
86
87     # check that the command has been called with an application
88     src.check_config_has_application( runner.cfg )
89
90     # check if application configuration file was migrated to newer repository approach
91     src.check_application_syntax_deprecated(runner.cfg, logger)
92
93     # write warning if platform is not declared as supported
94     src.check_platform_is_supported( runner.cfg, logger )
95
96     products_infos = src.product.get_products_list(options, runner.cfg, logger)
97     # Construct the arguments to pass to the clean, source and patch commands
98     args_appli = runner.cfg.VARS.application + " "  # useful whitespace
99     if options.products:
100         listProd = list(options.products)
101     else: # no product interpeted as all products
102         listProd = [name for name, tmp in products_infos]
103
104     git_server = src.get_git_server(runner.cfg,logger)
105
106     # current git server hosts only opensource repositories - then remove products which are not hosted
107     if not src.git_server_has_all_repositories(runner.cfg, git_server):
108         not_opensource_products = [p for p in products_infos if src.product.product_is_not_opensource(p[1])]
109         listProd = [p for p in listProd if p not in [name for name, tmp in not_opensource_products]]
110         logger.flush()
111         if len(not_opensource_products) > 0:
112             lp = ','.join([ name for name, tmp in not_opensource_products])
113             msg = "WARNING: Following products are not available, since these are closed-source products: %s !" % lp
114             logger.write("\n%s\n\n" % src.printcolors.printcWarning(msg), 1)
115     if options.complete:
116         # remove products that are already prepared 'completion mode)
117         pi_already_prepared=find_products_already_prepared(products_infos)
118         l_already_prepared = [i for i, tmp in pi_already_prepared]
119         newList, removedList = removeInList(listProd, l_already_prepared)
120         listProd = newList
121         if len(newList) == 0 and len(removedList) > 0 :
122             msg = "\nAll the products are already installed, do nothing!\n"
123             logger.write(src.printcolors.printcWarning(msg), 1)
124             return 0
125         if len(removedList) > 0 :
126             msg = "\nList of already prepared products that are skipped : %s\n" % ",".join(removedList)
127             logger.write(msg, 3)
128         
129
130     args_product_opt = '--products ' + ",".join(listProd)
131     do_source = (len(listProd) > 0)
132
133
134     ldev_products = [p for p in products_infos if src.product.product_is_dev(p[1])]
135     newList = listProd # default
136     if not options.force and len(ldev_products) > 0:
137         l_products_not_getted = find_products_already_prepared(ldev_products)
138         listNot = [i for i, tmp in l_products_not_getted]
139         newList, removedList = removeInList(listProd, listNot)
140         if len(removedList) > 0:
141             msg = _("""\
142 Do not get the source of the following products in development mode.
143 Use the --force option to overwrite it.
144 """)
145             msg += "\n%s\n" % ",".join(removedList)
146             logger.write(src.printcolors.printcWarning(msg), 1)
147
148     args_product_opt_clean = '--products ' + ",".join(newList)
149     do_clean = (len(newList) > 0)
150     
151     newList = listProd # default
152     if not options.force_patch and len(ldev_products) > 0:
153         l_products_with_patchs = find_products_with_patchs(ldev_products)
154         listNot = [i for i, tmp in l_products_with_patchs]
155         newList, removedList = removeInList(listProd, listNot)
156         if len(removedList) > 0:
157             msg = _("""\
158 Do not patch the following products in development mode.
159 Use the --force_patch option to overwrite it.
160 """)
161             msg += "\n%s\n" % ",".join(removedList)
162             logger.write(src.printcolors.printcWarning(msg), 1)
163                                                      
164     args_product_opt_patch = '--products ' + ",".join(newList)
165     do_patch = (len(newList) > 0)
166       
167     # Construct the final commands arguments
168     args_clean = args_appli + args_product_opt_clean + " --sources"
169     args_source = args_appli + args_product_opt  
170     args_patch = args_appli + args_product_opt_patch
171     # Initialize the results to a running status
172     res_clean = 0
173     res_source = 0
174     res_patch = 0
175     
176     # Call the commands using the API
177     if do_clean:
178         msg = _("Clean the source directories ...")
179         logger.write(msg, 3)
180         logger.flush()
181         res_clean = runner.clean(args_clean, batch=True, verbose = 0, logger_add_link = logger)
182         if res_clean == 0:
183             logger.write('%s\n' % src.printcolors.printc(src.OK_STATUS), 3)
184         else:
185             logger.write('%s\n' % src.printcolors.printc(src.KO_STATUS), 3)
186     if do_source:
187         msg = _("Get the sources of the products ...")
188         logger.write(msg, 5)
189         res_source = runner.source(args_source, logger_add_link = logger)
190         if res_source == 0:
191             logger.write('%s\n' % src.printcolors.printc(src.OK_STATUS), 5)
192         else:
193             logger.write('%s\n' % src.printcolors.printc(src.KO_STATUS), 5)
194     if do_patch:
195         msg = _("Patch the product sources (if any) ...")
196         logger.write(msg, 5)
197         res_patch = runner.patch(args_patch, logger_add_link = logger)
198         if res_patch == 0:
199             logger.write('%s\n' % src.printcolors.printc(src.OK_STATUS), 5)
200         else:
201             logger.write('%s\n' % src.printcolors.printc(src.KO_STATUS), 5)
202     
203     return res_clean + res_source + res_patch
204
205
206 def removeInList(aList, removeList):
207     """Removes elements of removeList list from aList
208     
209     :param aList: (list) The list from which to remove elements
210     :param removeList: (list) The list which contains elements to remove
211     :return: (list, list) (list with elements removed, list of elements removed) 
212     """
213     res1 = [i for i in aList if i not in removeList]
214     res2 = [i for i in aList if i in removeList]
215     return (res1, res2)
216
217