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