##// END OF EJS Templates
setup: fail if bz2 is not available
Dirkjan Ochtman -
r10761:16a13fdb stable
parent child Browse files
Show More
@@ -1,308 +1,314 b''
1 1 #!/usr/bin/env python
2 2 #
3 3 # This is the mercurial setup script.
4 4 #
5 5 # 'python setup.py install', or
6 6 # 'python setup.py --help' for more options
7 7
8 8 import sys
9 9 if not hasattr(sys, 'version_info') or sys.version_info < (2, 4, 0, 'final'):
10 10 raise SystemExit("Mercurial requires Python 2.4 or later.")
11 11
12 12 # Solaris Python packaging brain damage
13 13 try:
14 14 import hashlib
15 15 sha = hashlib.sha1()
16 16 except:
17 17 try:
18 18 import sha
19 19 except:
20 20 raise SystemExit(
21 21 "Couldn't import standard hashlib (incomplete Python install).")
22 22
23 23 try:
24 24 import zlib
25 25 except:
26 26 raise SystemExit(
27 27 "Couldn't import standard zlib (incomplete Python install).")
28 28
29 try:
30 import bz2
31 except:
32 raise SystemExit(
33 "Couldn't import standard bz2 (incomplete Python install).")
34
29 35 import os, subprocess, time
30 36 import shutil
31 37 import tempfile
32 38 from distutils.core import setup, Extension
33 39 from distutils.dist import Distribution
34 40 from distutils.command.install_data import install_data
35 41 from distutils.command.build import build
36 42 from distutils.command.build_py import build_py
37 43 from distutils.spawn import spawn, find_executable
38 44 from distutils.ccompiler import new_compiler
39 45
40 46 scripts = ['hg']
41 47 if os.name == 'nt':
42 48 scripts.append('contrib/win32/hg.bat')
43 49
44 50 # simplified version of distutils.ccompiler.CCompiler.has_function
45 51 # that actually removes its temporary files.
46 52 def hasfunction(cc, funcname):
47 53 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
48 54 devnull = oldstderr = None
49 55 try:
50 56 try:
51 57 fname = os.path.join(tmpdir, 'funcname.c')
52 58 f = open(fname, 'w')
53 59 f.write('int main(void) {\n')
54 60 f.write(' %s();\n' % funcname)
55 61 f.write('}\n')
56 62 f.close()
57 63 # Redirect stderr to /dev/null to hide any error messages
58 64 # from the compiler.
59 65 # This will have to be changed if we ever have to check
60 66 # for a function on Windows.
61 67 devnull = open('/dev/null', 'w')
62 68 oldstderr = os.dup(sys.stderr.fileno())
63 69 os.dup2(devnull.fileno(), sys.stderr.fileno())
64 70 objects = cc.compile([fname], output_dir=tmpdir)
65 71 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
66 72 except:
67 73 return False
68 74 return True
69 75 finally:
70 76 if oldstderr is not None:
71 77 os.dup2(oldstderr, sys.stderr.fileno())
72 78 if devnull is not None:
73 79 devnull.close()
74 80 shutil.rmtree(tmpdir)
75 81
76 82 # py2exe needs to be installed to work
77 83 try:
78 84 import py2exe
79 85 py2exeloaded = True
80 86
81 87 # Help py2exe to find win32com.shell
82 88 try:
83 89 import modulefinder
84 90 import win32com
85 91 for p in win32com.__path__[1:]: # Take the path to win32comext
86 92 modulefinder.AddPackagePath("win32com", p)
87 93 pn = "win32com.shell"
88 94 __import__(pn)
89 95 m = sys.modules[pn]
90 96 for p in m.__path__[1:]:
91 97 modulefinder.AddPackagePath(pn, p)
92 98 except ImportError:
93 99 pass
94 100
95 101 except ImportError:
96 102 py2exeloaded = False
97 103 pass
98 104
99 105 def runcmd(cmd, env):
100 106 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
101 107 stderr=subprocess.PIPE, env=env)
102 108 out, err = p.communicate()
103 109 # If root is executing setup.py, but the repository is owned by
104 110 # another user (as in "sudo python setup.py install") we will get
105 111 # trust warnings since the .hg/hgrc file is untrusted. That is
106 112 # fine, we don't want to load it anyway. Python may warn about
107 113 # a missing __init__.py in mercurial/locale, we also ignore that.
108 114 err = [e for e in err.splitlines()
109 115 if not e.startswith('Not trusting file') \
110 116 and not e.startswith('warning: Not importing')]
111 117 if err:
112 118 return ''
113 119 return out
114 120
115 121 version = ''
116 122
117 123 if os.path.isdir('.hg'):
118 124 # Execute hg out of this directory with a custom environment which
119 125 # includes the pure Python modules in mercurial/pure. We also take
120 126 # care to not use any hgrc files and do no localization.
121 127 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
122 128 env = {'PYTHONPATH': os.pathsep.join(pypath),
123 129 'HGRCPATH': '',
124 130 'LANGUAGE': 'C'}
125 131 if 'LD_LIBRARY_PATH' in os.environ:
126 132 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
127 133 if 'SystemRoot' in os.environ:
128 134 # Copy SystemRoot into the custom environment for Python 2.6
129 135 # under Windows. Otherwise, the subprocess will fail with
130 136 # error 0xc0150004. See: http://bugs.python.org/issue3440
131 137 env['SystemRoot'] = os.environ['SystemRoot']
132 138 cmd = [sys.executable, 'hg', 'id', '-i', '-t']
133 139 l = runcmd(cmd, env).split()
134 140 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
135 141 l.pop()
136 142 if len(l) > 1: # tag found
137 143 version = l[-1]
138 144 if l[0].endswith('+'): # propagate the dirty status to the tag
139 145 version += '+'
140 146 elif len(l) == 1: # no tag found
141 147 cmd = [sys.executable, 'hg', 'parents', '--template',
142 148 '{latesttag}+{latesttagdistance}-']
143 149 version = runcmd(cmd, env) + l[0]
144 150 if version.endswith('+'):
145 151 version += time.strftime('%Y%m%d')
146 152 elif os.path.exists('.hg_archival.txt'):
147 153 kw = dict([[t.strip() for t in l.split(':', 1)]
148 154 for l in open('.hg_archival.txt')])
149 155 if 'tag' in kw:
150 156 version = kw['tag']
151 157 elif 'latesttag' in kw:
152 158 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
153 159 else:
154 160 version = kw.get('node', '')[:12]
155 161
156 162 if version:
157 163 f = open("mercurial/__version__.py", "w")
158 164 f.write('# this file is autogenerated by setup.py\n')
159 165 f.write('version = "%s"\n' % version)
160 166 f.close()
161 167
162 168
163 169 try:
164 170 from mercurial import __version__
165 171 version = __version__.version
166 172 except ImportError:
167 173 version = 'unknown'
168 174
169 175 class hgbuildmo(build):
170 176
171 177 description = "build translations (.mo files)"
172 178
173 179 def run(self):
174 180 if not find_executable('msgfmt'):
175 181 self.warn("could not find msgfmt executable, no translations "
176 182 "will be built")
177 183 return
178 184
179 185 podir = 'i18n'
180 186 if not os.path.isdir(podir):
181 187 self.warn("could not find %s/ directory" % podir)
182 188 return
183 189
184 190 join = os.path.join
185 191 for po in os.listdir(podir):
186 192 if not po.endswith('.po'):
187 193 continue
188 194 pofile = join(podir, po)
189 195 modir = join('locale', po[:-3], 'LC_MESSAGES')
190 196 mofile = join(modir, 'hg.mo')
191 197 mobuildfile = join('mercurial', mofile)
192 198 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
193 199 if sys.platform != 'sunos5':
194 200 # msgfmt on Solaris does not know about -c
195 201 cmd.append('-c')
196 202 self.mkpath(join('mercurial', modir))
197 203 self.make_file([pofile], mobuildfile, spawn, (cmd,))
198 204
199 205 # Insert hgbuildmo first so that files in mercurial/locale/ are found
200 206 # when build_py is run next.
201 207 build.sub_commands.insert(0, ('build_mo', None))
202 208
203 209 Distribution.pure = 0
204 210 Distribution.global_options.append(('pure', None, "use pure (slow) Python "
205 211 "code instead of C extensions"))
206 212
207 213 class hgbuildpy(build_py):
208 214
209 215 def finalize_options(self):
210 216 build_py.finalize_options(self)
211 217
212 218 if self.distribution.pure:
213 219 if self.py_modules is None:
214 220 self.py_modules = []
215 221 for ext in self.distribution.ext_modules:
216 222 if ext.name.startswith("mercurial."):
217 223 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
218 224 self.distribution.ext_modules = []
219 225
220 226 def find_modules(self):
221 227 modules = build_py.find_modules(self)
222 228 for module in modules:
223 229 if module[0] == "mercurial.pure":
224 230 if module[1] != "__init__":
225 231 yield ("mercurial", module[1], module[2])
226 232 else:
227 233 yield module
228 234
229 235 cmdclass = {'build_mo': hgbuildmo,
230 236 'build_py': hgbuildpy}
231 237
232 238 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
233 239 'hgext.highlight', 'hgext.zeroconf']
234 240
235 241 pymodules = []
236 242
237 243 extmodules = [
238 244 Extension('mercurial.base85', ['mercurial/base85.c']),
239 245 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
240 246 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
241 247 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
242 248 Extension('mercurial.parsers', ['mercurial/parsers.c']),
243 249 ]
244 250
245 251 # disable osutil.c under windows + python 2.4 (issue1364)
246 252 if sys.platform == 'win32' and sys.version_info < (2, 5, 0, 'final'):
247 253 pymodules.append('mercurial.pure.osutil')
248 254 else:
249 255 extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
250 256
251 257 if sys.platform == 'linux2' and os.uname()[2] > '2.6':
252 258 # The inotify extension is only usable with Linux 2.6 kernels.
253 259 # You also need a reasonably recent C library.
254 260 cc = new_compiler()
255 261 if hasfunction(cc, 'inotify_add_watch'):
256 262 extmodules.append(Extension('hgext.inotify.linux._inotify',
257 263 ['hgext/inotify/linux/_inotify.c']))
258 264 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
259 265
260 266 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
261 267 'help/*.txt']}
262 268
263 269 def ordinarypath(p):
264 270 return p and p[0] != '.' and p[-1] != '~'
265 271
266 272 for root in ('templates',):
267 273 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
268 274 curdir = curdir.split(os.sep, 1)[1]
269 275 dirs[:] = filter(ordinarypath, dirs)
270 276 for f in filter(ordinarypath, files):
271 277 f = os.path.join(curdir, f)
272 278 packagedata['mercurial'].append(f)
273 279
274 280 datafiles = []
275 281 setupversion = version
276 282 extra = {}
277 283
278 284 if py2exeloaded:
279 285 extra['console'] = [
280 286 {'script':'hg',
281 287 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others',
282 288 'product_version':version}]
283 289
284 290 if os.name == 'nt':
285 291 # Windows binary file versions for exe/dll files must have the
286 292 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
287 293 setupversion = version.split('+', 1)[0]
288 294
289 295 setup(name='mercurial',
290 296 version=setupversion,
291 297 author='Matt Mackall',
292 298 author_email='mpm@selenic.com',
293 299 url='http://mercurial.selenic.com/',
294 300 description='Scalable distributed SCM',
295 301 license='GNU GPLv2+',
296 302 scripts=scripts,
297 303 packages=packages,
298 304 py_modules=pymodules,
299 305 ext_modules=extmodules,
300 306 data_files=datafiles,
301 307 package_data=packagedata,
302 308 cmdclass=cmdclass,
303 309 options=dict(py2exe=dict(packages=['hgext', 'email']),
304 310 bdist_mpkg=dict(zipdist=True,
305 311 license='COPYING',
306 312 readme='contrib/macosx/Readme.html',
307 313 welcome='contrib/macosx/Welcome.html')),
308 314 **extra)
General Comments 0
You need to be logged in to leave comments. Login now