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