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 10da5a1f25dd
parent 12660 6ed5ae6264c2
child 12663 8269af351a64
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	Sat Oct 09 11:55:25 2010 -0500
+++ b/hg	Tue Aug 17 15:44:38 2010 +0200
@@ -7,6 +7,17 @@
 # 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()
@@ -17,7 +28,6 @@
     sys.stderr.write("(check your install and PYTHONPATH)\n")
     sys.exit(-1)
 
-import sys
 import mercurial.util
 import mercurial.dispatch
 
--- a/setup.py	Sat Oct 09 11:55:25 2010 -0500
+++ b/setup.py	Tue Aug 17 15:44:38 2010 +0200
@@ -52,6 +52,7 @@
 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
@@ -216,6 +217,7 @@
             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))
@@ -260,9 +262,52 @@
             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']