Salome HOME
[bos #32522][EDF] SALOME on Demand. Added extension_query module. Some refactoring...
[modules/kernel.git] / bin / SalomeOnDemandTK / extension_remover.py
1 #!/usr/bin/env python3
2 # -*- coding:utf-8 -*-
3 # Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
4 #
5 # Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
6 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
7 #
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
12 #
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 # Lesser General Public License for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21 #
22 # See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #
24
25 #  File   : extension_remover.py
26 #  Author : Konstantin Leontev, Open Cascade
27 #
28 #  @package SalomeOnDemandTK
29 #  @brief Set of utility to remove SALOME python extensions.
30
31 """Set of utility to remove SALOME python extensions.
32 """
33
34 import os
35 import sys
36 import shutil
37 from traceback import format_exc
38
39 from .extension_utilities import logger, \
40     DFILE_EXT, CFILE_EXT, SALOME_EXTDIR, \
41     isvalid_dirname, list_dependants, is_empty_dir, find_salomexd, find_salomexc, find_envpy
42
43
44 def remove_if_empty(top_dir, directory):
45     """
46     Recursively remove empty directories from the given one to the top.
47
48     Args:
49         top_dir - top parent directory that can be removed as well
50         directory - the given directory
51
52     Returns:
53         None.
54     """
55
56     #logger.debug('Check if %s is empty...', directory)
57     if not is_empty_dir(directory):
58         return
59
60     logger.debug('Directory %s is empty. Remove it.', directory)
61     os.rmdir(directory)
62
63     # Don't go up than top root
64     if top_dir == directory:
65         return
66
67     # Remove the parent dir as well
68     parent_dir = os.path.abspath(os.path.join(directory, os.pardir))
69     remove_if_empty(top_dir, parent_dir)
70
71
72 def remove_bylist(root_dir, salomexc):
73     """
74     Remove files and directories listed in the given salomexc file.
75
76     Args:
77         root_dir - a root dir for listed files
78         salomexc - file that contents a list of files to remove.
79
80     Returns:
81         True if all the files were deleted without critical errors.
82     """
83
84     logger.debug('Remove files from %s dir listed in %s...',
85         root_dir, salomexc)
86
87     try:
88         with open(salomexc, 'r', encoding='UTF-8') as file:
89             for line in file:
90                 path_to_remove = os.path.join(root_dir, line.strip())
91                 logger.debug('Remove file %s...', path_to_remove)
92
93                 if os.path.isfile(path_to_remove):
94                     os.remove(path_to_remove)
95
96                     # Remove the parent folder if empty
97                     parent_dir = os.path.dirname(path_to_remove)
98                     remove_if_empty(root_dir, parent_dir)
99
100                 elif os.path.islink(path_to_remove):
101                     os.unlink(path_to_remove)
102
103                     # Remove the parent folder if empty
104                     parent_dir = os.path.dirname(path_to_remove)
105                     remove_if_empty(root_dir, parent_dir)
106
107                 elif os.path.isdir(path_to_remove):
108                     logger.warning('Directories are not expected to be listed in %s file! '
109                         'Remove %s anyway.',
110                         salomexc, path_to_remove)
111                     # Use instead of rmdir here, because dir can be not empty
112                     shutil.rmtree(path_to_remove)
113
114                 else:
115                     logger.error('Unexpected path %s!'
116                         'It is not a file or directory. Skip.',
117                         path_to_remove)
118
119     except OSError:
120         logger.error(format_exc())
121         return False
122
123     return True
124
125 def remove_salomex(install_dir, salomex_name):
126     """
127     Remove a salome extension from SALOME install root.
128
129     Args:
130         salome_root - path to SALOME install root directory.
131         salomex_name - a name of salome extension to remove.
132
133     Returns:
134         None.
135     """
136
137     logger.debug('Starting remove a salome extension %s', salomex_name)
138
139     # Check if provided dirname is valid
140     if not isvalid_dirname(install_dir):
141         return
142
143     # Check if the given extension is installed
144     logger.debug('Check if an extension %s is installed:', salomex_name)
145
146     salomexd = find_salomexd(install_dir, salomex_name)
147     if not salomexd:
148         logger.debug('Cannot find a description file for extension %s! '
149             'Extension has been already removed or %s file was deleted by mistake. '
150             'In the former case we can use %s file to clean up.',
151             salomex_name, DFILE_EXT, CFILE_EXT)
152
153     salomexc = find_salomexc(install_dir, salomex_name)
154     if not salomexc:
155         logger.debug('Cannot find %s for extension %s! '
156             'Going to exit from extension removing process.',
157             salomexc, salomex_name)
158         return
159
160     # Check if we cannot remove an extension because of dependencies
161     dependants = list_dependants(install_dir, salomex_name)
162     if len(dependants) > 0:
163         logger.error('Cannot remove an extension %s because followed extensions depend on it: %s! '
164             'Going to exit from extension removing process.',
165             salomex_name, dependants)
166         return
167
168     # Try to remove all the files listed in the control file
169     if not remove_bylist(os.path.join(install_dir, SALOME_EXTDIR), salomexc):
170         return
171
172     # Remove control file
173     os.remove(salomexc)
174
175     # Remove env file
176     env_py = find_envpy(install_dir, salomex_name)
177     if env_py:
178         os.remove(env_py)
179     else:
180         logger.error('Cannot find and remove %s file! ', env_py)
181
182     # Remove description file
183     if salomexd:
184         os.remove(salomexd)
185
186     logger.debug('An extension %s was removed from %s',
187         salomex_name, install_dir)
188
189
190 if __name__ == '__main__':
191     if len(sys.argv) == 3:
192         arg_1, arg_2 = sys.argv[1:] # pylint: disable=unbalanced-tuple-unpacking
193         remove_salomex(arg_1, arg_2)
194     else:
195         logger.error('You must provide all the arguments!')
196         logger.info(remove_salomex.__doc__)