##// END OF EJS Templates
setup: raise when executing with python3 without c2to3 argument
Simon Heimberg -
r15500:d5abe76d default
parent child Browse files
Show More
@@ -1,484 +1,485 b''
1 #
1 #
2 # This is the mercurial setup script.
2 # This is the mercurial setup script.
3 #
3 #
4 # 'python setup.py install', or
4 # 'python setup.py install', or
5 # 'python setup.py --help' for more options
5 # 'python setup.py --help' for more options
6
6
7 import sys, platform
7 import sys, platform
8 if getattr(sys, 'version_info', (0, 0, 0)) < (2, 4, 0, 'final'):
8 if getattr(sys, 'version_info', (0, 0, 0)) < (2, 4, 0, 'final'):
9 raise SystemExit("Mercurial requires Python 2.4 or later.")
9 raise SystemExit("Mercurial requires Python 2.4 or later.")
10
10
11 if sys.version_info[0] >= 3:
11 if sys.version_info[0] >= 3:
12 def b(s):
12 def b(s):
13 '''A helper function to emulate 2.6+ bytes literals using string
13 '''A helper function to emulate 2.6+ bytes literals using string
14 literals.'''
14 literals.'''
15 return s.encode('latin1')
15 return s.encode('latin1')
16 else:
16 else:
17 def b(s):
17 def b(s):
18 '''A helper function to emulate 2.6+ bytes literals using string
18 '''A helper function to emulate 2.6+ bytes literals using string
19 literals.'''
19 literals.'''
20 return s
20 return s
21
21
22 # Solaris Python packaging brain damage
22 # Solaris Python packaging brain damage
23 try:
23 try:
24 import hashlib
24 import hashlib
25 sha = hashlib.sha1()
25 sha = hashlib.sha1()
26 except:
26 except:
27 try:
27 try:
28 import sha
28 import sha
29 except:
29 except:
30 raise SystemExit(
30 raise SystemExit(
31 "Couldn't import standard hashlib (incomplete Python install).")
31 "Couldn't import standard hashlib (incomplete Python install).")
32
32
33 try:
33 try:
34 import zlib
34 import zlib
35 except:
35 except:
36 raise SystemExit(
36 raise SystemExit(
37 "Couldn't import standard zlib (incomplete Python install).")
37 "Couldn't import standard zlib (incomplete Python install).")
38
38
39 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
39 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
40 isironpython = False
40 isironpython = False
41 try:
41 try:
42 isironpython = platform.python_implementation().lower().find("ironpython") != -1
42 isironpython = platform.python_implementation().lower().find("ironpython") != -1
43 except:
43 except:
44 pass
44 pass
45
45
46 if isironpython:
46 if isironpython:
47 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
47 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
48 else:
48 else:
49 try:
49 try:
50 import bz2
50 import bz2
51 except:
51 except:
52 raise SystemExit(
52 raise SystemExit(
53 "Couldn't import standard bz2 (incomplete Python install).")
53 "Couldn't import standard bz2 (incomplete Python install).")
54
54
55 import os, subprocess, time
55 import os, subprocess, time
56 import shutil
56 import shutil
57 import tempfile
57 import tempfile
58 from distutils import log
58 from distutils import log
59 from distutils.core import setup, Command, Extension
59 from distutils.core import setup, Command, Extension
60 from distutils.dist import Distribution
60 from distutils.dist import Distribution
61 from distutils.command.build import build
61 from distutils.command.build import build
62 from distutils.command.build_ext import build_ext
62 from distutils.command.build_ext import build_ext
63 from distutils.command.build_py import build_py
63 from distutils.command.build_py import build_py
64 from distutils.command.install_scripts import install_scripts
64 from distutils.command.install_scripts import install_scripts
65 from distutils.spawn import spawn, find_executable
65 from distutils.spawn import spawn, find_executable
66 from distutils.ccompiler import new_compiler
66 from distutils.ccompiler import new_compiler
67 from distutils.errors import CCompilerError, DistutilsExecError
67 from distutils.errors import CCompilerError, DistutilsExecError
68 from distutils.sysconfig import get_python_inc
68 from distutils.sysconfig import get_python_inc
69 from distutils.version import StrictVersion
69 from distutils.version import StrictVersion
70
70
71 convert2to3 = '--c2to3' in sys.argv
71 convert2to3 = '--c2to3' in sys.argv
72 if convert2to3:
72 if convert2to3:
73 try:
73 try:
74 from distutils.command.build_py import build_py_2to3 as build_py
74 from distutils.command.build_py import build_py_2to3 as build_py
75 from lib2to3.refactor import get_fixers_from_package as getfixers
75 from lib2to3.refactor import get_fixers_from_package as getfixers
76 except ImportError:
76 except ImportError:
77 if sys.version_info[0] < 3:
77 if sys.version_info[0] < 3:
78 raise SystemExit("--c2to3 is only compatible with python3.")
78 raise SystemExit("--c2to3 is only compatible with python3.")
79 raise
79 raise
80 sys.path.append('contrib')
80 sys.path.append('contrib')
81
81 elif sys.version_info[0] >= 3:
82 raise SystemExit("setup.py with python3 needs --c2to3 (experimental)")
82
83
83 scripts = ['hg']
84 scripts = ['hg']
84 if os.name == 'nt':
85 if os.name == 'nt':
85 scripts.append('contrib/win32/hg.bat')
86 scripts.append('contrib/win32/hg.bat')
86
87
87 # simplified version of distutils.ccompiler.CCompiler.has_function
88 # simplified version of distutils.ccompiler.CCompiler.has_function
88 # that actually removes its temporary files.
89 # that actually removes its temporary files.
89 def hasfunction(cc, funcname):
90 def hasfunction(cc, funcname):
90 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
91 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
91 devnull = oldstderr = None
92 devnull = oldstderr = None
92 try:
93 try:
93 try:
94 try:
94 fname = os.path.join(tmpdir, 'funcname.c')
95 fname = os.path.join(tmpdir, 'funcname.c')
95 f = open(fname, 'w')
96 f = open(fname, 'w')
96 f.write('int main(void) {\n')
97 f.write('int main(void) {\n')
97 f.write(' %s();\n' % funcname)
98 f.write(' %s();\n' % funcname)
98 f.write('}\n')
99 f.write('}\n')
99 f.close()
100 f.close()
100 # Redirect stderr to /dev/null to hide any error messages
101 # Redirect stderr to /dev/null to hide any error messages
101 # from the compiler.
102 # from the compiler.
102 # This will have to be changed if we ever have to check
103 # This will have to be changed if we ever have to check
103 # for a function on Windows.
104 # for a function on Windows.
104 devnull = open('/dev/null', 'w')
105 devnull = open('/dev/null', 'w')
105 oldstderr = os.dup(sys.stderr.fileno())
106 oldstderr = os.dup(sys.stderr.fileno())
106 os.dup2(devnull.fileno(), sys.stderr.fileno())
107 os.dup2(devnull.fileno(), sys.stderr.fileno())
107 objects = cc.compile([fname], output_dir=tmpdir)
108 objects = cc.compile([fname], output_dir=tmpdir)
108 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
109 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
109 except:
110 except:
110 return False
111 return False
111 return True
112 return True
112 finally:
113 finally:
113 if oldstderr is not None:
114 if oldstderr is not None:
114 os.dup2(oldstderr, sys.stderr.fileno())
115 os.dup2(oldstderr, sys.stderr.fileno())
115 if devnull is not None:
116 if devnull is not None:
116 devnull.close()
117 devnull.close()
117 shutil.rmtree(tmpdir)
118 shutil.rmtree(tmpdir)
118
119
119 # py2exe needs to be installed to work
120 # py2exe needs to be installed to work
120 try:
121 try:
121 import py2exe
122 import py2exe
122 py2exeloaded = True
123 py2exeloaded = True
123 except ImportError:
124 except ImportError:
124 py2exeloaded = False
125 py2exeloaded = False
125
126
126 def runcmd(cmd, env):
127 def runcmd(cmd, env):
127 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
128 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
128 stderr=subprocess.PIPE, env=env)
129 stderr=subprocess.PIPE, env=env)
129 out, err = p.communicate()
130 out, err = p.communicate()
130 return out, err
131 return out, err
131
132
132 def runhg(cmd, env):
133 def runhg(cmd, env):
133 out, err = runcmd(cmd, env)
134 out, err = runcmd(cmd, env)
134 # If root is executing setup.py, but the repository is owned by
135 # If root is executing setup.py, but the repository is owned by
135 # another user (as in "sudo python setup.py install") we will get
136 # another user (as in "sudo python setup.py install") we will get
136 # trust warnings since the .hg/hgrc file is untrusted. That is
137 # trust warnings since the .hg/hgrc file is untrusted. That is
137 # fine, we don't want to load it anyway. Python may warn about
138 # fine, we don't want to load it anyway. Python may warn about
138 # a missing __init__.py in mercurial/locale, we also ignore that.
139 # a missing __init__.py in mercurial/locale, we also ignore that.
139 err = [e for e in err.splitlines()
140 err = [e for e in err.splitlines()
140 if not e.startswith(b('Not trusting file')) \
141 if not e.startswith(b('Not trusting file')) \
141 and not e.startswith(b('warning: Not importing'))]
142 and not e.startswith(b('warning: Not importing'))]
142 if err:
143 if err:
143 return ''
144 return ''
144 return out
145 return out
145
146
146 version = ''
147 version = ''
147
148
148 # Execute hg out of this directory with a custom environment which
149 # Execute hg out of this directory with a custom environment which
149 # includes the pure Python modules in mercurial/pure. We also take
150 # includes the pure Python modules in mercurial/pure. We also take
150 # care to not use any hgrc files and do no localization.
151 # care to not use any hgrc files and do no localization.
151 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
152 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
152 env = {'PYTHONPATH': os.pathsep.join(pypath),
153 env = {'PYTHONPATH': os.pathsep.join(pypath),
153 'HGRCPATH': '',
154 'HGRCPATH': '',
154 'LANGUAGE': 'C'}
155 'LANGUAGE': 'C'}
155 if 'LD_LIBRARY_PATH' in os.environ:
156 if 'LD_LIBRARY_PATH' in os.environ:
156 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
157 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
157 if 'SystemRoot' in os.environ:
158 if 'SystemRoot' in os.environ:
158 # Copy SystemRoot into the custom environment for Python 2.6
159 # Copy SystemRoot into the custom environment for Python 2.6
159 # under Windows. Otherwise, the subprocess will fail with
160 # under Windows. Otherwise, the subprocess will fail with
160 # error 0xc0150004. See: http://bugs.python.org/issue3440
161 # error 0xc0150004. See: http://bugs.python.org/issue3440
161 env['SystemRoot'] = os.environ['SystemRoot']
162 env['SystemRoot'] = os.environ['SystemRoot']
162
163
163 if os.path.isdir('.hg'):
164 if os.path.isdir('.hg'):
164 cmd = [sys.executable, 'hg', 'id', '-i', '-t']
165 cmd = [sys.executable, 'hg', 'id', '-i', '-t']
165 l = runhg(cmd, env).split()
166 l = runhg(cmd, env).split()
166 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
167 while len(l) > 1 and l[-1][0].isalpha(): # remove non-numbered tags
167 l.pop()
168 l.pop()
168 if len(l) > 1: # tag found
169 if len(l) > 1: # tag found
169 version = l[-1]
170 version = l[-1]
170 if l[0].endswith('+'): # propagate the dirty status to the tag
171 if l[0].endswith('+'): # propagate the dirty status to the tag
171 version += '+'
172 version += '+'
172 elif len(l) == 1: # no tag found
173 elif len(l) == 1: # no tag found
173 cmd = [sys.executable, 'hg', 'parents', '--template',
174 cmd = [sys.executable, 'hg', 'parents', '--template',
174 '{latesttag}+{latesttagdistance}-']
175 '{latesttag}+{latesttagdistance}-']
175 version = runhg(cmd, env) + l[0]
176 version = runhg(cmd, env) + l[0]
176 if version.endswith('+'):
177 if version.endswith('+'):
177 version += time.strftime('%Y%m%d')
178 version += time.strftime('%Y%m%d')
178 elif os.path.exists('.hg_archival.txt'):
179 elif os.path.exists('.hg_archival.txt'):
179 kw = dict([[t.strip() for t in l.split(':', 1)]
180 kw = dict([[t.strip() for t in l.split(':', 1)]
180 for l in open('.hg_archival.txt')])
181 for l in open('.hg_archival.txt')])
181 if 'tag' in kw:
182 if 'tag' in kw:
182 version = kw['tag']
183 version = kw['tag']
183 elif 'latesttag' in kw:
184 elif 'latesttag' in kw:
184 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
185 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
185 else:
186 else:
186 version = kw.get('node', '')[:12]
187 version = kw.get('node', '')[:12]
187
188
188 if version:
189 if version:
189 f = open("mercurial/__version__.py", "w")
190 f = open("mercurial/__version__.py", "w")
190 f.write('# this file is autogenerated by setup.py\n')
191 f.write('# this file is autogenerated by setup.py\n')
191 f.write('version = "%s"\n' % version)
192 f.write('version = "%s"\n' % version)
192 f.close()
193 f.close()
193
194
194
195
195 try:
196 try:
196 from mercurial import __version__
197 from mercurial import __version__
197 version = __version__.version
198 version = __version__.version
198 except ImportError:
199 except ImportError:
199 version = 'unknown'
200 version = 'unknown'
200
201
201 class hgbuild(build):
202 class hgbuild(build):
202 # Insert hgbuildmo first so that files in mercurial/locale/ are found
203 # Insert hgbuildmo first so that files in mercurial/locale/ are found
203 # when build_py is run next.
204 # when build_py is run next.
204 sub_commands = [('build_mo', None),
205 sub_commands = [('build_mo', None),
205 # We also need build_ext before build_py. Otherwise, when 2to3 is called (in
206 # We also need build_ext before build_py. Otherwise, when 2to3 is called (in
206 # build_py), it will not find osutil & friends, thinking that those modules are
207 # build_py), it will not find osutil & friends, thinking that those modules are
207 # global and, consequently, making a mess, now that all module imports are
208 # global and, consequently, making a mess, now that all module imports are
208 # global.
209 # global.
209 ('build_ext', build.has_ext_modules),
210 ('build_ext', build.has_ext_modules),
210 ] + build.sub_commands
211 ] + build.sub_commands
211
212
212 class hgbuildmo(Command):
213 class hgbuildmo(Command):
213
214
214 description = "build translations (.mo files)"
215 description = "build translations (.mo files)"
215
216
216 def run(self):
217 def run(self):
217 if not find_executable('msgfmt'):
218 if not find_executable('msgfmt'):
218 self.warn("could not find msgfmt executable, no translations "
219 self.warn("could not find msgfmt executable, no translations "
219 "will be built")
220 "will be built")
220 return
221 return
221
222
222 podir = 'i18n'
223 podir = 'i18n'
223 if not os.path.isdir(podir):
224 if not os.path.isdir(podir):
224 self.warn("could not find %s/ directory" % podir)
225 self.warn("could not find %s/ directory" % podir)
225 return
226 return
226
227
227 join = os.path.join
228 join = os.path.join
228 for po in os.listdir(podir):
229 for po in os.listdir(podir):
229 if not po.endswith('.po'):
230 if not po.endswith('.po'):
230 continue
231 continue
231 pofile = join(podir, po)
232 pofile = join(podir, po)
232 modir = join('locale', po[:-3], 'LC_MESSAGES')
233 modir = join('locale', po[:-3], 'LC_MESSAGES')
233 mofile = join(modir, 'hg.mo')
234 mofile = join(modir, 'hg.mo')
234 mobuildfile = join('mercurial', mofile)
235 mobuildfile = join('mercurial', mofile)
235 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
236 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
236 if sys.platform != 'sunos5':
237 if sys.platform != 'sunos5':
237 # msgfmt on Solaris does not know about -c
238 # msgfmt on Solaris does not know about -c
238 cmd.append('-c')
239 cmd.append('-c')
239 self.mkpath(join('mercurial', modir))
240 self.mkpath(join('mercurial', modir))
240 self.make_file([pofile], mobuildfile, spawn, (cmd,))
241 self.make_file([pofile], mobuildfile, spawn, (cmd,))
241
242
242 def initialize_options(self):
243 def initialize_options(self):
243 pass
244 pass
244
245
245 def finalize_options(self):
246 def finalize_options(self):
246 pass
247 pass
247
248
248
249
249 class hgdist(Distribution):
250 class hgdist(Distribution):
250 pure = 0
251 pure = 0
251
252
252 global_options = Distribution.global_options + \
253 global_options = Distribution.global_options + \
253 [('pure', None, "use pure (slow) Python "
254 [('pure', None, "use pure (slow) Python "
254 "code instead of C extensions"),
255 "code instead of C extensions"),
255 ('c2to3', None, "(experimental!) convert "
256 ('c2to3', None, "(experimental!) convert "
256 "code with 2to3"),
257 "code with 2to3"),
257 ]
258 ]
258
259
259 def has_ext_modules(self):
260 def has_ext_modules(self):
260 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
261 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
261 # too late for some cases
262 # too late for some cases
262 return not self.pure and Distribution.has_ext_modules(self)
263 return not self.pure and Distribution.has_ext_modules(self)
263
264
264 class hgbuildext(build_ext):
265 class hgbuildext(build_ext):
265
266
266 def build_extension(self, ext):
267 def build_extension(self, ext):
267 try:
268 try:
268 build_ext.build_extension(self, ext)
269 build_ext.build_extension(self, ext)
269 except CCompilerError:
270 except CCompilerError:
270 if not getattr(ext, 'optional', False):
271 if not getattr(ext, 'optional', False):
271 raise
272 raise
272 log.warn("Failed to build optional extension '%s' (skipping)",
273 log.warn("Failed to build optional extension '%s' (skipping)",
273 ext.name)
274 ext.name)
274
275
275 class hgbuildpy(build_py):
276 class hgbuildpy(build_py):
276 if convert2to3:
277 if convert2to3:
277 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
278 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
278 getfixers("hgfixes")))
279 getfixers("hgfixes")))
279
280
280 def finalize_options(self):
281 def finalize_options(self):
281 build_py.finalize_options(self)
282 build_py.finalize_options(self)
282
283
283 if self.distribution.pure:
284 if self.distribution.pure:
284 if self.py_modules is None:
285 if self.py_modules is None:
285 self.py_modules = []
286 self.py_modules = []
286 for ext in self.distribution.ext_modules:
287 for ext in self.distribution.ext_modules:
287 if ext.name.startswith("mercurial."):
288 if ext.name.startswith("mercurial."):
288 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
289 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
289 self.distribution.ext_modules = []
290 self.distribution.ext_modules = []
290 else:
291 else:
291 if not os.path.exists(os.path.join(get_python_inc(), 'Python.h')):
292 if not os.path.exists(os.path.join(get_python_inc(), 'Python.h')):
292 raise SystemExit("Python headers are required to build Mercurial")
293 raise SystemExit("Python headers are required to build Mercurial")
293
294
294 def find_modules(self):
295 def find_modules(self):
295 modules = build_py.find_modules(self)
296 modules = build_py.find_modules(self)
296 for module in modules:
297 for module in modules:
297 if module[0] == "mercurial.pure":
298 if module[0] == "mercurial.pure":
298 if module[1] != "__init__":
299 if module[1] != "__init__":
299 yield ("mercurial", module[1], module[2])
300 yield ("mercurial", module[1], module[2])
300 else:
301 else:
301 yield module
302 yield module
302
303
303 class buildhgextindex(Command):
304 class buildhgextindex(Command):
304 description = 'generate prebuilt index of hgext (for frozen package)'
305 description = 'generate prebuilt index of hgext (for frozen package)'
305 user_options = []
306 user_options = []
306 _indexfilename = 'hgext/__index__.py'
307 _indexfilename = 'hgext/__index__.py'
307
308
308 def initialize_options(self):
309 def initialize_options(self):
309 pass
310 pass
310
311
311 def finalize_options(self):
312 def finalize_options(self):
312 pass
313 pass
313
314
314 def run(self):
315 def run(self):
315 if os.path.exists(self._indexfilename):
316 if os.path.exists(self._indexfilename):
316 os.unlink(self._indexfilename)
317 os.unlink(self._indexfilename)
317
318
318 # here no extension enabled, disabled() lists up everything
319 # here no extension enabled, disabled() lists up everything
319 code = ('import pprint; from mercurial import extensions; '
320 code = ('import pprint; from mercurial import extensions; '
320 'pprint.pprint(extensions.disabled())')
321 'pprint.pprint(extensions.disabled())')
321 out, err = runcmd([sys.executable, '-c', code], env)
322 out, err = runcmd([sys.executable, '-c', code], env)
322 if err:
323 if err:
323 raise DistutilsExecError(err)
324 raise DistutilsExecError(err)
324
325
325 f = open(self._indexfilename, 'w')
326 f = open(self._indexfilename, 'w')
326 f.write('# this file is autogenerated by setup.py\n')
327 f.write('# this file is autogenerated by setup.py\n')
327 f.write('docs = ')
328 f.write('docs = ')
328 f.write(out)
329 f.write(out)
329 f.close()
330 f.close()
330
331
331 class hginstallscripts(install_scripts):
332 class hginstallscripts(install_scripts):
332 '''
333 '''
333 This is a specialization of install_scripts that replaces the @LIBDIR@ with
334 This is a specialization of install_scripts that replaces the @LIBDIR@ with
334 the configured directory for modules. If possible, the path is made relative
335 the configured directory for modules. If possible, the path is made relative
335 to the directory for scripts.
336 to the directory for scripts.
336 '''
337 '''
337
338
338 def initialize_options(self):
339 def initialize_options(self):
339 install_scripts.initialize_options(self)
340 install_scripts.initialize_options(self)
340
341
341 self.install_lib = None
342 self.install_lib = None
342
343
343 def finalize_options(self):
344 def finalize_options(self):
344 install_scripts.finalize_options(self)
345 install_scripts.finalize_options(self)
345 self.set_undefined_options('install',
346 self.set_undefined_options('install',
346 ('install_lib', 'install_lib'))
347 ('install_lib', 'install_lib'))
347
348
348 def run(self):
349 def run(self):
349 install_scripts.run(self)
350 install_scripts.run(self)
350
351
351 if (os.path.splitdrive(self.install_dir)[0] !=
352 if (os.path.splitdrive(self.install_dir)[0] !=
352 os.path.splitdrive(self.install_lib)[0]):
353 os.path.splitdrive(self.install_lib)[0]):
353 # can't make relative paths from one drive to another, so use an
354 # can't make relative paths from one drive to another, so use an
354 # absolute path instead
355 # absolute path instead
355 libdir = self.install_lib
356 libdir = self.install_lib
356 else:
357 else:
357 common = os.path.commonprefix((self.install_dir, self.install_lib))
358 common = os.path.commonprefix((self.install_dir, self.install_lib))
358 rest = self.install_dir[len(common):]
359 rest = self.install_dir[len(common):]
359 uplevel = len([n for n in os.path.split(rest) if n])
360 uplevel = len([n for n in os.path.split(rest) if n])
360
361
361 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
362 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
362
363
363 for outfile in self.outfiles:
364 for outfile in self.outfiles:
364 fp = open(outfile, 'rb')
365 fp = open(outfile, 'rb')
365 data = fp.read()
366 data = fp.read()
366 fp.close()
367 fp.close()
367
368
368 # skip binary files
369 # skip binary files
369 if b('\0') in data:
370 if b('\0') in data:
370 continue
371 continue
371
372
372 data = data.replace('@LIBDIR@', libdir.encode('string_escape'))
373 data = data.replace('@LIBDIR@', libdir.encode('string_escape'))
373 fp = open(outfile, 'wb')
374 fp = open(outfile, 'wb')
374 fp.write(data)
375 fp.write(data)
375 fp.close()
376 fp.close()
376
377
377 cmdclass = {'build': hgbuild,
378 cmdclass = {'build': hgbuild,
378 'build_mo': hgbuildmo,
379 'build_mo': hgbuildmo,
379 'build_ext': hgbuildext,
380 'build_ext': hgbuildext,
380 'build_py': hgbuildpy,
381 'build_py': hgbuildpy,
381 'build_hgextindex': buildhgextindex,
382 'build_hgextindex': buildhgextindex,
382 'install_scripts': hginstallscripts}
383 'install_scripts': hginstallscripts}
383
384
384 packages = ['mercurial', 'mercurial.hgweb',
385 packages = ['mercurial', 'mercurial.hgweb',
385 'mercurial.httpclient', 'mercurial.httpclient.tests',
386 'mercurial.httpclient', 'mercurial.httpclient.tests',
386 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
387 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
387 'hgext.largefiles']
388 'hgext.largefiles']
388
389
389 pymodules = []
390 pymodules = []
390
391
391 extmodules = [
392 extmodules = [
392 Extension('mercurial.base85', ['mercurial/base85.c']),
393 Extension('mercurial.base85', ['mercurial/base85.c']),
393 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
394 Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
394 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
395 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
395 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
396 Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
396 Extension('mercurial.parsers', ['mercurial/parsers.c']),
397 Extension('mercurial.parsers', ['mercurial/parsers.c']),
397 ]
398 ]
398
399
399 osutil_ldflags = []
400 osutil_ldflags = []
400
401
401 if sys.platform == 'darwin':
402 if sys.platform == 'darwin':
402 osutil_ldflags += ['-framework', 'ApplicationServices']
403 osutil_ldflags += ['-framework', 'ApplicationServices']
403
404
404 # disable osutil.c under windows + python 2.4 (issue1364)
405 # disable osutil.c under windows + python 2.4 (issue1364)
405 if sys.platform == 'win32' and sys.version_info < (2, 5, 0, 'final'):
406 if sys.platform == 'win32' and sys.version_info < (2, 5, 0, 'final'):
406 pymodules.append('mercurial.pure.osutil')
407 pymodules.append('mercurial.pure.osutil')
407 else:
408 else:
408 extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c'],
409 extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c'],
409 extra_link_args=osutil_ldflags))
410 extra_link_args=osutil_ldflags))
410
411
411 if sys.platform.startswith('linux') and os.uname()[2] > '2.6':
412 if sys.platform.startswith('linux') and os.uname()[2] > '2.6':
412 # The inotify extension is only usable with Linux 2.6 kernels.
413 # The inotify extension is only usable with Linux 2.6 kernels.
413 # You also need a reasonably recent C library.
414 # You also need a reasonably recent C library.
414 # In any case, if it fails to build the error will be skipped ('optional').
415 # In any case, if it fails to build the error will be skipped ('optional').
415 cc = new_compiler()
416 cc = new_compiler()
416 if hasfunction(cc, 'inotify_add_watch'):
417 if hasfunction(cc, 'inotify_add_watch'):
417 inotify = Extension('hgext.inotify.linux._inotify',
418 inotify = Extension('hgext.inotify.linux._inotify',
418 ['hgext/inotify/linux/_inotify.c'],
419 ['hgext/inotify/linux/_inotify.c'],
419 ['mercurial'])
420 ['mercurial'])
420 inotify.optional = True
421 inotify.optional = True
421 extmodules.append(inotify)
422 extmodules.append(inotify)
422 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
423 packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
423
424
424 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
425 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
425 'help/*.txt']}
426 'help/*.txt']}
426
427
427 def ordinarypath(p):
428 def ordinarypath(p):
428 return p and p[0] != '.' and p[-1] != '~'
429 return p and p[0] != '.' and p[-1] != '~'
429
430
430 for root in ('templates',):
431 for root in ('templates',):
431 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
432 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
432 curdir = curdir.split(os.sep, 1)[1]
433 curdir = curdir.split(os.sep, 1)[1]
433 dirs[:] = filter(ordinarypath, dirs)
434 dirs[:] = filter(ordinarypath, dirs)
434 for f in filter(ordinarypath, files):
435 for f in filter(ordinarypath, files):
435 f = os.path.join(curdir, f)
436 f = os.path.join(curdir, f)
436 packagedata['mercurial'].append(f)
437 packagedata['mercurial'].append(f)
437
438
438 datafiles = []
439 datafiles = []
439 setupversion = version
440 setupversion = version
440 extra = {}
441 extra = {}
441
442
442 if py2exeloaded:
443 if py2exeloaded:
443 extra['console'] = [
444 extra['console'] = [
444 {'script':'hg',
445 {'script':'hg',
445 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others',
446 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others',
446 'product_version':version}]
447 'product_version':version}]
447 # sub command of 'build' because 'py2exe' does not handle sub_commands
448 # sub command of 'build' because 'py2exe' does not handle sub_commands
448 build.sub_commands.insert(0, ('build_hgextindex', None))
449 build.sub_commands.insert(0, ('build_hgextindex', None))
449
450
450 if os.name == 'nt':
451 if os.name == 'nt':
451 # Windows binary file versions for exe/dll files must have the
452 # Windows binary file versions for exe/dll files must have the
452 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
453 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
453 setupversion = version.split('+', 1)[0]
454 setupversion = version.split('+', 1)[0]
454
455
455 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
456 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
456 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
457 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
457 # distutils.sysconfig
458 # distutils.sysconfig
458 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()[0]
459 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()[0]
459 # Also parse only first digit, because 3.2.1 can't be parsed nicely
460 # Also parse only first digit, because 3.2.1 can't be parsed nicely
460 if (version.startswith('Xcode') and
461 if (version.startswith('Xcode') and
461 StrictVersion(version.split()[1]) >= StrictVersion('4.0')):
462 StrictVersion(version.split()[1]) >= StrictVersion('4.0')):
462 os.environ['ARCHFLAGS'] = ''
463 os.environ['ARCHFLAGS'] = ''
463
464
464 setup(name='mercurial',
465 setup(name='mercurial',
465 version=setupversion,
466 version=setupversion,
466 author='Matt Mackall',
467 author='Matt Mackall',
467 author_email='mpm@selenic.com',
468 author_email='mpm@selenic.com',
468 url='http://mercurial.selenic.com/',
469 url='http://mercurial.selenic.com/',
469 description='Scalable distributed SCM',
470 description='Scalable distributed SCM',
470 license='GNU GPLv2+',
471 license='GNU GPLv2+',
471 scripts=scripts,
472 scripts=scripts,
472 packages=packages,
473 packages=packages,
473 py_modules=pymodules,
474 py_modules=pymodules,
474 ext_modules=extmodules,
475 ext_modules=extmodules,
475 data_files=datafiles,
476 data_files=datafiles,
476 package_data=packagedata,
477 package_data=packagedata,
477 cmdclass=cmdclass,
478 cmdclass=cmdclass,
478 distclass=hgdist,
479 distclass=hgdist,
479 options=dict(py2exe=dict(packages=['hgext', 'email']),
480 options=dict(py2exe=dict(packages=['hgext', 'email']),
480 bdist_mpkg=dict(zipdist=True,
481 bdist_mpkg=dict(zipdist=True,
481 license='COPYING',
482 license='COPYING',
482 readme='contrib/macosx/Readme.html',
483 readme='contrib/macosx/Readme.html',
483 welcome='contrib/macosx/Welcome.html')),
484 welcome='contrib/macosx/Welcome.html')),
484 **extra)
485 **extra)
General Comments 0
You need to be logged in to leave comments. Login now