Repository: ipython/ipython

Issue:
sys_info missing git hash in sdists
#1538 changed how sys_info works, but the way it is done it puts no info in sdists.  This should be fixed, though it is not critical as most sdist installs are from releases.



Discussion:

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -52,7 +52,6 @@
 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
 
 from distutils.core import setup
-from distutils.command.upload import upload
 
 # On Python 3, we need distribute (new setuptools) to do the 2to3 conversion
 if PY3:
@@ -166,14 +165,16 @@ def cleanup():
 package_data = find_package_data()
 data_files = find_data_files()
 
-setup_args['cmdclass'] = {'build_py': record_commit_info('IPython')}
 setup_args['packages'] = packages
 setup_args['package_data'] = package_data
 setup_args['data_files'] = data_files
 
 #---------------------------------------------------------------------------
-# custom upload_wininst command
+# custom distutils commands
 #---------------------------------------------------------------------------
+# imports here, so they are after setuptools import if there was one
+from distutils.command.sdist import sdist
+from distutils.command.upload import upload
 
 class UploadWindowsInstallers(upload):
     
@@ -194,7 +195,11 @@ def run(self):
         for dist_file in glob(self.files):
             self.upload_file('bdist_wininst', 'any', dist_file)
 
-setup_args['cmdclass']['upload_wininst'] = UploadWindowsInstallers
+setup_args['cmdclass'] = {
+    'build_py': record_commit_info('IPython'),
+    'sdist' : record_commit_info('IPython', sdist),
+    'upload_wininst' : UploadWindowsInstallers,
+}
 
 #---------------------------------------------------------------------------
 # Handle scripts, dependencies, and setuptools specific things
diff --git a/setupbase.py b/setupbase.py
--- a/setupbase.py
+++ b/setupbase.py
@@ -369,7 +369,7 @@ def check_for_dependencies():
     check_for_readline()
 
 def record_commit_info(pkg_dir, build_cmd=build_py):
-    """ Return extended build command class for recording commit
+    """ Return extended build or sdist command class for recording commit
     
     records git commit in IPython.utils._sysinfo.commit
     
@@ -380,18 +380,40 @@ class MyBuildPy(build_cmd):
         ''' Subclass to write commit data into installation tree '''
         def run(self):
             build_cmd.run(self)
+            # this one will only fire for build commands
+            if hasattr(self, 'build_lib'):
+                self._record_commit(self.build_lib)
+        
+        def make_release_tree(self, base_dir, files):
+            # this one will fire for sdist
+            build_cmd.make_release_tree(self, base_dir, files)
+            self._record_commit(base_dir)
+        
+        def _record_commit(self, base_dir):
             import subprocess
             proc = subprocess.Popen('git rev-parse --short HEAD',
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE,
                                     shell=True)
             repo_commit, _ = proc.communicate()
-            repo_commit = repo_commit.strip()
-            # We write the installation commit even if it's empty
-            out_pth = pjoin(self.build_lib, pkg_dir, 'utils', '_sysinfo.py')
+            repo_commit = repo_commit.strip().decode("ascii")
+            
+            out_pth = pjoin(base_dir, pkg_dir, 'utils', '_sysinfo.py')
+            if os.path.isfile(out_pth) and not repo_commit:
+                # nothing to write, don't clobber
+                return
+            
+            print("writing git commit '%s' to %s" % (repo_commit, out_pth))
+            
+            # remove to avoid overwriting original via hard link
+            try:
+                os.remove(out_pth)
+            except (IOError, OSError):
+                pass
+            print (out_pth, file=sys.stderr)
             with open(out_pth, 'w') as out_file:
                 out_file.writelines([
                     '# GENERATED BY setup.py\n',
-                    'commit = "%s"\n' % repo_commit.decode('ascii'),
+                    'commit = "%s"\n' % repo_commit,
                 ])
     return MyBuildPy


Test patch: