##// END OF EJS Templates
setup: create a module for the modulepolicy...
timeless -
r28430:17b85d73 default
parent child Browse files
Show More
@@ -1,68 +1,69 b''
1 1 syntax: glob
2 2
3 3 *.elc
4 4 *.tmp
5 5 *.orig
6 6 *.rej
7 7 *~
8 8 *.mergebackup
9 9 *.o
10 10 *.so
11 11 *.dll
12 12 *.exe
13 13 *.pyd
14 14 *.pyc
15 15 *.pyo
16 16 *$py.class
17 17 *.swp
18 18 *.prof
19 19 *.zip
20 20 \#*\#
21 21 .\#*
22 22 tests/.coverage*
23 23 tests/.testtimes*
24 24 tests/.hypothesis
25 25 tests/hypothesis-generated
26 26 tests/annotated
27 27 tests/*.err
28 28 tests/htmlcov
29 29 build
30 30 contrib/chg/chg
31 31 contrib/hgsh/hgsh
32 32 contrib/vagrant/.vagrant
33 33 dist
34 34 packages
35 35 doc/common.txt
36 36 doc/*.[0-9]
37 37 doc/*.[0-9].txt
38 38 doc/*.[0-9].gendoc.txt
39 39 doc/*.[0-9].{x,ht}ml
40 40 MANIFEST
41 41 MANIFEST.in
42 42 patches
43 mercurial/__modulepolicy__.py
43 44 mercurial/__version__.py
44 45 mercurial/hgpythonlib.h
45 46 mercurial.egg-info
46 47 .DS_Store
47 48 tags
48 49 cscope.*
49 50 .idea/*
50 51 i18n/hg.pot
51 52 locale/*/LC_MESSAGES/hg.mo
52 53 hgext/__index__.py
53 54
54 55 # files installed with a local --pure build
55 56 mercurial/base85.py
56 57 mercurial/bdiff.py
57 58 mercurial/diffhelpers.py
58 59 mercurial/mpatch.py
59 60 mercurial/osutil.py
60 61 mercurial/parsers.py
61 62
62 63 syntax: regexp
63 64 ^\.pc/
64 65 ^\.(pydev)?project
65 66
66 67 # hackable windows distribution additions
67 68 ^hg-python
68 69 ^hg.py$
@@ -1,226 +1,227 b''
1 1 # If you want to change PREFIX, do not just edit it below. The changed
2 2 # value wont get passed on to recursive make calls. You should instead
3 3 # override the variable on the command like:
4 4 #
5 5 # % make PREFIX=/opt/ install
6 6
7 7 PREFIX=/usr/local
8 8 export PREFIX
9 9 PYTHON=python
10 10 $(eval HGROOT := $(shell pwd))
11 11 HGPYTHONS ?= $(HGROOT)/build/pythons
12 12 PURE=
13 13 PYFILES:=$(shell find mercurial hgext doc -name '*.py')
14 14 DOCFILES=mercurial/help/*.txt
15 15 export LANGUAGE=C
16 16 export LC_ALL=C
17 17 TESTFLAGS ?= $(shell echo $$HGTESTFLAGS)
18 18
19 19 # Set this to e.g. "mingw32" to use a non-default compiler.
20 20 COMPILER=
21 21
22 22 help:
23 23 @echo 'Commonly used make targets:'
24 24 @echo ' all - build program and documentation'
25 25 @echo ' install - install program and man pages to $$PREFIX ($(PREFIX))'
26 26 @echo ' install-home - install with setup.py install --home=$$HOME ($(HOME))'
27 27 @echo ' local - build for inplace usage'
28 28 @echo ' tests - run all tests in the automatic test suite'
29 29 @echo ' test-foo - run only specified tests (e.g. test-merge1.t)'
30 30 @echo ' dist - run all tests and create a source tarball in dist/'
31 31 @echo ' clean - remove files created by other targets'
32 32 @echo ' (except installed files or dist source tarball)'
33 33 @echo ' update-pot - update i18n/hg.pot'
34 34 @echo
35 35 @echo 'Example for a system-wide installation under /usr/local:'
36 36 @echo ' make all && su -c "make install" && hg version'
37 37 @echo
38 38 @echo 'Example for a local installation (usable in this directory):'
39 39 @echo ' make local && ./hg version'
40 40
41 41 all: build doc
42 42
43 43 local:
44 44 $(PYTHON) setup.py $(PURE) \
45 45 build_py -c -d . \
46 46 build_ext $(COMPILER:%=-c %) -i \
47 47 build_hgexe $(COMPILER:%=-c %) -i \
48 48 build_mo
49 49 env HGRCPATH= $(PYTHON) hg version
50 50
51 51 build:
52 52 $(PYTHON) setup.py $(PURE) build $(COMPILER:%=-c %)
53 53
54 54 wheel:
55 55 FORCE_SETUPTOOLS=1 $(PYTHON) setup.py $(PURE) bdist_wheel $(COMPILER:%=-c %)
56 56
57 57 doc:
58 58 $(MAKE) -C doc
59 59
60 60 clean:
61 61 -$(PYTHON) setup.py clean --all # ignore errors from this command
62 62 find contrib doc hgext i18n mercurial tests \
63 63 \( -name '*.py[cdo]' -o -name '*.so' \) -exec rm -f '{}' ';'
64 64 rm -f $(addprefix mercurial/,$(notdir $(wildcard mercurial/pure/[a-z]*.py)))
65 65 rm -f MANIFEST MANIFEST.in hgext/__index__.py tests/*.err
66 rm -f mercurial/__modulepolicy__.py
66 67 if test -d .hg; then rm -f mercurial/__version__.py; fi
67 68 rm -rf build mercurial/locale
68 69 $(MAKE) -C doc clean
69 70
70 71 install: install-bin install-doc
71 72
72 73 install-bin: build
73 74 $(PYTHON) setup.py $(PURE) install --root="$(DESTDIR)/" --prefix="$(PREFIX)" --force
74 75
75 76 install-doc: doc
76 77 cd doc && $(MAKE) $(MFLAGS) install
77 78
78 79 install-home: install-home-bin install-home-doc
79 80
80 81 install-home-bin: build
81 82 $(PYTHON) setup.py $(PURE) install --home="$(HOME)" --prefix="" --force
82 83
83 84 install-home-doc: doc
84 85 cd doc && $(MAKE) $(MFLAGS) PREFIX="$(HOME)" install
85 86
86 87 MANIFEST-doc:
87 88 $(MAKE) -C doc MANIFEST
88 89
89 90 MANIFEST.in: MANIFEST-doc
90 91 hg manifest | sed -e 's/^/include /' > MANIFEST.in
91 92 echo include mercurial/__version__.py >> MANIFEST.in
92 93 sed -e 's/^/include /' < doc/MANIFEST >> MANIFEST.in
93 94
94 95 dist: tests dist-notests
95 96
96 97 dist-notests: doc MANIFEST.in
97 98 TAR_OPTIONS="--owner=root --group=root --mode=u+w,go-w,a+rX-s" $(PYTHON) setup.py -q sdist
98 99
99 100 check: tests
100 101
101 102 tests:
102 103 cd tests && $(PYTHON) run-tests.py $(TESTFLAGS)
103 104
104 105 test-%:
105 106 cd tests && $(PYTHON) run-tests.py $(TESTFLAGS) $@
106 107
107 108 testpy-%:
108 109 @echo Looking for Python $* in $(HGPYTHONS)
109 110 [ -e $(HGPYTHONS)/$*/bin/python ] || ( \
110 111 cd $$(mktemp --directory --tmpdir) && \
111 112 $(MAKE) -f $(HGROOT)/contrib/Makefile.python PYTHONVER=$* PREFIX=$(HGPYTHONS)/$* python )
112 113 cd tests && $(HGPYTHONS)/$*/bin/python run-tests.py $(TESTFLAGS)
113 114
114 115 check-code:
115 116 hg manifest | xargs python contrib/check-code.py
116 117
117 118 update-pot: i18n/hg.pot
118 119
119 120 i18n/hg.pot: $(PYFILES) $(DOCFILES) i18n/posplit i18n/hggettext
120 121 $(PYTHON) i18n/hggettext mercurial/commands.py \
121 122 hgext/*.py hgext/*/__init__.py \
122 123 mercurial/fileset.py mercurial/revset.py \
123 124 mercurial/templatefilters.py mercurial/templatekw.py \
124 125 mercurial/templater.py \
125 126 mercurial/filemerge.py \
126 127 mercurial/hgweb/webcommands.py \
127 128 $(DOCFILES) > i18n/hg.pot.tmp
128 129 # All strings marked for translation in Mercurial contain
129 130 # ASCII characters only. But some files contain string
130 131 # literals like this '\037\213'. xgettext thinks it has to
131 132 # parse them even though they are not marked for translation.
132 133 # Extracting with an explicit encoding of ISO-8859-1 will make
133 134 # xgettext "parse" and ignore them.
134 135 echo $(PYFILES) | xargs \
135 136 xgettext --package-name "Mercurial" \
136 137 --msgid-bugs-address "<mercurial-devel@selenic.com>" \
137 138 --copyright-holder "Matt Mackall <mpm@selenic.com> and others" \
138 139 --from-code ISO-8859-1 --join --sort-by-file --add-comments=i18n: \
139 140 -d hg -p i18n -o hg.pot.tmp
140 141 $(PYTHON) i18n/posplit i18n/hg.pot.tmp
141 142 # The target file is not created before the last step. So it never is in
142 143 # an intermediate state.
143 144 mv -f i18n/hg.pot.tmp i18n/hg.pot
144 145
145 146 %.po: i18n/hg.pot
146 147 # work on a temporary copy for never having a half completed target
147 148 cp $@ $@.tmp
148 149 msgmerge --no-location --update $@.tmp $^
149 150 mv -f $@.tmp $@
150 151
151 152 # Packaging targets
152 153
153 154 osx:
154 155 python -c 'import bdist_mpkg.script_bdist_mpkg' || \
155 156 (echo "Missing bdist_mpkg (easy_install bdist_mpkg)"; false)
156 157 rm -rf dist/mercurial-*.mpkg
157 158 python -m bdist_mpkg.script_bdist_mpkg setup.py --
158 159 python contrib/fixpax.py dist/mercurial-*.mpkg/Contents/Packages/*.pkg/Contents/Archive.pax.gz
159 160 mkdir -p packages/osx
160 161 N=`cd dist && echo mercurial-*.mpkg | sed 's,\.mpkg$$,,'` && hdiutil create -srcfolder dist/$$N.mpkg/ -scrub -volname "$$N" -ov packages/osx/$$N.dmg
161 162 rm -rf dist/mercurial-*.mpkg
162 163
163 164 deb:
164 165 contrib/builddeb
165 166
166 167 docker-debian-jessie:
167 168 mkdir -p packages/debian-jessie
168 169 contrib/dockerdeb debian jessie
169 170
170 171 fedora20:
171 172 mkdir -p packages/fedora20
172 173 contrib/buildrpm
173 174 cp rpmbuild/RPMS/*/* packages/fedora20
174 175 cp rpmbuild/SRPMS/* packages/fedora20
175 176 rm -rf rpmbuild
176 177
177 178 docker-fedora20:
178 179 mkdir -p packages/fedora20
179 180 contrib/dockerrpm fedora20
180 181
181 182 fedora21:
182 183 mkdir -p packages/fedora21
183 184 contrib/buildrpm
184 185 cp rpmbuild/RPMS/*/* packages/fedora21
185 186 cp rpmbuild/SRPMS/* packages/fedora21
186 187 rm -rf rpmbuild
187 188
188 189 docker-fedora21:
189 190 mkdir -p packages/fedora21
190 191 contrib/dockerrpm fedora21
191 192
192 193 centos5:
193 194 mkdir -p packages/centos5
194 195 contrib/buildrpm --withpython
195 196 cp rpmbuild/RPMS/*/* packages/centos5
196 197 cp rpmbuild/SRPMS/* packages/centos5
197 198
198 199 docker-centos5:
199 200 mkdir -p packages/centos5
200 201 contrib/dockerrpm centos5 --withpython
201 202
202 203 centos6:
203 204 mkdir -p packages/centos6
204 205 contrib/buildrpm
205 206 cp rpmbuild/RPMS/*/* packages/centos6
206 207 cp rpmbuild/SRPMS/* packages/centos6
207 208
208 209 docker-centos6:
209 210 mkdir -p packages/centos6
210 211 contrib/dockerrpm centos6
211 212
212 213 centos7:
213 214 mkdir -p packages/centos7
214 215 contrib/buildrpm
215 216 cp rpmbuild/RPMS/*/* packages/centos7
216 217 cp rpmbuild/SRPMS/* packages/centos7
217 218
218 219 docker-centos7:
219 220 mkdir -p packages/centos7
220 221 contrib/dockerrpm centos7
221 222
222 223 .PHONY: help all local build doc clean install install-bin install-doc \
223 224 install-home install-home-bin install-home-doc \
224 225 dist dist-notests check tests check-code update-pot \
225 226 osx fedora20 docker-fedora20 fedora21 docker-fedora21 \
226 227 centos5 docker-centos5 centos6 docker-centos6 centos7 docker-centos7
@@ -1,144 +1,147 b''
1 1 # __init__.py - Startup and module loading logic for Mercurial.
2 2 #
3 3 # Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import imp
11 11 import os
12 12 import sys
13 13 import zipimport
14 14
15 15 __all__ = []
16 16
17 17 # Rules for how modules can be loaded. Values are:
18 18 #
19 19 # c - require C extensions
20 20 # allow - allow pure Python implementation when C loading fails
21 21 # py - only load pure Python modules
22 modulepolicy = '@MODULELOADPOLICY@'
23
22 #
24 23 # By default, require the C extensions for performance reasons.
25 if modulepolicy == '@' 'MODULELOADPOLICY' '@':
26 modulepolicy = 'c'
24 modulepolicy = 'c'
25 try:
26 from . import __modulepolicy__
27 modulepolicy = __modulepolicy__.modulepolicy
28 except ImportError:
29 pass
27 30
28 31 # PyPy doesn't load C extensions.
29 32 #
30 33 # The canonical way to do this is to test platform.python_implementation().
31 34 # But we don't import platform and don't bloat for it here.
32 35 if '__pypy__' in sys.builtin_module_names:
33 36 modulepolicy = 'py'
34 37
35 38 # Environment variable can always force settings.
36 39 modulepolicy = os.environ.get('HGMODULEPOLICY', modulepolicy)
37 40
38 41 # Modules that have both Python and C implementations. See also the
39 42 # set of .py files under mercurial/pure/.
40 43 _dualmodules = set([
41 44 'mercurial.base85',
42 45 'mercurial.bdiff',
43 46 'mercurial.diffhelpers',
44 47 'mercurial.mpatch',
45 48 'mercurial.osutil',
46 49 'mercurial.parsers',
47 50 ])
48 51
49 52 class hgimporter(object):
50 53 """Object that conforms to import hook interface defined in PEP-302."""
51 54 def find_module(self, name, path=None):
52 55 # We only care about modules that have both C and pure implementations.
53 56 if name in _dualmodules:
54 57 return self
55 58 return None
56 59
57 60 def load_module(self, name):
58 61 mod = sys.modules.get(name, None)
59 62 if mod:
60 63 return mod
61 64
62 65 mercurial = sys.modules['mercurial']
63 66
64 67 # The zip importer behaves sufficiently differently from the default
65 68 # importer to warrant its own code path.
66 69 loader = getattr(mercurial, '__loader__', None)
67 70 if isinstance(loader, zipimport.zipimporter):
68 71 def ziploader(*paths):
69 72 """Obtain a zipimporter for a directory under the main zip."""
70 73 path = os.path.join(loader.archive, *paths)
71 74 zl = sys.path_importer_cache.get(path)
72 75 if not zl:
73 76 zl = zipimport.zipimporter(path)
74 77 return zl
75 78
76 79 try:
77 80 if modulepolicy == 'py':
78 81 raise ImportError()
79 82
80 83 zl = ziploader('mercurial')
81 84 mod = zl.load_module(name)
82 85 # Unlike imp, ziploader doesn't expose module metadata that
83 86 # indicates the type of module. So just assume what we found
84 87 # is OK (even though it could be a pure Python module).
85 88 except ImportError:
86 89 if modulepolicy == 'c':
87 90 raise
88 91 zl = ziploader('mercurial', 'pure')
89 92 mod = zl.load_module(name)
90 93
91 94 sys.modules[name] = mod
92 95 return mod
93 96
94 97 # Unlike the default importer which searches special locations and
95 98 # sys.path, we only look in the directory where "mercurial" was
96 99 # imported from.
97 100
98 101 # imp.find_module doesn't support submodules (modules with ".").
99 102 # Instead you have to pass the parent package's __path__ attribute
100 103 # as the path argument.
101 104 stem = name.split('.')[-1]
102 105
103 106 try:
104 107 if modulepolicy == 'py':
105 108 raise ImportError()
106 109
107 110 modinfo = imp.find_module(stem, mercurial.__path__)
108 111
109 112 # The Mercurial installer used to copy files from
110 113 # mercurial/pure/*.py to mercurial/*.py. Therefore, it's possible
111 114 # for some installations to have .py files under mercurial/*.
112 115 # Loading Python modules when we expected C versions could result
113 116 # in a) poor performance b) loading a version from a previous
114 117 # Mercurial version, potentially leading to incompatibility. Either
115 118 # scenario is bad. So we verify that modules loaded from
116 119 # mercurial/* are C extensions. If the current policy allows the
117 120 # loading of .py modules, the module will be re-imported from
118 121 # mercurial/pure/* below.
119 122 if modinfo[2][2] != imp.C_EXTENSION:
120 123 raise ImportError('.py version of %s found where C '
121 124 'version should exist' % name)
122 125
123 126 except ImportError:
124 127 if modulepolicy == 'c':
125 128 raise
126 129
127 130 # Could not load the C extension and pure Python is allowed. So
128 131 # try to load them.
129 132 from . import pure
130 133 modinfo = imp.find_module(stem, pure.__path__)
131 134 if not modinfo:
132 135 raise ImportError('could not find mercurial module %s' %
133 136 name)
134 137
135 138 mod = imp.load_module(name, *modinfo)
136 139 sys.modules[name] = mod
137 140 return mod
138 141
139 142 # We automagically register our custom importer as a side-effect of loading.
140 143 # This is necessary to ensure that any entry points are able to import
141 144 # mercurial.* modules without having to perform this registration themselves.
142 145 if not any(isinstance(x, hgimporter) for x in sys.meta_path):
143 146 # meta_path is used before any implicit finders and before sys.path.
144 147 sys.meta_path.insert(0, hgimporter())
@@ -1,673 +1,668 b''
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 scripts = ['hg']
88 88 if os.name == 'nt':
89 89 # We remove hg.bat if we are able to build hg.exe.
90 90 scripts.append('contrib/win32/hg.bat')
91 91
92 92 # simplified version of distutils.ccompiler.CCompiler.has_function
93 93 # that actually removes its temporary files.
94 94 def hasfunction(cc, funcname):
95 95 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
96 96 devnull = oldstderr = None
97 97 try:
98 98 fname = os.path.join(tmpdir, 'funcname.c')
99 99 f = open(fname, 'w')
100 100 f.write('int main(void) {\n')
101 101 f.write(' %s();\n' % funcname)
102 102 f.write('}\n')
103 103 f.close()
104 104 # Redirect stderr to /dev/null to hide any error messages
105 105 # from the compiler.
106 106 # This will have to be changed if we ever have to check
107 107 # for a function on Windows.
108 108 devnull = open('/dev/null', 'w')
109 109 oldstderr = os.dup(sys.stderr.fileno())
110 110 os.dup2(devnull.fileno(), sys.stderr.fileno())
111 111 objects = cc.compile([fname], output_dir=tmpdir)
112 112 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
113 113 return True
114 114 except Exception:
115 115 return False
116 116 finally:
117 117 if oldstderr is not None:
118 118 os.dup2(oldstderr, sys.stderr.fileno())
119 119 if devnull is not None:
120 120 devnull.close()
121 121 shutil.rmtree(tmpdir)
122 122
123 123 # py2exe needs to be installed to work
124 124 try:
125 125 import py2exe
126 126 py2exe.Distribution # silence unused import warning
127 127 py2exeloaded = True
128 128 # import py2exe's patched Distribution class
129 129 from distutils.core import Distribution
130 130 except ImportError:
131 131 py2exeloaded = False
132 132
133 133 def runcmd(cmd, env):
134 134 if (sys.platform == 'plan9'
135 135 and (sys.version_info[0] == 2 and sys.version_info[1] < 7)):
136 136 # subprocess kludge to work around issues in half-baked Python
137 137 # ports, notably bichued/python:
138 138 _, out, err = os.popen3(cmd)
139 139 return str(out), str(err)
140 140 else:
141 141 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
142 142 stderr=subprocess.PIPE, env=env)
143 143 out, err = p.communicate()
144 144 return out, err
145 145
146 146 def runhg(cmd, env):
147 147 out, err = runcmd(cmd, env)
148 148 # If root is executing setup.py, but the repository is owned by
149 149 # another user (as in "sudo python setup.py install") we will get
150 150 # trust warnings since the .hg/hgrc file is untrusted. That is
151 151 # fine, we don't want to load it anyway. Python may warn about
152 152 # a missing __init__.py in mercurial/locale, we also ignore that.
153 153 err = [e for e in err.splitlines()
154 154 if not e.startswith(b'not trusting file') \
155 155 and not e.startswith(b'warning: Not importing') \
156 156 and not e.startswith(b'obsolete feature not enabled')]
157 157 if err:
158 158 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr)
159 159 printf(b'\n'.join([b' ' + e for e in err]), file=sys.stderr)
160 160 return ''
161 161 return out
162 162
163 163 version = ''
164 164
165 165 # Execute hg out of this directory with a custom environment which takes care
166 166 # to not use any hgrc files and do no localization.
167 167 env = {'HGMODULEPOLICY': 'py',
168 168 'HGRCPATH': '',
169 169 'LANGUAGE': 'C'}
170 170 if 'LD_LIBRARY_PATH' in os.environ:
171 171 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
172 172 if 'SystemRoot' in os.environ:
173 173 # Copy SystemRoot into the custom environment for Python 2.6
174 174 # under Windows. Otherwise, the subprocess will fail with
175 175 # error 0xc0150004. See: http://bugs.python.org/issue3440
176 176 env['SystemRoot'] = os.environ['SystemRoot']
177 177
178 178 if os.path.isdir('.hg'):
179 179 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
180 180 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
181 181 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
182 182 if numerictags: # tag(s) found
183 183 version = numerictags[-1]
184 184 if hgid.endswith('+'): # propagate the dirty status to the tag
185 185 version += '+'
186 186 else: # no tag found
187 187 ltagcmd = [sys.executable, 'hg', 'parents', '--template',
188 188 '{latesttag}']
189 189 ltag = runhg(ltagcmd, env)
190 190 changessincecmd = [sys.executable, 'hg', 'log', '-T', 'x\n', '-r',
191 191 "only(.,'%s')" % ltag]
192 192 changessince = len(runhg(changessincecmd, env).splitlines())
193 193 version = '%s+%s-%s' % (ltag, changessince, hgid)
194 194 if version.endswith('+'):
195 195 version += time.strftime('%Y%m%d')
196 196 elif os.path.exists('.hg_archival.txt'):
197 197 kw = dict([[t.strip() for t in l.split(':', 1)]
198 198 for l in open('.hg_archival.txt')])
199 199 if 'tag' in kw:
200 200 version = kw['tag']
201 201 elif 'latesttag' in kw:
202 202 if 'changessincelatesttag' in kw:
203 203 version = '%(latesttag)s+%(changessincelatesttag)s-%(node).12s' % kw
204 204 else:
205 205 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
206 206 else:
207 207 version = kw.get('node', '')[:12]
208 208
209 209 if version:
210 210 with open("mercurial/__version__.py", "w") as f:
211 211 f.write('# this file is autogenerated by setup.py\n')
212 212 f.write('version = "%s"\n' % version)
213 213
214 214 try:
215 215 from mercurial import __version__
216 216 version = __version__.version
217 217 except ImportError:
218 218 version = 'unknown'
219 219
220 220 class hgbuild(build):
221 221 # Insert hgbuildmo first so that files in mercurial/locale/ are found
222 222 # when build_py is run next.
223 223 sub_commands = [('build_mo', None)] + build.sub_commands
224 224
225 225 class hgbuildmo(build):
226 226
227 227 description = "build translations (.mo files)"
228 228
229 229 def run(self):
230 230 if not find_executable('msgfmt'):
231 231 self.warn("could not find msgfmt executable, no translations "
232 232 "will be built")
233 233 return
234 234
235 235 podir = 'i18n'
236 236 if not os.path.isdir(podir):
237 237 self.warn("could not find %s/ directory" % podir)
238 238 return
239 239
240 240 join = os.path.join
241 241 for po in os.listdir(podir):
242 242 if not po.endswith('.po'):
243 243 continue
244 244 pofile = join(podir, po)
245 245 modir = join('locale', po[:-3], 'LC_MESSAGES')
246 246 mofile = join(modir, 'hg.mo')
247 247 mobuildfile = join('mercurial', mofile)
248 248 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
249 249 if sys.platform != 'sunos5':
250 250 # msgfmt on Solaris does not know about -c
251 251 cmd.append('-c')
252 252 self.mkpath(join('mercurial', modir))
253 253 self.make_file([pofile], mobuildfile, spawn, (cmd,))
254 254
255 255
256 256 class hgdist(Distribution):
257 257 pure = ispypy
258 258
259 259 global_options = Distribution.global_options + \
260 260 [('pure', None, "use pure (slow) Python "
261 261 "code instead of C extensions"),
262 262 ]
263 263
264 264 def has_ext_modules(self):
265 265 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
266 266 # too late for some cases
267 267 return not self.pure and Distribution.has_ext_modules(self)
268 268
269 269 class hgbuildext(build_ext):
270 270
271 271 def build_extension(self, ext):
272 272 try:
273 273 build_ext.build_extension(self, ext)
274 274 except CCompilerError:
275 275 if not getattr(ext, 'optional', False):
276 276 raise
277 277 log.warn("Failed to build optional extension '%s' (skipping)",
278 278 ext.name)
279 279
280 280 class hgbuildscripts(build_scripts):
281 281 def run(self):
282 282 if os.name != 'nt' or self.distribution.pure:
283 283 return build_scripts.run(self)
284 284
285 285 exebuilt = False
286 286 try:
287 287 self.run_command('build_hgexe')
288 288 exebuilt = True
289 289 except (DistutilsError, CCompilerError):
290 290 log.warn('failed to build optional hg.exe')
291 291
292 292 if exebuilt:
293 293 # Copying hg.exe to the scripts build directory ensures it is
294 294 # installed by the install_scripts command.
295 295 hgexecommand = self.get_finalized_command('build_hgexe')
296 296 dest = os.path.join(self.build_dir, 'hg.exe')
297 297 self.mkpath(self.build_dir)
298 298 self.copy_file(hgexecommand.hgexepath, dest)
299 299
300 300 # Remove hg.bat because it is redundant with hg.exe.
301 301 self.scripts.remove('contrib/win32/hg.bat')
302 302
303 303 return build_scripts.run(self)
304 304
305 305 class hgbuildpy(build_py):
306 306 def finalize_options(self):
307 307 build_py.finalize_options(self)
308 308
309 309 if self.distribution.pure:
310 310 self.distribution.ext_modules = []
311 311 else:
312 312 h = os.path.join(get_python_inc(), 'Python.h')
313 313 if not os.path.exists(h):
314 314 raise SystemExit('Python headers are required to build '
315 315 'Mercurial but weren\'t found in %s' % h)
316 316
317 def copy_file(self, *args, **kwargs):
318 dst, copied = build_py.copy_file(self, *args, **kwargs)
317 def run(self):
318 if self.distribution.pure:
319 modulepolicy = 'py'
320 else:
321 modulepolicy = 'c'
322 with open("mercurial/__modulepolicy__.py", "w") as f:
323 f.write('# this file is autogenerated by setup.py\n')
324 f.write('modulepolicy = "%s"\n' % modulepolicy)
319 325
320 if copied and dst.endswith('__init__.py'):
321 if self.distribution.pure:
322 modulepolicy = 'py'
323 else:
324 modulepolicy = 'c'
325 content = open(dst, 'rb').read()
326 content = content.replace(b'@MODULELOADPOLICY@',
327 modulepolicy.encode(libdir_escape))
328 with open(dst, 'wb') as fh:
329 fh.write(content)
330
331 return dst, copied
326 build_py.run(self)
332 327
333 328 class buildhgextindex(Command):
334 329 description = 'generate prebuilt index of hgext (for frozen package)'
335 330 user_options = []
336 331 _indexfilename = 'hgext/__index__.py'
337 332
338 333 def initialize_options(self):
339 334 pass
340 335
341 336 def finalize_options(self):
342 337 pass
343 338
344 339 def run(self):
345 340 if os.path.exists(self._indexfilename):
346 341 with open(self._indexfilename, 'w') as f:
347 342 f.write('# empty\n')
348 343
349 344 # here no extension enabled, disabled() lists up everything
350 345 code = ('import pprint; from mercurial import extensions; '
351 346 'pprint.pprint(extensions.disabled())')
352 347 out, err = runcmd([sys.executable, '-c', code], env)
353 348 if err:
354 349 raise DistutilsExecError(err)
355 350
356 351 with open(self._indexfilename, 'w') as f:
357 352 f.write('# this file is autogenerated by setup.py\n')
358 353 f.write('docs = ')
359 354 f.write(out)
360 355
361 356 class buildhgexe(build_ext):
362 357 description = 'compile hg.exe from mercurial/exewrapper.c'
363 358
364 359 def build_extensions(self):
365 360 if os.name != 'nt':
366 361 return
367 362 if isinstance(self.compiler, HackedMingw32CCompiler):
368 363 self.compiler.compiler_so = self.compiler.compiler # no -mdll
369 364 self.compiler.dll_libraries = [] # no -lmsrvc90
370 365 hv = sys.hexversion
371 366 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
372 367 with open('mercurial/hgpythonlib.h', 'wb') as f:
373 368 f.write('/* this file is autogenerated by setup.py */\n')
374 369 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
375 370 objects = self.compiler.compile(['mercurial/exewrapper.c'],
376 371 output_dir=self.build_temp)
377 372 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
378 373 target = os.path.join(dir, 'hg')
379 374 self.compiler.link_executable(objects, target,
380 375 libraries=[],
381 376 output_dir=self.build_temp)
382 377
383 378 @property
384 379 def hgexepath(self):
385 380 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
386 381 return os.path.join(self.build_temp, dir, 'hg.exe')
387 382
388 383 class hginstalllib(install_lib):
389 384 '''
390 385 This is a specialization of install_lib that replaces the copy_file used
391 386 there so that it supports setting the mode of files after copying them,
392 387 instead of just preserving the mode that the files originally had. If your
393 388 system has a umask of something like 027, preserving the permissions when
394 389 copying will lead to a broken install.
395 390
396 391 Note that just passing keep_permissions=False to copy_file would be
397 392 insufficient, as it might still be applying a umask.
398 393 '''
399 394
400 395 def run(self):
401 396 realcopyfile = file_util.copy_file
402 397 def copyfileandsetmode(*args, **kwargs):
403 398 src, dst = args[0], args[1]
404 399 dst, copied = realcopyfile(*args, **kwargs)
405 400 if copied:
406 401 st = os.stat(src)
407 402 # Persist executable bit (apply it to group and other if user
408 403 # has it)
409 404 if st[stat.ST_MODE] & stat.S_IXUSR:
410 405 setmode = int('0755', 8)
411 406 else:
412 407 setmode = int('0644', 8)
413 408 m = stat.S_IMODE(st[stat.ST_MODE])
414 409 m = (m & ~int('0777', 8)) | setmode
415 410 os.chmod(dst, m)
416 411 file_util.copy_file = copyfileandsetmode
417 412 try:
418 413 install_lib.run(self)
419 414 finally:
420 415 file_util.copy_file = realcopyfile
421 416
422 417 class hginstallscripts(install_scripts):
423 418 '''
424 419 This is a specialization of install_scripts that replaces the @LIBDIR@ with
425 420 the configured directory for modules. If possible, the path is made relative
426 421 to the directory for scripts.
427 422 '''
428 423
429 424 def initialize_options(self):
430 425 install_scripts.initialize_options(self)
431 426
432 427 self.install_lib = None
433 428
434 429 def finalize_options(self):
435 430 install_scripts.finalize_options(self)
436 431 self.set_undefined_options('install',
437 432 ('install_lib', 'install_lib'))
438 433
439 434 def run(self):
440 435 install_scripts.run(self)
441 436
442 437 # It only makes sense to replace @LIBDIR@ with the install path if
443 438 # the install path is known. For wheels, the logic below calculates
444 439 # the libdir to be "../..". This is because the internal layout of a
445 440 # wheel archive looks like:
446 441 #
447 442 # mercurial-3.6.1.data/scripts/hg
448 443 # mercurial/__init__.py
449 444 #
450 445 # When installing wheels, the subdirectories of the "<pkg>.data"
451 446 # directory are translated to system local paths and files therein
452 447 # are copied in place. The mercurial/* files are installed into the
453 448 # site-packages directory. However, the site-packages directory
454 449 # isn't known until wheel install time. This means we have no clue
455 450 # at wheel generation time what the installed site-packages directory
456 451 # will be. And, wheels don't appear to provide the ability to register
457 452 # custom code to run during wheel installation. This all means that
458 453 # we can't reliably set the libdir in wheels: the default behavior
459 454 # of looking in sys.path must do.
460 455
461 456 if (os.path.splitdrive(self.install_dir)[0] !=
462 457 os.path.splitdrive(self.install_lib)[0]):
463 458 # can't make relative paths from one drive to another, so use an
464 459 # absolute path instead
465 460 libdir = self.install_lib
466 461 else:
467 462 common = os.path.commonprefix((self.install_dir, self.install_lib))
468 463 rest = self.install_dir[len(common):]
469 464 uplevel = len([n for n in os.path.split(rest) if n])
470 465
471 466 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
472 467
473 468 for outfile in self.outfiles:
474 469 with open(outfile, 'rb') as fp:
475 470 data = fp.read()
476 471
477 472 # skip binary files
478 473 if b'\0' in data:
479 474 continue
480 475
481 476 # During local installs, the shebang will be rewritten to the final
482 477 # install path. During wheel packaging, the shebang has a special
483 478 # value.
484 479 if data.startswith(b'#!python'):
485 480 log.info('not rewriting @LIBDIR@ in %s because install path '
486 481 'not known' % outfile)
487 482 continue
488 483
489 484 data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape))
490 485 with open(outfile, 'wb') as fp:
491 486 fp.write(data)
492 487
493 488 cmdclass = {'build': hgbuild,
494 489 'build_mo': hgbuildmo,
495 490 'build_ext': hgbuildext,
496 491 'build_py': hgbuildpy,
497 492 'build_scripts': hgbuildscripts,
498 493 'build_hgextindex': buildhgextindex,
499 494 'install_lib': hginstalllib,
500 495 'install_scripts': hginstallscripts,
501 496 'build_hgexe': buildhgexe,
502 497 }
503 498
504 499 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
505 500 'mercurial.pure',
506 501 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
507 502 'hgext.largefiles']
508 503
509 504 common_depends = ['mercurial/util.h']
510 505
511 506 osutil_ldflags = []
512 507
513 508 if sys.platform == 'darwin':
514 509 osutil_ldflags += ['-framework', 'ApplicationServices']
515 510
516 511 extmodules = [
517 512 Extension('mercurial.base85', ['mercurial/base85.c'],
518 513 depends=common_depends),
519 514 Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
520 515 depends=common_depends),
521 516 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
522 517 depends=common_depends),
523 518 Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
524 519 depends=common_depends),
525 520 Extension('mercurial.parsers', ['mercurial/dirs.c',
526 521 'mercurial/manifest.c',
527 522 'mercurial/parsers.c',
528 523 'mercurial/pathencode.c'],
529 524 depends=common_depends),
530 525 Extension('mercurial.osutil', ['mercurial/osutil.c'],
531 526 extra_link_args=osutil_ldflags,
532 527 depends=common_depends),
533 528 ]
534 529
535 530 try:
536 531 from distutils import cygwinccompiler
537 532
538 533 # the -mno-cygwin option has been deprecated for years
539 534 compiler = cygwinccompiler.Mingw32CCompiler
540 535
541 536 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
542 537 def __init__(self, *args, **kwargs):
543 538 compiler.__init__(self, *args, **kwargs)
544 539 for i in 'compiler compiler_so linker_exe linker_so'.split():
545 540 try:
546 541 getattr(self, i).remove('-mno-cygwin')
547 542 except ValueError:
548 543 pass
549 544
550 545 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
551 546 except ImportError:
552 547 # the cygwinccompiler package is not available on some Python
553 548 # distributions like the ones from the optware project for Synology
554 549 # DiskStation boxes
555 550 class HackedMingw32CCompiler(object):
556 551 pass
557 552
558 553 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
559 554 'help/*.txt',
560 555 'help/internals/*.txt',
561 556 'default.d/*.rc',
562 557 'dummycert.pem']}
563 558
564 559 def ordinarypath(p):
565 560 return p and p[0] != '.' and p[-1] != '~'
566 561
567 562 for root in ('templates',):
568 563 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
569 564 curdir = curdir.split(os.sep, 1)[1]
570 565 dirs[:] = filter(ordinarypath, dirs)
571 566 for f in filter(ordinarypath, files):
572 567 f = os.path.join(curdir, f)
573 568 packagedata['mercurial'].append(f)
574 569
575 570 datafiles = []
576 571 setupversion = version
577 572 extra = {}
578 573
579 574 if py2exeloaded:
580 575 extra['console'] = [
581 576 {'script':'hg',
582 577 'copyright':'Copyright (C) 2005-2016 Matt Mackall and others',
583 578 'product_version':version}]
584 579 # sub command of 'build' because 'py2exe' does not handle sub_commands
585 580 build.sub_commands.insert(0, ('build_hgextindex', None))
586 581 # put dlls in sub directory so that they won't pollute PATH
587 582 extra['zipfile'] = 'lib/library.zip'
588 583
589 584 if os.name == 'nt':
590 585 # Windows binary file versions for exe/dll files must have the
591 586 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
592 587 setupversion = version.split('+', 1)[0]
593 588
594 589 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
595 590 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
596 591 if version:
597 592 version = version[0]
598 593 if sys.version_info[0] == 3:
599 594 version = version.decode('utf-8')
600 595 xcode4 = (version.startswith('Xcode') and
601 596 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
602 597 xcode51 = re.match(r'^Xcode\s+5\.1', version) is not None
603 598 else:
604 599 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
605 600 # installed, but instead with only command-line tools. Assume
606 601 # that only happens on >= Lion, thus no PPC support.
607 602 xcode4 = True
608 603 xcode51 = False
609 604
610 605 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
611 606 # distutils.sysconfig
612 607 if xcode4:
613 608 os.environ['ARCHFLAGS'] = ''
614 609
615 610 # XCode 5.1 changes clang such that it now fails to compile if the
616 611 # -mno-fused-madd flag is passed, but the version of Python shipped with
617 612 # OS X 10.9 Mavericks includes this flag. This causes problems in all
618 613 # C extension modules, and a bug has been filed upstream at
619 614 # http://bugs.python.org/issue21244. We also need to patch this here
620 615 # so Mercurial can continue to compile in the meantime.
621 616 if xcode51:
622 617 cflags = get_config_var('CFLAGS')
623 618 if cflags and re.search(r'-mno-fused-madd\b', cflags) is not None:
624 619 os.environ['CFLAGS'] = (
625 620 os.environ.get('CFLAGS', '') + ' -Qunused-arguments')
626 621
627 622 setup(name='mercurial',
628 623 version=setupversion,
629 624 author='Matt Mackall and many others',
630 625 author_email='mercurial@selenic.com',
631 626 url='https://mercurial-scm.org/',
632 627 download_url='https://mercurial-scm.org/release/',
633 628 description=('Fast scalable distributed SCM (revision control, version '
634 629 'control) system'),
635 630 long_description=('Mercurial is a distributed SCM tool written in Python.'
636 631 ' It is used by a number of large projects that require'
637 632 ' fast, reliable distributed revision control, such as '
638 633 'Mozilla.'),
639 634 license='GNU GPLv2 or any later version',
640 635 classifiers=[
641 636 'Development Status :: 6 - Mature',
642 637 'Environment :: Console',
643 638 'Intended Audience :: Developers',
644 639 'Intended Audience :: System Administrators',
645 640 'License :: OSI Approved :: GNU General Public License (GPL)',
646 641 'Natural Language :: Danish',
647 642 'Natural Language :: English',
648 643 'Natural Language :: German',
649 644 'Natural Language :: Italian',
650 645 'Natural Language :: Japanese',
651 646 'Natural Language :: Portuguese (Brazilian)',
652 647 'Operating System :: Microsoft :: Windows',
653 648 'Operating System :: OS Independent',
654 649 'Operating System :: POSIX',
655 650 'Programming Language :: C',
656 651 'Programming Language :: Python',
657 652 'Topic :: Software Development :: Version Control',
658 653 ],
659 654 scripts=scripts,
660 655 packages=packages,
661 656 ext_modules=extmodules,
662 657 data_files=datafiles,
663 658 package_data=packagedata,
664 659 cmdclass=cmdclass,
665 660 distclass=hgdist,
666 661 options={'py2exe': {'packages': ['hgext', 'email']},
667 662 'bdist_mpkg': {'zipdist': False,
668 663 'license': 'COPYING',
669 664 'readme': 'contrib/macosx/Readme.html',
670 665 'welcome': 'contrib/macosx/Welcome.html',
671 666 },
672 667 },
673 668 **extra)
General Comments 0
You need to be logged in to leave comments. Login now