##// END OF EJS Templates
protect record_commit_info from configparser error
MinRK -
Show More
@@ -1,378 +1,382 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 This module defines the things that are used in setup.py for building IPython
3 This module defines the things that are used in setup.py for building IPython
4
4
5 This includes:
5 This includes:
6
6
7 * The basic arguments to setup
7 * The basic arguments to setup
8 * Functions for finding things like packages, package data, etc.
8 * Functions for finding things like packages, package data, etc.
9 * A function for checking dependencies.
9 * A function for checking dependencies.
10 """
10 """
11 from __future__ import print_function
11 from __future__ import print_function
12
12
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14 # Copyright (C) 2008 The IPython Development Team
14 # Copyright (C) 2008 The IPython Development Team
15 #
15 #
16 # Distributed under the terms of the BSD License. The full license is in
16 # Distributed under the terms of the BSD License. The full license is in
17 # the file COPYING, distributed as part of this software.
17 # the file COPYING, distributed as part of this software.
18 #-------------------------------------------------------------------------------
18 #-------------------------------------------------------------------------------
19
19
20 #-------------------------------------------------------------------------------
20 #-------------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-------------------------------------------------------------------------------
22 #-------------------------------------------------------------------------------
23 import os
23 import os
24 import sys
24 import sys
25
25
26 try:
26 try:
27 from configparser import ConfigParser
27 from configparser import ConfigParser
28 except:
28 except:
29 from ConfigParser import ConfigParser
29 from ConfigParser import ConfigParser
30 from distutils.command.build_py import build_py
30 from distutils.command.build_py import build_py
31 from glob import glob
31 from glob import glob
32
32
33 from setupext import install_data_ext
33 from setupext import install_data_ext
34
34
35 #-------------------------------------------------------------------------------
35 #-------------------------------------------------------------------------------
36 # Useful globals and utility functions
36 # Useful globals and utility functions
37 #-------------------------------------------------------------------------------
37 #-------------------------------------------------------------------------------
38
38
39 # A few handy globals
39 # A few handy globals
40 isfile = os.path.isfile
40 isfile = os.path.isfile
41 pjoin = os.path.join
41 pjoin = os.path.join
42
42
43 def oscmd(s):
43 def oscmd(s):
44 print(">", s)
44 print(">", s)
45 os.system(s)
45 os.system(s)
46
46
47 try:
47 try:
48 execfile
48 execfile
49 except NameError:
49 except NameError:
50 def execfile(fname, globs, locs=None):
50 def execfile(fname, globs, locs=None):
51 locs = locs or globs
51 locs = locs or globs
52 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
52 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
53
53
54 # A little utility we'll need below, since glob() does NOT allow you to do
54 # A little utility we'll need below, since glob() does NOT allow you to do
55 # exclusion on multiple endings!
55 # exclusion on multiple endings!
56 def file_doesnt_endwith(test,endings):
56 def file_doesnt_endwith(test,endings):
57 """Return true if test is a file and its name does NOT end with any
57 """Return true if test is a file and its name does NOT end with any
58 of the strings listed in endings."""
58 of the strings listed in endings."""
59 if not isfile(test):
59 if not isfile(test):
60 return False
60 return False
61 for e in endings:
61 for e in endings:
62 if test.endswith(e):
62 if test.endswith(e):
63 return False
63 return False
64 return True
64 return True
65
65
66 #---------------------------------------------------------------------------
66 #---------------------------------------------------------------------------
67 # Basic project information
67 # Basic project information
68 #---------------------------------------------------------------------------
68 #---------------------------------------------------------------------------
69
69
70 # release.py contains version, authors, license, url, keywords, etc.
70 # release.py contains version, authors, license, url, keywords, etc.
71 execfile(pjoin('IPython','core','release.py'), globals())
71 execfile(pjoin('IPython','core','release.py'), globals())
72
72
73 # Create a dict with the basic information
73 # Create a dict with the basic information
74 # This dict is eventually passed to setup after additional keys are added.
74 # This dict is eventually passed to setup after additional keys are added.
75 setup_args = dict(
75 setup_args = dict(
76 name = name,
76 name = name,
77 version = version,
77 version = version,
78 description = description,
78 description = description,
79 long_description = long_description,
79 long_description = long_description,
80 author = author,
80 author = author,
81 author_email = author_email,
81 author_email = author_email,
82 url = url,
82 url = url,
83 download_url = download_url,
83 download_url = download_url,
84 license = license,
84 license = license,
85 platforms = platforms,
85 platforms = platforms,
86 keywords = keywords,
86 keywords = keywords,
87 classifiers = classifiers,
87 classifiers = classifiers,
88 cmdclass = {'install_data': install_data_ext},
88 cmdclass = {'install_data': install_data_ext},
89 )
89 )
90
90
91
91
92 #---------------------------------------------------------------------------
92 #---------------------------------------------------------------------------
93 # Find packages
93 # Find packages
94 #---------------------------------------------------------------------------
94 #---------------------------------------------------------------------------
95
95
96 def find_packages():
96 def find_packages():
97 """
97 """
98 Find all of IPython's packages.
98 Find all of IPython's packages.
99 """
99 """
100 excludes = ['deathrow']
100 excludes = ['deathrow']
101 packages = []
101 packages = []
102 for dir,subdirs,files in os.walk('IPython'):
102 for dir,subdirs,files in os.walk('IPython'):
103 package = dir.replace(os.path.sep, '.')
103 package = dir.replace(os.path.sep, '.')
104 if any([ package.startswith('IPython.'+exc) for exc in excludes ]):
104 if any([ package.startswith('IPython.'+exc) for exc in excludes ]):
105 # package is to be excluded (e.g. deathrow)
105 # package is to be excluded (e.g. deathrow)
106 continue
106 continue
107 if '__init__.py' not in files:
107 if '__init__.py' not in files:
108 # not a package
108 # not a package
109 continue
109 continue
110 packages.append(package)
110 packages.append(package)
111 return packages
111 return packages
112
112
113 #---------------------------------------------------------------------------
113 #---------------------------------------------------------------------------
114 # Find package data
114 # Find package data
115 #---------------------------------------------------------------------------
115 #---------------------------------------------------------------------------
116
116
117 def find_package_data():
117 def find_package_data():
118 """
118 """
119 Find IPython's package_data.
119 Find IPython's package_data.
120 """
120 """
121 # This is not enough for these things to appear in an sdist.
121 # This is not enough for these things to appear in an sdist.
122 # We need to muck with the MANIFEST to get this to work
122 # We need to muck with the MANIFEST to get this to work
123
123
124 # walk notebook resources:
124 # walk notebook resources:
125 cwd = os.getcwd()
125 cwd = os.getcwd()
126 os.chdir(os.path.join('IPython', 'frontend', 'html', 'notebook'))
126 os.chdir(os.path.join('IPython', 'frontend', 'html', 'notebook'))
127 static_walk = list(os.walk('static'))
127 static_walk = list(os.walk('static'))
128 os.chdir(cwd)
128 os.chdir(cwd)
129 static_data = []
129 static_data = []
130 for parent, dirs, files in static_walk:
130 for parent, dirs, files in static_walk:
131 for f in files:
131 for f in files:
132 static_data.append(os.path.join(parent, f))
132 static_data.append(os.path.join(parent, f))
133
133
134 package_data = {
134 package_data = {
135 'IPython.config.profile' : ['README', '*/*.py'],
135 'IPython.config.profile' : ['README', '*/*.py'],
136 'IPython.testing' : ['*.txt'],
136 'IPython.testing' : ['*.txt'],
137 'IPython.frontend.html.notebook' : ['templates/*'] + static_data,
137 'IPython.frontend.html.notebook' : ['templates/*'] + static_data,
138 'IPython.frontend.qt.console' : ['resources/icon/*.svg'],
138 'IPython.frontend.qt.console' : ['resources/icon/*.svg'],
139 }
139 }
140 return package_data
140 return package_data
141
141
142
142
143 #---------------------------------------------------------------------------
143 #---------------------------------------------------------------------------
144 # Find data files
144 # Find data files
145 #---------------------------------------------------------------------------
145 #---------------------------------------------------------------------------
146
146
147 def make_dir_struct(tag,base,out_base):
147 def make_dir_struct(tag,base,out_base):
148 """Make the directory structure of all files below a starting dir.
148 """Make the directory structure of all files below a starting dir.
149
149
150 This is just a convenience routine to help build a nested directory
150 This is just a convenience routine to help build a nested directory
151 hierarchy because distutils is too stupid to do this by itself.
151 hierarchy because distutils is too stupid to do this by itself.
152
152
153 XXX - this needs a proper docstring!
153 XXX - this needs a proper docstring!
154 """
154 """
155
155
156 # we'll use these a lot below
156 # we'll use these a lot below
157 lbase = len(base)
157 lbase = len(base)
158 pathsep = os.path.sep
158 pathsep = os.path.sep
159 lpathsep = len(pathsep)
159 lpathsep = len(pathsep)
160
160
161 out = []
161 out = []
162 for (dirpath,dirnames,filenames) in os.walk(base):
162 for (dirpath,dirnames,filenames) in os.walk(base):
163 # we need to strip out the dirpath from the base to map it to the
163 # we need to strip out the dirpath from the base to map it to the
164 # output (installation) path. This requires possibly stripping the
164 # output (installation) path. This requires possibly stripping the
165 # path separator, because otherwise pjoin will not work correctly
165 # path separator, because otherwise pjoin will not work correctly
166 # (pjoin('foo/','/bar') returns '/bar').
166 # (pjoin('foo/','/bar') returns '/bar').
167
167
168 dp_eff = dirpath[lbase:]
168 dp_eff = dirpath[lbase:]
169 if dp_eff.startswith(pathsep):
169 if dp_eff.startswith(pathsep):
170 dp_eff = dp_eff[lpathsep:]
170 dp_eff = dp_eff[lpathsep:]
171 # The output path must be anchored at the out_base marker
171 # The output path must be anchored at the out_base marker
172 out_path = pjoin(out_base,dp_eff)
172 out_path = pjoin(out_base,dp_eff)
173 # Now we can generate the final filenames. Since os.walk only produces
173 # Now we can generate the final filenames. Since os.walk only produces
174 # filenames, we must join back with the dirpath to get full valid file
174 # filenames, we must join back with the dirpath to get full valid file
175 # paths:
175 # paths:
176 pfiles = [pjoin(dirpath,f) for f in filenames]
176 pfiles = [pjoin(dirpath,f) for f in filenames]
177 # Finally, generate the entry we need, which is a pari of (output
177 # Finally, generate the entry we need, which is a pari of (output
178 # path, files) for use as a data_files parameter in install_data.
178 # path, files) for use as a data_files parameter in install_data.
179 out.append((out_path, pfiles))
179 out.append((out_path, pfiles))
180
180
181 return out
181 return out
182
182
183
183
184 def find_data_files():
184 def find_data_files():
185 """
185 """
186 Find IPython's data_files.
186 Find IPython's data_files.
187
187
188 Most of these are docs.
188 Most of these are docs.
189 """
189 """
190
190
191 docdirbase = pjoin('share', 'doc', 'ipython')
191 docdirbase = pjoin('share', 'doc', 'ipython')
192 manpagebase = pjoin('share', 'man', 'man1')
192 manpagebase = pjoin('share', 'man', 'man1')
193
193
194 # Simple file lists can be made by hand
194 # Simple file lists can be made by hand
195 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
195 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
196 if not manpages:
196 if not manpages:
197 # When running from a source tree, the manpages aren't gzipped
197 # When running from a source tree, the manpages aren't gzipped
198 manpages = filter(isfile, glob(pjoin('docs','man','*.1')))
198 manpages = filter(isfile, glob(pjoin('docs','man','*.1')))
199 igridhelpfiles = filter(isfile,
199 igridhelpfiles = filter(isfile,
200 glob(pjoin('IPython','extensions','igrid_help.*')))
200 glob(pjoin('IPython','extensions','igrid_help.*')))
201
201
202 # For nested structures, use the utility above
202 # For nested structures, use the utility above
203 example_files = make_dir_struct(
203 example_files = make_dir_struct(
204 'data',
204 'data',
205 pjoin('docs','examples'),
205 pjoin('docs','examples'),
206 pjoin(docdirbase,'examples')
206 pjoin(docdirbase,'examples')
207 )
207 )
208 manual_files = make_dir_struct(
208 manual_files = make_dir_struct(
209 'data',
209 'data',
210 pjoin('docs','html'),
210 pjoin('docs','html'),
211 pjoin(docdirbase,'manual')
211 pjoin(docdirbase,'manual')
212 )
212 )
213
213
214 # And assemble the entire output list
214 # And assemble the entire output list
215 data_files = [ (manpagebase, manpages),
215 data_files = [ (manpagebase, manpages),
216 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
216 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
217 ] + manual_files + example_files
217 ] + manual_files + example_files
218
218
219 return data_files
219 return data_files
220
220
221
221
222 def make_man_update_target(manpage):
222 def make_man_update_target(manpage):
223 """Return a target_update-compliant tuple for the given manpage.
223 """Return a target_update-compliant tuple for the given manpage.
224
224
225 Parameters
225 Parameters
226 ----------
226 ----------
227 manpage : string
227 manpage : string
228 Name of the manpage, must include the section number (trailing number).
228 Name of the manpage, must include the section number (trailing number).
229
229
230 Example
230 Example
231 -------
231 -------
232
232
233 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
233 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
234 ('docs/man/ipython.1.gz',
234 ('docs/man/ipython.1.gz',
235 ['docs/man/ipython.1'],
235 ['docs/man/ipython.1'],
236 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
236 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
237 """
237 """
238 man_dir = pjoin('docs', 'man')
238 man_dir = pjoin('docs', 'man')
239 manpage_gz = manpage + '.gz'
239 manpage_gz = manpage + '.gz'
240 manpath = pjoin(man_dir, manpage)
240 manpath = pjoin(man_dir, manpage)
241 manpath_gz = pjoin(man_dir, manpage_gz)
241 manpath_gz = pjoin(man_dir, manpage_gz)
242 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
242 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
243 locals() )
243 locals() )
244 return (manpath_gz, [manpath], gz_cmd)
244 return (manpath_gz, [manpath], gz_cmd)
245
245
246 #---------------------------------------------------------------------------
246 #---------------------------------------------------------------------------
247 # Find scripts
247 # Find scripts
248 #---------------------------------------------------------------------------
248 #---------------------------------------------------------------------------
249
249
250 def find_scripts(entry_points=False, suffix=''):
250 def find_scripts(entry_points=False, suffix=''):
251 """Find IPython's scripts.
251 """Find IPython's scripts.
252
252
253 if entry_points is True:
253 if entry_points is True:
254 return setuptools entry_point-style definitions
254 return setuptools entry_point-style definitions
255 else:
255 else:
256 return file paths of plain scripts [default]
256 return file paths of plain scripts [default]
257
257
258 suffix is appended to script names if entry_points is True, so that the
258 suffix is appended to script names if entry_points is True, so that the
259 Python 3 scripts get named "ipython3" etc.
259 Python 3 scripts get named "ipython3" etc.
260 """
260 """
261 if entry_points:
261 if entry_points:
262 console_scripts = [s % suffix for s in [
262 console_scripts = [s % suffix for s in [
263 'ipython%s = IPython.frontend.terminal.ipapp:launch_new_instance',
263 'ipython%s = IPython.frontend.terminal.ipapp:launch_new_instance',
264 'pycolor%s = IPython.utils.PyColorize:main',
264 'pycolor%s = IPython.utils.PyColorize:main',
265 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
265 'ipcontroller%s = IPython.parallel.apps.ipcontrollerapp:launch_new_instance',
266 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
266 'ipengine%s = IPython.parallel.apps.ipengineapp:launch_new_instance',
267 'iplogger%s = IPython.parallel.apps.iploggerapp:launch_new_instance',
267 'iplogger%s = IPython.parallel.apps.iploggerapp:launch_new_instance',
268 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
268 'ipcluster%s = IPython.parallel.apps.ipclusterapp:launch_new_instance',
269 'iptest%s = IPython.testing.iptest:main',
269 'iptest%s = IPython.testing.iptest:main',
270 'irunner%s = IPython.lib.irunner:main'
270 'irunner%s = IPython.lib.irunner:main'
271 ]]
271 ]]
272 gui_scripts = [s % suffix for s in [
272 gui_scripts = [s % suffix for s in [
273 'ipython%s-qtconsole = IPython.frontend.qt.console.qtconsoleapp:main',
273 'ipython%s-qtconsole = IPython.frontend.qt.console.qtconsoleapp:main',
274 ]]
274 ]]
275 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
275 scripts = dict(console_scripts=console_scripts, gui_scripts=gui_scripts)
276 else:
276 else:
277 parallel_scripts = pjoin('IPython','parallel','scripts')
277 parallel_scripts = pjoin('IPython','parallel','scripts')
278 main_scripts = pjoin('IPython','scripts')
278 main_scripts = pjoin('IPython','scripts')
279 scripts = [
279 scripts = [
280 pjoin(parallel_scripts, 'ipengine'),
280 pjoin(parallel_scripts, 'ipengine'),
281 pjoin(parallel_scripts, 'ipcontroller'),
281 pjoin(parallel_scripts, 'ipcontroller'),
282 pjoin(parallel_scripts, 'ipcluster'),
282 pjoin(parallel_scripts, 'ipcluster'),
283 pjoin(parallel_scripts, 'iplogger'),
283 pjoin(parallel_scripts, 'iplogger'),
284 pjoin(main_scripts, 'ipython'),
284 pjoin(main_scripts, 'ipython'),
285 pjoin(main_scripts, 'pycolor'),
285 pjoin(main_scripts, 'pycolor'),
286 pjoin(main_scripts, 'irunner'),
286 pjoin(main_scripts, 'irunner'),
287 pjoin(main_scripts, 'iptest')
287 pjoin(main_scripts, 'iptest')
288 ]
288 ]
289 return scripts
289 return scripts
290
290
291 #---------------------------------------------------------------------------
291 #---------------------------------------------------------------------------
292 # Verify all dependencies
292 # Verify all dependencies
293 #---------------------------------------------------------------------------
293 #---------------------------------------------------------------------------
294
294
295 def check_for_dependencies():
295 def check_for_dependencies():
296 """Check for IPython's dependencies.
296 """Check for IPython's dependencies.
297
297
298 This function should NOT be called if running under setuptools!
298 This function should NOT be called if running under setuptools!
299 """
299 """
300 from setupext.setupext import (
300 from setupext.setupext import (
301 print_line, print_raw, print_status,
301 print_line, print_raw, print_status,
302 check_for_sphinx, check_for_pygments,
302 check_for_sphinx, check_for_pygments,
303 check_for_nose, check_for_pexpect,
303 check_for_nose, check_for_pexpect,
304 check_for_pyzmq, check_for_readline
304 check_for_pyzmq, check_for_readline
305 )
305 )
306 print_line()
306 print_line()
307 print_raw("BUILDING IPYTHON")
307 print_raw("BUILDING IPYTHON")
308 print_status('python', sys.version)
308 print_status('python', sys.version)
309 print_status('platform', sys.platform)
309 print_status('platform', sys.platform)
310 if sys.platform == 'win32':
310 if sys.platform == 'win32':
311 print_status('Windows version', sys.getwindowsversion())
311 print_status('Windows version', sys.getwindowsversion())
312
312
313 print_raw("")
313 print_raw("")
314 print_raw("OPTIONAL DEPENDENCIES")
314 print_raw("OPTIONAL DEPENDENCIES")
315
315
316 check_for_sphinx()
316 check_for_sphinx()
317 check_for_pygments()
317 check_for_pygments()
318 check_for_nose()
318 check_for_nose()
319 check_for_pexpect()
319 check_for_pexpect()
320 check_for_pyzmq()
320 check_for_pyzmq()
321 check_for_readline()
321 check_for_readline()
322
322
323 def record_commit_info(pkg_dir, build_cmd=build_py):
323 def record_commit_info(pkg_dir, build_cmd=build_py):
324 """ Return extended build command class for recording commit
324 """ Return extended build command class for recording commit
325
325
326 The extended command tries to run git to find the current commit, getting
326 The extended command tries to run git to find the current commit, getting
327 the empty string if it fails. It then writes the commit hash into a file
327 the empty string if it fails. It then writes the commit hash into a file
328 in the `pkg_dir` path, named ``.git_commit_info.ini``.
328 in the `pkg_dir` path, named ``.git_commit_info.ini``.
329
329
330 In due course this information can be used by the package after it is
330 In due course this information can be used by the package after it is
331 installed, to tell you what commit it was installed from if known.
331 installed, to tell you what commit it was installed from if known.
332
332
333 To make use of this system, you need a package with a .git_commit_info.ini
333 To make use of this system, you need a package with a .git_commit_info.ini
334 file - e.g. ``myproject/.git_commit_info.ini`` - that might well look like
334 file - e.g. ``myproject/.git_commit_info.ini`` - that might well look like
335 this::
335 this::
336
336
337 # This is an ini file that may contain information about the code state
337 # This is an ini file that may contain information about the code state
338 [commit hash]
338 [commit hash]
339 # The line below may contain a valid hash if it has been substituted
339 # The line below may contain a valid hash if it has been substituted
340 # during 'git archive'
340 # during 'git archive'
341 archive_subst_hash=$Format:%h$
341 archive_subst_hash=$Format:%h$
342 # This line may be modified by the install process
342 # This line may be modified by the install process
343 install_hash=
343 install_hash=
344
344
345 The .git_commit_info file above is also designed to be used with git
345 The .git_commit_info file above is also designed to be used with git
346 substitution - so you probably also want a ``.gitattributes`` file in the
346 substitution - so you probably also want a ``.gitattributes`` file in the
347 root directory of your working tree that contains something like this::
347 root directory of your working tree that contains something like this::
348
348
349 myproject/.git_commit_info.ini export-subst
349 myproject/.git_commit_info.ini export-subst
350
350
351 That will cause the ``.git_commit_info.ini`` file to get filled in by ``git
351 That will cause the ``.git_commit_info.ini`` file to get filled in by ``git
352 archive`` - useful in case someone makes such an archive - for example with
352 archive`` - useful in case someone makes such an archive - for example with
353 via the github 'download source' button.
353 via the github 'download source' button.
354
354
355 Although all the above will work as is, you might consider having something
355 Although all the above will work as is, you might consider having something
356 like a ``get_info()`` function in your package to display the commit
356 like a ``get_info()`` function in your package to display the commit
357 information at the terminal. See the ``pkg_info.py`` module in the nipy
357 information at the terminal. See the ``pkg_info.py`` module in the nipy
358 package for an example.
358 package for an example.
359 """
359 """
360 class MyBuildPy(build_cmd):
360 class MyBuildPy(build_cmd):
361 ''' Subclass to write commit data into installation tree '''
361 ''' Subclass to write commit data into installation tree '''
362 def run(self):
362 def run(self):
363 build_cmd.run(self)
363 build_cmd.run(self)
364 import subprocess
364 import subprocess
365 proc = subprocess.Popen('git rev-parse --short HEAD',
365 proc = subprocess.Popen('git rev-parse --short HEAD',
366 stdout=subprocess.PIPE,
366 stdout=subprocess.PIPE,
367 stderr=subprocess.PIPE,
367 stderr=subprocess.PIPE,
368 shell=True)
368 shell=True)
369 repo_commit, _ = proc.communicate()
369 repo_commit, _ = proc.communicate()
370 # We write the installation commit even if it's empty
370 # We write the installation commit even if it's empty
371 cfg_parser = ConfigParser()
371 cfg_parser = ConfigParser()
372 cfg_parser.read(pjoin(pkg_dir, '.git_commit_info.ini'))
372 cfg_parser.read(pjoin(pkg_dir, '.git_commit_info.ini'))
373 if not cfg_parser.has_section('commit hash'):
374 # just in case the ini file is empty or doesn't exist, somehow
375 # we don't want the next line to raise
376 cfg_parser.add_section('commit hash')
373 cfg_parser.set('commit hash', 'install_hash', repo_commit.decode('ascii'))
377 cfg_parser.set('commit hash', 'install_hash', repo_commit.decode('ascii'))
374 out_pth = pjoin(self.build_lib, pkg_dir, '.git_commit_info.ini')
378 out_pth = pjoin(self.build_lib, pkg_dir, '.git_commit_info.ini')
375 out_file = open(out_pth, 'wt')
379 out_file = open(out_pth, 'wt')
376 cfg_parser.write(out_file)
380 cfg_parser.write(out_file)
377 out_file.close()
381 out_file.close()
378 return MyBuildPy
382 return MyBuildPy
General Comments 0
You need to be logged in to leave comments. Login now