mercurial/crew

view setup.py @ 10736:a528a1046dba

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

Contact: Thomas Arendsen Hein <hg@intevation.org> - Intevation GmbH