##// END OF EJS Templates
setup: handle more invalid python3 syntax...
Augie Fackler -
r20696:77ab0abb default
parent child Browse files
Show More
@@ -1,564 +1,571 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 printf = eval('print')
17 libdir_escape = 'unicode_escape'
16 else:
18 else:
19 libdir_escape = 'string_escape'
17 def b(s):
20 def b(s):
18 '''A helper function to emulate 2.6+ bytes literals using string
21 '''A helper function to emulate 2.6+ bytes literals using string
19 literals.'''
22 literals.'''
20 return s
23 return s
24 def printf(*args, **kwargs):
25 f = kwargs.get('file', sys.stdout)
26 end = kwargs.get('end', '\n')
27 f.write(b' '.join(args) + end)
21
28
22 # Solaris Python packaging brain damage
29 # Solaris Python packaging brain damage
23 try:
30 try:
24 import hashlib
31 import hashlib
25 sha = hashlib.sha1()
32 sha = hashlib.sha1()
26 except ImportError:
33 except ImportError:
27 try:
34 try:
28 import sha
35 import sha
29 except ImportError:
36 except ImportError:
30 raise SystemExit(
37 raise SystemExit(
31 "Couldn't import standard hashlib (incomplete Python install).")
38 "Couldn't import standard hashlib (incomplete Python install).")
32
39
33 try:
40 try:
34 import zlib
41 import zlib
35 except ImportError:
42 except ImportError:
36 raise SystemExit(
43 raise SystemExit(
37 "Couldn't import standard zlib (incomplete Python install).")
44 "Couldn't import standard zlib (incomplete Python install).")
38
45
39 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
46 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
40 isironpython = False
47 isironpython = False
41 try:
48 try:
42 isironpython = (platform.python_implementation()
49 isironpython = (platform.python_implementation()
43 .lower().find("ironpython") != -1)
50 .lower().find("ironpython") != -1)
44 except AttributeError:
51 except AttributeError:
45 pass
52 pass
46
53
47 if isironpython:
54 if isironpython:
48 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
55 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
49 else:
56 else:
50 try:
57 try:
51 import bz2
58 import bz2
52 except ImportError:
59 except ImportError:
53 raise SystemExit(
60 raise SystemExit(
54 "Couldn't import standard bz2 (incomplete Python install).")
61 "Couldn't import standard bz2 (incomplete Python install).")
55
62
56 import os, subprocess, time
63 import os, subprocess, time
57 import shutil
64 import shutil
58 import tempfile
65 import tempfile
59 from distutils import log
66 from distutils import log
60 from distutils.core import setup, Command, Extension
67 from distutils.core import setup, Command, Extension
61 from distutils.dist import Distribution
68 from distutils.dist import Distribution
62 from distutils.command.build import build
69 from distutils.command.build import build
63 from distutils.command.build_ext import build_ext
70 from distutils.command.build_ext import build_ext
64 from distutils.command.build_py import build_py
71 from distutils.command.build_py import build_py
65 from distutils.command.install_scripts import install_scripts
72 from distutils.command.install_scripts import install_scripts
66 from distutils.spawn import spawn, find_executable
73 from distutils.spawn import spawn, find_executable
67 from distutils import cygwinccompiler
74 from distutils import cygwinccompiler
68 from distutils.errors import CCompilerError, DistutilsExecError
75 from distutils.errors import CCompilerError, DistutilsExecError
69 from distutils.sysconfig import get_python_inc
76 from distutils.sysconfig import get_python_inc
70 from distutils.version import StrictVersion
77 from distutils.version import StrictVersion
71
78
72 convert2to3 = '--c2to3' in sys.argv
79 convert2to3 = '--c2to3' in sys.argv
73 if convert2to3:
80 if convert2to3:
74 try:
81 try:
75 from distutils.command.build_py import build_py_2to3 as build_py
82 from distutils.command.build_py import build_py_2to3 as build_py
76 from lib2to3.refactor import get_fixers_from_package as getfixers
83 from lib2to3.refactor import get_fixers_from_package as getfixers
77 except ImportError:
84 except ImportError:
78 if sys.version_info[0] < 3:
85 if sys.version_info[0] < 3:
79 raise SystemExit("--c2to3 is only compatible with python3.")
86 raise SystemExit("--c2to3 is only compatible with python3.")
80 raise
87 raise
81 sys.path.append('contrib')
88 sys.path.append('contrib')
82 elif sys.version_info[0] >= 3:
89 elif sys.version_info[0] >= 3:
83 raise SystemExit("setup.py with python3 needs --c2to3 (experimental)")
90 raise SystemExit("setup.py with python3 needs --c2to3 (experimental)")
84
91
85 scripts = ['hg']
92 scripts = ['hg']
86 if os.name == 'nt':
93 if os.name == 'nt':
87 scripts.append('contrib/win32/hg.bat')
94 scripts.append('contrib/win32/hg.bat')
88
95
89 # simplified version of distutils.ccompiler.CCompiler.has_function
96 # simplified version of distutils.ccompiler.CCompiler.has_function
90 # that actually removes its temporary files.
97 # that actually removes its temporary files.
91 def hasfunction(cc, funcname):
98 def hasfunction(cc, funcname):
92 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
99 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
93 devnull = oldstderr = None
100 devnull = oldstderr = None
94 try:
101 try:
95 try:
102 try:
96 fname = os.path.join(tmpdir, 'funcname.c')
103 fname = os.path.join(tmpdir, 'funcname.c')
97 f = open(fname, 'w')
104 f = open(fname, 'w')
98 f.write('int main(void) {\n')
105 f.write('int main(void) {\n')
99 f.write(' %s();\n' % funcname)
106 f.write(' %s();\n' % funcname)
100 f.write('}\n')
107 f.write('}\n')
101 f.close()
108 f.close()
102 # Redirect stderr to /dev/null to hide any error messages
109 # Redirect stderr to /dev/null to hide any error messages
103 # from the compiler.
110 # from the compiler.
104 # This will have to be changed if we ever have to check
111 # This will have to be changed if we ever have to check
105 # for a function on Windows.
112 # for a function on Windows.
106 devnull = open('/dev/null', 'w')
113 devnull = open('/dev/null', 'w')
107 oldstderr = os.dup(sys.stderr.fileno())
114 oldstderr = os.dup(sys.stderr.fileno())
108 os.dup2(devnull.fileno(), sys.stderr.fileno())
115 os.dup2(devnull.fileno(), sys.stderr.fileno())
109 objects = cc.compile([fname], output_dir=tmpdir)
116 objects = cc.compile([fname], output_dir=tmpdir)
110 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
117 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
111 except Exception:
118 except Exception:
112 return False
119 return False
113 return True
120 return True
114 finally:
121 finally:
115 if oldstderr is not None:
122 if oldstderr is not None:
116 os.dup2(oldstderr, sys.stderr.fileno())
123 os.dup2(oldstderr, sys.stderr.fileno())
117 if devnull is not None:
124 if devnull is not None:
118 devnull.close()
125 devnull.close()
119 shutil.rmtree(tmpdir)
126 shutil.rmtree(tmpdir)
120
127
121 # py2exe needs to be installed to work
128 # py2exe needs to be installed to work
122 try:
129 try:
123 import py2exe
130 import py2exe
124 py2exeloaded = True
131 py2exeloaded = True
125 # import py2exe's patched Distribution class
132 # import py2exe's patched Distribution class
126 from distutils.core import Distribution
133 from distutils.core import Distribution
127 except ImportError:
134 except ImportError:
128 py2exeloaded = False
135 py2exeloaded = False
129
136
130 def runcmd(cmd, env):
137 def runcmd(cmd, env):
131 if sys.platform == 'plan9':
138 if sys.platform == 'plan9':
132 # subprocess kludge to work around issues in half-baked Python
139 # subprocess kludge to work around issues in half-baked Python
133 # ports, notably bichued/python:
140 # ports, notably bichued/python:
134 _, out, err = os.popen3(cmd)
141 _, out, err = os.popen3(cmd)
135 return str(out), str(err)
142 return str(out), str(err)
136 else:
143 else:
137 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
144 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
138 stderr=subprocess.PIPE, env=env)
145 stderr=subprocess.PIPE, env=env)
139 out, err = p.communicate()
146 out, err = p.communicate()
140 return out, err
147 return out, err
141
148
142 def runhg(cmd, env):
149 def runhg(cmd, env):
143 out, err = runcmd(cmd, env)
150 out, err = runcmd(cmd, env)
144 # If root is executing setup.py, but the repository is owned by
151 # If root is executing setup.py, but the repository is owned by
145 # another user (as in "sudo python setup.py install") we will get
152 # another user (as in "sudo python setup.py install") we will get
146 # trust warnings since the .hg/hgrc file is untrusted. That is
153 # trust warnings since the .hg/hgrc file is untrusted. That is
147 # fine, we don't want to load it anyway. Python may warn about
154 # fine, we don't want to load it anyway. Python may warn about
148 # a missing __init__.py in mercurial/locale, we also ignore that.
155 # a missing __init__.py in mercurial/locale, we also ignore that.
149 err = [e for e in err.splitlines()
156 err = [e for e in err.splitlines()
150 if not e.startswith(b('not trusting file')) \
157 if not e.startswith(b('not trusting file')) \
151 and not e.startswith(b('warning: Not importing')) \
158 and not e.startswith(b('warning: Not importing')) \
152 and not e.startswith(b('obsolete feature not enabled'))]
159 and not e.startswith(b('obsolete feature not enabled'))]
153 if err:
160 if err:
154 print >> sys.stderr, "stderr from '%s':" % (' '.join(cmd))
161 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr)
155 print >> sys.stderr, '\n'.join([' ' + e for e in err])
162 printf(b('\n').join([b(' ') + e for e in err]), file=sys.stderr)
156 return ''
163 return ''
157 return out
164 return out
158
165
159 version = ''
166 version = ''
160
167
161 # Execute hg out of this directory with a custom environment which
168 # Execute hg out of this directory with a custom environment which
162 # includes the pure Python modules in mercurial/pure. We also take
169 # includes the pure Python modules in mercurial/pure. We also take
163 # care to not use any hgrc files and do no localization.
170 # care to not use any hgrc files and do no localization.
164 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
171 pypath = ['mercurial', os.path.join('mercurial', 'pure')]
165 env = {'PYTHONPATH': os.pathsep.join(pypath),
172 env = {'PYTHONPATH': os.pathsep.join(pypath),
166 'HGRCPATH': '',
173 'HGRCPATH': '',
167 'LANGUAGE': 'C'}
174 'LANGUAGE': 'C'}
168 if 'LD_LIBRARY_PATH' in os.environ:
175 if 'LD_LIBRARY_PATH' in os.environ:
169 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
176 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
170 if 'SystemRoot' in os.environ:
177 if 'SystemRoot' in os.environ:
171 # Copy SystemRoot into the custom environment for Python 2.6
178 # Copy SystemRoot into the custom environment for Python 2.6
172 # under Windows. Otherwise, the subprocess will fail with
179 # under Windows. Otherwise, the subprocess will fail with
173 # error 0xc0150004. See: http://bugs.python.org/issue3440
180 # error 0xc0150004. See: http://bugs.python.org/issue3440
174 env['SystemRoot'] = os.environ['SystemRoot']
181 env['SystemRoot'] = os.environ['SystemRoot']
175
182
176 if os.path.isdir('.hg'):
183 if os.path.isdir('.hg'):
177 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
184 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
178 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
185 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
179 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
186 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
180 if numerictags: # tag(s) found
187 if numerictags: # tag(s) found
181 version = numerictags[-1]
188 version = numerictags[-1]
182 if hgid.endswith('+'): # propagate the dirty status to the tag
189 if hgid.endswith('+'): # propagate the dirty status to the tag
183 version += '+'
190 version += '+'
184 else: # no tag found
191 else: # no tag found
185 cmd = [sys.executable, 'hg', 'parents', '--template',
192 cmd = [sys.executable, 'hg', 'parents', '--template',
186 '{latesttag}+{latesttagdistance}-']
193 '{latesttag}+{latesttagdistance}-']
187 version = runhg(cmd, env) + hgid
194 version = runhg(cmd, env) + hgid
188 if version.endswith('+'):
195 if version.endswith('+'):
189 version += time.strftime('%Y%m%d')
196 version += time.strftime('%Y%m%d')
190 elif os.path.exists('.hg_archival.txt'):
197 elif os.path.exists('.hg_archival.txt'):
191 kw = dict([[t.strip() for t in l.split(':', 1)]
198 kw = dict([[t.strip() for t in l.split(':', 1)]
192 for l in open('.hg_archival.txt')])
199 for l in open('.hg_archival.txt')])
193 if 'tag' in kw:
200 if 'tag' in kw:
194 version = kw['tag']
201 version = kw['tag']
195 elif 'latesttag' in kw:
202 elif 'latesttag' in kw:
196 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
203 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
197 else:
204 else:
198 version = kw.get('node', '')[:12]
205 version = kw.get('node', '')[:12]
199
206
200 if version:
207 if version:
201 f = open("mercurial/__version__.py", "w")
208 f = open("mercurial/__version__.py", "w")
202 f.write('# this file is autogenerated by setup.py\n')
209 f.write('# this file is autogenerated by setup.py\n')
203 f.write('version = "%s"\n' % version)
210 f.write('version = "%s"\n' % version)
204 f.close()
211 f.close()
205
212
206
213
207 try:
214 try:
208 from mercurial import __version__
215 from mercurial import __version__
209 version = __version__.version
216 version = __version__.version
210 except ImportError:
217 except ImportError:
211 version = 'unknown'
218 version = 'unknown'
212
219
213 class hgbuild(build):
220 class hgbuild(build):
214 # Insert hgbuildmo first so that files in mercurial/locale/ are found
221 # Insert hgbuildmo first so that files in mercurial/locale/ are found
215 # when build_py is run next.
222 # when build_py is run next.
216 sub_commands = [('build_mo', None),
223 sub_commands = [('build_mo', None),
217
224
218 # We also need build_ext before build_py. Otherwise, when 2to3 is
225 # We also need build_ext before build_py. Otherwise, when 2to3 is
219 # called (in build_py), it will not find osutil & friends,
226 # called (in build_py), it will not find osutil & friends,
220 # thinking that those modules are global and, consequently, making
227 # thinking that those modules are global and, consequently, making
221 # a mess, now that all module imports are global.
228 # a mess, now that all module imports are global.
222
229
223 ('build_ext', build.has_ext_modules),
230 ('build_ext', build.has_ext_modules),
224 ] + build.sub_commands
231 ] + build.sub_commands
225
232
226 class hgbuildmo(build):
233 class hgbuildmo(build):
227
234
228 description = "build translations (.mo files)"
235 description = "build translations (.mo files)"
229
236
230 def run(self):
237 def run(self):
231 if not find_executable('msgfmt'):
238 if not find_executable('msgfmt'):
232 self.warn("could not find msgfmt executable, no translations "
239 self.warn("could not find msgfmt executable, no translations "
233 "will be built")
240 "will be built")
234 return
241 return
235
242
236 podir = 'i18n'
243 podir = 'i18n'
237 if not os.path.isdir(podir):
244 if not os.path.isdir(podir):
238 self.warn("could not find %s/ directory" % podir)
245 self.warn("could not find %s/ directory" % podir)
239 return
246 return
240
247
241 join = os.path.join
248 join = os.path.join
242 for po in os.listdir(podir):
249 for po in os.listdir(podir):
243 if not po.endswith('.po'):
250 if not po.endswith('.po'):
244 continue
251 continue
245 pofile = join(podir, po)
252 pofile = join(podir, po)
246 modir = join('locale', po[:-3], 'LC_MESSAGES')
253 modir = join('locale', po[:-3], 'LC_MESSAGES')
247 mofile = join(modir, 'hg.mo')
254 mofile = join(modir, 'hg.mo')
248 mobuildfile = join('mercurial', mofile)
255 mobuildfile = join('mercurial', mofile)
249 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
256 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
250 if sys.platform != 'sunos5':
257 if sys.platform != 'sunos5':
251 # msgfmt on Solaris does not know about -c
258 # msgfmt on Solaris does not know about -c
252 cmd.append('-c')
259 cmd.append('-c')
253 self.mkpath(join('mercurial', modir))
260 self.mkpath(join('mercurial', modir))
254 self.make_file([pofile], mobuildfile, spawn, (cmd,))
261 self.make_file([pofile], mobuildfile, spawn, (cmd,))
255
262
256
263
257 class hgdist(Distribution):
264 class hgdist(Distribution):
258 pure = 0
265 pure = 0
259
266
260 global_options = Distribution.global_options + \
267 global_options = Distribution.global_options + \
261 [('pure', None, "use pure (slow) Python "
268 [('pure', None, "use pure (slow) Python "
262 "code instead of C extensions"),
269 "code instead of C extensions"),
263 ('c2to3', None, "(experimental!) convert "
270 ('c2to3', None, "(experimental!) convert "
264 "code with 2to3"),
271 "code with 2to3"),
265 ]
272 ]
266
273
267 def has_ext_modules(self):
274 def has_ext_modules(self):
268 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
275 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
269 # too late for some cases
276 # too late for some cases
270 return not self.pure and Distribution.has_ext_modules(self)
277 return not self.pure and Distribution.has_ext_modules(self)
271
278
272 class hgbuildext(build_ext):
279 class hgbuildext(build_ext):
273
280
274 def build_extension(self, ext):
281 def build_extension(self, ext):
275 try:
282 try:
276 build_ext.build_extension(self, ext)
283 build_ext.build_extension(self, ext)
277 except CCompilerError:
284 except CCompilerError:
278 if not getattr(ext, 'optional', False):
285 if not getattr(ext, 'optional', False):
279 raise
286 raise
280 log.warn("Failed to build optional extension '%s' (skipping)",
287 log.warn("Failed to build optional extension '%s' (skipping)",
281 ext.name)
288 ext.name)
282
289
283 class hgbuildpy(build_py):
290 class hgbuildpy(build_py):
284 if convert2to3:
291 if convert2to3:
285 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
292 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
286 getfixers("hgfixes")))
293 getfixers("hgfixes")))
287
294
288 def finalize_options(self):
295 def finalize_options(self):
289 build_py.finalize_options(self)
296 build_py.finalize_options(self)
290
297
291 if self.distribution.pure:
298 if self.distribution.pure:
292 if self.py_modules is None:
299 if self.py_modules is None:
293 self.py_modules = []
300 self.py_modules = []
294 for ext in self.distribution.ext_modules:
301 for ext in self.distribution.ext_modules:
295 if ext.name.startswith("mercurial."):
302 if ext.name.startswith("mercurial."):
296 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
303 self.py_modules.append("mercurial.pure.%s" % ext.name[10:])
297 self.distribution.ext_modules = []
304 self.distribution.ext_modules = []
298 else:
305 else:
299 h = os.path.join(get_python_inc(), 'Python.h')
306 h = os.path.join(get_python_inc(), 'Python.h')
300 if not os.path.exists(h):
307 if not os.path.exists(h):
301 raise SystemExit('Python headers are required to build '
308 raise SystemExit('Python headers are required to build '
302 'Mercurial but weren\'t found in %s' % h)
309 'Mercurial but weren\'t found in %s' % h)
303
310
304 def find_modules(self):
311 def find_modules(self):
305 modules = build_py.find_modules(self)
312 modules = build_py.find_modules(self)
306 for module in modules:
313 for module in modules:
307 if module[0] == "mercurial.pure":
314 if module[0] == "mercurial.pure":
308 if module[1] != "__init__":
315 if module[1] != "__init__":
309 yield ("mercurial", module[1], module[2])
316 yield ("mercurial", module[1], module[2])
310 else:
317 else:
311 yield module
318 yield module
312
319
313 class buildhgextindex(Command):
320 class buildhgextindex(Command):
314 description = 'generate prebuilt index of hgext (for frozen package)'
321 description = 'generate prebuilt index of hgext (for frozen package)'
315 user_options = []
322 user_options = []
316 _indexfilename = 'hgext/__index__.py'
323 _indexfilename = 'hgext/__index__.py'
317
324
318 def initialize_options(self):
325 def initialize_options(self):
319 pass
326 pass
320
327
321 def finalize_options(self):
328 def finalize_options(self):
322 pass
329 pass
323
330
324 def run(self):
331 def run(self):
325 if os.path.exists(self._indexfilename):
332 if os.path.exists(self._indexfilename):
326 os.unlink(self._indexfilename)
333 os.unlink(self._indexfilename)
327
334
328 # here no extension enabled, disabled() lists up everything
335 # here no extension enabled, disabled() lists up everything
329 code = ('import pprint; from mercurial import extensions; '
336 code = ('import pprint; from mercurial import extensions; '
330 'pprint.pprint(extensions.disabled())')
337 'pprint.pprint(extensions.disabled())')
331 out, err = runcmd([sys.executable, '-c', code], env)
338 out, err = runcmd([sys.executable, '-c', code], env)
332 if err:
339 if err:
333 raise DistutilsExecError(err)
340 raise DistutilsExecError(err)
334
341
335 f = open(self._indexfilename, 'w')
342 f = open(self._indexfilename, 'w')
336 f.write('# this file is autogenerated by setup.py\n')
343 f.write('# this file is autogenerated by setup.py\n')
337 f.write('docs = ')
344 f.write('docs = ')
338 f.write(out)
345 f.write(out)
339 f.close()
346 f.close()
340
347
341 class buildhgexe(build_ext):
348 class buildhgexe(build_ext):
342 description = 'compile hg.exe from mercurial/exewrapper.c'
349 description = 'compile hg.exe from mercurial/exewrapper.c'
343
350
344 def build_extensions(self):
351 def build_extensions(self):
345 if os.name != 'nt':
352 if os.name != 'nt':
346 return
353 return
347 if isinstance(self.compiler, HackedMingw32CCompiler):
354 if isinstance(self.compiler, HackedMingw32CCompiler):
348 self.compiler.compiler_so = self.compiler.compiler # no -mdll
355 self.compiler.compiler_so = self.compiler.compiler # no -mdll
349 self.compiler.dll_libraries = [] # no -lmsrvc90
356 self.compiler.dll_libraries = [] # no -lmsrvc90
350 hv = sys.hexversion
357 hv = sys.hexversion
351 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
358 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
352 f = open('mercurial/hgpythonlib.h', 'wb')
359 f = open('mercurial/hgpythonlib.h', 'wb')
353 f.write('/* this file is autogenerated by setup.py */\n')
360 f.write('/* this file is autogenerated by setup.py */\n')
354 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
361 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
355 f.close()
362 f.close()
356 objects = self.compiler.compile(['mercurial/exewrapper.c'],
363 objects = self.compiler.compile(['mercurial/exewrapper.c'],
357 output_dir=self.build_temp)
364 output_dir=self.build_temp)
358 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
365 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
359 target = os.path.join(dir, 'hg')
366 target = os.path.join(dir, 'hg')
360 self.compiler.link_executable(objects, target,
367 self.compiler.link_executable(objects, target,
361 libraries=[],
368 libraries=[],
362 output_dir=self.build_temp)
369 output_dir=self.build_temp)
363
370
364 class hginstallscripts(install_scripts):
371 class hginstallscripts(install_scripts):
365 '''
372 '''
366 This is a specialization of install_scripts that replaces the @LIBDIR@ with
373 This is a specialization of install_scripts that replaces the @LIBDIR@ with
367 the configured directory for modules. If possible, the path is made relative
374 the configured directory for modules. If possible, the path is made relative
368 to the directory for scripts.
375 to the directory for scripts.
369 '''
376 '''
370
377
371 def initialize_options(self):
378 def initialize_options(self):
372 install_scripts.initialize_options(self)
379 install_scripts.initialize_options(self)
373
380
374 self.install_lib = None
381 self.install_lib = None
375
382
376 def finalize_options(self):
383 def finalize_options(self):
377 install_scripts.finalize_options(self)
384 install_scripts.finalize_options(self)
378 self.set_undefined_options('install',
385 self.set_undefined_options('install',
379 ('install_lib', 'install_lib'))
386 ('install_lib', 'install_lib'))
380
387
381 def run(self):
388 def run(self):
382 install_scripts.run(self)
389 install_scripts.run(self)
383
390
384 if (os.path.splitdrive(self.install_dir)[0] !=
391 if (os.path.splitdrive(self.install_dir)[0] !=
385 os.path.splitdrive(self.install_lib)[0]):
392 os.path.splitdrive(self.install_lib)[0]):
386 # can't make relative paths from one drive to another, so use an
393 # can't make relative paths from one drive to another, so use an
387 # absolute path instead
394 # absolute path instead
388 libdir = self.install_lib
395 libdir = self.install_lib
389 else:
396 else:
390 common = os.path.commonprefix((self.install_dir, self.install_lib))
397 common = os.path.commonprefix((self.install_dir, self.install_lib))
391 rest = self.install_dir[len(common):]
398 rest = self.install_dir[len(common):]
392 uplevel = len([n for n in os.path.split(rest) if n])
399 uplevel = len([n for n in os.path.split(rest) if n])
393
400
394 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
401 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
395
402
396 for outfile in self.outfiles:
403 for outfile in self.outfiles:
397 fp = open(outfile, 'rb')
404 fp = open(outfile, 'rb')
398 data = fp.read()
405 data = fp.read()
399 fp.close()
406 fp.close()
400
407
401 # skip binary files
408 # skip binary files
402 if b('\0') in data:
409 if b('\0') in data:
403 continue
410 continue
404
411
405 data = data.replace('@LIBDIR@', libdir.encode('string_escape'))
412 data = data.replace(b('@LIBDIR@'), libdir.encode(libdir_escape))
406 fp = open(outfile, 'wb')
413 fp = open(outfile, 'wb')
407 fp.write(data)
414 fp.write(data)
408 fp.close()
415 fp.close()
409
416
410 cmdclass = {'build': hgbuild,
417 cmdclass = {'build': hgbuild,
411 'build_mo': hgbuildmo,
418 'build_mo': hgbuildmo,
412 'build_ext': hgbuildext,
419 'build_ext': hgbuildext,
413 'build_py': hgbuildpy,
420 'build_py': hgbuildpy,
414 'build_hgextindex': buildhgextindex,
421 'build_hgextindex': buildhgextindex,
415 'install_scripts': hginstallscripts,
422 'install_scripts': hginstallscripts,
416 'build_hgexe': buildhgexe,
423 'build_hgexe': buildhgexe,
417 }
424 }
418
425
419 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
426 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
420 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
427 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
421 'hgext.largefiles']
428 'hgext.largefiles']
422
429
423 pymodules = []
430 pymodules = []
424
431
425 common_depends = ['mercurial/util.h']
432 common_depends = ['mercurial/util.h']
426
433
427 extmodules = [
434 extmodules = [
428 Extension('mercurial.base85', ['mercurial/base85.c'],
435 Extension('mercurial.base85', ['mercurial/base85.c'],
429 depends=common_depends),
436 depends=common_depends),
430 Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
437 Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
431 depends=common_depends),
438 depends=common_depends),
432 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
439 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
433 depends=common_depends),
440 depends=common_depends),
434 Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
441 Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
435 depends=common_depends),
442 depends=common_depends),
436 Extension('mercurial.parsers', ['mercurial/dirs.c',
443 Extension('mercurial.parsers', ['mercurial/dirs.c',
437 'mercurial/parsers.c',
444 'mercurial/parsers.c',
438 'mercurial/pathencode.c'],
445 'mercurial/pathencode.c'],
439 depends=common_depends),
446 depends=common_depends),
440 ]
447 ]
441
448
442 osutil_ldflags = []
449 osutil_ldflags = []
443
450
444 if sys.platform == 'darwin':
451 if sys.platform == 'darwin':
445 osutil_ldflags += ['-framework', 'ApplicationServices']
452 osutil_ldflags += ['-framework', 'ApplicationServices']
446
453
447 # disable osutil.c under windows + python 2.4 (issue1364)
454 # disable osutil.c under windows + python 2.4 (issue1364)
448 if sys.platform == 'win32' and sys.version_info < (2, 5, 0, 'final'):
455 if sys.platform == 'win32' and sys.version_info < (2, 5, 0, 'final'):
449 pymodules.append('mercurial.pure.osutil')
456 pymodules.append('mercurial.pure.osutil')
450 else:
457 else:
451 extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c'],
458 extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c'],
452 extra_link_args=osutil_ldflags,
459 extra_link_args=osutil_ldflags,
453 depends=common_depends))
460 depends=common_depends))
454
461
455 # the -mno-cygwin option has been deprecated for years
462 # the -mno-cygwin option has been deprecated for years
456 Mingw32CCompiler = cygwinccompiler.Mingw32CCompiler
463 Mingw32CCompiler = cygwinccompiler.Mingw32CCompiler
457
464
458 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
465 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
459 def __init__(self, *args, **kwargs):
466 def __init__(self, *args, **kwargs):
460 Mingw32CCompiler.__init__(self, *args, **kwargs)
467 Mingw32CCompiler.__init__(self, *args, **kwargs)
461 for i in 'compiler compiler_so linker_exe linker_so'.split():
468 for i in 'compiler compiler_so linker_exe linker_so'.split():
462 try:
469 try:
463 getattr(self, i).remove('-mno-cygwin')
470 getattr(self, i).remove('-mno-cygwin')
464 except ValueError:
471 except ValueError:
465 pass
472 pass
466
473
467 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
474 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
468
475
469 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
476 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
470 'help/*.txt']}
477 'help/*.txt']}
471
478
472 def ordinarypath(p):
479 def ordinarypath(p):
473 return p and p[0] != '.' and p[-1] != '~'
480 return p and p[0] != '.' and p[-1] != '~'
474
481
475 for root in ('templates',):
482 for root in ('templates',):
476 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
483 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
477 curdir = curdir.split(os.sep, 1)[1]
484 curdir = curdir.split(os.sep, 1)[1]
478 dirs[:] = filter(ordinarypath, dirs)
485 dirs[:] = filter(ordinarypath, dirs)
479 for f in filter(ordinarypath, files):
486 for f in filter(ordinarypath, files):
480 f = os.path.join(curdir, f)
487 f = os.path.join(curdir, f)
481 packagedata['mercurial'].append(f)
488 packagedata['mercurial'].append(f)
482
489
483 datafiles = []
490 datafiles = []
484 setupversion = version
491 setupversion = version
485 extra = {}
492 extra = {}
486
493
487 if py2exeloaded:
494 if py2exeloaded:
488 extra['console'] = [
495 extra['console'] = [
489 {'script':'hg',
496 {'script':'hg',
490 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others',
497 'copyright':'Copyright (C) 2005-2010 Matt Mackall and others',
491 'product_version':version}]
498 'product_version':version}]
492 # sub command of 'build' because 'py2exe' does not handle sub_commands
499 # sub command of 'build' because 'py2exe' does not handle sub_commands
493 build.sub_commands.insert(0, ('build_hgextindex', None))
500 build.sub_commands.insert(0, ('build_hgextindex', None))
494
501
495 if os.name == 'nt':
502 if os.name == 'nt':
496 # Windows binary file versions for exe/dll files must have the
503 # Windows binary file versions for exe/dll files must have the
497 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
504 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
498 setupversion = version.split('+', 1)[0]
505 setupversion = version.split('+', 1)[0]
499
506
500 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
507 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
501 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
508 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
502 # distutils.sysconfig
509 # distutils.sysconfig
503 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
510 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
504 if version:
511 if version:
505 version = version[0]
512 version = version[0]
506 xcode4 = (version.startswith('Xcode') and
513 xcode4 = (version.startswith('Xcode') and
507 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
514 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
508 else:
515 else:
509 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
516 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
510 # installed, but instead with only command-line tools. Assume
517 # installed, but instead with only command-line tools. Assume
511 # that only happens on >= Lion, thus no PPC support.
518 # that only happens on >= Lion, thus no PPC support.
512 xcode4 = True
519 xcode4 = True
513
520
514 if xcode4:
521 if xcode4:
515 os.environ['ARCHFLAGS'] = ''
522 os.environ['ARCHFLAGS'] = ''
516
523
517 setup(name='mercurial',
524 setup(name='mercurial',
518 version=setupversion,
525 version=setupversion,
519 author='Matt Mackall and many others',
526 author='Matt Mackall and many others',
520 author_email='mercurial@selenic.com',
527 author_email='mercurial@selenic.com',
521 url='http://mercurial.selenic.com/',
528 url='http://mercurial.selenic.com/',
522 download_url='http://mercurial.selenic.com/release/',
529 download_url='http://mercurial.selenic.com/release/',
523 description=('Fast scalable distributed SCM (revision control, version '
530 description=('Fast scalable distributed SCM (revision control, version '
524 'control) system'),
531 'control) system'),
525 long_description=('Mercurial is a distributed SCM tool written in Python.'
532 long_description=('Mercurial is a distributed SCM tool written in Python.'
526 ' It is used by a number of large projects that require'
533 ' It is used by a number of large projects that require'
527 ' fast, reliable distributed revision control, such as '
534 ' fast, reliable distributed revision control, such as '
528 'Mozilla.'),
535 'Mozilla.'),
529 license='GNU GPLv2 or any later version',
536 license='GNU GPLv2 or any later version',
530 classifiers=[
537 classifiers=[
531 'Development Status :: 6 - Mature',
538 'Development Status :: 6 - Mature',
532 'Environment :: Console',
539 'Environment :: Console',
533 'Intended Audience :: Developers',
540 'Intended Audience :: Developers',
534 'Intended Audience :: System Administrators',
541 'Intended Audience :: System Administrators',
535 'License :: OSI Approved :: GNU General Public License (GPL)',
542 'License :: OSI Approved :: GNU General Public License (GPL)',
536 'Natural Language :: Danish',
543 'Natural Language :: Danish',
537 'Natural Language :: English',
544 'Natural Language :: English',
538 'Natural Language :: German',
545 'Natural Language :: German',
539 'Natural Language :: Italian',
546 'Natural Language :: Italian',
540 'Natural Language :: Japanese',
547 'Natural Language :: Japanese',
541 'Natural Language :: Portuguese (Brazilian)',
548 'Natural Language :: Portuguese (Brazilian)',
542 'Operating System :: Microsoft :: Windows',
549 'Operating System :: Microsoft :: Windows',
543 'Operating System :: OS Independent',
550 'Operating System :: OS Independent',
544 'Operating System :: POSIX',
551 'Operating System :: POSIX',
545 'Programming Language :: C',
552 'Programming Language :: C',
546 'Programming Language :: Python',
553 'Programming Language :: Python',
547 'Topic :: Software Development :: Version Control',
554 'Topic :: Software Development :: Version Control',
548 ],
555 ],
549 scripts=scripts,
556 scripts=scripts,
550 packages=packages,
557 packages=packages,
551 py_modules=pymodules,
558 py_modules=pymodules,
552 ext_modules=extmodules,
559 ext_modules=extmodules,
553 data_files=datafiles,
560 data_files=datafiles,
554 package_data=packagedata,
561 package_data=packagedata,
555 cmdclass=cmdclass,
562 cmdclass=cmdclass,
556 distclass=hgdist,
563 distclass=hgdist,
557 options={'py2exe': {'packages': ['hgext', 'email']},
564 options={'py2exe': {'packages': ['hgext', 'email']},
558 'bdist_mpkg': {'zipdist': True,
565 'bdist_mpkg': {'zipdist': True,
559 'license': 'COPYING',
566 'license': 'COPYING',
560 'readme': 'contrib/macosx/Readme.html',
567 'readme': 'contrib/macosx/Readme.html',
561 'welcome': 'contrib/macosx/Welcome.html',
568 'welcome': 'contrib/macosx/Welcome.html',
562 },
569 },
563 },
570 },
564 **extra)
571 **extra)
General Comments 0
You need to be logged in to leave comments. Login now