setup: set mode 644 or 755 on installed files
authorKyle Lippincott <spectral@google.com>
Tue, 30 Sep 2014 17:13:54 -0700
changeset 22640 e88a634e0195
parent 22639 79c4178b2169
child 22641 ffd0f6b1c29d
setup: set mode 644 or 755 on installed files
setup.py
--- a/setup.py	Thu Oct 02 21:58:10 2014 +0900
+++ b/setup.py	Tue Sep 30 17:13:54 2014 -0700
@@ -63,7 +63,7 @@
         raise SystemExit(
             "Couldn't import standard bz2 (incomplete Python install).")
 
-import os, subprocess, time
+import os, stat, subprocess, time
 import re
 import shutil
 import tempfile
@@ -73,9 +73,10 @@
 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_lib import install_lib
 from distutils.command.install_scripts import install_scripts
 from distutils.spawn import spawn, find_executable
-from distutils import cygwinccompiler
+from distutils import cygwinccompiler, file_util
 from distutils.errors import CCompilerError, DistutilsExecError
 from distutils.sysconfig import get_python_inc, get_config_var
 from distutils.version import StrictVersion
@@ -375,6 +376,39 @@
                                       libraries=[],
                                       output_dir=self.build_temp)
 
+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.
+
+    Note that just passing keep_permissions=False to copy_file would be
+    insufficient, as it might still be applying a umask.
+    '''
+
+    def run(self):
+        realcopyfile = file_util.copy_file
+        def copyfileandsetmode(*args, **kwargs):
+            src, dst = args[0], args[1]
+            dst, copied = realcopyfile(*args, **kwargs)
+            if copied:
+                st = os.stat(src)
+                # Persist executable bit (apply it to group and other if user
+                # has it)
+                if st[stat.ST_MODE] & stat.S_IXUSR:
+                    setmode = 0755
+                else:
+                    setmode = 0644
+                os.chmod(dst, (stat.S_IMODE(st[stat.ST_MODE]) & ~0777) |
+                         setmode)
+        file_util.copy_file = copyfileandsetmode
+        try:
+            install_lib.run(self)
+        finally:
+            file_util.copy_file = realcopyfile
+
 class hginstallscripts(install_scripts):
     '''
     This is a specialization of install_scripts that replaces the @LIBDIR@ with
@@ -426,6 +460,7 @@
             'build_ext': hgbuildext,
             'build_py': hgbuildpy,
             'build_hgextindex': buildhgextindex,
+            'install_lib': hginstalllib,
             'install_scripts': hginstallscripts,
             'build_hgexe': buildhgexe,
             }