Salome HOME
First integration of Salome On Demand
[modules/kernel.git] / bin / SalomeOnDemandTK / extension_builder.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_builder.py
26 #  Author : Konstantin Leontev, Open Cascade
27 #
28 #  @package SalomeOnDemandTK
29 #  @brief Set of utility functions those help to build SALOME python extensions.
30
31 """Build salome extension archive in tar.gz format.
32 """
33
34 import tarfile
35 import os
36 import sys
37 import io
38 from traceback import format_exc
39
40 from .extension_utilities import logger, \
41     BFILE_EXT, DFILE_EXT, PYFILE_EXT, EXTNAME_KEY, ARCFILE_EXT, SALOME_EXTDIR, CFILE_EXT, \
42     isvalid_filename, isvalid_dirname, read_salomexd, read_salomexb, list_files_filter, \
43     list_tonewline_str
44
45
46 def add_files(ext, files_abs, files_rel):
47     """
48     Add selected files into salome extension archive.
49
50     Args:
51         ext - a file oject to pack in.
52         files_abs - a list of the files with abs file names.
53         files_rel - a list of the files with rel file names.
54
55     Returns:
56         None.
57     """
58
59     logger.debug('Add selected files into archive %s directory...', SALOME_EXTDIR)
60
61     # Set progress bar, because it can get some time for large archives
62     progress_count = 0
63     total_count = len(files_abs)
64     default_terminator = logger.handlers[0].terminator
65     logger.handlers[0].terminator = ''
66     for (file_abs, file_rel) in zip(files_abs, files_rel):
67         ext.add(file_abs, os.path.normpath(SALOME_EXTDIR + '/' + file_rel))
68
69         # Progress bar's length is 100 symbols.
70         progress_count += 1
71         logger.debug('\r|%-100s|', '=' * int(100 * progress_count/(total_count - 1)))
72
73     # Reset terminator to default value, otherwise all the followed logs will be in one line
74     logger.debug('\n')
75     logger.handlers[0].terminator = default_terminator
76
77
78 def create_salomex(salomexb, salomexd, env_py, top_repository):
79     """
80     Makes salome extension archive from provided in salomexb file directories.
81
82     Args:
83         salomexb - a path to the <extension>.salomexb file.
84         salomexd - a path to the <extension>.salomexd file.
85         env_py - a path to the <ext>_env.py file.
86         top_repository - a root directory for all the paths listed inside salomexb file.
87
88     Returns:
89         None.
90     """
91
92     logger.debug('Starting create an salome extension file')
93
94     # Check if provided filenames are valid
95     if  not isvalid_filename(salomexb, BFILE_EXT) or \
96         not isvalid_filename(salomexd, DFILE_EXT) or \
97         not isvalid_filename(env_py, PYFILE_EXT) or \
98         not isvalid_dirname(top_repository):
99         return
100
101     # Try to get info from salomexd file
102     salome_ext_name = ''
103     salomexd_content = read_salomexd(salomexd)
104     if EXTNAME_KEY in salomexd_content and salomexd_content[EXTNAME_KEY]:
105         salome_ext_name = salomexd_content[EXTNAME_KEY]
106     else:
107         # Now as a last resort we get a name right from salomexd filename
108         # We need to decide if we can handle this case handsomely
109         salome_ext_name = os.path.basename(salomexd)
110         logger.warning('Cannot get a SALOME extension name from salomexd file! \
111             Use salomexd file name as an extension name.')
112
113     logger.debug('Set an extension name as: %s', salome_ext_name)
114
115     try:
116         with tarfile.open(salome_ext_name + '.' + ARCFILE_EXT, "w:gz") as ext:
117             # Write all included files to the extension's dir
118
119             # Get the file's matching pattern in the first place
120             included_files_patterns = read_salomexb(salomexb)
121             logger.debug('Included files pattern: %s', included_files_patterns)
122             if not included_files_patterns:
123                 # We don't have any pattern, so we don't know what we must put inside an archive
124                 logger.error('Cannot create salomex file: \
125                     a list of included files patterns is empty.')
126                 return
127
128             # List of the files those actually written to the archive.
129             # It goes to the salomexc file then.
130             files_abs, files_rel = list_files_filter(top_repository, included_files_patterns)
131             id = 0
132             for f in files_rel:
133                 fsplit = f.split('/')
134                 del fsplit[0]
135                 files_rel[id] = '/'.join(fsplit)
136                 id +=1
137             add_files(ext, files_abs, files_rel)
138
139             # Write the control file - list of the files inside extension's dir
140             logger.debug('Write the %s control file into archive root...', CFILE_EXT)
141             included_files_data = list_tonewline_str(files_rel).encode('utf8')
142             info = tarfile.TarInfo(salome_ext_name + '.' + CFILE_EXT)
143             info.size = len(included_files_data)
144             ext.addfile(info, io.BytesIO(included_files_data))
145
146             # Write the description file as is
147             logger.debug('Copy the %s file into archive root...', salomexd)
148             ext.add(salomexd, os.path.basename(salomexd))
149
150             # Write the env_py file as is
151             logger.debug('Copy the %s file into archive root...', env_py)
152             ext.add(env_py, os.path.basename(env_py))
153
154             logger.debug('SALOME extension %s was created.', salome_ext_name)
155
156     except OSError:
157         logger.error(format_exc())
158
159
160 if __name__ == '__main__':
161     if len(sys.argv) == 5:
162         arg_1, arg_2, arg_3, arg_4 = sys.argv[1:5]
163         create_salomex(arg_1, arg_2, arg_3, arg_4)
164     else:
165         logger.error('You must provide all the arguments!')
166         logger.info(create_salomex.__doc__)