@@ -74,21 +74,26 @@ if 'FORCE_SETUPTOOLS' in os.environ:
from setuptools import setup
else:
from distutils.core import setup
from distutils.core import Command, Extension
from distutils.dist import Distribution
from distutils.command.build import build
from distutils.command.build_ext import build_ext
from distutils.command.build_py import build_py
+from distutils.command.build_scripts import build_scripts
from distutils.command.install_lib import install_lib
from distutils.command.install_scripts import install_scripts
from distutils.spawn import spawn, find_executable
from distutils import file_util
-from distutils.errors import CCompilerError, DistutilsExecError
+from distutils.errors import (
+ CCompilerError,
+ DistutilsError,
+ DistutilsExecError,
+)
from distutils.sysconfig import get_python_inc, get_config_var
from distutils.version import StrictVersion
convert2to3 = '--c2to3' in sys.argv
if convert2to3:
try:
from distutils.command.build_py import build_py_2to3 as build_py
from lib2to3.refactor import get_fixers_from_package as getfixers
@@ -97,16 +102,17 @@ if convert2to3:
raise SystemExit("--c2to3 is only compatible with python3.")
raise
sys.path.append('contrib')
elif sys.version_info[0] >= 3:
raise SystemExit("setup.py with python3 needs --c2to3 (experimental)")
scripts = ['hg']
if os.name == 'nt':
+ # We remove hg.bat if we are able to build hg.exe.
scripts.append('contrib/win32/hg.bat')
# simplified version of distutils.ccompiler.CCompiler.has_function
# that actually removes its temporary files.
def hasfunction(cc, funcname):
tmpdir = tempfile.mkdtemp(prefix='hg-install-')
devnull = oldstderr = None
try:
@@ -299,16 +305,42 @@ class hgbuildext(build_ext):
try:
build_ext.build_extension(self, ext)
except CCompilerError:
if not getattr(ext, 'optional', False):
raise
log.warn("Failed to build optional extension '%s' (skipping)",
ext.name)
+class hgbuildscripts(build_scripts):
+ def run(self):
+ if os.name != 'nt':
+ return build_scripts.run(self)
+
+ exebuilt = False
+ try:
+ self.run_command('build_hgexe')
+ exebuilt = True
+ except (DistutilsError, CCompilerError):
+ log.warn('failed to build optional hg.exe')
+
+ if exebuilt:
+ # Copying hg.exe to the scripts build directory ensures it is
+ # installed by the install_scripts command.
+ hgexecommand = self.get_finalized_command('build_hgexe')
+ dest = os.path.join(self.build_dir, 'hg.exe')
+ self.mkpath(self.build_dir)
+ self.copy_file(hgexecommand.hgexepath, dest)
+
+ # Remove hg.bat because it is redundant with hg.exe.
+ self.scripts.remove('contrib/win32/hg.bat')
+
+ return build_scripts.run(self)
+
+
class hgbuildpy(build_py):
if convert2to3:
fixer_names = sorted(set(getfixers("lib2to3.fixes") +
getfixers("hgfixes")))
def finalize_options(self):
build_py.finalize_options(self)
@@ -384,16 +416,22 @@ class buildhgexe(build_ext):
objects = self.compiler.compile(['mercurial/exewrapper.c'],
output_dir=self.build_temp)
dir = os.path.dirname(self.get_ext_fullpath('dummy'))
target = os.path.join(dir, 'hg')
self.compiler.link_executable(objects, target,
libraries=[],
output_dir=self.build_temp)
+ @property
+ def hgexepath(self):
+ dir = os.path.dirname(self.get_ext_fullpath('dummy'))
+ return os.path.join(self.build_temp, dir, 'hg.exe')
+
+
class hginstalllib(install_lib):
'''
This is a specialization of install_lib that replaces the copy_file used
there so that it supports setting the mode of files after copying them,
instead of just preserving the mode that the files originally had. If your
system has a umask of something like 027, preserving the permissions when
copying will lead to a broken install.
@@ -468,16 +506,17 @@ class hginstallscripts(install_scripts):
fp = open(outfile, 'wb')
fp.write(data)
fp.close()
cmdclass = {'build': hgbuild,
'build_mo': hgbuildmo,
'build_ext': hgbuildext,
'build_py': hgbuildpy,
+ 'build_scripts': hgbuildscripts,
'build_hgextindex': buildhgextindex,
'install_lib': hginstalllib,
'install_scripts': hginstallscripts,
'build_hgexe': buildhgexe,
}
packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
'mercurial.pure',