setup/hg: always load Mercurial from where it was installed.
authorDan Villiom Podlaski Christiansen <danchr@gmail.com>
Tue, 17 Aug 2010 15:44:38 +0200
changeset 12661 10da5a1f25dd820741067c5ce47c06bd6fc3a850
parent 12660 6ed5ae6264c23323d154e7474deef19852791371
child 12663 8269af351a64b186a575fdd492e19e28e9575397
push id1
push usergszorc@mozilla.com
push dateWed, 18 Mar 2015 16:34:57 +0000
setup/hg: always load Mercurial from where it was installed. This provides two new features: - Mercurial may be installed into a non-standard location without having to set PYTHONPATH. - Multiple installations can use Mercurial from different locations.
hg
setup.py
--- a/hg
+++ b/hg
@@ -2,26 +2,36 @@
 #
 # mercurial - scalable distributed SCM
 #
 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
 #
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
+import os
+import sys
+
+libdir = '@LIBDIR@'
+
+if libdir != '@' 'LIBDIR' '@':
+    if not os.path.isabs(libdir):
+        libdir = os.path.join(os.path.dirname(__file__), libdir)
+        libdir = os.path.abspath(libdir)
+    sys.path.insert(0, libdir)
+
 # enable importing on demand to reduce startup time
 try:
     from mercurial import demandimport; demandimport.enable()
 except ImportError:
     import sys
     sys.stderr.write("abort: couldn't find mercurial libraries in [%s]\n" %
                      ' '.join(sys.path))
     sys.stderr.write("(check your install and PYTHONPATH)\n")
     sys.exit(-1)
 
-import sys
 import mercurial.util
 import mercurial.dispatch
 
 for fp in (sys.stdin, sys.stdout, sys.stderr):
     mercurial.util.set_binary(fp)
 
 mercurial.dispatch.run()
--- a/setup.py
+++ b/setup.py
@@ -47,16 +47,17 @@ import os, subprocess, time
 import shutil
 import tempfile
 from distutils import log
 from distutils.core import setup, 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.install_scripts import install_scripts
 from distutils.spawn import spawn, find_executable
 from distutils.ccompiler import new_compiler
 from distutils.errors import CCompilerError
 from distutils.sysconfig import get_python_inc
 
 scripts = ['hg']
 if os.name == 'nt':
     scripts.append('contrib/win32/hg.bat')
@@ -211,16 +212,17 @@ class hgbuildmo(build):
             mobuildfile = join('mercurial', mofile)
             cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
             if sys.platform != 'sunos5':
                 # msgfmt on Solaris does not know about -c
                 cmd.append('-c')
             self.mkpath(join('mercurial', modir))
             self.make_file([pofile], mobuildfile, spawn, (cmd,))
 
+
 # Insert hgbuildmo first so that files in mercurial/locale/ are found
 # when build_py is run next.
 build.sub_commands.insert(0, ('build_mo', None))
 
 Distribution.pure = 0
 Distribution.global_options.append(('pure', None, "use pure (slow) Python "
                                     "code instead of C extensions"))
 
@@ -255,19 +257,62 @@ class hgbuildpy(build_py):
         modules = build_py.find_modules(self)
         for module in modules:
             if module[0] == "mercurial.pure":
                 if module[1] != "__init__":
                     yield ("mercurial", module[1], module[2])
             else:
                 yield module
 
+class hginstallscripts(install_scripts):
+    '''
+    This is a specialization of install_scripts that replaces the @LIBDIR@ with
+    the configured directory for modules. If possible, the path is made relative
+    to the directory for scripts.
+    '''
+
+    def initialize_options(self):
+        install_scripts.initialize_options(self)
+
+        self.install_lib = None
+
+    def finalize_options(self):
+        install_scripts.finalize_options(self)
+        self.set_undefined_options('install',
+                                   ('install_lib', 'install_lib'))
+
+    def run(self):
+        install_scripts.run(self)
+
+        if (os.path.splitdrive(self.install_dir)[0] !=
+            os.path.splitdrive(self.install_lib)[0]):
+            # can't make relative paths from one drive to another, so use an
+            # absolute path instead
+            libdir = self.install_lib
+        else:
+            common = os.path.commonprefix((self.install_dir, self.install_lib))
+            rest = self.install_dir[len(common):]
+            uplevel = len([n for n in os.path.split(rest) if n])
+
+            libdir =  uplevel * ('..' + os.sep) + self.install_lib[len(common):]
+
+        for outfile in self.outfiles:
+            data = open(outfile, 'rb').read()
+
+            # skip binary files
+            if '\0' in data:
+                continue
+
+            data = data.replace('@LIBDIR@', libdir)
+            open(outfile, 'wb').write(data)
+
 cmdclass = {'build_mo': hgbuildmo,
             'build_ext': hgbuildext,
-            'build_py': hgbuildpy}
+            'build_py': hgbuildpy,
+            'install_scripts': hginstallscripts}
 
 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
             'hgext.highlight', 'hgext.zeroconf']
 
 pymodules = []
 
 extmodules = [
     Extension('mercurial.base85', ['mercurial/base85.c']),