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