##// END OF EJS Templates
setup: drop support for Python 2.6 (BC)...
Gregory Szorc -
r32228:feb910d2 default
parent child Browse files
Show More
@@ -1,53 +1,53 b''
1 Source: mercurial
1 Source: mercurial
2 Section: vcs
2 Section: vcs
3 Priority: optional
3 Priority: optional
4 Maintainer: Mercurial Developers <mercurial-devel@mercurial-scm.org>
4 Maintainer: Mercurial Developers <mercurial-devel@mercurial-scm.org>
5 Build-Depends:
5 Build-Depends:
6 debhelper (>= 9),
6 debhelper (>= 9),
7 dh-python,
7 dh-python,
8 netbase,
8 netbase,
9 python-all,
9 python-all,
10 python-all-dev,
10 python-all-dev,
11 python-docutils,
11 python-docutils,
12 unzip,
12 unzip,
13 zip
13 zip
14 Standards-Version: 3.9.4
14 Standards-Version: 3.9.4
15 X-Python-Version: >= 2.6
15 X-Python-Version: >= 2.7
16
16
17 Package: mercurial
17 Package: mercurial
18 Depends:
18 Depends:
19 python,
19 python,
20 ${shlibs:Depends},
20 ${shlibs:Depends},
21 ${misc:Depends},
21 ${misc:Depends},
22 ${python:Depends},
22 ${python:Depends},
23 mercurial-common (= ${source:Version})
23 mercurial-common (= ${source:Version})
24 Architecture: any
24 Architecture: any
25 Description: fast, easy to use, distributed revision control tool.
25 Description: fast, easy to use, distributed revision control tool.
26 Mercurial is a fast, lightweight Source Control Management system designed
26 Mercurial is a fast, lightweight Source Control Management system designed
27 for efficient handling of very large distributed projects.
27 for efficient handling of very large distributed projects.
28 .
28 .
29 Its features include:
29 Its features include:
30 * O(1) delta-compressed file storage and retrieval scheme
30 * O(1) delta-compressed file storage and retrieval scheme
31 * Complete cross-indexing of files and changesets for efficient exploration
31 * Complete cross-indexing of files and changesets for efficient exploration
32 of project history
32 of project history
33 * Robust SHA1-based integrity checking and append-only storage model
33 * Robust SHA1-based integrity checking and append-only storage model
34 * Decentralized development model with arbitrary merging between trees
34 * Decentralized development model with arbitrary merging between trees
35 * Easy-to-use command-line interface
35 * Easy-to-use command-line interface
36 * Integrated stand-alone web interface
36 * Integrated stand-alone web interface
37 * Small Python codebase
37 * Small Python codebase
38
38
39 Package: mercurial-common
39 Package: mercurial-common
40 Architecture: all
40 Architecture: all
41 Depends:
41 Depends:
42 ${misc:Depends},
42 ${misc:Depends},
43 ${python:Depends},
43 ${python:Depends},
44 Recommends: mercurial (= ${source:Version}), ca-certificates
44 Recommends: mercurial (= ${source:Version}), ca-certificates
45 Suggests: wish
45 Suggests: wish
46 Breaks: mercurial (<< ${source:Version})
46 Breaks: mercurial (<< ${source:Version})
47 Replaces: mercurial (<< 2.6.3)
47 Replaces: mercurial (<< 2.6.3)
48 Description: easy-to-use, scalable distributed version control system (common files)
48 Description: easy-to-use, scalable distributed version control system (common files)
49 Mercurial is a fast, lightweight Source Control Management system designed
49 Mercurial is a fast, lightweight Source Control Management system designed
50 for efficient handling of very large distributed projects.
50 for efficient handling of very large distributed projects.
51 .
51 .
52 This package contains the architecture independent components of Mercurial,
52 This package contains the architecture independent components of Mercurial,
53 and is generally useless without the mercurial package.
53 and is generally useless without the mercurial package.
@@ -1,162 +1,162 b''
1 %global emacs_lispdir %{_datadir}/emacs/site-lisp
1 %global emacs_lispdir %{_datadir}/emacs/site-lisp
2
2
3 %define withpython %{nil}
3 %define withpython %{nil}
4
4
5 %if "%{?withpython}"
5 %if "%{?withpython}"
6
6
7 %global pythonver %{withpython}
7 %global pythonver %{withpython}
8 %global pythonname Python-%{withpython}
8 %global pythonname Python-%{withpython}
9 %global docutilsname docutils-0.12
9 %global docutilsname docutils-0.12
10 %global docutilsmd5 4622263b62c5c771c03502afa3157768
10 %global docutilsmd5 4622263b62c5c771c03502afa3157768
11 %global pythonhg python-hg
11 %global pythonhg python-hg
12 %global hgpyprefix /opt/%{pythonhg}
12 %global hgpyprefix /opt/%{pythonhg}
13 # byte compilation will fail on some some Python /test/ files
13 # byte compilation will fail on some some Python /test/ files
14 %global _python_bytecompile_errors_terminate_build 0
14 %global _python_bytecompile_errors_terminate_build 0
15
15
16 %else
16 %else
17
17
18 %global pythonver %(python -c 'import sys;print ".".join(map(str, sys.version_info[:2]))')
18 %global pythonver %(python -c 'import sys;print ".".join(map(str, sys.version_info[:2]))')
19
19
20 %endif
20 %endif
21
21
22 Summary: A fast, lightweight Source Control Management system
22 Summary: A fast, lightweight Source Control Management system
23 Name: mercurial
23 Name: mercurial
24 Version: snapshot
24 Version: snapshot
25 Release: 0
25 Release: 0
26 License: GPLv2+
26 License: GPLv2+
27 Group: Development/Tools
27 Group: Development/Tools
28 URL: https://mercurial-scm.org/
28 URL: https://mercurial-scm.org/
29 Source0: %{name}-%{version}-%{release}.tar.gz
29 Source0: %{name}-%{version}-%{release}.tar.gz
30 %if "%{?withpython}"
30 %if "%{?withpython}"
31 Source1: %{pythonname}.tgz
31 Source1: %{pythonname}.tgz
32 Source2: %{docutilsname}.tar.gz
32 Source2: %{docutilsname}.tar.gz
33 %endif
33 %endif
34 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
34 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
35
35
36 BuildRequires: make, gcc, gettext
36 BuildRequires: make, gcc, gettext
37 %if "%{?withpython}"
37 %if "%{?withpython}"
38 BuildRequires: readline-devel, openssl-devel, ncurses-devel, zlib-devel, bzip2-devel
38 BuildRequires: readline-devel, openssl-devel, ncurses-devel, zlib-devel, bzip2-devel
39 %else
39 %else
40 BuildRequires: python >= 2.6, python-devel, python-docutils >= 0.5
40 BuildRequires: python >= 2.7, python-devel, python-docutils >= 0.5
41 Requires: python >= 2.6
41 Requires: python >= 2.7
42 %endif
42 %endif
43 # The hgk extension uses the wish tcl interpreter, but we don't enforce it
43 # The hgk extension uses the wish tcl interpreter, but we don't enforce it
44 #Requires: tk
44 #Requires: tk
45
45
46 %description
46 %description
47 Mercurial is a fast, lightweight source control management system designed
47 Mercurial is a fast, lightweight source control management system designed
48 for efficient handling of very large distributed projects.
48 for efficient handling of very large distributed projects.
49
49
50 %prep
50 %prep
51
51
52 %if "%{?withpython}"
52 %if "%{?withpython}"
53 %setup -q -n mercurial-%{version}-%{release} -a1 -a2
53 %setup -q -n mercurial-%{version}-%{release} -a1 -a2
54 # despite the comments in cgi.py, we do this to prevent rpmdeps from picking /usr/local/bin/python up
54 # despite the comments in cgi.py, we do this to prevent rpmdeps from picking /usr/local/bin/python up
55 sed -i '1c#! /usr/bin/env python' %{pythonname}/Lib/cgi.py
55 sed -i '1c#! /usr/bin/env python' %{pythonname}/Lib/cgi.py
56 %else
56 %else
57 %setup -q -n mercurial-%{version}-%{release}
57 %setup -q -n mercurial-%{version}-%{release}
58 %endif
58 %endif
59
59
60 %build
60 %build
61
61
62 %if "%{?withpython}"
62 %if "%{?withpython}"
63
63
64 PYPATH=$PWD/%{pythonname}
64 PYPATH=$PWD/%{pythonname}
65 cd $PYPATH
65 cd $PYPATH
66 ./configure --prefix=%{hgpyprefix}
66 ./configure --prefix=%{hgpyprefix}
67 make all %{?_smp_mflags}
67 make all %{?_smp_mflags}
68 cd -
68 cd -
69
69
70 cd %{docutilsname}
70 cd %{docutilsname}
71 LD_LIBRARY_PATH=$PYPATH $PYPATH/python setup.py build
71 LD_LIBRARY_PATH=$PYPATH $PYPATH/python setup.py build
72 cd -
72 cd -
73
73
74 # verify Python environment
74 # verify Python environment
75 LD_LIBRARY_PATH=$PYPATH PYTHONPATH=$PWD/%{docutilsname} $PYPATH/python -c 'import sys, zlib, bz2, ssl, curses, readline'
75 LD_LIBRARY_PATH=$PYPATH PYTHONPATH=$PWD/%{docutilsname} $PYPATH/python -c 'import sys, zlib, bz2, ssl, curses, readline'
76
76
77 # set environment for make
77 # set environment for make
78 export PATH=$PYPATH:$PATH
78 export PATH=$PYPATH:$PATH
79 export LD_LIBRARY_PATH=$PYPATH
79 export LD_LIBRARY_PATH=$PYPATH
80 export CFLAGS="-L $PYPATH"
80 export CFLAGS="-L $PYPATH"
81 export PYTHONPATH=$PWD/%{docutilsname}
81 export PYTHONPATH=$PWD/%{docutilsname}
82
82
83 %endif
83 %endif
84
84
85 make all
85 make all
86
86
87 %install
87 %install
88 rm -rf $RPM_BUILD_ROOT
88 rm -rf $RPM_BUILD_ROOT
89
89
90 %if "%{?withpython}"
90 %if "%{?withpython}"
91
91
92 PYPATH=$PWD/%{pythonname}
92 PYPATH=$PWD/%{pythonname}
93 cd $PYPATH
93 cd $PYPATH
94 make install DESTDIR=$RPM_BUILD_ROOT
94 make install DESTDIR=$RPM_BUILD_ROOT
95 # these .a are not necessary and they are readonly and strip fails - kill them!
95 # these .a are not necessary and they are readonly and strip fails - kill them!
96 rm -f %{buildroot}%{hgpyprefix}/lib/{,python2.*/config}/libpython2.*.a
96 rm -f %{buildroot}%{hgpyprefix}/lib/{,python2.*/config}/libpython2.*.a
97 cd -
97 cd -
98
98
99 cd %{docutilsname}
99 cd %{docutilsname}
100 LD_LIBRARY_PATH=$PYPATH $PYPATH/python setup.py install --root="$RPM_BUILD_ROOT"
100 LD_LIBRARY_PATH=$PYPATH $PYPATH/python setup.py install --root="$RPM_BUILD_ROOT"
101 cd -
101 cd -
102
102
103 PATH=$PYPATH:$PATH LD_LIBRARY_PATH=$PYPATH make install DESTDIR=$RPM_BUILD_ROOT PREFIX=%{hgpyprefix} MANDIR=%{_mandir}
103 PATH=$PYPATH:$PATH LD_LIBRARY_PATH=$PYPATH make install DESTDIR=$RPM_BUILD_ROOT PREFIX=%{hgpyprefix} MANDIR=%{_mandir}
104 mkdir -p $RPM_BUILD_ROOT%{_bindir}
104 mkdir -p $RPM_BUILD_ROOT%{_bindir}
105 ( cd $RPM_BUILD_ROOT%{_bindir}/ && ln -s ../..%{hgpyprefix}/bin/hg . )
105 ( cd $RPM_BUILD_ROOT%{_bindir}/ && ln -s ../..%{hgpyprefix}/bin/hg . )
106 ( cd $RPM_BUILD_ROOT%{_bindir}/ && ln -s ../..%{hgpyprefix}/bin/python2.? %{pythonhg} )
106 ( cd $RPM_BUILD_ROOT%{_bindir}/ && ln -s ../..%{hgpyprefix}/bin/python2.? %{pythonhg} )
107
107
108 %else
108 %else
109
109
110 make install DESTDIR=$RPM_BUILD_ROOT PREFIX=%{_prefix} MANDIR=%{_mandir}
110 make install DESTDIR=$RPM_BUILD_ROOT PREFIX=%{_prefix} MANDIR=%{_mandir}
111
111
112 %endif
112 %endif
113
113
114 install -m 755 contrib/hgk $RPM_BUILD_ROOT%{_bindir}/
114 install -m 755 contrib/hgk $RPM_BUILD_ROOT%{_bindir}/
115 install -m 755 contrib/hg-ssh $RPM_BUILD_ROOT%{_bindir}/
115 install -m 755 contrib/hg-ssh $RPM_BUILD_ROOT%{_bindir}/
116
116
117 bash_completion_dir=$RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d
117 bash_completion_dir=$RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d
118 mkdir -p $bash_completion_dir
118 mkdir -p $bash_completion_dir
119 install -m 644 contrib/bash_completion $bash_completion_dir/mercurial.sh
119 install -m 644 contrib/bash_completion $bash_completion_dir/mercurial.sh
120
120
121 zsh_completion_dir=$RPM_BUILD_ROOT%{_datadir}/zsh/site-functions
121 zsh_completion_dir=$RPM_BUILD_ROOT%{_datadir}/zsh/site-functions
122 mkdir -p $zsh_completion_dir
122 mkdir -p $zsh_completion_dir
123 install -m 644 contrib/zsh_completion $zsh_completion_dir/_mercurial
123 install -m 644 contrib/zsh_completion $zsh_completion_dir/_mercurial
124
124
125 mkdir -p $RPM_BUILD_ROOT%{emacs_lispdir}
125 mkdir -p $RPM_BUILD_ROOT%{emacs_lispdir}
126 install -m 644 contrib/mercurial.el $RPM_BUILD_ROOT%{emacs_lispdir}/
126 install -m 644 contrib/mercurial.el $RPM_BUILD_ROOT%{emacs_lispdir}/
127 install -m 644 contrib/mq.el $RPM_BUILD_ROOT%{emacs_lispdir}/
127 install -m 644 contrib/mq.el $RPM_BUILD_ROOT%{emacs_lispdir}/
128
128
129 mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/mercurial/hgrc.d
129 mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/mercurial/hgrc.d
130
130
131 %clean
131 %clean
132 rm -rf $RPM_BUILD_ROOT
132 rm -rf $RPM_BUILD_ROOT
133
133
134 %files
134 %files
135 %defattr(-,root,root,-)
135 %defattr(-,root,root,-)
136 %doc CONTRIBUTORS COPYING doc/README doc/hg*.txt doc/hg*.html *.cgi contrib/*.fcgi
136 %doc CONTRIBUTORS COPYING doc/README doc/hg*.txt doc/hg*.html *.cgi contrib/*.fcgi
137 %doc %attr(644,root,root) %{_mandir}/man?/hg*
137 %doc %attr(644,root,root) %{_mandir}/man?/hg*
138 %doc %attr(644,root,root) contrib/*.svg
138 %doc %attr(644,root,root) contrib/*.svg
139 %dir %{_datadir}/zsh/
139 %dir %{_datadir}/zsh/
140 %dir %{_datadir}/zsh/site-functions/
140 %dir %{_datadir}/zsh/site-functions/
141 %{_datadir}/zsh/site-functions/_mercurial
141 %{_datadir}/zsh/site-functions/_mercurial
142 %dir %{_datadir}/emacs/site-lisp/
142 %dir %{_datadir}/emacs/site-lisp/
143 %{_datadir}/emacs/site-lisp/mercurial.el
143 %{_datadir}/emacs/site-lisp/mercurial.el
144 %{_datadir}/emacs/site-lisp/mq.el
144 %{_datadir}/emacs/site-lisp/mq.el
145 %{_bindir}/hg
145 %{_bindir}/hg
146 %{_bindir}/hgk
146 %{_bindir}/hgk
147 %{_bindir}/hg-ssh
147 %{_bindir}/hg-ssh
148 %dir %{_sysconfdir}/bash_completion.d/
148 %dir %{_sysconfdir}/bash_completion.d/
149 %config(noreplace) %{_sysconfdir}/bash_completion.d/mercurial.sh
149 %config(noreplace) %{_sysconfdir}/bash_completion.d/mercurial.sh
150 %dir %{_sysconfdir}/mercurial
150 %dir %{_sysconfdir}/mercurial
151 %dir %{_sysconfdir}/mercurial/hgrc.d
151 %dir %{_sysconfdir}/mercurial/hgrc.d
152 %if "%{?withpython}"
152 %if "%{?withpython}"
153 %{_bindir}/%{pythonhg}
153 %{_bindir}/%{pythonhg}
154 %{hgpyprefix}
154 %{hgpyprefix}
155 %else
155 %else
156 %if "%{?pythonver}" != "2.4"
156 %if "%{?pythonver}" != "2.4"
157 %{_libdir}/python%{pythonver}/site-packages/%{name}-*-py%{pythonver}.egg-info
157 %{_libdir}/python%{pythonver}/site-packages/%{name}-*-py%{pythonver}.egg-info
158 %endif
158 %endif
159 %{_libdir}/python%{pythonver}/site-packages/%{name}
159 %{_libdir}/python%{pythonver}/site-packages/%{name}
160 %{_libdir}/python%{pythonver}/site-packages/hgext
160 %{_libdir}/python%{pythonver}/site-packages/hgext
161 %{_libdir}/python%{pythonver}/site-packages/hgext3rd
161 %{_libdir}/python%{pythonver}/site-packages/hgext3rd
162 %endif
162 %endif
@@ -1,799 +1,799 b''
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 sys.version_info < (2, 6, 0, 'final'):
8 if sys.version_info < (2, 7, 0, 'final'):
9 raise SystemExit("Mercurial requires Python 2.6 or later.")
9 raise SystemExit('Mercurial requires Python 2.7 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 ctypes
60 import ctypes
61 import os, stat, subprocess, time
61 import os, stat, subprocess, time
62 import re
62 import re
63 import shutil
63 import shutil
64 import tempfile
64 import tempfile
65 from distutils import log
65 from distutils import log
66 # We have issues with setuptools on some platforms and builders. Until
66 # We have issues with setuptools on some platforms and builders. Until
67 # those are resolved, setuptools is opt-in except for platforms where
67 # those are resolved, setuptools is opt-in except for platforms where
68 # we don't have issues.
68 # we don't have issues.
69 if os.name == 'nt' or 'FORCE_SETUPTOOLS' in os.environ:
69 if os.name == 'nt' or 'FORCE_SETUPTOOLS' in os.environ:
70 from setuptools import setup
70 from setuptools import setup
71 else:
71 else:
72 from distutils.core import setup
72 from distutils.core import setup
73 from distutils.ccompiler import new_compiler
73 from distutils.ccompiler import new_compiler
74 from distutils.core import Command, Extension
74 from distutils.core import Command, Extension
75 from distutils.dist import Distribution
75 from distutils.dist import Distribution
76 from distutils.command.build import build
76 from distutils.command.build import build
77 from distutils.command.build_ext import build_ext
77 from distutils.command.build_ext import build_ext
78 from distutils.command.build_py import build_py
78 from distutils.command.build_py import build_py
79 from distutils.command.build_scripts import build_scripts
79 from distutils.command.build_scripts import build_scripts
80 from distutils.command.install_lib import install_lib
80 from distutils.command.install_lib import install_lib
81 from distutils.command.install_scripts import install_scripts
81 from distutils.command.install_scripts import install_scripts
82 from distutils.spawn import spawn, find_executable
82 from distutils.spawn import spawn, find_executable
83 from distutils import file_util
83 from distutils import file_util
84 from distutils.errors import (
84 from distutils.errors import (
85 CCompilerError,
85 CCompilerError,
86 DistutilsError,
86 DistutilsError,
87 DistutilsExecError,
87 DistutilsExecError,
88 )
88 )
89 from distutils.sysconfig import get_python_inc, get_config_var
89 from distutils.sysconfig import get_python_inc, get_config_var
90 from distutils.version import StrictVersion
90 from distutils.version import StrictVersion
91
91
92 scripts = ['hg']
92 scripts = ['hg']
93 if os.name == 'nt':
93 if os.name == 'nt':
94 # We remove hg.bat if we are able to build hg.exe.
94 # We remove hg.bat if we are able to build hg.exe.
95 scripts.append('contrib/win32/hg.bat')
95 scripts.append('contrib/win32/hg.bat')
96
96
97 def cancompile(cc, code):
97 def cancompile(cc, code):
98 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
98 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
99 devnull = oldstderr = None
99 devnull = oldstderr = None
100 try:
100 try:
101 fname = os.path.join(tmpdir, 'testcomp.c')
101 fname = os.path.join(tmpdir, 'testcomp.c')
102 f = open(fname, 'w')
102 f = open(fname, 'w')
103 f.write(code)
103 f.write(code)
104 f.close()
104 f.close()
105 # Redirect stderr to /dev/null to hide any error messages
105 # Redirect stderr to /dev/null to hide any error messages
106 # from the compiler.
106 # from the compiler.
107 # This will have to be changed if we ever have to check
107 # This will have to be changed if we ever have to check
108 # for a function on Windows.
108 # for a function on Windows.
109 devnull = open('/dev/null', 'w')
109 devnull = open('/dev/null', 'w')
110 oldstderr = os.dup(sys.stderr.fileno())
110 oldstderr = os.dup(sys.stderr.fileno())
111 os.dup2(devnull.fileno(), sys.stderr.fileno())
111 os.dup2(devnull.fileno(), sys.stderr.fileno())
112 objects = cc.compile([fname], output_dir=tmpdir)
112 objects = cc.compile([fname], output_dir=tmpdir)
113 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
113 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
114 return True
114 return True
115 except Exception:
115 except Exception:
116 return False
116 return False
117 finally:
117 finally:
118 if oldstderr is not None:
118 if oldstderr is not None:
119 os.dup2(oldstderr, sys.stderr.fileno())
119 os.dup2(oldstderr, sys.stderr.fileno())
120 if devnull is not None:
120 if devnull is not None:
121 devnull.close()
121 devnull.close()
122 shutil.rmtree(tmpdir)
122 shutil.rmtree(tmpdir)
123
123
124 # simplified version of distutils.ccompiler.CCompiler.has_function
124 # simplified version of distutils.ccompiler.CCompiler.has_function
125 # that actually removes its temporary files.
125 # that actually removes its temporary files.
126 def hasfunction(cc, funcname):
126 def hasfunction(cc, funcname):
127 code = 'int main(void) { %s(); }\n' % funcname
127 code = 'int main(void) { %s(); }\n' % funcname
128 return cancompile(cc, code)
128 return cancompile(cc, code)
129
129
130 def hasheader(cc, headername):
130 def hasheader(cc, headername):
131 code = '#include <%s>\nint main(void) { return 0; }\n' % headername
131 code = '#include <%s>\nint main(void) { return 0; }\n' % headername
132 return cancompile(cc, code)
132 return cancompile(cc, code)
133
133
134 # py2exe needs to be installed to work
134 # py2exe needs to be installed to work
135 try:
135 try:
136 import py2exe
136 import py2exe
137 py2exe.Distribution # silence unused import warning
137 py2exe.Distribution # silence unused import warning
138 py2exeloaded = True
138 py2exeloaded = True
139 # import py2exe's patched Distribution class
139 # import py2exe's patched Distribution class
140 from distutils.core import Distribution
140 from distutils.core import Distribution
141 except ImportError:
141 except ImportError:
142 py2exeloaded = False
142 py2exeloaded = False
143
143
144 def runcmd(cmd, env):
144 def runcmd(cmd, env):
145 if (sys.platform == 'plan9'
145 if (sys.platform == 'plan9'
146 and (sys.version_info[0] == 2 and sys.version_info[1] < 7)):
146 and (sys.version_info[0] == 2 and sys.version_info[1] < 7)):
147 # subprocess kludge to work around issues in half-baked Python
147 # subprocess kludge to work around issues in half-baked Python
148 # ports, notably bichued/python:
148 # ports, notably bichued/python:
149 _, out, err = os.popen3(cmd)
149 _, out, err = os.popen3(cmd)
150 return str(out), str(err)
150 return str(out), str(err)
151 else:
151 else:
152 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
152 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
153 stderr=subprocess.PIPE, env=env)
153 stderr=subprocess.PIPE, env=env)
154 out, err = p.communicate()
154 out, err = p.communicate()
155 return out, err
155 return out, err
156
156
157 def runhg(cmd, env):
157 def runhg(cmd, env):
158 out, err = runcmd(cmd, env)
158 out, err = runcmd(cmd, env)
159 # If root is executing setup.py, but the repository is owned by
159 # If root is executing setup.py, but the repository is owned by
160 # another user (as in "sudo python setup.py install") we will get
160 # another user (as in "sudo python setup.py install") we will get
161 # trust warnings since the .hg/hgrc file is untrusted. That is
161 # trust warnings since the .hg/hgrc file is untrusted. That is
162 # fine, we don't want to load it anyway. Python may warn about
162 # fine, we don't want to load it anyway. Python may warn about
163 # a missing __init__.py in mercurial/locale, we also ignore that.
163 # a missing __init__.py in mercurial/locale, we also ignore that.
164 err = [e for e in err.splitlines()
164 err = [e for e in err.splitlines()
165 if not e.startswith(b'not trusting file') \
165 if not e.startswith(b'not trusting file') \
166 and not e.startswith(b'warning: Not importing') \
166 and not e.startswith(b'warning: Not importing') \
167 and not e.startswith(b'obsolete feature not enabled')]
167 and not e.startswith(b'obsolete feature not enabled')]
168 if err:
168 if err:
169 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr)
169 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr)
170 printf(b'\n'.join([b' ' + e for e in err]), file=sys.stderr)
170 printf(b'\n'.join([b' ' + e for e in err]), file=sys.stderr)
171 return ''
171 return ''
172 return out
172 return out
173
173
174 version = ''
174 version = ''
175
175
176 # Execute hg out of this directory with a custom environment which takes care
176 # Execute hg out of this directory with a custom environment which takes care
177 # to not use any hgrc files and do no localization.
177 # to not use any hgrc files and do no localization.
178 env = {'HGMODULEPOLICY': 'py',
178 env = {'HGMODULEPOLICY': 'py',
179 'HGRCPATH': '',
179 'HGRCPATH': '',
180 'LANGUAGE': 'C',
180 'LANGUAGE': 'C',
181 'PATH': ''} # make pypi modules that use os.environ['PATH'] happy
181 'PATH': ''} # make pypi modules that use os.environ['PATH'] happy
182 if 'LD_LIBRARY_PATH' in os.environ:
182 if 'LD_LIBRARY_PATH' in os.environ:
183 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
183 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
184 if 'SystemRoot' in os.environ:
184 if 'SystemRoot' in os.environ:
185 # Copy SystemRoot into the custom environment for Python 2.6
185 # Copy SystemRoot into the custom environment for Python 2.6
186 # under Windows. Otherwise, the subprocess will fail with
186 # under Windows. Otherwise, the subprocess will fail with
187 # error 0xc0150004. See: http://bugs.python.org/issue3440
187 # error 0xc0150004. See: http://bugs.python.org/issue3440
188 env['SystemRoot'] = os.environ['SystemRoot']
188 env['SystemRoot'] = os.environ['SystemRoot']
189
189
190 if os.path.isdir('.hg'):
190 if os.path.isdir('.hg'):
191 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
191 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
192 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
192 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
193 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
193 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
194 if numerictags: # tag(s) found
194 if numerictags: # tag(s) found
195 version = numerictags[-1]
195 version = numerictags[-1]
196 if hgid.endswith('+'): # propagate the dirty status to the tag
196 if hgid.endswith('+'): # propagate the dirty status to the tag
197 version += '+'
197 version += '+'
198 else: # no tag found
198 else: # no tag found
199 ltagcmd = [sys.executable, 'hg', 'parents', '--template',
199 ltagcmd = [sys.executable, 'hg', 'parents', '--template',
200 '{latesttag}']
200 '{latesttag}']
201 ltag = runhg(ltagcmd, env)
201 ltag = runhg(ltagcmd, env)
202 changessincecmd = [sys.executable, 'hg', 'log', '-T', 'x\n', '-r',
202 changessincecmd = [sys.executable, 'hg', 'log', '-T', 'x\n', '-r',
203 "only(.,'%s')" % ltag]
203 "only(.,'%s')" % ltag]
204 changessince = len(runhg(changessincecmd, env).splitlines())
204 changessince = len(runhg(changessincecmd, env).splitlines())
205 version = '%s+%s-%s' % (ltag, changessince, hgid)
205 version = '%s+%s-%s' % (ltag, changessince, hgid)
206 if version.endswith('+'):
206 if version.endswith('+'):
207 version += time.strftime('%Y%m%d')
207 version += time.strftime('%Y%m%d')
208 elif os.path.exists('.hg_archival.txt'):
208 elif os.path.exists('.hg_archival.txt'):
209 kw = dict([[t.strip() for t in l.split(':', 1)]
209 kw = dict([[t.strip() for t in l.split(':', 1)]
210 for l in open('.hg_archival.txt')])
210 for l in open('.hg_archival.txt')])
211 if 'tag' in kw:
211 if 'tag' in kw:
212 version = kw['tag']
212 version = kw['tag']
213 elif 'latesttag' in kw:
213 elif 'latesttag' in kw:
214 if 'changessincelatesttag' in kw:
214 if 'changessincelatesttag' in kw:
215 version = '%(latesttag)s+%(changessincelatesttag)s-%(node).12s' % kw
215 version = '%(latesttag)s+%(changessincelatesttag)s-%(node).12s' % kw
216 else:
216 else:
217 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
217 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
218 else:
218 else:
219 version = kw.get('node', '')[:12]
219 version = kw.get('node', '')[:12]
220
220
221 if version:
221 if version:
222 with open("mercurial/__version__.py", "w") as f:
222 with open("mercurial/__version__.py", "w") as f:
223 f.write('# this file is autogenerated by setup.py\n')
223 f.write('# this file is autogenerated by setup.py\n')
224 f.write('version = "%s"\n' % version)
224 f.write('version = "%s"\n' % version)
225
225
226 try:
226 try:
227 oldpolicy = os.environ.get('HGMODULEPOLICY', None)
227 oldpolicy = os.environ.get('HGMODULEPOLICY', None)
228 os.environ['HGMODULEPOLICY'] = 'py'
228 os.environ['HGMODULEPOLICY'] = 'py'
229 from mercurial import __version__
229 from mercurial import __version__
230 version = __version__.version
230 version = __version__.version
231 except ImportError:
231 except ImportError:
232 version = 'unknown'
232 version = 'unknown'
233 finally:
233 finally:
234 if oldpolicy is None:
234 if oldpolicy is None:
235 del os.environ['HGMODULEPOLICY']
235 del os.environ['HGMODULEPOLICY']
236 else:
236 else:
237 os.environ['HGMODULEPOLICY'] = oldpolicy
237 os.environ['HGMODULEPOLICY'] = oldpolicy
238
238
239 class hgbuild(build):
239 class hgbuild(build):
240 # Insert hgbuildmo first so that files in mercurial/locale/ are found
240 # Insert hgbuildmo first so that files in mercurial/locale/ are found
241 # when build_py is run next.
241 # when build_py is run next.
242 sub_commands = [('build_mo', None)] + build.sub_commands
242 sub_commands = [('build_mo', None)] + build.sub_commands
243
243
244 class hgbuildmo(build):
244 class hgbuildmo(build):
245
245
246 description = "build translations (.mo files)"
246 description = "build translations (.mo files)"
247
247
248 def run(self):
248 def run(self):
249 if not find_executable('msgfmt'):
249 if not find_executable('msgfmt'):
250 self.warn("could not find msgfmt executable, no translations "
250 self.warn("could not find msgfmt executable, no translations "
251 "will be built")
251 "will be built")
252 return
252 return
253
253
254 podir = 'i18n'
254 podir = 'i18n'
255 if not os.path.isdir(podir):
255 if not os.path.isdir(podir):
256 self.warn("could not find %s/ directory" % podir)
256 self.warn("could not find %s/ directory" % podir)
257 return
257 return
258
258
259 join = os.path.join
259 join = os.path.join
260 for po in os.listdir(podir):
260 for po in os.listdir(podir):
261 if not po.endswith('.po'):
261 if not po.endswith('.po'):
262 continue
262 continue
263 pofile = join(podir, po)
263 pofile = join(podir, po)
264 modir = join('locale', po[:-3], 'LC_MESSAGES')
264 modir = join('locale', po[:-3], 'LC_MESSAGES')
265 mofile = join(modir, 'hg.mo')
265 mofile = join(modir, 'hg.mo')
266 mobuildfile = join('mercurial', mofile)
266 mobuildfile = join('mercurial', mofile)
267 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
267 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
268 if sys.platform != 'sunos5':
268 if sys.platform != 'sunos5':
269 # msgfmt on Solaris does not know about -c
269 # msgfmt on Solaris does not know about -c
270 cmd.append('-c')
270 cmd.append('-c')
271 self.mkpath(join('mercurial', modir))
271 self.mkpath(join('mercurial', modir))
272 self.make_file([pofile], mobuildfile, spawn, (cmd,))
272 self.make_file([pofile], mobuildfile, spawn, (cmd,))
273
273
274
274
275 class hgdist(Distribution):
275 class hgdist(Distribution):
276 pure = False
276 pure = False
277 cffi = ispypy
277 cffi = ispypy
278
278
279 global_options = Distribution.global_options + \
279 global_options = Distribution.global_options + \
280 [('pure', None, "use pure (slow) Python "
280 [('pure', None, "use pure (slow) Python "
281 "code instead of C extensions"),
281 "code instead of C extensions"),
282 ]
282 ]
283
283
284 def has_ext_modules(self):
284 def has_ext_modules(self):
285 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
285 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
286 # too late for some cases
286 # too late for some cases
287 return not self.pure and Distribution.has_ext_modules(self)
287 return not self.pure and Distribution.has_ext_modules(self)
288
288
289 # This is ugly as a one-liner. So use a variable.
289 # This is ugly as a one-liner. So use a variable.
290 buildextnegops = dict(getattr(build_ext, 'negative_options', {}))
290 buildextnegops = dict(getattr(build_ext, 'negative_options', {}))
291 buildextnegops['no-zstd'] = 'zstd'
291 buildextnegops['no-zstd'] = 'zstd'
292
292
293 class hgbuildext(build_ext):
293 class hgbuildext(build_ext):
294 user_options = build_ext.user_options + [
294 user_options = build_ext.user_options + [
295 ('zstd', None, 'compile zstd bindings [default]'),
295 ('zstd', None, 'compile zstd bindings [default]'),
296 ('no-zstd', None, 'do not compile zstd bindings'),
296 ('no-zstd', None, 'do not compile zstd bindings'),
297 ]
297 ]
298
298
299 boolean_options = build_ext.boolean_options + ['zstd']
299 boolean_options = build_ext.boolean_options + ['zstd']
300 negative_opt = buildextnegops
300 negative_opt = buildextnegops
301
301
302 def initialize_options(self):
302 def initialize_options(self):
303 self.zstd = True
303 self.zstd = True
304 return build_ext.initialize_options(self)
304 return build_ext.initialize_options(self)
305
305
306 def build_extensions(self):
306 def build_extensions(self):
307 # Filter out zstd if disabled via argument.
307 # Filter out zstd if disabled via argument.
308 if not self.zstd:
308 if not self.zstd:
309 self.extensions = [e for e in self.extensions
309 self.extensions = [e for e in self.extensions
310 if e.name != 'mercurial.zstd']
310 if e.name != 'mercurial.zstd']
311
311
312 return build_ext.build_extensions(self)
312 return build_ext.build_extensions(self)
313
313
314 def build_extension(self, ext):
314 def build_extension(self, ext):
315 try:
315 try:
316 build_ext.build_extension(self, ext)
316 build_ext.build_extension(self, ext)
317 except CCompilerError:
317 except CCompilerError:
318 if not getattr(ext, 'optional', False):
318 if not getattr(ext, 'optional', False):
319 raise
319 raise
320 log.warn("Failed to build optional extension '%s' (skipping)",
320 log.warn("Failed to build optional extension '%s' (skipping)",
321 ext.name)
321 ext.name)
322
322
323 class hgbuildscripts(build_scripts):
323 class hgbuildscripts(build_scripts):
324 def run(self):
324 def run(self):
325 if os.name != 'nt' or self.distribution.pure:
325 if os.name != 'nt' or self.distribution.pure:
326 return build_scripts.run(self)
326 return build_scripts.run(self)
327
327
328 exebuilt = False
328 exebuilt = False
329 try:
329 try:
330 self.run_command('build_hgexe')
330 self.run_command('build_hgexe')
331 exebuilt = True
331 exebuilt = True
332 except (DistutilsError, CCompilerError):
332 except (DistutilsError, CCompilerError):
333 log.warn('failed to build optional hg.exe')
333 log.warn('failed to build optional hg.exe')
334
334
335 if exebuilt:
335 if exebuilt:
336 # Copying hg.exe to the scripts build directory ensures it is
336 # Copying hg.exe to the scripts build directory ensures it is
337 # installed by the install_scripts command.
337 # installed by the install_scripts command.
338 hgexecommand = self.get_finalized_command('build_hgexe')
338 hgexecommand = self.get_finalized_command('build_hgexe')
339 dest = os.path.join(self.build_dir, 'hg.exe')
339 dest = os.path.join(self.build_dir, 'hg.exe')
340 self.mkpath(self.build_dir)
340 self.mkpath(self.build_dir)
341 self.copy_file(hgexecommand.hgexepath, dest)
341 self.copy_file(hgexecommand.hgexepath, dest)
342
342
343 # Remove hg.bat because it is redundant with hg.exe.
343 # Remove hg.bat because it is redundant with hg.exe.
344 self.scripts.remove('contrib/win32/hg.bat')
344 self.scripts.remove('contrib/win32/hg.bat')
345
345
346 return build_scripts.run(self)
346 return build_scripts.run(self)
347
347
348 class hgbuildpy(build_py):
348 class hgbuildpy(build_py):
349 def finalize_options(self):
349 def finalize_options(self):
350 build_py.finalize_options(self)
350 build_py.finalize_options(self)
351
351
352 if self.distribution.pure:
352 if self.distribution.pure:
353 self.distribution.ext_modules = []
353 self.distribution.ext_modules = []
354 elif self.distribution.cffi:
354 elif self.distribution.cffi:
355 from mercurial.cffi import (
355 from mercurial.cffi import (
356 bdiff,
356 bdiff,
357 mpatch,
357 mpatch,
358 )
358 )
359 exts = [mpatch.ffi.distutils_extension(),
359 exts = [mpatch.ffi.distutils_extension(),
360 bdiff.ffi.distutils_extension()]
360 bdiff.ffi.distutils_extension()]
361 # cffi modules go here
361 # cffi modules go here
362 if sys.platform == 'darwin':
362 if sys.platform == 'darwin':
363 from mercurial.cffi import osutil
363 from mercurial.cffi import osutil
364 exts.append(osutil.ffi.distutils_extension())
364 exts.append(osutil.ffi.distutils_extension())
365 self.distribution.ext_modules = exts
365 self.distribution.ext_modules = exts
366 else:
366 else:
367 h = os.path.join(get_python_inc(), 'Python.h')
367 h = os.path.join(get_python_inc(), 'Python.h')
368 if not os.path.exists(h):
368 if not os.path.exists(h):
369 raise SystemExit('Python headers are required to build '
369 raise SystemExit('Python headers are required to build '
370 'Mercurial but weren\'t found in %s' % h)
370 'Mercurial but weren\'t found in %s' % h)
371
371
372 def run(self):
372 def run(self):
373 if self.distribution.pure:
373 if self.distribution.pure:
374 modulepolicy = 'py'
374 modulepolicy = 'py'
375 else:
375 else:
376 modulepolicy = 'c'
376 modulepolicy = 'c'
377 with open("mercurial/__modulepolicy__.py", "w") as f:
377 with open("mercurial/__modulepolicy__.py", "w") as f:
378 f.write('# this file is autogenerated by setup.py\n')
378 f.write('# this file is autogenerated by setup.py\n')
379 f.write('modulepolicy = b"%s"\n' % modulepolicy)
379 f.write('modulepolicy = b"%s"\n' % modulepolicy)
380
380
381 build_py.run(self)
381 build_py.run(self)
382
382
383 class buildhgextindex(Command):
383 class buildhgextindex(Command):
384 description = 'generate prebuilt index of hgext (for frozen package)'
384 description = 'generate prebuilt index of hgext (for frozen package)'
385 user_options = []
385 user_options = []
386 _indexfilename = 'hgext/__index__.py'
386 _indexfilename = 'hgext/__index__.py'
387
387
388 def initialize_options(self):
388 def initialize_options(self):
389 pass
389 pass
390
390
391 def finalize_options(self):
391 def finalize_options(self):
392 pass
392 pass
393
393
394 def run(self):
394 def run(self):
395 if os.path.exists(self._indexfilename):
395 if os.path.exists(self._indexfilename):
396 with open(self._indexfilename, 'w') as f:
396 with open(self._indexfilename, 'w') as f:
397 f.write('# empty\n')
397 f.write('# empty\n')
398
398
399 # here no extension enabled, disabled() lists up everything
399 # here no extension enabled, disabled() lists up everything
400 code = ('import pprint; from mercurial import extensions; '
400 code = ('import pprint; from mercurial import extensions; '
401 'pprint.pprint(extensions.disabled())')
401 'pprint.pprint(extensions.disabled())')
402 out, err = runcmd([sys.executable, '-c', code], env)
402 out, err = runcmd([sys.executable, '-c', code], env)
403 if err:
403 if err:
404 raise DistutilsExecError(err)
404 raise DistutilsExecError(err)
405
405
406 with open(self._indexfilename, 'w') as f:
406 with open(self._indexfilename, 'w') as f:
407 f.write('# this file is autogenerated by setup.py\n')
407 f.write('# this file is autogenerated by setup.py\n')
408 f.write('docs = ')
408 f.write('docs = ')
409 f.write(out)
409 f.write(out)
410
410
411 class buildhgexe(build_ext):
411 class buildhgexe(build_ext):
412 description = 'compile hg.exe from mercurial/exewrapper.c'
412 description = 'compile hg.exe from mercurial/exewrapper.c'
413
413
414 def build_extensions(self):
414 def build_extensions(self):
415 if os.name != 'nt':
415 if os.name != 'nt':
416 return
416 return
417 if isinstance(self.compiler, HackedMingw32CCompiler):
417 if isinstance(self.compiler, HackedMingw32CCompiler):
418 self.compiler.compiler_so = self.compiler.compiler # no -mdll
418 self.compiler.compiler_so = self.compiler.compiler # no -mdll
419 self.compiler.dll_libraries = [] # no -lmsrvc90
419 self.compiler.dll_libraries = [] # no -lmsrvc90
420
420
421 # Different Python installs can have different Python library
421 # Different Python installs can have different Python library
422 # names. e.g. the official CPython distribution uses pythonXY.dll
422 # names. e.g. the official CPython distribution uses pythonXY.dll
423 # and MinGW uses libpythonX.Y.dll.
423 # and MinGW uses libpythonX.Y.dll.
424 _kernel32 = ctypes.windll.kernel32
424 _kernel32 = ctypes.windll.kernel32
425 _kernel32.GetModuleFileNameA.argtypes = [ctypes.c_void_p,
425 _kernel32.GetModuleFileNameA.argtypes = [ctypes.c_void_p,
426 ctypes.c_void_p,
426 ctypes.c_void_p,
427 ctypes.c_ulong]
427 ctypes.c_ulong]
428 _kernel32.GetModuleFileNameA.restype = ctypes.c_ulong
428 _kernel32.GetModuleFileNameA.restype = ctypes.c_ulong
429 size = 1000
429 size = 1000
430 buf = ctypes.create_string_buffer(size + 1)
430 buf = ctypes.create_string_buffer(size + 1)
431 filelen = _kernel32.GetModuleFileNameA(sys.dllhandle, ctypes.byref(buf),
431 filelen = _kernel32.GetModuleFileNameA(sys.dllhandle, ctypes.byref(buf),
432 size)
432 size)
433
433
434 if filelen > 0 and filelen != size:
434 if filelen > 0 and filelen != size:
435 dllbasename = os.path.basename(buf.value)
435 dllbasename = os.path.basename(buf.value)
436 if not dllbasename.lower().endswith('.dll'):
436 if not dllbasename.lower().endswith('.dll'):
437 raise SystemExit('Python DLL does not end with .dll: %s' %
437 raise SystemExit('Python DLL does not end with .dll: %s' %
438 dllbasename)
438 dllbasename)
439 pythonlib = dllbasename[:-4]
439 pythonlib = dllbasename[:-4]
440 else:
440 else:
441 log.warn('could not determine Python DLL filename; '
441 log.warn('could not determine Python DLL filename; '
442 'assuming pythonXY')
442 'assuming pythonXY')
443
443
444 hv = sys.hexversion
444 hv = sys.hexversion
445 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
445 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
446
446
447 log.info('using %s as Python library name' % pythonlib)
447 log.info('using %s as Python library name' % pythonlib)
448 with open('mercurial/hgpythonlib.h', 'wb') as f:
448 with open('mercurial/hgpythonlib.h', 'wb') as f:
449 f.write('/* this file is autogenerated by setup.py */\n')
449 f.write('/* this file is autogenerated by setup.py */\n')
450 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
450 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
451 objects = self.compiler.compile(['mercurial/exewrapper.c'],
451 objects = self.compiler.compile(['mercurial/exewrapper.c'],
452 output_dir=self.build_temp)
452 output_dir=self.build_temp)
453 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
453 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
454 target = os.path.join(dir, 'hg')
454 target = os.path.join(dir, 'hg')
455 self.compiler.link_executable(objects, target,
455 self.compiler.link_executable(objects, target,
456 libraries=[],
456 libraries=[],
457 output_dir=self.build_temp)
457 output_dir=self.build_temp)
458
458
459 @property
459 @property
460 def hgexepath(self):
460 def hgexepath(self):
461 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
461 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
462 return os.path.join(self.build_temp, dir, 'hg.exe')
462 return os.path.join(self.build_temp, dir, 'hg.exe')
463
463
464 class hginstalllib(install_lib):
464 class hginstalllib(install_lib):
465 '''
465 '''
466 This is a specialization of install_lib that replaces the copy_file used
466 This is a specialization of install_lib that replaces the copy_file used
467 there so that it supports setting the mode of files after copying them,
467 there so that it supports setting the mode of files after copying them,
468 instead of just preserving the mode that the files originally had. If your
468 instead of just preserving the mode that the files originally had. If your
469 system has a umask of something like 027, preserving the permissions when
469 system has a umask of something like 027, preserving the permissions when
470 copying will lead to a broken install.
470 copying will lead to a broken install.
471
471
472 Note that just passing keep_permissions=False to copy_file would be
472 Note that just passing keep_permissions=False to copy_file would be
473 insufficient, as it might still be applying a umask.
473 insufficient, as it might still be applying a umask.
474 '''
474 '''
475
475
476 def run(self):
476 def run(self):
477 realcopyfile = file_util.copy_file
477 realcopyfile = file_util.copy_file
478 def copyfileandsetmode(*args, **kwargs):
478 def copyfileandsetmode(*args, **kwargs):
479 src, dst = args[0], args[1]
479 src, dst = args[0], args[1]
480 dst, copied = realcopyfile(*args, **kwargs)
480 dst, copied = realcopyfile(*args, **kwargs)
481 if copied:
481 if copied:
482 st = os.stat(src)
482 st = os.stat(src)
483 # Persist executable bit (apply it to group and other if user
483 # Persist executable bit (apply it to group and other if user
484 # has it)
484 # has it)
485 if st[stat.ST_MODE] & stat.S_IXUSR:
485 if st[stat.ST_MODE] & stat.S_IXUSR:
486 setmode = int('0755', 8)
486 setmode = int('0755', 8)
487 else:
487 else:
488 setmode = int('0644', 8)
488 setmode = int('0644', 8)
489 m = stat.S_IMODE(st[stat.ST_MODE])
489 m = stat.S_IMODE(st[stat.ST_MODE])
490 m = (m & ~int('0777', 8)) | setmode
490 m = (m & ~int('0777', 8)) | setmode
491 os.chmod(dst, m)
491 os.chmod(dst, m)
492 file_util.copy_file = copyfileandsetmode
492 file_util.copy_file = copyfileandsetmode
493 try:
493 try:
494 install_lib.run(self)
494 install_lib.run(self)
495 finally:
495 finally:
496 file_util.copy_file = realcopyfile
496 file_util.copy_file = realcopyfile
497
497
498 class hginstallscripts(install_scripts):
498 class hginstallscripts(install_scripts):
499 '''
499 '''
500 This is a specialization of install_scripts that replaces the @LIBDIR@ with
500 This is a specialization of install_scripts that replaces the @LIBDIR@ with
501 the configured directory for modules. If possible, the path is made relative
501 the configured directory for modules. If possible, the path is made relative
502 to the directory for scripts.
502 to the directory for scripts.
503 '''
503 '''
504
504
505 def initialize_options(self):
505 def initialize_options(self):
506 install_scripts.initialize_options(self)
506 install_scripts.initialize_options(self)
507
507
508 self.install_lib = None
508 self.install_lib = None
509
509
510 def finalize_options(self):
510 def finalize_options(self):
511 install_scripts.finalize_options(self)
511 install_scripts.finalize_options(self)
512 self.set_undefined_options('install',
512 self.set_undefined_options('install',
513 ('install_lib', 'install_lib'))
513 ('install_lib', 'install_lib'))
514
514
515 def run(self):
515 def run(self):
516 install_scripts.run(self)
516 install_scripts.run(self)
517
517
518 # It only makes sense to replace @LIBDIR@ with the install path if
518 # It only makes sense to replace @LIBDIR@ with the install path if
519 # the install path is known. For wheels, the logic below calculates
519 # the install path is known. For wheels, the logic below calculates
520 # the libdir to be "../..". This is because the internal layout of a
520 # the libdir to be "../..". This is because the internal layout of a
521 # wheel archive looks like:
521 # wheel archive looks like:
522 #
522 #
523 # mercurial-3.6.1.data/scripts/hg
523 # mercurial-3.6.1.data/scripts/hg
524 # mercurial/__init__.py
524 # mercurial/__init__.py
525 #
525 #
526 # When installing wheels, the subdirectories of the "<pkg>.data"
526 # When installing wheels, the subdirectories of the "<pkg>.data"
527 # directory are translated to system local paths and files therein
527 # directory are translated to system local paths and files therein
528 # are copied in place. The mercurial/* files are installed into the
528 # are copied in place. The mercurial/* files are installed into the
529 # site-packages directory. However, the site-packages directory
529 # site-packages directory. However, the site-packages directory
530 # isn't known until wheel install time. This means we have no clue
530 # isn't known until wheel install time. This means we have no clue
531 # at wheel generation time what the installed site-packages directory
531 # at wheel generation time what the installed site-packages directory
532 # will be. And, wheels don't appear to provide the ability to register
532 # will be. And, wheels don't appear to provide the ability to register
533 # custom code to run during wheel installation. This all means that
533 # custom code to run during wheel installation. This all means that
534 # we can't reliably set the libdir in wheels: the default behavior
534 # we can't reliably set the libdir in wheels: the default behavior
535 # of looking in sys.path must do.
535 # of looking in sys.path must do.
536
536
537 if (os.path.splitdrive(self.install_dir)[0] !=
537 if (os.path.splitdrive(self.install_dir)[0] !=
538 os.path.splitdrive(self.install_lib)[0]):
538 os.path.splitdrive(self.install_lib)[0]):
539 # can't make relative paths from one drive to another, so use an
539 # can't make relative paths from one drive to another, so use an
540 # absolute path instead
540 # absolute path instead
541 libdir = self.install_lib
541 libdir = self.install_lib
542 else:
542 else:
543 common = os.path.commonprefix((self.install_dir, self.install_lib))
543 common = os.path.commonprefix((self.install_dir, self.install_lib))
544 rest = self.install_dir[len(common):]
544 rest = self.install_dir[len(common):]
545 uplevel = len([n for n in os.path.split(rest) if n])
545 uplevel = len([n for n in os.path.split(rest) if n])
546
546
547 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
547 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
548
548
549 for outfile in self.outfiles:
549 for outfile in self.outfiles:
550 with open(outfile, 'rb') as fp:
550 with open(outfile, 'rb') as fp:
551 data = fp.read()
551 data = fp.read()
552
552
553 # skip binary files
553 # skip binary files
554 if b'\0' in data:
554 if b'\0' in data:
555 continue
555 continue
556
556
557 # During local installs, the shebang will be rewritten to the final
557 # During local installs, the shebang will be rewritten to the final
558 # install path. During wheel packaging, the shebang has a special
558 # install path. During wheel packaging, the shebang has a special
559 # value.
559 # value.
560 if data.startswith(b'#!python'):
560 if data.startswith(b'#!python'):
561 log.info('not rewriting @LIBDIR@ in %s because install path '
561 log.info('not rewriting @LIBDIR@ in %s because install path '
562 'not known' % outfile)
562 'not known' % outfile)
563 continue
563 continue
564
564
565 data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape))
565 data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape))
566 with open(outfile, 'wb') as fp:
566 with open(outfile, 'wb') as fp:
567 fp.write(data)
567 fp.write(data)
568
568
569 cmdclass = {'build': hgbuild,
569 cmdclass = {'build': hgbuild,
570 'build_mo': hgbuildmo,
570 'build_mo': hgbuildmo,
571 'build_ext': hgbuildext,
571 'build_ext': hgbuildext,
572 'build_py': hgbuildpy,
572 'build_py': hgbuildpy,
573 'build_scripts': hgbuildscripts,
573 'build_scripts': hgbuildscripts,
574 'build_hgextindex': buildhgextindex,
574 'build_hgextindex': buildhgextindex,
575 'install_lib': hginstalllib,
575 'install_lib': hginstalllib,
576 'install_scripts': hginstallscripts,
576 'install_scripts': hginstallscripts,
577 'build_hgexe': buildhgexe,
577 'build_hgexe': buildhgexe,
578 }
578 }
579
579
580 packages = ['mercurial',
580 packages = ['mercurial',
581 'mercurial.cext',
581 'mercurial.cext',
582 'mercurial.hgweb',
582 'mercurial.hgweb',
583 'mercurial.httpclient',
583 'mercurial.httpclient',
584 'mercurial.pure',
584 'mercurial.pure',
585 'hgext', 'hgext.convert', 'hgext.fsmonitor',
585 'hgext', 'hgext.convert', 'hgext.fsmonitor',
586 'hgext.fsmonitor.pywatchman', 'hgext.highlight',
586 'hgext.fsmonitor.pywatchman', 'hgext.highlight',
587 'hgext.largefiles', 'hgext.zeroconf', 'hgext3rd']
587 'hgext.largefiles', 'hgext.zeroconf', 'hgext3rd']
588
588
589 common_depends = ['mercurial/bitmanipulation.h',
589 common_depends = ['mercurial/bitmanipulation.h',
590 'mercurial/compat.h',
590 'mercurial/compat.h',
591 'mercurial/util.h']
591 'mercurial/util.h']
592 common_include_dirs = ['mercurial']
592 common_include_dirs = ['mercurial']
593
593
594 osutil_cflags = []
594 osutil_cflags = []
595 osutil_ldflags = []
595 osutil_ldflags = []
596
596
597 # platform specific macros
597 # platform specific macros
598 for plat, func in [('bsd', 'setproctitle')]:
598 for plat, func in [('bsd', 'setproctitle')]:
599 if re.search(plat, sys.platform) and hasfunction(new_compiler(), func):
599 if re.search(plat, sys.platform) and hasfunction(new_compiler(), func):
600 osutil_cflags.append('-DHAVE_%s' % func.upper())
600 osutil_cflags.append('-DHAVE_%s' % func.upper())
601
601
602 for plat, macro, code in [
602 for plat, macro, code in [
603 ('bsd|darwin', 'BSD_STATFS', '''
603 ('bsd|darwin', 'BSD_STATFS', '''
604 #include <sys/param.h>
604 #include <sys/param.h>
605 #include <sys/mount.h>
605 #include <sys/mount.h>
606 int main() { struct statfs s; return sizeof(s.f_fstypename); }
606 int main() { struct statfs s; return sizeof(s.f_fstypename); }
607 '''),
607 '''),
608 ('linux', 'LINUX_STATFS', '''
608 ('linux', 'LINUX_STATFS', '''
609 #include <linux/magic.h>
609 #include <linux/magic.h>
610 #include <sys/vfs.h>
610 #include <sys/vfs.h>
611 int main() { struct statfs s; return sizeof(s.f_type); }
611 int main() { struct statfs s; return sizeof(s.f_type); }
612 '''),
612 '''),
613 ]:
613 ]:
614 if re.search(plat, sys.platform) and cancompile(new_compiler(), code):
614 if re.search(plat, sys.platform) and cancompile(new_compiler(), code):
615 osutil_cflags.append('-DHAVE_%s' % macro)
615 osutil_cflags.append('-DHAVE_%s' % macro)
616
616
617 if sys.platform == 'darwin':
617 if sys.platform == 'darwin':
618 osutil_ldflags += ['-framework', 'ApplicationServices']
618 osutil_ldflags += ['-framework', 'ApplicationServices']
619
619
620 extmodules = [
620 extmodules = [
621 Extension('mercurial.base85', ['mercurial/base85.c'],
621 Extension('mercurial.base85', ['mercurial/base85.c'],
622 include_dirs=common_include_dirs,
622 include_dirs=common_include_dirs,
623 depends=common_depends),
623 depends=common_depends),
624 Extension('mercurial.bdiff', ['mercurial/bdiff.c',
624 Extension('mercurial.bdiff', ['mercurial/bdiff.c',
625 'mercurial/bdiff_module.c'],
625 'mercurial/bdiff_module.c'],
626 include_dirs=common_include_dirs,
626 include_dirs=common_include_dirs,
627 depends=common_depends + ['mercurial/bdiff.h']),
627 depends=common_depends + ['mercurial/bdiff.h']),
628 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
628 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
629 include_dirs=common_include_dirs,
629 include_dirs=common_include_dirs,
630 depends=common_depends),
630 depends=common_depends),
631 Extension('mercurial.mpatch', ['mercurial/mpatch.c',
631 Extension('mercurial.mpatch', ['mercurial/mpatch.c',
632 'mercurial/mpatch_module.c'],
632 'mercurial/mpatch_module.c'],
633 include_dirs=common_include_dirs,
633 include_dirs=common_include_dirs,
634 depends=common_depends),
634 depends=common_depends),
635 Extension('mercurial.parsers', ['mercurial/dirs.c',
635 Extension('mercurial.parsers', ['mercurial/dirs.c',
636 'mercurial/manifest.c',
636 'mercurial/manifest.c',
637 'mercurial/parsers.c',
637 'mercurial/parsers.c',
638 'mercurial/pathencode.c'],
638 'mercurial/pathencode.c'],
639 include_dirs=common_include_dirs,
639 include_dirs=common_include_dirs,
640 depends=common_depends),
640 depends=common_depends),
641 Extension('mercurial.osutil', ['mercurial/osutil.c'],
641 Extension('mercurial.osutil', ['mercurial/osutil.c'],
642 include_dirs=common_include_dirs,
642 include_dirs=common_include_dirs,
643 extra_compile_args=osutil_cflags,
643 extra_compile_args=osutil_cflags,
644 extra_link_args=osutil_ldflags,
644 extra_link_args=osutil_ldflags,
645 depends=common_depends),
645 depends=common_depends),
646 Extension('hgext.fsmonitor.pywatchman.bser',
646 Extension('hgext.fsmonitor.pywatchman.bser',
647 ['hgext/fsmonitor/pywatchman/bser.c']),
647 ['hgext/fsmonitor/pywatchman/bser.c']),
648 ]
648 ]
649
649
650 sys.path.insert(0, 'contrib/python-zstandard')
650 sys.path.insert(0, 'contrib/python-zstandard')
651 import setup_zstd
651 import setup_zstd
652 extmodules.append(setup_zstd.get_c_extension(name='mercurial.zstd'))
652 extmodules.append(setup_zstd.get_c_extension(name='mercurial.zstd'))
653
653
654 try:
654 try:
655 from distutils import cygwinccompiler
655 from distutils import cygwinccompiler
656
656
657 # the -mno-cygwin option has been deprecated for years
657 # the -mno-cygwin option has been deprecated for years
658 compiler = cygwinccompiler.Mingw32CCompiler
658 compiler = cygwinccompiler.Mingw32CCompiler
659
659
660 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
660 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
661 def __init__(self, *args, **kwargs):
661 def __init__(self, *args, **kwargs):
662 compiler.__init__(self, *args, **kwargs)
662 compiler.__init__(self, *args, **kwargs)
663 for i in 'compiler compiler_so linker_exe linker_so'.split():
663 for i in 'compiler compiler_so linker_exe linker_so'.split():
664 try:
664 try:
665 getattr(self, i).remove('-mno-cygwin')
665 getattr(self, i).remove('-mno-cygwin')
666 except ValueError:
666 except ValueError:
667 pass
667 pass
668
668
669 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
669 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
670 except ImportError:
670 except ImportError:
671 # the cygwinccompiler package is not available on some Python
671 # the cygwinccompiler package is not available on some Python
672 # distributions like the ones from the optware project for Synology
672 # distributions like the ones from the optware project for Synology
673 # DiskStation boxes
673 # DiskStation boxes
674 class HackedMingw32CCompiler(object):
674 class HackedMingw32CCompiler(object):
675 pass
675 pass
676
676
677 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
677 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
678 'help/*.txt',
678 'help/*.txt',
679 'help/internals/*.txt',
679 'help/internals/*.txt',
680 'default.d/*.rc',
680 'default.d/*.rc',
681 'dummycert.pem']}
681 'dummycert.pem']}
682
682
683 def ordinarypath(p):
683 def ordinarypath(p):
684 return p and p[0] != '.' and p[-1] != '~'
684 return p and p[0] != '.' and p[-1] != '~'
685
685
686 for root in ('templates',):
686 for root in ('templates',):
687 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
687 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
688 curdir = curdir.split(os.sep, 1)[1]
688 curdir = curdir.split(os.sep, 1)[1]
689 dirs[:] = filter(ordinarypath, dirs)
689 dirs[:] = filter(ordinarypath, dirs)
690 for f in filter(ordinarypath, files):
690 for f in filter(ordinarypath, files):
691 f = os.path.join(curdir, f)
691 f = os.path.join(curdir, f)
692 packagedata['mercurial'].append(f)
692 packagedata['mercurial'].append(f)
693
693
694 datafiles = []
694 datafiles = []
695
695
696 # distutils expects version to be str/unicode. Converting it to
696 # distutils expects version to be str/unicode. Converting it to
697 # unicode on Python 2 still works because it won't contain any
697 # unicode on Python 2 still works because it won't contain any
698 # non-ascii bytes and will be implicitly converted back to bytes
698 # non-ascii bytes and will be implicitly converted back to bytes
699 # when operated on.
699 # when operated on.
700 assert isinstance(version, bytes)
700 assert isinstance(version, bytes)
701 setupversion = version.decode('ascii')
701 setupversion = version.decode('ascii')
702
702
703 extra = {}
703 extra = {}
704
704
705 if py2exeloaded:
705 if py2exeloaded:
706 extra['console'] = [
706 extra['console'] = [
707 {'script':'hg',
707 {'script':'hg',
708 'copyright':'Copyright (C) 2005-2017 Matt Mackall and others',
708 'copyright':'Copyright (C) 2005-2017 Matt Mackall and others',
709 'product_version':version}]
709 'product_version':version}]
710 # sub command of 'build' because 'py2exe' does not handle sub_commands
710 # sub command of 'build' because 'py2exe' does not handle sub_commands
711 build.sub_commands.insert(0, ('build_hgextindex', None))
711 build.sub_commands.insert(0, ('build_hgextindex', None))
712 # put dlls in sub directory so that they won't pollute PATH
712 # put dlls in sub directory so that they won't pollute PATH
713 extra['zipfile'] = 'lib/library.zip'
713 extra['zipfile'] = 'lib/library.zip'
714
714
715 if os.name == 'nt':
715 if os.name == 'nt':
716 # Windows binary file versions for exe/dll files must have the
716 # Windows binary file versions for exe/dll files must have the
717 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
717 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
718 setupversion = version.split('+', 1)[0]
718 setupversion = version.split('+', 1)[0]
719
719
720 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
720 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
721 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
721 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
722 if version:
722 if version:
723 version = version[0]
723 version = version[0]
724 if sys.version_info[0] == 3:
724 if sys.version_info[0] == 3:
725 version = version.decode('utf-8')
725 version = version.decode('utf-8')
726 xcode4 = (version.startswith('Xcode') and
726 xcode4 = (version.startswith('Xcode') and
727 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
727 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
728 xcode51 = re.match(r'^Xcode\s+5\.1', version) is not None
728 xcode51 = re.match(r'^Xcode\s+5\.1', version) is not None
729 else:
729 else:
730 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
730 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
731 # installed, but instead with only command-line tools. Assume
731 # installed, but instead with only command-line tools. Assume
732 # that only happens on >= Lion, thus no PPC support.
732 # that only happens on >= Lion, thus no PPC support.
733 xcode4 = True
733 xcode4 = True
734 xcode51 = False
734 xcode51 = False
735
735
736 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
736 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
737 # distutils.sysconfig
737 # distutils.sysconfig
738 if xcode4:
738 if xcode4:
739 os.environ['ARCHFLAGS'] = ''
739 os.environ['ARCHFLAGS'] = ''
740
740
741 # XCode 5.1 changes clang such that it now fails to compile if the
741 # XCode 5.1 changes clang such that it now fails to compile if the
742 # -mno-fused-madd flag is passed, but the version of Python shipped with
742 # -mno-fused-madd flag is passed, but the version of Python shipped with
743 # OS X 10.9 Mavericks includes this flag. This causes problems in all
743 # OS X 10.9 Mavericks includes this flag. This causes problems in all
744 # C extension modules, and a bug has been filed upstream at
744 # C extension modules, and a bug has been filed upstream at
745 # http://bugs.python.org/issue21244. We also need to patch this here
745 # http://bugs.python.org/issue21244. We also need to patch this here
746 # so Mercurial can continue to compile in the meantime.
746 # so Mercurial can continue to compile in the meantime.
747 if xcode51:
747 if xcode51:
748 cflags = get_config_var('CFLAGS')
748 cflags = get_config_var('CFLAGS')
749 if cflags and re.search(r'-mno-fused-madd\b', cflags) is not None:
749 if cflags and re.search(r'-mno-fused-madd\b', cflags) is not None:
750 os.environ['CFLAGS'] = (
750 os.environ['CFLAGS'] = (
751 os.environ.get('CFLAGS', '') + ' -Qunused-arguments')
751 os.environ.get('CFLAGS', '') + ' -Qunused-arguments')
752
752
753 setup(name='mercurial',
753 setup(name='mercurial',
754 version=setupversion,
754 version=setupversion,
755 author='Matt Mackall and many others',
755 author='Matt Mackall and many others',
756 author_email='mercurial@mercurial-scm.org',
756 author_email='mercurial@mercurial-scm.org',
757 url='https://mercurial-scm.org/',
757 url='https://mercurial-scm.org/',
758 download_url='https://mercurial-scm.org/release/',
758 download_url='https://mercurial-scm.org/release/',
759 description=('Fast scalable distributed SCM (revision control, version '
759 description=('Fast scalable distributed SCM (revision control, version '
760 'control) system'),
760 'control) system'),
761 long_description=('Mercurial is a distributed SCM tool written in Python.'
761 long_description=('Mercurial is a distributed SCM tool written in Python.'
762 ' It is used by a number of large projects that require'
762 ' It is used by a number of large projects that require'
763 ' fast, reliable distributed revision control, such as '
763 ' fast, reliable distributed revision control, such as '
764 'Mozilla.'),
764 'Mozilla.'),
765 license='GNU GPLv2 or any later version',
765 license='GNU GPLv2 or any later version',
766 classifiers=[
766 classifiers=[
767 'Development Status :: 6 - Mature',
767 'Development Status :: 6 - Mature',
768 'Environment :: Console',
768 'Environment :: Console',
769 'Intended Audience :: Developers',
769 'Intended Audience :: Developers',
770 'Intended Audience :: System Administrators',
770 'Intended Audience :: System Administrators',
771 'License :: OSI Approved :: GNU General Public License (GPL)',
771 'License :: OSI Approved :: GNU General Public License (GPL)',
772 'Natural Language :: Danish',
772 'Natural Language :: Danish',
773 'Natural Language :: English',
773 'Natural Language :: English',
774 'Natural Language :: German',
774 'Natural Language :: German',
775 'Natural Language :: Italian',
775 'Natural Language :: Italian',
776 'Natural Language :: Japanese',
776 'Natural Language :: Japanese',
777 'Natural Language :: Portuguese (Brazilian)',
777 'Natural Language :: Portuguese (Brazilian)',
778 'Operating System :: Microsoft :: Windows',
778 'Operating System :: Microsoft :: Windows',
779 'Operating System :: OS Independent',
779 'Operating System :: OS Independent',
780 'Operating System :: POSIX',
780 'Operating System :: POSIX',
781 'Programming Language :: C',
781 'Programming Language :: C',
782 'Programming Language :: Python',
782 'Programming Language :: Python',
783 'Topic :: Software Development :: Version Control',
783 'Topic :: Software Development :: Version Control',
784 ],
784 ],
785 scripts=scripts,
785 scripts=scripts,
786 packages=packages,
786 packages=packages,
787 ext_modules=extmodules,
787 ext_modules=extmodules,
788 data_files=datafiles,
788 data_files=datafiles,
789 package_data=packagedata,
789 package_data=packagedata,
790 cmdclass=cmdclass,
790 cmdclass=cmdclass,
791 distclass=hgdist,
791 distclass=hgdist,
792 options={'py2exe': {'packages': ['hgext', 'email']},
792 options={'py2exe': {'packages': ['hgext', 'email']},
793 'bdist_mpkg': {'zipdist': False,
793 'bdist_mpkg': {'zipdist': False,
794 'license': 'COPYING',
794 'license': 'COPYING',
795 'readme': 'contrib/macosx/Readme.html',
795 'readme': 'contrib/macosx/Readme.html',
796 'welcome': 'contrib/macosx/Welcome.html',
796 'welcome': 'contrib/macosx/Welcome.html',
797 },
797 },
798 },
798 },
799 **extra)
799 **extra)
General Comments 0
You need to be logged in to leave comments. Login now