From cf36362823ee0663913f0b2bf29fb08d388e7f3b Mon Sep 17 00:00:00 2001
From: Christoph Groth <christoph.groth@cea.fr>
Date: Tue, 8 Oct 2013 15:56:52 +0200
Subject: [PATCH] improve version extraction from git

* Only extract the version from Git when the top level directory of the Git
  repository coincides with the root directory of the Kwant distribution

* Disregard tags on branches that were merged-in (with Git >= 1.8.4).
---
 kwant/version.py | 30 +++++++++++++++++++++++++-----
 setup.py         | 35 +++++++++++++++++++++++++++--------
 2 files changed, 52 insertions(+), 13 deletions(-)

diff --git a/kwant/version.py b/kwant/version.py
index 1ff77439..9ceb4777 100644
--- a/kwant/version.py
+++ b/kwant/version.py
@@ -11,25 +11,44 @@ import os
 
 __all__ = ['version']
 
+distr_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
 # When changing this function, remember to also change its twin in ../setup.py.
 def get_version_from_git():
-    kwant_dir = os.path.dirname(os.path.abspath(__file__))
     try:
-        p = subprocess.Popen(['git', 'describe'], cwd=kwant_dir,
+        p = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'],
+                             cwd=distr_root,
                              stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     except OSError:
         return
-
     if p.wait() != 0:
         return
-    version = p.communicate()[0].strip()
+    # TODO: use os.path.samefile once we depend on Python >= 3.3.
+    if os.path.normpath(p.communicate()[0].rstrip('\n')) != distr_root:
+        # The top-level directory of the current Git repository is not the same
+        # as the root directory of the Kwant distribution: do not extract the
+        # version from Git.
+        return
+
+    # git describe --first-parent does not take into account tags from branches
+    # that were merged-in.
+    for opts in [['--first-parent'], []]:
+        try:
+            p = subprocess.Popen(['git', 'describe'] + opts, cwd=distr_root,
+                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        except OSError:
+            return
+        if p.wait() == 0:
+            break
+    else:
+        return
+    version = p.communicate()[0].rstrip('\n')
 
     if version[0] == 'v':
         version = version[1:]
 
     try:
-        p = subprocess.Popen(['git', 'diff', '--quiet'], cwd=kwant_dir)
+        p = subprocess.Popen(['git', 'diff', '--quiet'], cwd=distr_root)
     except OSError:
         version += '-confused'  # This should never happen.
     else:
@@ -37,6 +56,7 @@ def get_version_from_git():
             version += '-dirty'
     return version
 
+
 version = get_version_from_git()
 if version is None:
     try:
diff --git a/setup.py b/setup.py
index 8b6074df..873a0498 100755
--- a/setup.py
+++ b/setup.py
@@ -49,7 +49,7 @@ if cythonize and cython_version:
 else:
     from distutils.command.build_ext import build_ext
 
-kwant_dir = os.path.dirname(os.path.abspath(__file__))
+distr_root = os.path.dirname(os.path.abspath(__file__))
 
 
 class kwant_build_ext(build_ext):
@@ -135,7 +135,7 @@ class test(Command):
 
 def git_lsfiles():
     try:
-        p = subprocess.Popen(['git', 'ls-files'], cwd=kwant_dir,
+        p = subprocess.Popen(['git', 'ls-files'], cwd=distr_root,
                              stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     except OSError:
         return
@@ -159,7 +159,7 @@ class kwant_sdist(distutils_sdist):
             # Check that MANIFEST exists and has not been generated by
             # distutils.
             try:
-                with open(kwant_dir + '/MANIFEST', 'r') as f:
+                with open(distr_root + '/MANIFEST', 'r') as f:
                     line = f.read()
             except IOError:
                 print >>sys.stderr, "error: MANIFEST file is missing and " \
@@ -168,7 +168,7 @@ class kwant_sdist(distutils_sdist):
             trustworthy = not line.strip().startswith('#')
         else:
             # Generate MANIFEST file.
-            with open(kwant_dir + '/MANIFEST', 'w') as f:
+            with open(distr_root + '/MANIFEST', 'w') as f:
                 for name in names:
                     a, sep, b = name.rpartition('/')
                     if b == '.gitignore':
@@ -200,20 +200,39 @@ with a comment).  It may well be incomplete."""
 # include a copy.
 def get_version_from_git():
     try:
-        p = subprocess.Popen(['git', 'describe'], cwd=kwant_dir,
+        p = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'],
+                             cwd=distr_root,
                              stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     except OSError:
         return
-
     if p.wait() != 0:
         return
-    version = p.communicate()[0].strip()
+    # TODO: use os.path.samefile once we depend on Python >= 3.3.
+    if os.path.normpath(p.communicate()[0].rstrip('\n')) != distr_root:
+        # The top-level directory of the current Git repository is not the same
+        # as the root directory of the Kwant distribution: do not extract the
+        # version from Git.
+        return
+
+    # git describe --first-parent does not take into account tags from branches
+    # that were merged-in.
+    for opts in [['--first-parent'], []]:
+        try:
+            p = subprocess.Popen(['git', 'describe'] + opts, cwd=distr_root,
+                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        except OSError:
+            return
+        if p.wait() == 0:
+            break
+    else:
+        return
+    version = p.communicate()[0].rstrip('\n')
 
     if version[0] == 'v':
         version = version[1:]
 
     try:
-        p = subprocess.Popen(['git', 'diff', '--quiet'], cwd=kwant_dir)
+        p = subprocess.Popen(['git', 'diff', '--quiet'], cwd=distr_root)
     except OSError:
         version += '-confused'  # This should never happen.
     else:
-- 
GitLab