Mercurial > hg
comparison setup.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | f9d35f01b8b3 |
children | c3e10f705a6c |
comparison
equal
deleted
inserted
replaced
43075:57875cf423c9 | 43076:2372284d9457 |
---|---|
15 # codecs.escape_encode() where it raises SystemError on empty bytestring | 15 # codecs.escape_encode() where it raises SystemError on empty bytestring |
16 # bug link: https://bugs.python.org/issue25270 | 16 # bug link: https://bugs.python.org/issue25270 |
17 # | 17 # |
18 # TODO: when we actually work on Python 3, use this string as the | 18 # TODO: when we actually work on Python 3, use this string as the |
19 # actual supportedpy string. | 19 # actual supportedpy string. |
20 supportedpy = ','.join([ | 20 supportedpy = ','.join( |
21 '>=2.7', | 21 [ |
22 '!=3.0.*', | 22 '>=2.7', |
23 '!=3.1.*', | 23 '!=3.0.*', |
24 '!=3.2.*', | 24 '!=3.1.*', |
25 '!=3.3.*', | 25 '!=3.2.*', |
26 '!=3.4.*', | 26 '!=3.3.*', |
27 '!=3.5.0', | 27 '!=3.4.*', |
28 '!=3.5.1', | 28 '!=3.5.0', |
29 '!=3.5.2', | 29 '!=3.5.1', |
30 '!=3.6.0', | 30 '!=3.5.2', |
31 '!=3.6.1', | 31 '!=3.6.0', |
32 ]) | 32 '!=3.6.1', |
33 ] | |
34 ) | |
33 | 35 |
34 import sys, platform | 36 import sys, platform |
35 import sysconfig | 37 import sysconfig |
38 | |
36 if sys.version_info[0] >= 3: | 39 if sys.version_info[0] >= 3: |
37 printf = eval('print') | 40 printf = eval('print') |
38 libdir_escape = 'unicode_escape' | 41 libdir_escape = 'unicode_escape' |
42 | |
39 def sysstr(s): | 43 def sysstr(s): |
40 return s.decode('latin-1') | 44 return s.decode('latin-1') |
45 | |
46 | |
41 else: | 47 else: |
42 libdir_escape = 'string_escape' | 48 libdir_escape = 'string_escape' |
49 | |
43 def printf(*args, **kwargs): | 50 def printf(*args, **kwargs): |
44 f = kwargs.get('file', sys.stdout) | 51 f = kwargs.get('file', sys.stdout) |
45 end = kwargs.get('end', '\n') | 52 end = kwargs.get('end', '\n') |
46 f.write(b' '.join(args) + end) | 53 f.write(b' '.join(args) + end) |
54 | |
47 def sysstr(s): | 55 def sysstr(s): |
48 return s | 56 return s |
57 | |
49 | 58 |
50 # Attempt to guide users to a modern pip - this means that 2.6 users | 59 # Attempt to guide users to a modern pip - this means that 2.6 users |
51 # should have a chance of getting a 4.2 release, and when we ratchet | 60 # should have a chance of getting a 4.2 release, and when we ratchet |
52 # the version requirement forward again hopefully everyone will get | 61 # the version requirement forward again hopefully everyone will get |
53 # something that works for them. | 62 # something that works for them. |
54 if sys.version_info < (2, 7, 0, 'final'): | 63 if sys.version_info < (2, 7, 0, 'final'): |
55 pip_message = ('This may be due to an out of date pip. ' | 64 pip_message = ( |
56 'Make sure you have pip >= 9.0.1.') | 65 'This may be due to an out of date pip. ' |
66 'Make sure you have pip >= 9.0.1.' | |
67 ) | |
57 try: | 68 try: |
58 import pip | 69 import pip |
70 | |
59 pip_version = tuple([int(x) for x in pip.__version__.split('.')[:3]]) | 71 pip_version = tuple([int(x) for x in pip.__version__.split('.')[:3]]) |
60 if pip_version < (9, 0, 1) : | 72 if pip_version < (9, 0, 1): |
61 pip_message = ( | 73 pip_message = ( |
62 'Your pip version is out of date, please install ' | 74 'Your pip version is out of date, please install ' |
63 'pip >= 9.0.1. pip {} detected.'.format(pip.__version__)) | 75 'pip >= 9.0.1. pip {} detected.'.format(pip.__version__) |
76 ) | |
64 else: | 77 else: |
65 # pip is new enough - it must be something else | 78 # pip is new enough - it must be something else |
66 pip_message = '' | 79 pip_message = '' |
67 except Exception: | 80 except Exception: |
68 pass | 81 pass |
69 error = """ | 82 error = """ |
70 Mercurial does not support Python older than 2.7. | 83 Mercurial does not support Python older than 2.7. |
71 Python {py} detected. | 84 Python {py} detected. |
72 {pip} | 85 {pip} |
73 """.format(py=sys.version_info, pip=pip_message) | 86 """.format( |
87 py=sys.version_info, pip=pip_message | |
88 ) | |
74 printf(error, file=sys.stderr) | 89 printf(error, file=sys.stderr) |
75 sys.exit(1) | 90 sys.exit(1) |
76 | 91 |
77 # We don't yet officially support Python 3. But we want to allow developers to | 92 # We don't yet officially support Python 3. But we want to allow developers to |
78 # hack on. Detect and disallow running on Python 3 by default. But provide a | 93 # hack on. Detect and disallow running on Python 3 by default. But provide a |
98 this command. No special environment variables or configuration changes are | 113 this command. No special environment variables or configuration changes are |
99 necessary to run `hg` with Python 3. | 114 necessary to run `hg` with Python 3. |
100 | 115 |
101 See https://www.mercurial-scm.org/wiki/Python3 for more on Mercurial's | 116 See https://www.mercurial-scm.org/wiki/Python3 for more on Mercurial's |
102 Python 3 support. | 117 Python 3 support. |
103 """.format(py='.'.join('%d' % x for x in sys.version_info[0:2])) | 118 """.format( |
119 py='.'.join('%d' % x for x in sys.version_info[0:2]) | |
120 ) | |
104 | 121 |
105 printf(error, file=sys.stderr) | 122 printf(error, file=sys.stderr) |
106 sys.exit(1) | 123 sys.exit(1) |
107 | 124 |
108 if sys.version_info[0] >= 3: | 125 if sys.version_info[0] >= 3: |
112 DYLIB_SUFFIX = sysconfig.get_config_vars()['SO'] | 129 DYLIB_SUFFIX = sysconfig.get_config_vars()['SO'] |
113 | 130 |
114 # Solaris Python packaging brain damage | 131 # Solaris Python packaging brain damage |
115 try: | 132 try: |
116 import hashlib | 133 import hashlib |
134 | |
117 sha = hashlib.sha1() | 135 sha = hashlib.sha1() |
118 except ImportError: | 136 except ImportError: |
119 try: | 137 try: |
120 import sha | 138 import sha |
121 sha.sha # silence unused import warning | 139 |
140 sha.sha # silence unused import warning | |
122 except ImportError: | 141 except ImportError: |
123 raise SystemExit( | 142 raise SystemExit( |
124 "Couldn't import standard hashlib (incomplete Python install).") | 143 "Couldn't import standard hashlib (incomplete Python install)." |
144 ) | |
125 | 145 |
126 try: | 146 try: |
127 import zlib | 147 import zlib |
128 zlib.compressobj # silence unused import warning | 148 |
149 zlib.compressobj # silence unused import warning | |
129 except ImportError: | 150 except ImportError: |
130 raise SystemExit( | 151 raise SystemExit( |
131 "Couldn't import standard zlib (incomplete Python install).") | 152 "Couldn't import standard zlib (incomplete Python install)." |
153 ) | |
132 | 154 |
133 # The base IronPython distribution (as of 2.7.1) doesn't support bz2 | 155 # The base IronPython distribution (as of 2.7.1) doesn't support bz2 |
134 isironpython = False | 156 isironpython = False |
135 try: | 157 try: |
136 isironpython = (platform.python_implementation() | 158 isironpython = ( |
137 .lower().find("ironpython") != -1) | 159 platform.python_implementation().lower().find("ironpython") != -1 |
160 ) | |
138 except AttributeError: | 161 except AttributeError: |
139 pass | 162 pass |
140 | 163 |
141 if isironpython: | 164 if isironpython: |
142 sys.stderr.write("warning: IronPython detected (no bz2 support)\n") | 165 sys.stderr.write("warning: IronPython detected (no bz2 support)\n") |
143 else: | 166 else: |
144 try: | 167 try: |
145 import bz2 | 168 import bz2 |
146 bz2.BZ2Compressor # silence unused import warning | 169 |
170 bz2.BZ2Compressor # silence unused import warning | |
147 except ImportError: | 171 except ImportError: |
148 raise SystemExit( | 172 raise SystemExit( |
149 "Couldn't import standard bz2 (incomplete Python install).") | 173 "Couldn't import standard bz2 (incomplete Python install)." |
174 ) | |
150 | 175 |
151 ispypy = "PyPy" in sys.version | 176 ispypy = "PyPy" in sys.version |
152 | 177 |
153 hgrustext = os.environ.get('HGWITHRUSTEXT') | 178 hgrustext = os.environ.get('HGWITHRUSTEXT') |
154 # TODO record it for proper rebuild upon changes | 179 # TODO record it for proper rebuild upon changes |
161 import stat, subprocess, time | 186 import stat, subprocess, time |
162 import re | 187 import re |
163 import shutil | 188 import shutil |
164 import tempfile | 189 import tempfile |
165 from distutils import log | 190 from distutils import log |
191 | |
166 # We have issues with setuptools on some platforms and builders. Until | 192 # We have issues with setuptools on some platforms and builders. Until |
167 # those are resolved, setuptools is opt-in except for platforms where | 193 # those are resolved, setuptools is opt-in except for platforms where |
168 # we don't have issues. | 194 # we don't have issues. |
169 issetuptools = (os.name == 'nt' or 'FORCE_SETUPTOOLS' in os.environ) | 195 issetuptools = os.name == 'nt' or 'FORCE_SETUPTOOLS' in os.environ |
170 if issetuptools: | 196 if issetuptools: |
171 from setuptools import setup | 197 from setuptools import setup |
172 else: | 198 else: |
173 from distutils.core import setup | 199 from distutils.core import setup |
174 from distutils.ccompiler import new_compiler | 200 from distutils.ccompiler import new_compiler |
192 from distutils.version import StrictVersion | 218 from distutils.version import StrictVersion |
193 | 219 |
194 # Explain to distutils.StrictVersion how our release candidates are versionned | 220 # Explain to distutils.StrictVersion how our release candidates are versionned |
195 StrictVersion.version_re = re.compile(r'^(\d+)\.(\d+)(\.(\d+))?-?(rc(\d+))?$') | 221 StrictVersion.version_re = re.compile(r'^(\d+)\.(\d+)(\.(\d+))?-?(rc(\d+))?$') |
196 | 222 |
223 | |
197 def write_if_changed(path, content): | 224 def write_if_changed(path, content): |
198 """Write content to a file iff the content hasn't changed.""" | 225 """Write content to a file iff the content hasn't changed.""" |
199 if os.path.exists(path): | 226 if os.path.exists(path): |
200 with open(path, 'rb') as fh: | 227 with open(path, 'rb') as fh: |
201 current = fh.read() | 228 current = fh.read() |
204 | 231 |
205 if current != content: | 232 if current != content: |
206 with open(path, 'wb') as fh: | 233 with open(path, 'wb') as fh: |
207 fh.write(content) | 234 fh.write(content) |
208 | 235 |
236 | |
209 scripts = ['hg'] | 237 scripts = ['hg'] |
210 if os.name == 'nt': | 238 if os.name == 'nt': |
211 # We remove hg.bat if we are able to build hg.exe. | 239 # We remove hg.bat if we are able to build hg.exe. |
212 scripts.append('contrib/win32/hg.bat') | 240 scripts.append('contrib/win32/hg.bat') |
241 | |
213 | 242 |
214 def cancompile(cc, code): | 243 def cancompile(cc, code): |
215 tmpdir = tempfile.mkdtemp(prefix='hg-install-') | 244 tmpdir = tempfile.mkdtemp(prefix='hg-install-') |
216 devnull = oldstderr = None | 245 devnull = oldstderr = None |
217 try: | 246 try: |
236 os.dup2(oldstderr, sys.stderr.fileno()) | 265 os.dup2(oldstderr, sys.stderr.fileno()) |
237 if devnull is not None: | 266 if devnull is not None: |
238 devnull.close() | 267 devnull.close() |
239 shutil.rmtree(tmpdir) | 268 shutil.rmtree(tmpdir) |
240 | 269 |
270 | |
241 # simplified version of distutils.ccompiler.CCompiler.has_function | 271 # simplified version of distutils.ccompiler.CCompiler.has_function |
242 # that actually removes its temporary files. | 272 # that actually removes its temporary files. |
243 def hasfunction(cc, funcname): | 273 def hasfunction(cc, funcname): |
244 code = 'int main(void) { %s(); }\n' % funcname | 274 code = 'int main(void) { %s(); }\n' % funcname |
245 return cancompile(cc, code) | 275 return cancompile(cc, code) |
246 | 276 |
277 | |
247 def hasheader(cc, headername): | 278 def hasheader(cc, headername): |
248 code = '#include <%s>\nint main(void) { return 0; }\n' % headername | 279 code = '#include <%s>\nint main(void) { return 0; }\n' % headername |
249 return cancompile(cc, code) | 280 return cancompile(cc, code) |
250 | 281 |
282 | |
251 # py2exe needs to be installed to work | 283 # py2exe needs to be installed to work |
252 try: | 284 try: |
253 import py2exe | 285 import py2exe |
254 py2exe.Distribution # silence unused import warning | 286 |
287 py2exe.Distribution # silence unused import warning | |
255 py2exeloaded = True | 288 py2exeloaded = True |
256 # import py2exe's patched Distribution class | 289 # import py2exe's patched Distribution class |
257 from distutils.core import Distribution | 290 from distutils.core import Distribution |
258 except ImportError: | 291 except ImportError: |
259 py2exeloaded = False | 292 py2exeloaded = False |
260 | 293 |
294 | |
261 def runcmd(cmd, env, cwd=None): | 295 def runcmd(cmd, env, cwd=None): |
262 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, | 296 p = subprocess.Popen( |
263 stderr=subprocess.PIPE, env=env, cwd=cwd) | 297 cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, cwd=cwd |
298 ) | |
264 out, err = p.communicate() | 299 out, err = p.communicate() |
265 return p.returncode, out, err | 300 return p.returncode, out, err |
301 | |
266 | 302 |
267 class hgcommand(object): | 303 class hgcommand(object): |
268 def __init__(self, cmd, env): | 304 def __init__(self, cmd, env): |
269 self.cmd = cmd | 305 self.cmd = cmd |
270 self.env = env | 306 self.env = env |
277 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr) | 313 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr) |
278 printf(err, file=sys.stderr) | 314 printf(err, file=sys.stderr) |
279 return '' | 315 return '' |
280 return out | 316 return out |
281 | 317 |
318 | |
282 def filterhgerr(err): | 319 def filterhgerr(err): |
283 # If root is executing setup.py, but the repository is owned by | 320 # If root is executing setup.py, but the repository is owned by |
284 # another user (as in "sudo python setup.py install") we will get | 321 # another user (as in "sudo python setup.py install") we will get |
285 # trust warnings since the .hg/hgrc file is untrusted. That is | 322 # trust warnings since the .hg/hgrc file is untrusted. That is |
286 # fine, we don't want to load it anyway. Python may warn about | 323 # fine, we don't want to load it anyway. Python may warn about |
287 # a missing __init__.py in mercurial/locale, we also ignore that. | 324 # a missing __init__.py in mercurial/locale, we also ignore that. |
288 err = [e for e in err.splitlines() | 325 err = [ |
289 if (not e.startswith(b'not trusting file') | 326 e |
290 and not e.startswith(b'warning: Not importing') | 327 for e in err.splitlines() |
291 and not e.startswith(b'obsolete feature not enabled') | 328 if ( |
292 and not e.startswith(b'*** failed to import extension') | 329 not e.startswith(b'not trusting file') |
293 and not e.startswith(b'devel-warn:') | 330 and not e.startswith(b'warning: Not importing') |
294 and not (e.startswith(b'(third party extension') | 331 and not e.startswith(b'obsolete feature not enabled') |
295 and e.endswith(b'or newer of Mercurial; disabling)')))] | 332 and not e.startswith(b'*** failed to import extension') |
333 and not e.startswith(b'devel-warn:') | |
334 and not ( | |
335 e.startswith(b'(third party extension') | |
336 and e.endswith(b'or newer of Mercurial; disabling)') | |
337 ) | |
338 ) | |
339 ] | |
296 return b'\n'.join(b' ' + e for e in err) | 340 return b'\n'.join(b' ' + e for e in err) |
341 | |
297 | 342 |
298 def findhg(): | 343 def findhg(): |
299 """Try to figure out how we should invoke hg for examining the local | 344 """Try to figure out how we should invoke hg for examining the local |
300 repository contents. | 345 repository contents. |
301 | 346 |
332 except EnvironmentError: | 377 except EnvironmentError: |
333 retcode = -1 | 378 retcode = -1 |
334 if retcode == 0 and not filterhgerr(err): | 379 if retcode == 0 and not filterhgerr(err): |
335 return hgcommand(hgcmd, hgenv) | 380 return hgcommand(hgcmd, hgenv) |
336 | 381 |
337 raise SystemExit('Unable to find a working hg binary to extract the ' | 382 raise SystemExit( |
338 'version from the repository tags') | 383 'Unable to find a working hg binary to extract the ' |
384 'version from the repository tags' | |
385 ) | |
386 | |
339 | 387 |
340 def localhgenv(): | 388 def localhgenv(): |
341 """Get an environment dictionary to use for invoking or importing | 389 """Get an environment dictionary to use for invoking or importing |
342 mercurial from the local repository.""" | 390 mercurial from the local repository.""" |
343 # Execute hg out of this directory with a custom environment which takes | 391 # Execute hg out of this directory with a custom environment which takes |
344 # care to not use any hgrc files and do no localization. | 392 # care to not use any hgrc files and do no localization. |
345 env = {'HGMODULEPOLICY': 'py', | 393 env = { |
346 'HGRCPATH': '', | 394 'HGMODULEPOLICY': 'py', |
347 'LANGUAGE': 'C', | 395 'HGRCPATH': '', |
348 'PATH': ''} # make pypi modules that use os.environ['PATH'] happy | 396 'LANGUAGE': 'C', |
397 'PATH': '', | |
398 } # make pypi modules that use os.environ['PATH'] happy | |
349 if 'LD_LIBRARY_PATH' in os.environ: | 399 if 'LD_LIBRARY_PATH' in os.environ: |
350 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH'] | 400 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH'] |
351 if 'SystemRoot' in os.environ: | 401 if 'SystemRoot' in os.environ: |
352 # SystemRoot is required by Windows to load various DLLs. See: | 402 # SystemRoot is required by Windows to load various DLLs. See: |
353 # https://bugs.python.org/issue13524#msg148850 | 403 # https://bugs.python.org/issue13524#msg148850 |
354 env['SystemRoot'] = os.environ['SystemRoot'] | 404 env['SystemRoot'] = os.environ['SystemRoot'] |
355 return env | 405 return env |
406 | |
356 | 407 |
357 version = '' | 408 version = '' |
358 | 409 |
359 if os.path.isdir('.hg'): | 410 if os.path.isdir('.hg'): |
360 hg = findhg() | 411 hg = findhg() |
365 # Bail out if hg is having problems interacting with this repository, | 416 # Bail out if hg is having problems interacting with this repository, |
366 # rather than falling through and producing a bogus version number. | 417 # rather than falling through and producing a bogus version number. |
367 # Continuing with an invalid version number will break extensions | 418 # Continuing with an invalid version number will break extensions |
368 # that define minimumhgversion. | 419 # that define minimumhgversion. |
369 raise SystemExit('Unable to determine hg version from local repository') | 420 raise SystemExit('Unable to determine hg version from local repository') |
370 if numerictags: # tag(s) found | 421 if numerictags: # tag(s) found |
371 version = numerictags[-1] | 422 version = numerictags[-1] |
372 if hgid.endswith('+'): # propagate the dirty status to the tag | 423 if hgid.endswith('+'): # propagate the dirty status to the tag |
373 version += '+' | 424 version += '+' |
374 else: # no tag found | 425 else: # no tag found |
375 ltagcmd = ['parents', '--template', '{latesttag}'] | 426 ltagcmd = ['parents', '--template', '{latesttag}'] |
376 ltag = sysstr(hg.run(ltagcmd)) | 427 ltag = sysstr(hg.run(ltagcmd)) |
377 changessincecmd = ['log', '-T', 'x\n', '-r', "only(.,'%s')" % ltag] | 428 changessincecmd = ['log', '-T', 'x\n', '-r', "only(.,'%s')" % ltag] |
378 changessince = len(hg.run(changessincecmd).splitlines()) | 429 changessince = len(hg.run(changessincecmd).splitlines()) |
379 version = '%s+%s-%s' % (ltag, changessince, hgid) | 430 version = '%s+%s-%s' % (ltag, changessince, hgid) |
380 if version.endswith('+'): | 431 if version.endswith('+'): |
381 version += time.strftime('%Y%m%d') | 432 version += time.strftime('%Y%m%d') |
382 elif os.path.exists('.hg_archival.txt'): | 433 elif os.path.exists('.hg_archival.txt'): |
383 kw = dict([[t.strip() for t in l.split(':', 1)] | 434 kw = dict( |
384 for l in open('.hg_archival.txt')]) | 435 [[t.strip() for t in l.split(':', 1)] for l in open('.hg_archival.txt')] |
436 ) | |
385 if 'tag' in kw: | 437 if 'tag' in kw: |
386 version = kw['tag'] | 438 version = kw['tag'] |
387 elif 'latesttag' in kw: | 439 elif 'latesttag' in kw: |
388 if 'changessincelatesttag' in kw: | 440 if 'changessincelatesttag' in kw: |
389 version = '%(latesttag)s+%(changessincelatesttag)s-%(node).12s' % kw | 441 version = '%(latesttag)s+%(changessincelatesttag)s-%(node).12s' % kw |
395 if version: | 447 if version: |
396 versionb = version | 448 versionb = version |
397 if not isinstance(versionb, bytes): | 449 if not isinstance(versionb, bytes): |
398 versionb = versionb.encode('ascii') | 450 versionb = versionb.encode('ascii') |
399 | 451 |
400 write_if_changed('mercurial/__version__.py', b''.join([ | 452 write_if_changed( |
401 b'# this file is autogenerated by setup.py\n' | 453 'mercurial/__version__.py', |
402 b'version = b"%s"\n' % versionb, | 454 b''.join( |
403 ])) | 455 [ |
456 b'# this file is autogenerated by setup.py\n' | |
457 b'version = b"%s"\n' % versionb, | |
458 ] | |
459 ), | |
460 ) | |
404 | 461 |
405 try: | 462 try: |
406 oldpolicy = os.environ.get('HGMODULEPOLICY', None) | 463 oldpolicy = os.environ.get('HGMODULEPOLICY', None) |
407 os.environ['HGMODULEPOLICY'] = 'py' | 464 os.environ['HGMODULEPOLICY'] = 'py' |
408 from mercurial import __version__ | 465 from mercurial import __version__ |
466 | |
409 version = __version__.version | 467 version = __version__.version |
410 except ImportError: | 468 except ImportError: |
411 version = b'unknown' | 469 version = b'unknown' |
412 finally: | 470 finally: |
413 if oldpolicy is None: | 471 if oldpolicy is None: |
414 del os.environ['HGMODULEPOLICY'] | 472 del os.environ['HGMODULEPOLICY'] |
415 else: | 473 else: |
416 os.environ['HGMODULEPOLICY'] = oldpolicy | 474 os.environ['HGMODULEPOLICY'] = oldpolicy |
417 | 475 |
476 | |
418 class hgbuild(build): | 477 class hgbuild(build): |
419 # Insert hgbuildmo first so that files in mercurial/locale/ are found | 478 # Insert hgbuildmo first so that files in mercurial/locale/ are found |
420 # when build_py is run next. | 479 # when build_py is run next. |
421 sub_commands = [('build_mo', None)] + build.sub_commands | 480 sub_commands = [('build_mo', None)] + build.sub_commands |
422 | 481 |
482 | |
423 class hgbuildmo(build): | 483 class hgbuildmo(build): |
424 | 484 |
425 description = "build translations (.mo files)" | 485 description = "build translations (.mo files)" |
426 | 486 |
427 def run(self): | 487 def run(self): |
428 if not find_executable('msgfmt'): | 488 if not find_executable('msgfmt'): |
429 self.warn("could not find msgfmt executable, no translations " | 489 self.warn( |
430 "will be built") | 490 "could not find msgfmt executable, no translations " |
491 "will be built" | |
492 ) | |
431 return | 493 return |
432 | 494 |
433 podir = 'i18n' | 495 podir = 'i18n' |
434 if not os.path.isdir(podir): | 496 if not os.path.isdir(podir): |
435 self.warn("could not find %s/ directory" % podir) | 497 self.warn("could not find %s/ directory" % podir) |
464 def has_ext_modules(self): | 526 def has_ext_modules(self): |
465 # self.ext_modules is emptied in hgbuildpy.finalize_options which is | 527 # self.ext_modules is emptied in hgbuildpy.finalize_options which is |
466 # too late for some cases | 528 # too late for some cases |
467 return not self.pure and Distribution.has_ext_modules(self) | 529 return not self.pure and Distribution.has_ext_modules(self) |
468 | 530 |
531 | |
469 # This is ugly as a one-liner. So use a variable. | 532 # This is ugly as a one-liner. So use a variable. |
470 buildextnegops = dict(getattr(build_ext, 'negative_options', {})) | 533 buildextnegops = dict(getattr(build_ext, 'negative_options', {})) |
471 buildextnegops['no-zstd'] = 'zstd' | 534 buildextnegops['no-zstd'] = 'zstd' |
472 buildextnegops['no-rust'] = 'rust' | 535 buildextnegops['no-rust'] = 'rust' |
473 | 536 |
537 | |
474 class hgbuildext(build_ext): | 538 class hgbuildext(build_ext): |
475 user_options = build_ext.user_options + [ | 539 user_options = build_ext.user_options + [ |
476 ('zstd', None, 'compile zstd bindings [default]'), | 540 ('zstd', None, 'compile zstd bindings [default]'), |
477 ('no-zstd', None, 'do not compile zstd bindings'), | 541 ('no-zstd', None, 'do not compile zstd bindings'), |
478 ('rust', None, | 542 ( |
479 'compile Rust extensions if they are in use ' | 543 'rust', |
480 '(requires Cargo) [default]'), | 544 None, |
545 'compile Rust extensions if they are in use ' | |
546 '(requires Cargo) [default]', | |
547 ), | |
481 ('no-rust', None, 'do not compile Rust extensions'), | 548 ('no-rust', None, 'do not compile Rust extensions'), |
482 ] | 549 ] |
483 | 550 |
484 boolean_options = build_ext.boolean_options + ['zstd', 'rust'] | 551 boolean_options = build_ext.boolean_options + ['zstd', 'rust'] |
485 negative_opt = buildextnegops | 552 negative_opt = buildextnegops |
497 self.parallel = True | 564 self.parallel = True |
498 | 565 |
499 return build_ext.finalize_options(self) | 566 return build_ext.finalize_options(self) |
500 | 567 |
501 def build_extensions(self): | 568 def build_extensions(self): |
502 ruststandalones = [e for e in self.extensions | 569 ruststandalones = [ |
503 if isinstance(e, RustStandaloneExtension)] | 570 e for e in self.extensions if isinstance(e, RustStandaloneExtension) |
504 self.extensions = [e for e in self.extensions | 571 ] |
505 if e not in ruststandalones] | 572 self.extensions = [ |
573 e for e in self.extensions if e not in ruststandalones | |
574 ] | |
506 # Filter out zstd if disabled via argument. | 575 # Filter out zstd if disabled via argument. |
507 if not self.zstd: | 576 if not self.zstd: |
508 self.extensions = [e for e in self.extensions | 577 self.extensions = [ |
509 if e.name != 'mercurial.zstd'] | 578 e for e in self.extensions if e.name != 'mercurial.zstd' |
579 ] | |
510 | 580 |
511 # Build Rust standalon extensions if it'll be used | 581 # Build Rust standalon extensions if it'll be used |
512 # and its build is not explictely disabled (for external build | 582 # and its build is not explictely disabled (for external build |
513 # as Linux distributions would do) | 583 # as Linux distributions would do) |
514 if self.distribution.rust and self.rust and hgrustext != 'direct-ffi': | 584 if self.distribution.rust and self.rust and hgrustext != 'direct-ffi': |
516 rustext.build('' if self.inplace else self.build_lib) | 586 rustext.build('' if self.inplace else self.build_lib) |
517 | 587 |
518 return build_ext.build_extensions(self) | 588 return build_ext.build_extensions(self) |
519 | 589 |
520 def build_extension(self, ext): | 590 def build_extension(self, ext): |
521 if (self.distribution.rust and self.rust | 591 if ( |
522 and isinstance(ext, RustExtension)): | 592 self.distribution.rust |
523 ext.rustbuild() | 593 and self.rust |
594 and isinstance(ext, RustExtension) | |
595 ): | |
596 ext.rustbuild() | |
524 try: | 597 try: |
525 build_ext.build_extension(self, ext) | 598 build_ext.build_extension(self, ext) |
526 except CCompilerError: | 599 except CCompilerError: |
527 if not getattr(ext, 'optional', False): | 600 if not getattr(ext, 'optional', False): |
528 raise | 601 raise |
529 log.warn("Failed to build optional extension '%s' (skipping)", | 602 log.warn( |
530 ext.name) | 603 "Failed to build optional extension '%s' (skipping)", ext.name |
604 ) | |
605 | |
531 | 606 |
532 class hgbuildscripts(build_scripts): | 607 class hgbuildscripts(build_scripts): |
533 def run(self): | 608 def run(self): |
534 if os.name != 'nt' or self.distribution.pure: | 609 if os.name != 'nt' or self.distribution.pure: |
535 return build_scripts.run(self) | 610 return build_scripts.run(self) |
552 # Remove hg.bat because it is redundant with hg.exe. | 627 # Remove hg.bat because it is redundant with hg.exe. |
553 self.scripts.remove('contrib/win32/hg.bat') | 628 self.scripts.remove('contrib/win32/hg.bat') |
554 | 629 |
555 return build_scripts.run(self) | 630 return build_scripts.run(self) |
556 | 631 |
632 | |
557 class hgbuildpy(build_py): | 633 class hgbuildpy(build_py): |
558 def finalize_options(self): | 634 def finalize_options(self): |
559 build_py.finalize_options(self) | 635 build_py.finalize_options(self) |
560 | 636 |
561 if self.distribution.pure: | 637 if self.distribution.pure: |
563 elif self.distribution.cffi: | 639 elif self.distribution.cffi: |
564 from mercurial.cffi import ( | 640 from mercurial.cffi import ( |
565 bdiffbuild, | 641 bdiffbuild, |
566 mpatchbuild, | 642 mpatchbuild, |
567 ) | 643 ) |
568 exts = [mpatchbuild.ffi.distutils_extension(), | 644 |
569 bdiffbuild.ffi.distutils_extension()] | 645 exts = [ |
646 mpatchbuild.ffi.distutils_extension(), | |
647 bdiffbuild.ffi.distutils_extension(), | |
648 ] | |
570 # cffi modules go here | 649 # cffi modules go here |
571 if sys.platform == 'darwin': | 650 if sys.platform == 'darwin': |
572 from mercurial.cffi import osutilbuild | 651 from mercurial.cffi import osutilbuild |
652 | |
573 exts.append(osutilbuild.ffi.distutils_extension()) | 653 exts.append(osutilbuild.ffi.distutils_extension()) |
574 self.distribution.ext_modules = exts | 654 self.distribution.ext_modules = exts |
575 else: | 655 else: |
576 h = os.path.join(get_python_inc(), 'Python.h') | 656 h = os.path.join(get_python_inc(), 'Python.h') |
577 if not os.path.exists(h): | 657 if not os.path.exists(h): |
578 raise SystemExit('Python headers are required to build ' | 658 raise SystemExit( |
579 'Mercurial but weren\'t found in %s' % h) | 659 'Python headers are required to build ' |
660 'Mercurial but weren\'t found in %s' % h | |
661 ) | |
580 | 662 |
581 def run(self): | 663 def run(self): |
582 basepath = os.path.join(self.build_lib, 'mercurial') | 664 basepath = os.path.join(self.build_lib, 'mercurial') |
583 self.mkpath(basepath) | 665 self.mkpath(basepath) |
584 | 666 |
589 # in-place build should run without rebuilding and Rust extensions | 671 # in-place build should run without rebuilding and Rust extensions |
590 modulepolicy = 'rust+c-allow' if rust else 'allow' | 672 modulepolicy = 'rust+c-allow' if rust else 'allow' |
591 else: | 673 else: |
592 modulepolicy = 'rust+c' if rust else 'c' | 674 modulepolicy = 'rust+c' if rust else 'c' |
593 | 675 |
594 content = b''.join([ | 676 content = b''.join( |
595 b'# this file is autogenerated by setup.py\n', | 677 [ |
596 b'modulepolicy = b"%s"\n' % modulepolicy.encode('ascii'), | 678 b'# this file is autogenerated by setup.py\n', |
597 ]) | 679 b'modulepolicy = b"%s"\n' % modulepolicy.encode('ascii'), |
598 write_if_changed(os.path.join(basepath, '__modulepolicy__.py'), | 680 ] |
599 content) | 681 ) |
682 write_if_changed(os.path.join(basepath, '__modulepolicy__.py'), content) | |
600 | 683 |
601 build_py.run(self) | 684 build_py.run(self) |
685 | |
602 | 686 |
603 class buildhgextindex(Command): | 687 class buildhgextindex(Command): |
604 description = 'generate prebuilt index of hgext (for frozen package)' | 688 description = 'generate prebuilt index of hgext (for frozen package)' |
605 user_options = [] | 689 user_options = [] |
606 _indexfilename = 'hgext/__index__.py' | 690 _indexfilename = 'hgext/__index__.py' |
615 if os.path.exists(self._indexfilename): | 699 if os.path.exists(self._indexfilename): |
616 with open(self._indexfilename, 'w') as f: | 700 with open(self._indexfilename, 'w') as f: |
617 f.write('# empty\n') | 701 f.write('# empty\n') |
618 | 702 |
619 # here no extension enabled, disabled() lists up everything | 703 # here no extension enabled, disabled() lists up everything |
620 code = ('import pprint; from mercurial import extensions; ' | 704 code = ( |
621 'pprint.pprint(extensions.disabled())') | 705 'import pprint; from mercurial import extensions; ' |
622 returncode, out, err = runcmd([sys.executable, '-c', code], | 706 'pprint.pprint(extensions.disabled())' |
623 localhgenv()) | 707 ) |
708 returncode, out, err = runcmd( | |
709 [sys.executable, '-c', code], localhgenv() | |
710 ) | |
624 if err or returncode != 0: | 711 if err or returncode != 0: |
625 raise DistutilsExecError(err) | 712 raise DistutilsExecError(err) |
626 | 713 |
627 with open(self._indexfilename, 'wb') as f: | 714 with open(self._indexfilename, 'wb') as f: |
628 f.write(b'# this file is autogenerated by setup.py\n') | 715 f.write(b'# this file is autogenerated by setup.py\n') |
629 f.write(b'docs = ') | 716 f.write(b'docs = ') |
630 f.write(out) | 717 f.write(out) |
631 | 718 |
719 | |
632 class buildhgexe(build_ext): | 720 class buildhgexe(build_ext): |
633 description = 'compile hg.exe from mercurial/exewrapper.c' | 721 description = 'compile hg.exe from mercurial/exewrapper.c' |
634 user_options = build_ext.user_options + [ | 722 user_options = build_ext.user_options + [ |
635 ('long-paths-support', None, 'enable support for long paths on ' | 723 ( |
636 'Windows (off by default and ' | 724 'long-paths-support', |
637 'experimental)'), | 725 None, |
726 'enable support for long paths on ' | |
727 'Windows (off by default and ' | |
728 'experimental)', | |
729 ), | |
638 ] | 730 ] |
639 | 731 |
640 LONG_PATHS_MANIFEST = """ | 732 LONG_PATHS_MANIFEST = """ |
641 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> | 733 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> |
642 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> | 734 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> |
654 | 746 |
655 def build_extensions(self): | 747 def build_extensions(self): |
656 if os.name != 'nt': | 748 if os.name != 'nt': |
657 return | 749 return |
658 if isinstance(self.compiler, HackedMingw32CCompiler): | 750 if isinstance(self.compiler, HackedMingw32CCompiler): |
659 self.compiler.compiler_so = self.compiler.compiler # no -mdll | 751 self.compiler.compiler_so = self.compiler.compiler # no -mdll |
660 self.compiler.dll_libraries = [] # no -lmsrvc90 | 752 self.compiler.dll_libraries = [] # no -lmsrvc90 |
661 | 753 |
662 # Different Python installs can have different Python library | 754 # Different Python installs can have different Python library |
663 # names. e.g. the official CPython distribution uses pythonXY.dll | 755 # names. e.g. the official CPython distribution uses pythonXY.dll |
664 # and MinGW uses libpythonX.Y.dll. | 756 # and MinGW uses libpythonX.Y.dll. |
665 _kernel32 = ctypes.windll.kernel32 | 757 _kernel32 = ctypes.windll.kernel32 |
666 _kernel32.GetModuleFileNameA.argtypes = [ctypes.c_void_p, | 758 _kernel32.GetModuleFileNameA.argtypes = [ |
667 ctypes.c_void_p, | 759 ctypes.c_void_p, |
668 ctypes.c_ulong] | 760 ctypes.c_void_p, |
761 ctypes.c_ulong, | |
762 ] | |
669 _kernel32.GetModuleFileNameA.restype = ctypes.c_ulong | 763 _kernel32.GetModuleFileNameA.restype = ctypes.c_ulong |
670 size = 1000 | 764 size = 1000 |
671 buf = ctypes.create_string_buffer(size + 1) | 765 buf = ctypes.create_string_buffer(size + 1) |
672 filelen = _kernel32.GetModuleFileNameA(sys.dllhandle, ctypes.byref(buf), | 766 filelen = _kernel32.GetModuleFileNameA( |
673 size) | 767 sys.dllhandle, ctypes.byref(buf), size |
768 ) | |
674 | 769 |
675 if filelen > 0 and filelen != size: | 770 if filelen > 0 and filelen != size: |
676 dllbasename = os.path.basename(buf.value) | 771 dllbasename = os.path.basename(buf.value) |
677 if not dllbasename.lower().endswith(b'.dll'): | 772 if not dllbasename.lower().endswith(b'.dll'): |
678 raise SystemExit('Python DLL does not end with .dll: %s' % | 773 raise SystemExit( |
679 dllbasename) | 774 'Python DLL does not end with .dll: %s' % dllbasename |
775 ) | |
680 pythonlib = dllbasename[:-4] | 776 pythonlib = dllbasename[:-4] |
681 else: | 777 else: |
682 log.warn('could not determine Python DLL filename; ' | 778 log.warn( |
683 'assuming pythonXY') | 779 'could not determine Python DLL filename; ' 'assuming pythonXY' |
780 ) | |
684 | 781 |
685 hv = sys.hexversion | 782 hv = sys.hexversion |
686 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff) | 783 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xFF) |
687 | 784 |
688 log.info('using %s as Python library name' % pythonlib) | 785 log.info('using %s as Python library name' % pythonlib) |
689 with open('mercurial/hgpythonlib.h', 'wb') as f: | 786 with open('mercurial/hgpythonlib.h', 'wb') as f: |
690 f.write(b'/* this file is autogenerated by setup.py */\n') | 787 f.write(b'/* this file is autogenerated by setup.py */\n') |
691 f.write(b'#define HGPYTHONLIB "%s"\n' % pythonlib) | 788 f.write(b'#define HGPYTHONLIB "%s"\n' % pythonlib) |
692 | 789 |
693 macros = None | 790 macros = None |
694 if sys.version_info[0] >= 3: | 791 if sys.version_info[0] >= 3: |
695 macros = [('_UNICODE', None), ('UNICODE', None)] | 792 macros = [('_UNICODE', None), ('UNICODE', None)] |
696 | 793 |
697 objects = self.compiler.compile(['mercurial/exewrapper.c'], | 794 objects = self.compiler.compile( |
698 output_dir=self.build_temp, | 795 ['mercurial/exewrapper.c'], |
699 macros=macros) | 796 output_dir=self.build_temp, |
797 macros=macros, | |
798 ) | |
700 dir = os.path.dirname(self.get_ext_fullpath('dummy')) | 799 dir = os.path.dirname(self.get_ext_fullpath('dummy')) |
701 self.hgtarget = os.path.join(dir, 'hg') | 800 self.hgtarget = os.path.join(dir, 'hg') |
702 self.compiler.link_executable(objects, self.hgtarget, | 801 self.compiler.link_executable( |
703 libraries=[], | 802 objects, self.hgtarget, libraries=[], output_dir=self.build_temp |
704 output_dir=self.build_temp) | 803 ) |
705 if self.long_paths_support: | 804 if self.long_paths_support: |
706 self.addlongpathsmanifest() | 805 self.addlongpathsmanifest() |
707 | 806 |
708 def addlongpathsmanifest(self): | 807 def addlongpathsmanifest(self): |
709 r"""Add manifest pieces so that hg.exe understands long paths | 808 r"""Add manifest pieces so that hg.exe understands long paths |
731 inputresource = '-inputresource:%s;#1' % exefname | 830 inputresource = '-inputresource:%s;#1' % exefname |
732 outputresource = '-outputresource:%s;#1' % exefname | 831 outputresource = '-outputresource:%s;#1' % exefname |
733 log.info("running mt.exe to update hg.exe's manifest in-place") | 832 log.info("running mt.exe to update hg.exe's manifest in-place") |
734 # supplying both -manifest and -inputresource to mt.exe makes | 833 # supplying both -manifest and -inputresource to mt.exe makes |
735 # it merge the embedded and supplied manifests in the -outputresource | 834 # it merge the embedded and supplied manifests in the -outputresource |
736 self.spawn(['mt.exe', '-nologo', '-manifest', manfname, | 835 self.spawn( |
737 inputresource, outputresource]) | 836 [ |
837 'mt.exe', | |
838 '-nologo', | |
839 '-manifest', | |
840 manfname, | |
841 inputresource, | |
842 outputresource, | |
843 ] | |
844 ) | |
738 log.info("done updating hg.exe's manifest") | 845 log.info("done updating hg.exe's manifest") |
739 os.remove(manfname) | 846 os.remove(manfname) |
740 | 847 |
741 @property | 848 @property |
742 def hgexepath(self): | 849 def hgexepath(self): |
743 dir = os.path.dirname(self.get_ext_fullpath('dummy')) | 850 dir = os.path.dirname(self.get_ext_fullpath('dummy')) |
744 return os.path.join(self.build_temp, dir, 'hg.exe') | 851 return os.path.join(self.build_temp, dir, 'hg.exe') |
852 | |
745 | 853 |
746 class hgbuilddoc(Command): | 854 class hgbuilddoc(Command): |
747 description = 'build documentation' | 855 description = 'build documentation' |
748 user_options = [ | 856 user_options = [ |
749 ('man', None, 'generate man pages'), | 857 ('man', None, 'generate man pages'), |
780 | 888 |
781 def gentxt(root): | 889 def gentxt(root): |
782 txt = 'doc/%s.txt' % root | 890 txt = 'doc/%s.txt' % root |
783 log.info('generating %s' % txt) | 891 log.info('generating %s' % txt) |
784 res, out, err = runcmd( | 892 res, out, err = runcmd( |
785 [sys.executable, 'gendoc.py', root], | 893 [sys.executable, 'gendoc.py', root], os.environ, cwd='doc' |
786 os.environ, | 894 ) |
787 cwd='doc') | |
788 if res: | 895 if res: |
789 raise SystemExit('error running gendoc.py: %s' % | 896 raise SystemExit( |
790 '\n'.join([out, err])) | 897 'error running gendoc.py: %s' % '\n'.join([out, err]) |
898 ) | |
791 | 899 |
792 with open(txt, 'wb') as fh: | 900 with open(txt, 'wb') as fh: |
793 fh.write(out) | 901 fh.write(out) |
794 | 902 |
795 def gengendoc(root): | 903 def gengendoc(root): |
797 | 905 |
798 log.info('generating %s' % gendoc) | 906 log.info('generating %s' % gendoc) |
799 res, out, err = runcmd( | 907 res, out, err = runcmd( |
800 [sys.executable, 'gendoc.py', '%s.gendoc' % root], | 908 [sys.executable, 'gendoc.py', '%s.gendoc' % root], |
801 os.environ, | 909 os.environ, |
802 cwd='doc') | 910 cwd='doc', |
911 ) | |
803 if res: | 912 if res: |
804 raise SystemExit('error running gendoc: %s' % | 913 raise SystemExit( |
805 '\n'.join([out, err])) | 914 'error running gendoc: %s' % '\n'.join([out, err]) |
915 ) | |
806 | 916 |
807 with open(gendoc, 'wb') as fh: | 917 with open(gendoc, 'wb') as fh: |
808 fh.write(out) | 918 fh.write(out) |
809 | 919 |
810 def genman(root): | 920 def genman(root): |
811 log.info('generating doc/%s' % root) | 921 log.info('generating doc/%s' % root) |
812 res, out, err = runcmd( | 922 res, out, err = runcmd( |
813 [sys.executable, 'runrst', 'hgmanpage', '--halt', 'warning', | 923 [ |
814 '--strip-elements-with-class', 'htmlonly', | 924 sys.executable, |
815 '%s.txt' % root, root], | 925 'runrst', |
926 'hgmanpage', | |
927 '--halt', | |
928 'warning', | |
929 '--strip-elements-with-class', | |
930 'htmlonly', | |
931 '%s.txt' % root, | |
932 root, | |
933 ], | |
816 os.environ, | 934 os.environ, |
817 cwd='doc') | 935 cwd='doc', |
936 ) | |
818 if res: | 937 if res: |
819 raise SystemExit('error running runrst: %s' % | 938 raise SystemExit( |
820 '\n'.join([out, err])) | 939 'error running runrst: %s' % '\n'.join([out, err]) |
940 ) | |
821 | 941 |
822 normalizecrlf('doc/%s' % root) | 942 normalizecrlf('doc/%s' % root) |
823 | 943 |
824 def genhtml(root): | 944 def genhtml(root): |
825 log.info('generating doc/%s.html' % root) | 945 log.info('generating doc/%s.html' % root) |
826 res, out, err = runcmd( | 946 res, out, err = runcmd( |
827 [sys.executable, 'runrst', 'html', '--halt', 'warning', | 947 [ |
828 '--link-stylesheet', '--stylesheet-path', 'style.css', | 948 sys.executable, |
829 '%s.txt' % root, '%s.html' % root], | 949 'runrst', |
950 'html', | |
951 '--halt', | |
952 'warning', | |
953 '--link-stylesheet', | |
954 '--stylesheet-path', | |
955 'style.css', | |
956 '%s.txt' % root, | |
957 '%s.html' % root, | |
958 ], | |
830 os.environ, | 959 os.environ, |
831 cwd='doc') | 960 cwd='doc', |
961 ) | |
832 if res: | 962 if res: |
833 raise SystemExit('error running runrst: %s' % | 963 raise SystemExit( |
834 '\n'.join([out, err])) | 964 'error running runrst: %s' % '\n'.join([out, err]) |
965 ) | |
835 | 966 |
836 normalizecrlf('doc/%s.html' % root) | 967 normalizecrlf('doc/%s.html' % root) |
837 | 968 |
838 # This logic is duplicated in doc/Makefile. | 969 # This logic is duplicated in doc/Makefile. |
839 sources = set(f for f in os.listdir('mercurial/help') | 970 sources = set( |
840 if re.search(r'[0-9]\.txt$', f)) | 971 f |
972 for f in os.listdir('mercurial/help') | |
973 if re.search(r'[0-9]\.txt$', f) | |
974 ) | |
841 | 975 |
842 # common.txt is a one-off. | 976 # common.txt is a one-off. |
843 gentxt('common') | 977 gentxt('common') |
844 | 978 |
845 for source in sorted(sources): | 979 for source in sorted(sources): |
852 if self.man: | 986 if self.man: |
853 genman(root) | 987 genman(root) |
854 if self.html: | 988 if self.html: |
855 genhtml(root) | 989 genhtml(root) |
856 | 990 |
991 | |
857 class hginstall(install): | 992 class hginstall(install): |
858 | 993 |
859 user_options = install.user_options + [ | 994 user_options = install.user_options + [ |
860 ('old-and-unmanageable', None, | 995 ( |
861 'noop, present for eggless setuptools compat'), | 996 'old-and-unmanageable', |
862 ('single-version-externally-managed', None, | 997 None, |
863 'noop, present for eggless setuptools compat'), | 998 'noop, present for eggless setuptools compat', |
999 ), | |
1000 ( | |
1001 'single-version-externally-managed', | |
1002 None, | |
1003 'noop, present for eggless setuptools compat', | |
1004 ), | |
864 ] | 1005 ] |
865 | 1006 |
866 # Also helps setuptools not be sad while we refuse to create eggs. | 1007 # Also helps setuptools not be sad while we refuse to create eggs. |
867 single_version_externally_managed = True | 1008 single_version_externally_managed = True |
868 | 1009 |
870 # Screen out egg related commands to prevent egg generation. But allow | 1011 # Screen out egg related commands to prevent egg generation. But allow |
871 # mercurial.egg-info generation, since that is part of modern | 1012 # mercurial.egg-info generation, since that is part of modern |
872 # packaging. | 1013 # packaging. |
873 excl = set(['bdist_egg']) | 1014 excl = set(['bdist_egg']) |
874 return filter(lambda x: x not in excl, install.get_sub_commands(self)) | 1015 return filter(lambda x: x not in excl, install.get_sub_commands(self)) |
1016 | |
875 | 1017 |
876 class hginstalllib(install_lib): | 1018 class hginstalllib(install_lib): |
877 ''' | 1019 ''' |
878 This is a specialization of install_lib that replaces the copy_file used | 1020 This is a specialization of install_lib that replaces the copy_file used |
879 there so that it supports setting the mode of files after copying them, | 1021 there so that it supports setting the mode of files after copying them, |
885 insufficient, as it might still be applying a umask. | 1027 insufficient, as it might still be applying a umask. |
886 ''' | 1028 ''' |
887 | 1029 |
888 def run(self): | 1030 def run(self): |
889 realcopyfile = file_util.copy_file | 1031 realcopyfile = file_util.copy_file |
1032 | |
890 def copyfileandsetmode(*args, **kwargs): | 1033 def copyfileandsetmode(*args, **kwargs): |
891 src, dst = args[0], args[1] | 1034 src, dst = args[0], args[1] |
892 dst, copied = realcopyfile(*args, **kwargs) | 1035 dst, copied = realcopyfile(*args, **kwargs) |
893 if copied: | 1036 if copied: |
894 st = os.stat(src) | 1037 st = os.stat(src) |
899 else: | 1042 else: |
900 setmode = int('0644', 8) | 1043 setmode = int('0644', 8) |
901 m = stat.S_IMODE(st[stat.ST_MODE]) | 1044 m = stat.S_IMODE(st[stat.ST_MODE]) |
902 m = (m & ~int('0777', 8)) | setmode | 1045 m = (m & ~int('0777', 8)) | setmode |
903 os.chmod(dst, m) | 1046 os.chmod(dst, m) |
1047 | |
904 file_util.copy_file = copyfileandsetmode | 1048 file_util.copy_file = copyfileandsetmode |
905 try: | 1049 try: |
906 install_lib.run(self) | 1050 install_lib.run(self) |
907 finally: | 1051 finally: |
908 file_util.copy_file = realcopyfile | 1052 file_util.copy_file = realcopyfile |
1053 | |
909 | 1054 |
910 class hginstallscripts(install_scripts): | 1055 class hginstallscripts(install_scripts): |
911 ''' | 1056 ''' |
912 This is a specialization of install_scripts that replaces the @LIBDIR@ with | 1057 This is a specialization of install_scripts that replaces the @LIBDIR@ with |
913 the configured directory for modules. If possible, the path is made relative | 1058 the configured directory for modules. If possible, the path is made relative |
919 | 1064 |
920 self.install_lib = None | 1065 self.install_lib = None |
921 | 1066 |
922 def finalize_options(self): | 1067 def finalize_options(self): |
923 install_scripts.finalize_options(self) | 1068 install_scripts.finalize_options(self) |
924 self.set_undefined_options('install', | 1069 self.set_undefined_options('install', ('install_lib', 'install_lib')) |
925 ('install_lib', 'install_lib')) | |
926 | 1070 |
927 def run(self): | 1071 def run(self): |
928 install_scripts.run(self) | 1072 install_scripts.run(self) |
929 | 1073 |
930 # It only makes sense to replace @LIBDIR@ with the install path if | 1074 # It only makes sense to replace @LIBDIR@ with the install path if |
944 # will be. And, wheels don't appear to provide the ability to register | 1088 # will be. And, wheels don't appear to provide the ability to register |
945 # custom code to run during wheel installation. This all means that | 1089 # custom code to run during wheel installation. This all means that |
946 # we can't reliably set the libdir in wheels: the default behavior | 1090 # we can't reliably set the libdir in wheels: the default behavior |
947 # of looking in sys.path must do. | 1091 # of looking in sys.path must do. |
948 | 1092 |
949 if (os.path.splitdrive(self.install_dir)[0] != | 1093 if ( |
950 os.path.splitdrive(self.install_lib)[0]): | 1094 os.path.splitdrive(self.install_dir)[0] |
1095 != os.path.splitdrive(self.install_lib)[0] | |
1096 ): | |
951 # can't make relative paths from one drive to another, so use an | 1097 # can't make relative paths from one drive to another, so use an |
952 # absolute path instead | 1098 # absolute path instead |
953 libdir = self.install_lib | 1099 libdir = self.install_lib |
954 else: | 1100 else: |
955 common = os.path.commonprefix((self.install_dir, self.install_lib)) | 1101 common = os.path.commonprefix((self.install_dir, self.install_lib)) |
956 rest = self.install_dir[len(common):] | 1102 rest = self.install_dir[len(common) :] |
957 uplevel = len([n for n in os.path.split(rest) if n]) | 1103 uplevel = len([n for n in os.path.split(rest) if n]) |
958 | 1104 |
959 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):] | 1105 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common) :] |
960 | 1106 |
961 for outfile in self.outfiles: | 1107 for outfile in self.outfiles: |
962 with open(outfile, 'rb') as fp: | 1108 with open(outfile, 'rb') as fp: |
963 data = fp.read() | 1109 data = fp.read() |
964 | 1110 |
968 | 1114 |
969 # During local installs, the shebang will be rewritten to the final | 1115 # During local installs, the shebang will be rewritten to the final |
970 # install path. During wheel packaging, the shebang has a special | 1116 # install path. During wheel packaging, the shebang has a special |
971 # value. | 1117 # value. |
972 if data.startswith(b'#!python'): | 1118 if data.startswith(b'#!python'): |
973 log.info('not rewriting @LIBDIR@ in %s because install path ' | 1119 log.info( |
974 'not known' % outfile) | 1120 'not rewriting @LIBDIR@ in %s because install path ' |
1121 'not known' % outfile | |
1122 ) | |
975 continue | 1123 continue |
976 | 1124 |
977 data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape)) | 1125 data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape)) |
978 with open(outfile, 'wb') as fp: | 1126 with open(outfile, 'wb') as fp: |
979 fp.write(data) | 1127 fp.write(data) |
1128 | |
980 | 1129 |
981 # virtualenv installs custom distutils/__init__.py and | 1130 # virtualenv installs custom distutils/__init__.py and |
982 # distutils/distutils.cfg files which essentially proxy back to the | 1131 # distutils/distutils.cfg files which essentially proxy back to the |
983 # "real" distutils in the main Python install. The presence of this | 1132 # "real" distutils in the main Python install. The presence of this |
984 # directory causes py2exe to pick up the "hacked" distutils package | 1133 # directory causes py2exe to pick up the "hacked" distutils package |
1018 modules[k] = v | 1167 modules[k] = v |
1019 | 1168 |
1020 res.modules = modules | 1169 res.modules = modules |
1021 | 1170 |
1022 import opcode | 1171 import opcode |
1023 distutilsreal = os.path.join(os.path.dirname(opcode.__file__), | 1172 |
1024 'distutils') | 1173 distutilsreal = os.path.join( |
1174 os.path.dirname(opcode.__file__), 'distutils' | |
1175 ) | |
1025 | 1176 |
1026 for root, dirs, files in os.walk(distutilsreal): | 1177 for root, dirs, files in os.walk(distutilsreal): |
1027 for f in sorted(files): | 1178 for f in sorted(files): |
1028 if not f.endswith('.py'): | 1179 if not f.endswith('.py'): |
1029 continue | 1180 continue |
1040 | 1191 |
1041 if modname.startswith('distutils.tests.'): | 1192 if modname.startswith('distutils.tests.'): |
1042 continue | 1193 continue |
1043 | 1194 |
1044 if modname.endswith('.__init__'): | 1195 if modname.endswith('.__init__'): |
1045 modname = modname[:-len('.__init__')] | 1196 modname = modname[: -len('.__init__')] |
1046 path = os.path.dirname(full) | 1197 path = os.path.dirname(full) |
1047 else: | 1198 else: |
1048 path = None | 1199 path = None |
1049 | 1200 |
1050 res.modules[modname] = py2exemodule(modname, full, | 1201 res.modules[modname] = py2exemodule( |
1051 path=path) | 1202 modname, full, path=path |
1203 ) | |
1052 | 1204 |
1053 if 'distutils' not in res.modules: | 1205 if 'distutils' not in res.modules: |
1054 raise SystemExit('could not find distutils modules') | 1206 raise SystemExit('could not find distutils modules') |
1055 | 1207 |
1056 return res | 1208 return res |
1057 | 1209 |
1058 cmdclass = {'build': hgbuild, | 1210 |
1059 'build_doc': hgbuilddoc, | 1211 cmdclass = { |
1060 'build_mo': hgbuildmo, | 1212 'build': hgbuild, |
1061 'build_ext': hgbuildext, | 1213 'build_doc': hgbuilddoc, |
1062 'build_py': hgbuildpy, | 1214 'build_mo': hgbuildmo, |
1063 'build_scripts': hgbuildscripts, | 1215 'build_ext': hgbuildext, |
1064 'build_hgextindex': buildhgextindex, | 1216 'build_py': hgbuildpy, |
1065 'install': hginstall, | 1217 'build_scripts': hgbuildscripts, |
1066 'install_lib': hginstalllib, | 1218 'build_hgextindex': buildhgextindex, |
1067 'install_scripts': hginstallscripts, | 1219 'install': hginstall, |
1068 'build_hgexe': buildhgexe, | 1220 'install_lib': hginstalllib, |
1069 } | 1221 'install_scripts': hginstallscripts, |
1222 'build_hgexe': buildhgexe, | |
1223 } | |
1070 | 1224 |
1071 if py2exehacked: | 1225 if py2exehacked: |
1072 cmdclass['py2exe'] = hgbuildpy2exe | 1226 cmdclass['py2exe'] = hgbuildpy2exe |
1073 | 1227 |
1074 packages = ['mercurial', | 1228 packages = [ |
1075 'mercurial.cext', | 1229 'mercurial', |
1076 'mercurial.cffi', | 1230 'mercurial.cext', |
1077 'mercurial.hgweb', | 1231 'mercurial.cffi', |
1078 'mercurial.interfaces', | 1232 'mercurial.hgweb', |
1079 'mercurial.pure', | 1233 'mercurial.interfaces', |
1080 'mercurial.thirdparty', | 1234 'mercurial.pure', |
1081 'mercurial.thirdparty.attr', | 1235 'mercurial.thirdparty', |
1082 'mercurial.thirdparty.zope', | 1236 'mercurial.thirdparty.attr', |
1083 'mercurial.thirdparty.zope.interface', | 1237 'mercurial.thirdparty.zope', |
1084 'mercurial.utils', | 1238 'mercurial.thirdparty.zope.interface', |
1085 'mercurial.revlogutils', | 1239 'mercurial.utils', |
1086 'mercurial.testing', | 1240 'mercurial.revlogutils', |
1087 'hgext', 'hgext.convert', 'hgext.fsmonitor', | 1241 'mercurial.testing', |
1088 'hgext.fastannotate', | 1242 'hgext', |
1089 'hgext.fsmonitor.pywatchman', | 1243 'hgext.convert', |
1090 'hgext.highlight', | 1244 'hgext.fsmonitor', |
1091 'hgext.infinitepush', | 1245 'hgext.fastannotate', |
1092 'hgext.largefiles', 'hgext.lfs', 'hgext.narrow', | 1246 'hgext.fsmonitor.pywatchman', |
1093 'hgext.remotefilelog', | 1247 'hgext.highlight', |
1094 'hgext.zeroconf', 'hgext3rd', | 1248 'hgext.infinitepush', |
1095 'hgdemandimport'] | 1249 'hgext.largefiles', |
1250 'hgext.lfs', | |
1251 'hgext.narrow', | |
1252 'hgext.remotefilelog', | |
1253 'hgext.zeroconf', | |
1254 'hgext3rd', | |
1255 'hgdemandimport', | |
1256 ] | |
1096 if sys.version_info[0] == 2: | 1257 if sys.version_info[0] == 2: |
1097 packages.extend(['mercurial.thirdparty.concurrent', | 1258 packages.extend( |
1098 'mercurial.thirdparty.concurrent.futures']) | 1259 [ |
1260 'mercurial.thirdparty.concurrent', | |
1261 'mercurial.thirdparty.concurrent.futures', | |
1262 ] | |
1263 ) | |
1099 | 1264 |
1100 if 'HG_PY2EXE_EXTRA_INSTALL_PACKAGES' in os.environ: | 1265 if 'HG_PY2EXE_EXTRA_INSTALL_PACKAGES' in os.environ: |
1101 # py2exe can't cope with namespace packages very well, so we have to | 1266 # py2exe can't cope with namespace packages very well, so we have to |
1102 # install any hgext3rd.* extensions that we want in the final py2exe | 1267 # install any hgext3rd.* extensions that we want in the final py2exe |
1103 # image here. This is gross, but you gotta do what you gotta do. | 1268 # image here. This is gross, but you gotta do what you gotta do. |
1104 packages.extend(os.environ['HG_PY2EXE_EXTRA_INSTALL_PACKAGES'].split(' ')) | 1269 packages.extend(os.environ['HG_PY2EXE_EXTRA_INSTALL_PACKAGES'].split(' ')) |
1105 | 1270 |
1106 common_depends = ['mercurial/bitmanipulation.h', | 1271 common_depends = [ |
1107 'mercurial/compat.h', | 1272 'mercurial/bitmanipulation.h', |
1108 'mercurial/cext/util.h'] | 1273 'mercurial/compat.h', |
1274 'mercurial/cext/util.h', | |
1275 ] | |
1109 common_include_dirs = ['mercurial'] | 1276 common_include_dirs = ['mercurial'] |
1110 | 1277 |
1111 osutil_cflags = [] | 1278 osutil_cflags = [] |
1112 osutil_ldflags = [] | 1279 osutil_ldflags = [] |
1113 | 1280 |
1115 for plat, func in [('bsd', 'setproctitle')]: | 1282 for plat, func in [('bsd', 'setproctitle')]: |
1116 if re.search(plat, sys.platform) and hasfunction(new_compiler(), func): | 1283 if re.search(plat, sys.platform) and hasfunction(new_compiler(), func): |
1117 osutil_cflags.append('-DHAVE_%s' % func.upper()) | 1284 osutil_cflags.append('-DHAVE_%s' % func.upper()) |
1118 | 1285 |
1119 for plat, macro, code in [ | 1286 for plat, macro, code in [ |
1120 ('bsd|darwin', 'BSD_STATFS', ''' | 1287 ( |
1288 'bsd|darwin', | |
1289 'BSD_STATFS', | |
1290 ''' | |
1121 #include <sys/param.h> | 1291 #include <sys/param.h> |
1122 #include <sys/mount.h> | 1292 #include <sys/mount.h> |
1123 int main() { struct statfs s; return sizeof(s.f_fstypename); } | 1293 int main() { struct statfs s; return sizeof(s.f_fstypename); } |
1124 '''), | 1294 ''', |
1125 ('linux', 'LINUX_STATFS', ''' | 1295 ), |
1296 ( | |
1297 'linux', | |
1298 'LINUX_STATFS', | |
1299 ''' | |
1126 #include <linux/magic.h> | 1300 #include <linux/magic.h> |
1127 #include <sys/vfs.h> | 1301 #include <sys/vfs.h> |
1128 int main() { struct statfs s; return sizeof(s.f_type); } | 1302 int main() { struct statfs s; return sizeof(s.f_type); } |
1129 '''), | 1303 ''', |
1304 ), | |
1130 ]: | 1305 ]: |
1131 if re.search(plat, sys.platform) and cancompile(new_compiler(), code): | 1306 if re.search(plat, sys.platform) and cancompile(new_compiler(), code): |
1132 osutil_cflags.append('-DHAVE_%s' % macro) | 1307 osutil_cflags.append('-DHAVE_%s' % macro) |
1133 | 1308 |
1134 if sys.platform == 'darwin': | 1309 if sys.platform == 'darwin': |
1148 'mercurial/thirdparty/xdiff/xprepare.h', | 1323 'mercurial/thirdparty/xdiff/xprepare.h', |
1149 'mercurial/thirdparty/xdiff/xtypes.h', | 1324 'mercurial/thirdparty/xdiff/xtypes.h', |
1150 'mercurial/thirdparty/xdiff/xutils.h', | 1325 'mercurial/thirdparty/xdiff/xutils.h', |
1151 ] | 1326 ] |
1152 | 1327 |
1328 | |
1153 class RustCompilationError(CCompilerError): | 1329 class RustCompilationError(CCompilerError): |
1154 """Exception class for Rust compilation errors.""" | 1330 """Exception class for Rust compilation errors.""" |
1331 | |
1155 | 1332 |
1156 class RustExtension(Extension): | 1333 class RustExtension(Extension): |
1157 """Base classes for concrete Rust Extension classes. | 1334 """Base classes for concrete Rust Extension classes. |
1158 """ | 1335 """ |
1159 | 1336 |
1160 rusttargetdir = os.path.join('rust', 'target', 'release') | 1337 rusttargetdir = os.path.join('rust', 'target', 'release') |
1161 | 1338 |
1162 def __init__(self, mpath, sources, rustlibname, subcrate, | 1339 def __init__( |
1163 py3_features=None, **kw): | 1340 self, mpath, sources, rustlibname, subcrate, py3_features=None, **kw |
1341 ): | |
1164 Extension.__init__(self, mpath, sources, **kw) | 1342 Extension.__init__(self, mpath, sources, **kw) |
1165 srcdir = self.rustsrcdir = os.path.join('rust', subcrate) | 1343 srcdir = self.rustsrcdir = os.path.join('rust', subcrate) |
1166 self.py3_features = py3_features | 1344 self.py3_features = py3_features |
1167 | 1345 |
1168 # adding Rust source and control files to depends so that the extension | 1346 # adding Rust source and control files to depends so that the extension |
1170 self.depends.append(os.path.join(srcdir, 'Cargo.toml')) | 1348 self.depends.append(os.path.join(srcdir, 'Cargo.toml')) |
1171 cargo_lock = os.path.join(srcdir, 'Cargo.lock') | 1349 cargo_lock = os.path.join(srcdir, 'Cargo.lock') |
1172 if os.path.exists(cargo_lock): | 1350 if os.path.exists(cargo_lock): |
1173 self.depends.append(cargo_lock) | 1351 self.depends.append(cargo_lock) |
1174 for dirpath, subdir, fnames in os.walk(os.path.join(srcdir, 'src')): | 1352 for dirpath, subdir, fnames in os.walk(os.path.join(srcdir, 'src')): |
1175 self.depends.extend(os.path.join(dirpath, fname) | 1353 self.depends.extend( |
1176 for fname in fnames | 1354 os.path.join(dirpath, fname) |
1177 if os.path.splitext(fname)[1] == '.rs') | 1355 for fname in fnames |
1356 if os.path.splitext(fname)[1] == '.rs' | |
1357 ) | |
1178 | 1358 |
1179 @staticmethod | 1359 @staticmethod |
1180 def rustdylibsuffix(): | 1360 def rustdylibsuffix(): |
1181 """Return the suffix for shared libraries produced by rustc. | 1361 """Return the suffix for shared libraries produced by rustc. |
1182 | 1362 |
1200 # invoke this build. | 1380 # invoke this build. |
1201 | 1381 |
1202 # Unix only fix (os.path.expanduser not really reliable if | 1382 # Unix only fix (os.path.expanduser not really reliable if |
1203 # HOME is shadowed like this) | 1383 # HOME is shadowed like this) |
1204 import pwd | 1384 import pwd |
1385 | |
1205 env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir | 1386 env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir |
1206 | 1387 |
1207 cargocmd = ['cargo', 'rustc', '-vv', '--release'] | 1388 cargocmd = ['cargo', 'rustc', '-vv', '--release'] |
1208 if sys.version_info[0] == 3 and self.py3_features is not None: | 1389 if sys.version_info[0] == 3 and self.py3_features is not None: |
1209 cargocmd.extend(('--features', self.py3_features, | 1390 cargocmd.extend( |
1210 '--no-default-features')) | 1391 ('--features', self.py3_features, '--no-default-features') |
1392 ) | |
1211 cargocmd.append('--') | 1393 cargocmd.append('--') |
1212 if sys.platform == 'darwin': | 1394 if sys.platform == 'darwin': |
1213 cargocmd.extend(("-C", "link-arg=-undefined", | 1395 cargocmd.extend( |
1214 "-C", "link-arg=dynamic_lookup")) | 1396 ("-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup") |
1397 ) | |
1215 try: | 1398 try: |
1216 subprocess.check_call(cargocmd, env=env, cwd=self.rustsrcdir) | 1399 subprocess.check_call(cargocmd, env=env, cwd=self.rustsrcdir) |
1217 except OSError as exc: | 1400 except OSError as exc: |
1218 if exc.errno == errno.ENOENT: | 1401 if exc.errno == errno.ENOENT: |
1219 raise RustCompilationError("Cargo not found") | 1402 raise RustCompilationError("Cargo not found") |
1220 elif exc.errno == errno.EACCES: | 1403 elif exc.errno == errno.EACCES: |
1221 raise RustCompilationError( | 1404 raise RustCompilationError( |
1222 "Cargo found, but permisssion to execute it is denied") | 1405 "Cargo found, but permisssion to execute it is denied" |
1406 ) | |
1223 else: | 1407 else: |
1224 raise | 1408 raise |
1225 except subprocess.CalledProcessError: | 1409 except subprocess.CalledProcessError: |
1226 raise RustCompilationError( | 1410 raise RustCompilationError( |
1227 "Cargo failed. Working directory: %r, " | 1411 "Cargo failed. Working directory: %r, " |
1228 "command: %r, environment: %r" | 1412 "command: %r, environment: %r" |
1229 % (self.rustsrcdir, cargocmd, env)) | 1413 % (self.rustsrcdir, cargocmd, env) |
1414 ) | |
1415 | |
1230 | 1416 |
1231 class RustEnhancedExtension(RustExtension): | 1417 class RustEnhancedExtension(RustExtension): |
1232 """A C Extension, conditionally enhanced with Rust code. | 1418 """A C Extension, conditionally enhanced with Rust code. |
1233 | 1419 |
1234 If the HGRUSTEXT environment variable is set to something else | 1420 If the HGRUSTEXT environment variable is set to something else |
1235 than 'cpython', the Rust sources get compiled and linked within the | 1421 than 'cpython', the Rust sources get compiled and linked within the |
1236 C target shared library object. | 1422 C target shared library object. |
1237 """ | 1423 """ |
1238 | 1424 |
1239 def __init__(self, mpath, sources, rustlibname, subcrate, **kw): | 1425 def __init__(self, mpath, sources, rustlibname, subcrate, **kw): |
1240 RustExtension.__init__(self, mpath, sources, rustlibname, subcrate, | 1426 RustExtension.__init__( |
1241 **kw) | 1427 self, mpath, sources, rustlibname, subcrate, **kw |
1428 ) | |
1242 if hgrustext != 'direct-ffi': | 1429 if hgrustext != 'direct-ffi': |
1243 return | 1430 return |
1244 self.extra_compile_args.append('-DWITH_RUST') | 1431 self.extra_compile_args.append('-DWITH_RUST') |
1245 self.libraries.append(rustlibname) | 1432 self.libraries.append(rustlibname) |
1246 self.library_dirs.append(self.rusttargetdir) | 1433 self.library_dirs.append(self.rusttargetdir) |
1247 | 1434 |
1248 def rustbuild(self): | 1435 def rustbuild(self): |
1249 if hgrustext == 'direct-ffi': | 1436 if hgrustext == 'direct-ffi': |
1250 RustExtension.rustbuild(self) | 1437 RustExtension.rustbuild(self) |
1251 | 1438 |
1439 | |
1252 class RustStandaloneExtension(RustExtension): | 1440 class RustStandaloneExtension(RustExtension): |
1253 | |
1254 def __init__(self, pydottedname, rustcrate, dylibname, **kw): | 1441 def __init__(self, pydottedname, rustcrate, dylibname, **kw): |
1255 RustExtension.__init__(self, pydottedname, [], dylibname, rustcrate, | 1442 RustExtension.__init__( |
1256 **kw) | 1443 self, pydottedname, [], dylibname, rustcrate, **kw |
1444 ) | |
1257 self.dylibname = dylibname | 1445 self.dylibname = dylibname |
1258 | 1446 |
1259 def build(self, target_dir): | 1447 def build(self, target_dir): |
1260 self.rustbuild() | 1448 self.rustbuild() |
1261 target = [target_dir] | 1449 target = [target_dir] |
1262 target.extend(self.name.split('.')) | 1450 target.extend(self.name.split('.')) |
1263 target[-1] += DYLIB_SUFFIX | 1451 target[-1] += DYLIB_SUFFIX |
1264 shutil.copy2(os.path.join(self.rusttargetdir, | 1452 shutil.copy2( |
1265 self.dylibname + self.rustdylibsuffix()), | 1453 os.path.join( |
1266 os.path.join(*target)) | 1454 self.rusttargetdir, self.dylibname + self.rustdylibsuffix() |
1455 ), | |
1456 os.path.join(*target), | |
1457 ) | |
1267 | 1458 |
1268 | 1459 |
1269 extmodules = [ | 1460 extmodules = [ |
1270 Extension('mercurial.cext.base85', ['mercurial/cext/base85.c'], | 1461 Extension( |
1271 include_dirs=common_include_dirs, | 1462 'mercurial.cext.base85', |
1272 depends=common_depends), | 1463 ['mercurial/cext/base85.c'], |
1273 Extension('mercurial.cext.bdiff', ['mercurial/bdiff.c', | 1464 include_dirs=common_include_dirs, |
1274 'mercurial/cext/bdiff.c'] + xdiff_srcs, | 1465 depends=common_depends, |
1275 include_dirs=common_include_dirs, | 1466 ), |
1276 depends=common_depends + ['mercurial/bdiff.h'] + xdiff_headers), | 1467 Extension( |
1277 Extension('mercurial.cext.mpatch', ['mercurial/mpatch.c', | 1468 'mercurial.cext.bdiff', |
1278 'mercurial/cext/mpatch.c'], | 1469 ['mercurial/bdiff.c', 'mercurial/cext/bdiff.c'] + xdiff_srcs, |
1279 include_dirs=common_include_dirs, | 1470 include_dirs=common_include_dirs, |
1280 depends=common_depends), | 1471 depends=common_depends + ['mercurial/bdiff.h'] + xdiff_headers, |
1472 ), | |
1473 Extension( | |
1474 'mercurial.cext.mpatch', | |
1475 ['mercurial/mpatch.c', 'mercurial/cext/mpatch.c'], | |
1476 include_dirs=common_include_dirs, | |
1477 depends=common_depends, | |
1478 ), | |
1281 RustEnhancedExtension( | 1479 RustEnhancedExtension( |
1282 'mercurial.cext.parsers', ['mercurial/cext/charencode.c', | 1480 'mercurial.cext.parsers', |
1283 'mercurial/cext/dirs.c', | 1481 [ |
1284 'mercurial/cext/manifest.c', | 1482 'mercurial/cext/charencode.c', |
1285 'mercurial/cext/parsers.c', | 1483 'mercurial/cext/dirs.c', |
1286 'mercurial/cext/pathencode.c', | 1484 'mercurial/cext/manifest.c', |
1287 'mercurial/cext/revlog.c'], | 1485 'mercurial/cext/parsers.c', |
1486 'mercurial/cext/pathencode.c', | |
1487 'mercurial/cext/revlog.c', | |
1488 ], | |
1288 'hgdirectffi', | 1489 'hgdirectffi', |
1289 'hg-direct-ffi', | 1490 'hg-direct-ffi', |
1290 include_dirs=common_include_dirs, | 1491 include_dirs=common_include_dirs, |
1291 depends=common_depends + ['mercurial/cext/charencode.h', | 1492 depends=common_depends |
1292 'mercurial/cext/revlog.h', | 1493 + [ |
1293 'rust/hg-core/src/ancestors.rs', | 1494 'mercurial/cext/charencode.h', |
1294 'rust/hg-core/src/lib.rs']), | 1495 'mercurial/cext/revlog.h', |
1295 Extension('mercurial.cext.osutil', ['mercurial/cext/osutil.c'], | 1496 'rust/hg-core/src/ancestors.rs', |
1296 include_dirs=common_include_dirs, | 1497 'rust/hg-core/src/lib.rs', |
1297 extra_compile_args=osutil_cflags, | 1498 ], |
1298 extra_link_args=osutil_ldflags, | 1499 ), |
1299 depends=common_depends), | |
1300 Extension( | 1500 Extension( |
1301 'mercurial.thirdparty.zope.interface._zope_interface_coptimizations', [ | 1501 'mercurial.cext.osutil', |
1302 'mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c', | 1502 ['mercurial/cext/osutil.c'], |
1303 ]), | 1503 include_dirs=common_include_dirs, |
1304 Extension('hgext.fsmonitor.pywatchman.bser', | 1504 extra_compile_args=osutil_cflags, |
1305 ['hgext/fsmonitor/pywatchman/bser.c']), | 1505 extra_link_args=osutil_ldflags, |
1306 RustStandaloneExtension('mercurial.rustext', 'hg-cpython', 'librusthg', | 1506 depends=common_depends, |
1307 py3_features='python3'), | 1507 ), |
1308 ] | 1508 Extension( |
1509 'mercurial.thirdparty.zope.interface._zope_interface_coptimizations', | |
1510 [ | |
1511 'mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c', | |
1512 ], | |
1513 ), | |
1514 Extension( | |
1515 'hgext.fsmonitor.pywatchman.bser', ['hgext/fsmonitor/pywatchman/bser.c'] | |
1516 ), | |
1517 RustStandaloneExtension( | |
1518 'mercurial.rustext', 'hg-cpython', 'librusthg', py3_features='python3' | |
1519 ), | |
1520 ] | |
1309 | 1521 |
1310 | 1522 |
1311 sys.path.insert(0, 'contrib/python-zstandard') | 1523 sys.path.insert(0, 'contrib/python-zstandard') |
1312 import setup_zstd | 1524 import setup_zstd |
1313 extmodules.append(setup_zstd.get_c_extension( | 1525 |
1314 name='mercurial.zstd', | 1526 extmodules.append( |
1315 root=os.path.abspath(os.path.dirname(__file__)))) | 1527 setup_zstd.get_c_extension( |
1528 name='mercurial.zstd', root=os.path.abspath(os.path.dirname(__file__)) | |
1529 ) | |
1530 ) | |
1316 | 1531 |
1317 try: | 1532 try: |
1318 from distutils import cygwinccompiler | 1533 from distutils import cygwinccompiler |
1319 | 1534 |
1320 # the -mno-cygwin option has been deprecated for years | 1535 # the -mno-cygwin option has been deprecated for years |
1335 # distributions like the ones from the optware project for Synology | 1550 # distributions like the ones from the optware project for Synology |
1336 # DiskStation boxes | 1551 # DiskStation boxes |
1337 class HackedMingw32CCompiler(object): | 1552 class HackedMingw32CCompiler(object): |
1338 pass | 1553 pass |
1339 | 1554 |
1555 | |
1340 if os.name == 'nt': | 1556 if os.name == 'nt': |
1341 # Allow compiler/linker flags to be added to Visual Studio builds. Passing | 1557 # Allow compiler/linker flags to be added to Visual Studio builds. Passing |
1342 # extra_link_args to distutils.extensions.Extension() doesn't have any | 1558 # extra_link_args to distutils.extensions.Extension() doesn't have any |
1343 # effect. | 1559 # effect. |
1344 from distutils import msvccompiler | 1560 from distutils import msvccompiler |
1352 self.ldflags_shared.append('/ignore:4197') | 1568 self.ldflags_shared.append('/ignore:4197') |
1353 self.ldflags_shared_debug.append('/ignore:4197') | 1569 self.ldflags_shared_debug.append('/ignore:4197') |
1354 | 1570 |
1355 msvccompiler.MSVCCompiler = HackedMSVCCompiler | 1571 msvccompiler.MSVCCompiler = HackedMSVCCompiler |
1356 | 1572 |
1357 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo', | 1573 packagedata = { |
1358 'help/*.txt', | 1574 'mercurial': [ |
1359 'help/internals/*.txt', | 1575 'locale/*/LC_MESSAGES/hg.mo', |
1360 'default.d/*.rc', | 1576 'help/*.txt', |
1361 'dummycert.pem']} | 1577 'help/internals/*.txt', |
1578 'default.d/*.rc', | |
1579 'dummycert.pem', | |
1580 ] | |
1581 } | |
1582 | |
1362 | 1583 |
1363 def ordinarypath(p): | 1584 def ordinarypath(p): |
1364 return p and p[0] != '.' and p[-1] != '~' | 1585 return p and p[0] != '.' and p[-1] != '~' |
1586 | |
1365 | 1587 |
1366 for root in ('templates',): | 1588 for root in ('templates',): |
1367 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)): | 1589 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)): |
1368 curdir = curdir.split(os.sep, 1)[1] | 1590 curdir = curdir.split(os.sep, 1)[1] |
1369 dirs[:] = filter(ordinarypath, dirs) | 1591 dirs[:] = filter(ordinarypath, dirs) |
1400 if issetuptools: | 1622 if issetuptools: |
1401 extra['python_requires'] = supportedpy | 1623 extra['python_requires'] = supportedpy |
1402 | 1624 |
1403 if py2exeloaded: | 1625 if py2exeloaded: |
1404 extra['console'] = [ | 1626 extra['console'] = [ |
1405 {'script':'hg', | 1627 { |
1406 'copyright':'Copyright (C) 2005-2019 Matt Mackall and others', | 1628 'script': 'hg', |
1407 'product_version':version}] | 1629 'copyright': 'Copyright (C) 2005-2019 Matt Mackall and others', |
1630 'product_version': version, | |
1631 } | |
1632 ] | |
1408 # Sub command of 'build' because 'py2exe' does not handle sub_commands. | 1633 # Sub command of 'build' because 'py2exe' does not handle sub_commands. |
1409 # Need to override hgbuild because it has a private copy of | 1634 # Need to override hgbuild because it has a private copy of |
1410 # build.sub_commands. | 1635 # build.sub_commands. |
1411 hgbuild.sub_commands.insert(0, ('build_hgextindex', None)) | 1636 hgbuild.sub_commands.insert(0, ('build_hgextindex', None)) |
1412 # put dlls in sub directory so that they won't pollute PATH | 1637 # put dlls in sub directory so that they won't pollute PATH |
1436 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[1].splitlines() | 1661 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[1].splitlines() |
1437 if version: | 1662 if version: |
1438 version = version[0] | 1663 version = version[0] |
1439 if sys.version_info[0] == 3: | 1664 if sys.version_info[0] == 3: |
1440 version = version.decode('utf-8') | 1665 version = version.decode('utf-8') |
1441 xcode4 = (version.startswith('Xcode') and | 1666 xcode4 = version.startswith('Xcode') and StrictVersion( |
1442 StrictVersion(version.split()[1]) >= StrictVersion('4.0')) | 1667 version.split()[1] |
1668 ) >= StrictVersion('4.0') | |
1443 xcode51 = re.match(r'^Xcode\s+5\.1', version) is not None | 1669 xcode51 = re.match(r'^Xcode\s+5\.1', version) is not None |
1444 else: | 1670 else: |
1445 # xcodebuild returns empty on OS X Lion with XCode 4.3 not | 1671 # xcodebuild returns empty on OS X Lion with XCode 4.3 not |
1446 # installed, but instead with only command-line tools. Assume | 1672 # installed, but instead with only command-line tools. Assume |
1447 # that only happens on >= Lion, thus no PPC support. | 1673 # that only happens on >= Lion, thus no PPC support. |
1461 # so Mercurial can continue to compile in the meantime. | 1687 # so Mercurial can continue to compile in the meantime. |
1462 if xcode51: | 1688 if xcode51: |
1463 cflags = get_config_var('CFLAGS') | 1689 cflags = get_config_var('CFLAGS') |
1464 if cflags and re.search(r'-mno-fused-madd\b', cflags) is not None: | 1690 if cflags and re.search(r'-mno-fused-madd\b', cflags) is not None: |
1465 os.environ['CFLAGS'] = ( | 1691 os.environ['CFLAGS'] = ( |
1466 os.environ.get('CFLAGS', '') + ' -Qunused-arguments') | 1692 os.environ.get('CFLAGS', '') + ' -Qunused-arguments' |
1467 | 1693 ) |
1468 setup(name='mercurial', | 1694 |
1469 version=setupversion, | 1695 setup( |
1470 author='Matt Mackall and many others', | 1696 name='mercurial', |
1471 author_email='mercurial@mercurial-scm.org', | 1697 version=setupversion, |
1472 url='https://mercurial-scm.org/', | 1698 author='Matt Mackall and many others', |
1473 download_url='https://mercurial-scm.org/release/', | 1699 author_email='mercurial@mercurial-scm.org', |
1474 description=('Fast scalable distributed SCM (revision control, version ' | 1700 url='https://mercurial-scm.org/', |
1475 'control) system'), | 1701 download_url='https://mercurial-scm.org/release/', |
1476 long_description=('Mercurial is a distributed SCM tool written in Python.' | 1702 description=( |
1477 ' It is used by a number of large projects that require' | 1703 'Fast scalable distributed SCM (revision control, version ' |
1478 ' fast, reliable distributed revision control, such as ' | 1704 'control) system' |
1479 'Mozilla.'), | 1705 ), |
1480 license='GNU GPLv2 or any later version', | 1706 long_description=( |
1481 classifiers=[ | 1707 'Mercurial is a distributed SCM tool written in Python.' |
1482 'Development Status :: 6 - Mature', | 1708 ' It is used by a number of large projects that require' |
1483 'Environment :: Console', | 1709 ' fast, reliable distributed revision control, such as ' |
1484 'Intended Audience :: Developers', | 1710 'Mozilla.' |
1485 'Intended Audience :: System Administrators', | 1711 ), |
1486 'License :: OSI Approved :: GNU General Public License (GPL)', | 1712 license='GNU GPLv2 or any later version', |
1487 'Natural Language :: Danish', | 1713 classifiers=[ |
1488 'Natural Language :: English', | 1714 'Development Status :: 6 - Mature', |
1489 'Natural Language :: German', | 1715 'Environment :: Console', |
1490 'Natural Language :: Italian', | 1716 'Intended Audience :: Developers', |
1491 'Natural Language :: Japanese', | 1717 'Intended Audience :: System Administrators', |
1492 'Natural Language :: Portuguese (Brazilian)', | 1718 'License :: OSI Approved :: GNU General Public License (GPL)', |
1493 'Operating System :: Microsoft :: Windows', | 1719 'Natural Language :: Danish', |
1494 'Operating System :: OS Independent', | 1720 'Natural Language :: English', |
1495 'Operating System :: POSIX', | 1721 'Natural Language :: German', |
1496 'Programming Language :: C', | 1722 'Natural Language :: Italian', |
1497 'Programming Language :: Python', | 1723 'Natural Language :: Japanese', |
1498 'Topic :: Software Development :: Version Control', | 1724 'Natural Language :: Portuguese (Brazilian)', |
1499 ], | 1725 'Operating System :: Microsoft :: Windows', |
1500 scripts=scripts, | 1726 'Operating System :: OS Independent', |
1501 packages=packages, | 1727 'Operating System :: POSIX', |
1502 ext_modules=extmodules, | 1728 'Programming Language :: C', |
1503 data_files=datafiles, | 1729 'Programming Language :: Python', |
1504 package_data=packagedata, | 1730 'Topic :: Software Development :: Version Control', |
1505 cmdclass=cmdclass, | 1731 ], |
1506 distclass=hgdist, | 1732 scripts=scripts, |
1507 options={ | 1733 packages=packages, |
1508 'py2exe': { | 1734 ext_modules=extmodules, |
1509 'bundle_files': 3, | 1735 data_files=datafiles, |
1510 'dll_excludes': py2exedllexcludes, | 1736 package_data=packagedata, |
1511 'excludes': py2exeexcludes, | 1737 cmdclass=cmdclass, |
1512 'packages': py2exepackages, | 1738 distclass=hgdist, |
1513 }, | 1739 options={ |
1514 'bdist_mpkg': { | 1740 'py2exe': { |
1515 'zipdist': False, | 1741 'bundle_files': 3, |
1516 'license': 'COPYING', | 1742 'dll_excludes': py2exedllexcludes, |
1517 'readme': 'contrib/packaging/macosx/Readme.html', | 1743 'excludes': py2exeexcludes, |
1518 'welcome': 'contrib/packaging/macosx/Welcome.html', | 1744 'packages': py2exepackages, |
1519 }, | 1745 }, |
1520 }, | 1746 'bdist_mpkg': { |
1521 **extra) | 1747 'zipdist': False, |
1748 'license': 'COPYING', | |
1749 'readme': 'contrib/packaging/macosx/Readme.html', | |
1750 'welcome': 'contrib/packaging/macosx/Welcome.html', | |
1751 }, | |
1752 }, | |
1753 **extra | |
1754 ) |