##// END OF EJS Templates
setup: avoid procedure related to hg.exe at setup.py --pure...
FUJIWARA Katsunori -
r28041:8da94662 stable
parent child Browse files
Show More
@@ -1,707 +1,707
1 1 #
2 2 # This is the mercurial setup script.
3 3 #
4 4 # 'python setup.py install', or
5 5 # 'python setup.py --help' for more options
6 6
7 7 import sys, platform
8 8 if getattr(sys, 'version_info', (0, 0, 0)) < (2, 6, 0, 'final'):
9 9 raise SystemExit("Mercurial requires Python 2.6 or later.")
10 10
11 11 if sys.version_info[0] >= 3:
12 12 printf = eval('print')
13 13 libdir_escape = 'unicode_escape'
14 14 else:
15 15 libdir_escape = 'string_escape'
16 16 def printf(*args, **kwargs):
17 17 f = kwargs.get('file', sys.stdout)
18 18 end = kwargs.get('end', '\n')
19 19 f.write(b' '.join(args) + end)
20 20
21 21 # Solaris Python packaging brain damage
22 22 try:
23 23 import hashlib
24 24 sha = hashlib.sha1()
25 25 except ImportError:
26 26 try:
27 27 import sha
28 28 sha.sha # silence unused import warning
29 29 except ImportError:
30 30 raise SystemExit(
31 31 "Couldn't import standard hashlib (incomplete Python install).")
32 32
33 33 try:
34 34 import zlib
35 35 zlib.compressobj # silence unused import warning
36 36 except ImportError:
37 37 raise SystemExit(
38 38 "Couldn't import standard zlib (incomplete Python install).")
39 39
40 40 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
41 41 isironpython = False
42 42 try:
43 43 isironpython = (platform.python_implementation()
44 44 .lower().find("ironpython") != -1)
45 45 except AttributeError:
46 46 pass
47 47
48 48 if isironpython:
49 49 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
50 50 else:
51 51 try:
52 52 import bz2
53 53 bz2.BZ2Compressor # silence unused import warning
54 54 except ImportError:
55 55 raise SystemExit(
56 56 "Couldn't import standard bz2 (incomplete Python install).")
57 57
58 58 ispypy = "PyPy" in sys.version
59 59
60 60 import os, stat, subprocess, time
61 61 import re
62 62 import shutil
63 63 import tempfile
64 64 from distutils import log
65 65 if 'FORCE_SETUPTOOLS' in os.environ:
66 66 from setuptools import setup
67 67 else:
68 68 from distutils.core import setup
69 69 from distutils.core import Command, Extension
70 70 from distutils.dist import Distribution
71 71 from distutils.command.build import build
72 72 from distutils.command.build_ext import build_ext
73 73 from distutils.command.build_py import build_py
74 74 from distutils.command.build_scripts import build_scripts
75 75 from distutils.command.install_lib import install_lib
76 76 from distutils.command.install_scripts import install_scripts
77 77 from distutils.spawn import spawn, find_executable
78 78 from distutils import file_util
79 79 from distutils.errors import (
80 80 CCompilerError,
81 81 DistutilsError,
82 82 DistutilsExecError,
83 83 )
84 84 from distutils.sysconfig import get_python_inc, get_config_var
85 85 from distutils.version import StrictVersion
86 86
87 87 convert2to3 = '--c2to3' in sys.argv
88 88 if convert2to3:
89 89 try:
90 90 from distutils.command.build_py import build_py_2to3 as build_py
91 91 from lib2to3.refactor import get_fixers_from_package as getfixers
92 92 except ImportError:
93 93 if sys.version_info[0] < 3:
94 94 raise SystemExit("--c2to3 is only compatible with python3.")
95 95 raise
96 96 sys.path.append('contrib')
97 97 elif sys.version_info[0] >= 3:
98 98 raise SystemExit("setup.py with python3 needs --c2to3 (experimental)")
99 99
100 100 scripts = ['hg']
101 101 if os.name == 'nt':
102 102 # We remove hg.bat if we are able to build hg.exe.
103 103 scripts.append('contrib/win32/hg.bat')
104 104
105 105 # simplified version of distutils.ccompiler.CCompiler.has_function
106 106 # that actually removes its temporary files.
107 107 def hasfunction(cc, funcname):
108 108 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
109 109 devnull = oldstderr = None
110 110 try:
111 111 fname = os.path.join(tmpdir, 'funcname.c')
112 112 f = open(fname, 'w')
113 113 f.write('int main(void) {\n')
114 114 f.write(' %s();\n' % funcname)
115 115 f.write('}\n')
116 116 f.close()
117 117 # Redirect stderr to /dev/null to hide any error messages
118 118 # from the compiler.
119 119 # This will have to be changed if we ever have to check
120 120 # for a function on Windows.
121 121 devnull = open('/dev/null', 'w')
122 122 oldstderr = os.dup(sys.stderr.fileno())
123 123 os.dup2(devnull.fileno(), sys.stderr.fileno())
124 124 objects = cc.compile([fname], output_dir=tmpdir)
125 125 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
126 126 return True
127 127 except Exception:
128 128 return False
129 129 finally:
130 130 if oldstderr is not None:
131 131 os.dup2(oldstderr, sys.stderr.fileno())
132 132 if devnull is not None:
133 133 devnull.close()
134 134 shutil.rmtree(tmpdir)
135 135
136 136 # py2exe needs to be installed to work
137 137 try:
138 138 import py2exe
139 139 py2exe.Distribution # silence unused import warning
140 140 py2exeloaded = True
141 141 # import py2exe's patched Distribution class
142 142 from distutils.core import Distribution
143 143 except ImportError:
144 144 py2exeloaded = False
145 145
146 146 def runcmd(cmd, env):
147 147 if (sys.platform == 'plan9'
148 148 and (sys.version_info[0] == 2 and sys.version_info[1] < 7)):
149 149 # subprocess kludge to work around issues in half-baked Python
150 150 # ports, notably bichued/python:
151 151 _, out, err = os.popen3(cmd)
152 152 return str(out), str(err)
153 153 else:
154 154 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
155 155 stderr=subprocess.PIPE, env=env)
156 156 out, err = p.communicate()
157 157 return out, err
158 158
159 159 def runhg(cmd, env):
160 160 out, err = runcmd(cmd, env)
161 161 # If root is executing setup.py, but the repository is owned by
162 162 # another user (as in "sudo python setup.py install") we will get
163 163 # trust warnings since the .hg/hgrc file is untrusted. That is
164 164 # fine, we don't want to load it anyway. Python may warn about
165 165 # a missing __init__.py in mercurial/locale, we also ignore that.
166 166 err = [e for e in err.splitlines()
167 167 if not e.startswith(b'not trusting file') \
168 168 and not e.startswith(b'warning: Not importing') \
169 169 and not e.startswith(b'obsolete feature not enabled')]
170 170 if err:
171 171 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr)
172 172 printf(b'\n'.join([b' ' + e for e in err]), file=sys.stderr)
173 173 return ''
174 174 return out
175 175
176 176 version = ''
177 177
178 178 # Execute hg out of this directory with a custom environment which takes care
179 179 # to not use any hgrc files and do no localization.
180 180 env = {'HGMODULEPOLICY': 'py',
181 181 'HGRCPATH': '',
182 182 'LANGUAGE': 'C'}
183 183 if 'LD_LIBRARY_PATH' in os.environ:
184 184 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
185 185 if 'SystemRoot' in os.environ:
186 186 # Copy SystemRoot into the custom environment for Python 2.6
187 187 # under Windows. Otherwise, the subprocess will fail with
188 188 # error 0xc0150004. See: http://bugs.python.org/issue3440
189 189 env['SystemRoot'] = os.environ['SystemRoot']
190 190
191 191 if os.path.isdir('.hg'):
192 192 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
193 193 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
194 194 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
195 195 if numerictags: # tag(s) found
196 196 version = numerictags[-1]
197 197 if hgid.endswith('+'): # propagate the dirty status to the tag
198 198 version += '+'
199 199 else: # no tag found
200 200 ltagcmd = [sys.executable, 'hg', 'parents', '--template',
201 201 '{latesttag}']
202 202 ltag = runhg(ltagcmd, env)
203 203 changessincecmd = [sys.executable, 'hg', 'log', '-T', 'x\n', '-r',
204 204 "only(.,'%s')" % ltag]
205 205 changessince = len(runhg(changessincecmd, env).splitlines())
206 206 version = '%s+%s-%s' % (ltag, changessince, hgid)
207 207 if version.endswith('+'):
208 208 version += time.strftime('%Y%m%d')
209 209 elif os.path.exists('.hg_archival.txt'):
210 210 kw = dict([[t.strip() for t in l.split(':', 1)]
211 211 for l in open('.hg_archival.txt')])
212 212 if 'tag' in kw:
213 213 version = kw['tag']
214 214 elif 'latesttag' in kw:
215 215 if 'changessincelatesttag' in kw:
216 216 version = '%(latesttag)s+%(changessincelatesttag)s-%(node).12s' % kw
217 217 else:
218 218 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
219 219 else:
220 220 version = kw.get('node', '')[:12]
221 221
222 222 if version:
223 223 f = open("mercurial/__version__.py", "w")
224 224 f.write('# this file is autogenerated by setup.py\n')
225 225 f.write('version = "%s"\n' % version)
226 226 f.close()
227 227
228 228
229 229 try:
230 230 from mercurial import __version__
231 231 version = __version__.version
232 232 except ImportError:
233 233 version = 'unknown'
234 234
235 235 class hgbuild(build):
236 236 # Insert hgbuildmo first so that files in mercurial/locale/ are found
237 237 # when build_py is run next.
238 238 sub_commands = [('build_mo', None),
239 239
240 240 # We also need build_ext before build_py. Otherwise, when 2to3 is
241 241 # called (in build_py), it will not find osutil & friends,
242 242 # thinking that those modules are global and, consequently, making
243 243 # a mess, now that all module imports are global.
244 244
245 245 ('build_ext', build.has_ext_modules),
246 246 ] + build.sub_commands
247 247
248 248 class hgbuildmo(build):
249 249
250 250 description = "build translations (.mo files)"
251 251
252 252 def run(self):
253 253 if not find_executable('msgfmt'):
254 254 self.warn("could not find msgfmt executable, no translations "
255 255 "will be built")
256 256 return
257 257
258 258 podir = 'i18n'
259 259 if not os.path.isdir(podir):
260 260 self.warn("could not find %s/ directory" % podir)
261 261 return
262 262
263 263 join = os.path.join
264 264 for po in os.listdir(podir):
265 265 if not po.endswith('.po'):
266 266 continue
267 267 pofile = join(podir, po)
268 268 modir = join('locale', po[:-3], 'LC_MESSAGES')
269 269 mofile = join(modir, 'hg.mo')
270 270 mobuildfile = join('mercurial', mofile)
271 271 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
272 272 if sys.platform != 'sunos5':
273 273 # msgfmt on Solaris does not know about -c
274 274 cmd.append('-c')
275 275 self.mkpath(join('mercurial', modir))
276 276 self.make_file([pofile], mobuildfile, spawn, (cmd,))
277 277
278 278
279 279 class hgdist(Distribution):
280 280 pure = ispypy
281 281
282 282 global_options = Distribution.global_options + \
283 283 [('pure', None, "use pure (slow) Python "
284 284 "code instead of C extensions"),
285 285 ('c2to3', None, "(experimental!) convert "
286 286 "code with 2to3"),
287 287 ]
288 288
289 289 def has_ext_modules(self):
290 290 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
291 291 # too late for some cases
292 292 return not self.pure and Distribution.has_ext_modules(self)
293 293
294 294 class hgbuildext(build_ext):
295 295
296 296 def build_extension(self, ext):
297 297 try:
298 298 build_ext.build_extension(self, ext)
299 299 except CCompilerError:
300 300 if not getattr(ext, 'optional', False):
301 301 raise
302 302 log.warn("Failed to build optional extension '%s' (skipping)",
303 303 ext.name)
304 304
305 305 class hgbuildscripts(build_scripts):
306 306 def run(self):
307 if os.name != 'nt':
307 if os.name != 'nt' or self.distribution.pure:
308 308 return build_scripts.run(self)
309 309
310 310 exebuilt = False
311 311 try:
312 312 self.run_command('build_hgexe')
313 313 exebuilt = True
314 314 except (DistutilsError, CCompilerError):
315 315 log.warn('failed to build optional hg.exe')
316 316
317 317 if exebuilt:
318 318 # Copying hg.exe to the scripts build directory ensures it is
319 319 # installed by the install_scripts command.
320 320 hgexecommand = self.get_finalized_command('build_hgexe')
321 321 dest = os.path.join(self.build_dir, 'hg.exe')
322 322 self.mkpath(self.build_dir)
323 323 self.copy_file(hgexecommand.hgexepath, dest)
324 324
325 325 # Remove hg.bat because it is redundant with hg.exe.
326 326 self.scripts.remove('contrib/win32/hg.bat')
327 327
328 328 return build_scripts.run(self)
329 329
330 330 class hgbuildpy(build_py):
331 331 if convert2to3:
332 332 fixer_names = sorted(set(getfixers("lib2to3.fixes") +
333 333 getfixers("hgfixes")))
334 334
335 335 def finalize_options(self):
336 336 build_py.finalize_options(self)
337 337
338 338 if self.distribution.pure:
339 339 self.distribution.ext_modules = []
340 340 else:
341 341 h = os.path.join(get_python_inc(), 'Python.h')
342 342 if not os.path.exists(h):
343 343 raise SystemExit('Python headers are required to build '
344 344 'Mercurial but weren\'t found in %s' % h)
345 345
346 346 def copy_file(self, *args, **kwargs):
347 347 dst, copied = build_py.copy_file(self, *args, **kwargs)
348 348
349 349 if copied and dst.endswith('__init__.py'):
350 350 if self.distribution.pure:
351 351 modulepolicy = 'py'
352 352 else:
353 353 modulepolicy = 'c'
354 354 content = open(dst, 'rb').read()
355 355 content = content.replace(b'@MODULELOADPOLICY@',
356 356 modulepolicy.encode(libdir_escape))
357 357 with open(dst, 'wb') as fh:
358 358 fh.write(content)
359 359
360 360 return dst, copied
361 361
362 362 class buildhgextindex(Command):
363 363 description = 'generate prebuilt index of hgext (for frozen package)'
364 364 user_options = []
365 365 _indexfilename = 'hgext/__index__.py'
366 366
367 367 def initialize_options(self):
368 368 pass
369 369
370 370 def finalize_options(self):
371 371 pass
372 372
373 373 def run(self):
374 374 if os.path.exists(self._indexfilename):
375 375 f = open(self._indexfilename, 'w')
376 376 f.write('# empty\n')
377 377 f.close()
378 378
379 379 # here no extension enabled, disabled() lists up everything
380 380 code = ('import pprint; from mercurial import extensions; '
381 381 'pprint.pprint(extensions.disabled())')
382 382 out, err = runcmd([sys.executable, '-c', code], env)
383 383 if err:
384 384 raise DistutilsExecError(err)
385 385
386 386 f = open(self._indexfilename, 'w')
387 387 f.write('# this file is autogenerated by setup.py\n')
388 388 f.write('docs = ')
389 389 f.write(out)
390 390 f.close()
391 391
392 392 class buildhgexe(build_ext):
393 393 description = 'compile hg.exe from mercurial/exewrapper.c'
394 394
395 395 def build_extensions(self):
396 396 if os.name != 'nt':
397 397 return
398 398 if isinstance(self.compiler, HackedMingw32CCompiler):
399 399 self.compiler.compiler_so = self.compiler.compiler # no -mdll
400 400 self.compiler.dll_libraries = [] # no -lmsrvc90
401 401 hv = sys.hexversion
402 402 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
403 403 f = open('mercurial/hgpythonlib.h', 'wb')
404 404 f.write('/* this file is autogenerated by setup.py */\n')
405 405 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
406 406 f.close()
407 407 objects = self.compiler.compile(['mercurial/exewrapper.c'],
408 408 output_dir=self.build_temp)
409 409 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
410 410 target = os.path.join(dir, 'hg')
411 411 self.compiler.link_executable(objects, target,
412 412 libraries=[],
413 413 output_dir=self.build_temp)
414 414
415 415 @property
416 416 def hgexepath(self):
417 417 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
418 418 return os.path.join(self.build_temp, dir, 'hg.exe')
419 419
420 420 class hginstalllib(install_lib):
421 421 '''
422 422 This is a specialization of install_lib that replaces the copy_file used
423 423 there so that it supports setting the mode of files after copying them,
424 424 instead of just preserving the mode that the files originally had. If your
425 425 system has a umask of something like 027, preserving the permissions when
426 426 copying will lead to a broken install.
427 427
428 428 Note that just passing keep_permissions=False to copy_file would be
429 429 insufficient, as it might still be applying a umask.
430 430 '''
431 431
432 432 def run(self):
433 433 realcopyfile = file_util.copy_file
434 434 def copyfileandsetmode(*args, **kwargs):
435 435 src, dst = args[0], args[1]
436 436 dst, copied = realcopyfile(*args, **kwargs)
437 437 if copied:
438 438 st = os.stat(src)
439 439 # Persist executable bit (apply it to group and other if user
440 440 # has it)
441 441 if st[stat.ST_MODE] & stat.S_IXUSR:
442 442 setmode = int('0755', 8)
443 443 else:
444 444 setmode = int('0644', 8)
445 445 m = stat.S_IMODE(st[stat.ST_MODE])
446 446 m = (m & ~int('0777', 8)) | setmode
447 447 os.chmod(dst, m)
448 448 file_util.copy_file = copyfileandsetmode
449 449 try:
450 450 install_lib.run(self)
451 451 finally:
452 452 file_util.copy_file = realcopyfile
453 453
454 454 class hginstallscripts(install_scripts):
455 455 '''
456 456 This is a specialization of install_scripts that replaces the @LIBDIR@ with
457 457 the configured directory for modules. If possible, the path is made relative
458 458 to the directory for scripts.
459 459 '''
460 460
461 461 def initialize_options(self):
462 462 install_scripts.initialize_options(self)
463 463
464 464 self.install_lib = None
465 465
466 466 def finalize_options(self):
467 467 install_scripts.finalize_options(self)
468 468 self.set_undefined_options('install',
469 469 ('install_lib', 'install_lib'))
470 470
471 471 def run(self):
472 472 install_scripts.run(self)
473 473
474 474 # It only makes sense to replace @LIBDIR@ with the install path if
475 475 # the install path is known. For wheels, the logic below calculates
476 476 # the libdir to be "../..". This is because the internal layout of a
477 477 # wheel archive looks like:
478 478 #
479 479 # mercurial-3.6.1.data/scripts/hg
480 480 # mercurial/__init__.py
481 481 #
482 482 # When installing wheels, the subdirectories of the "<pkg>.data"
483 483 # directory are translated to system local paths and files therein
484 484 # are copied in place. The mercurial/* files are installed into the
485 485 # site-packages directory. However, the site-packages directory
486 486 # isn't known until wheel install time. This means we have no clue
487 487 # at wheel generation time what the installed site-packages directory
488 488 # will be. And, wheels don't appear to provide the ability to register
489 489 # custom code to run during wheel installation. This all means that
490 490 # we can't reliably set the libdir in wheels: the default behavior
491 491 # of looking in sys.path must do.
492 492
493 493 if (os.path.splitdrive(self.install_dir)[0] !=
494 494 os.path.splitdrive(self.install_lib)[0]):
495 495 # can't make relative paths from one drive to another, so use an
496 496 # absolute path instead
497 497 libdir = self.install_lib
498 498 else:
499 499 common = os.path.commonprefix((self.install_dir, self.install_lib))
500 500 rest = self.install_dir[len(common):]
501 501 uplevel = len([n for n in os.path.split(rest) if n])
502 502
503 503 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
504 504
505 505 for outfile in self.outfiles:
506 506 fp = open(outfile, 'rb')
507 507 data = fp.read()
508 508 fp.close()
509 509
510 510 # skip binary files
511 511 if b'\0' in data:
512 512 continue
513 513
514 514 # During local installs, the shebang will be rewritten to the final
515 515 # install path. During wheel packaging, the shebang has a special
516 516 # value.
517 517 if data.startswith(b'#!python'):
518 518 log.info('not rewriting @LIBDIR@ in %s because install path '
519 519 'not known' % outfile)
520 520 continue
521 521
522 522 data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape))
523 523 fp = open(outfile, 'wb')
524 524 fp.write(data)
525 525 fp.close()
526 526
527 527 cmdclass = {'build': hgbuild,
528 528 'build_mo': hgbuildmo,
529 529 'build_ext': hgbuildext,
530 530 'build_py': hgbuildpy,
531 531 'build_scripts': hgbuildscripts,
532 532 'build_hgextindex': buildhgextindex,
533 533 'install_lib': hginstalllib,
534 534 'install_scripts': hginstallscripts,
535 535 'build_hgexe': buildhgexe,
536 536 }
537 537
538 538 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
539 539 'mercurial.pure',
540 540 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
541 541 'hgext.largefiles']
542 542
543 543 common_depends = ['mercurial/util.h']
544 544
545 545 osutil_ldflags = []
546 546
547 547 if sys.platform == 'darwin':
548 548 osutil_ldflags += ['-framework', 'ApplicationServices']
549 549
550 550 extmodules = [
551 551 Extension('mercurial.base85', ['mercurial/base85.c'],
552 552 depends=common_depends),
553 553 Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
554 554 depends=common_depends),
555 555 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
556 556 depends=common_depends),
557 557 Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
558 558 depends=common_depends),
559 559 Extension('mercurial.parsers', ['mercurial/dirs.c',
560 560 'mercurial/manifest.c',
561 561 'mercurial/parsers.c',
562 562 'mercurial/pathencode.c'],
563 563 depends=common_depends),
564 564 Extension('mercurial.osutil', ['mercurial/osutil.c'],
565 565 extra_link_args=osutil_ldflags,
566 566 depends=common_depends),
567 567 ]
568 568
569 569 try:
570 570 from distutils import cygwinccompiler
571 571
572 572 # the -mno-cygwin option has been deprecated for years
573 573 compiler = cygwinccompiler.Mingw32CCompiler
574 574
575 575 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
576 576 def __init__(self, *args, **kwargs):
577 577 compiler.__init__(self, *args, **kwargs)
578 578 for i in 'compiler compiler_so linker_exe linker_so'.split():
579 579 try:
580 580 getattr(self, i).remove('-mno-cygwin')
581 581 except ValueError:
582 582 pass
583 583
584 584 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
585 585 except ImportError:
586 586 # the cygwinccompiler package is not available on some Python
587 587 # distributions like the ones from the optware project for Synology
588 588 # DiskStation boxes
589 589 class HackedMingw32CCompiler(object):
590 590 pass
591 591
592 592 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
593 593 'help/*.txt',
594 594 'help/internals/*.txt',
595 595 'default.d/*.rc',
596 596 'dummycert.pem']}
597 597
598 598 def ordinarypath(p):
599 599 return p and p[0] != '.' and p[-1] != '~'
600 600
601 601 for root in ('templates',):
602 602 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
603 603 curdir = curdir.split(os.sep, 1)[1]
604 604 dirs[:] = filter(ordinarypath, dirs)
605 605 for f in filter(ordinarypath, files):
606 606 f = os.path.join(curdir, f)
607 607 packagedata['mercurial'].append(f)
608 608
609 609 datafiles = []
610 610 setupversion = version
611 611 extra = {}
612 612
613 613 if py2exeloaded:
614 614 extra['console'] = [
615 615 {'script':'hg',
616 616 'copyright':'Copyright (C) 2005-2016 Matt Mackall and others',
617 617 'product_version':version}]
618 618 # sub command of 'build' because 'py2exe' does not handle sub_commands
619 619 build.sub_commands.insert(0, ('build_hgextindex', None))
620 620 # put dlls in sub directory so that they won't pollute PATH
621 621 extra['zipfile'] = 'lib/library.zip'
622 622
623 623 if os.name == 'nt':
624 624 # Windows binary file versions for exe/dll files must have the
625 625 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
626 626 setupversion = version.split('+', 1)[0]
627 627
628 628 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
629 629 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
630 630 if version:
631 631 version = version[0]
632 632 if sys.version_info[0] == 3:
633 633 version = version.decode('utf-8')
634 634 xcode4 = (version.startswith('Xcode') and
635 635 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
636 636 xcode51 = re.match(r'^Xcode\s+5\.1', version) is not None
637 637 else:
638 638 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
639 639 # installed, but instead with only command-line tools. Assume
640 640 # that only happens on >= Lion, thus no PPC support.
641 641 xcode4 = True
642 642 xcode51 = False
643 643
644 644 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
645 645 # distutils.sysconfig
646 646 if xcode4:
647 647 os.environ['ARCHFLAGS'] = ''
648 648
649 649 # XCode 5.1 changes clang such that it now fails to compile if the
650 650 # -mno-fused-madd flag is passed, but the version of Python shipped with
651 651 # OS X 10.9 Mavericks includes this flag. This causes problems in all
652 652 # C extension modules, and a bug has been filed upstream at
653 653 # http://bugs.python.org/issue21244. We also need to patch this here
654 654 # so Mercurial can continue to compile in the meantime.
655 655 if xcode51:
656 656 cflags = get_config_var('CFLAGS')
657 657 if cflags and re.search(r'-mno-fused-madd\b', cflags) is not None:
658 658 os.environ['CFLAGS'] = (
659 659 os.environ.get('CFLAGS', '') + ' -Qunused-arguments')
660 660
661 661 setup(name='mercurial',
662 662 version=setupversion,
663 663 author='Matt Mackall and many others',
664 664 author_email='mercurial@selenic.com',
665 665 url='https://mercurial-scm.org/',
666 666 download_url='https://mercurial-scm.org/release/',
667 667 description=('Fast scalable distributed SCM (revision control, version '
668 668 'control) system'),
669 669 long_description=('Mercurial is a distributed SCM tool written in Python.'
670 670 ' It is used by a number of large projects that require'
671 671 ' fast, reliable distributed revision control, such as '
672 672 'Mozilla.'),
673 673 license='GNU GPLv2 or any later version',
674 674 classifiers=[
675 675 'Development Status :: 6 - Mature',
676 676 'Environment :: Console',
677 677 'Intended Audience :: Developers',
678 678 'Intended Audience :: System Administrators',
679 679 'License :: OSI Approved :: GNU General Public License (GPL)',
680 680 'Natural Language :: Danish',
681 681 'Natural Language :: English',
682 682 'Natural Language :: German',
683 683 'Natural Language :: Italian',
684 684 'Natural Language :: Japanese',
685 685 'Natural Language :: Portuguese (Brazilian)',
686 686 'Operating System :: Microsoft :: Windows',
687 687 'Operating System :: OS Independent',
688 688 'Operating System :: POSIX',
689 689 'Programming Language :: C',
690 690 'Programming Language :: Python',
691 691 'Topic :: Software Development :: Version Control',
692 692 ],
693 693 scripts=scripts,
694 694 packages=packages,
695 695 ext_modules=extmodules,
696 696 data_files=datafiles,
697 697 package_data=packagedata,
698 698 cmdclass=cmdclass,
699 699 distclass=hgdist,
700 700 options={'py2exe': {'packages': ['hgext', 'email']},
701 701 'bdist_mpkg': {'zipdist': False,
702 702 'license': 'COPYING',
703 703 'readme': 'contrib/macosx/Readme.html',
704 704 'welcome': 'contrib/macosx/Welcome.html',
705 705 },
706 706 },
707 707 **extra)
General Comments 0
You need to be logged in to leave comments. Login now