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