2010-06-02

Python setuptools hack: get revision from git-svn

Python egg 打包有赖于 setuptools。setuptools 有一个功能很有意思,就是准备打包的软件如果使用了 subversion 版本控制系统,会自动将当前SVN的提交版本号附加在生成的软件包文件名中。 例如:pySvnManager-0.4.1dev-r131.tar.gz 中的 r131 含义就是从 svn 的 131 提交版本创建的源码包。 但是如果使用 git-svn来检出 svn 版本库,再运行打包命令 "python setup.py sdist",就失去了这个帅呆了的功能。怎么办呢? Hack 一下 setuptools 呗,之前就干过。

曾经的 Hack: setuptools 不支持新版本的 SVN

之前就遇到过,当使用最新的 SVN 客户端时,setuptools 用于从 .svn/entries 文件解析出当前提交版本时,因不能识别 SVN 版本而失败。 从下面的代码可以看到,当 SVN 新版本推出后,setuptools 需要进行相应的更新,这肯定要有一个时间差。
 f = open(os.path.join(base,'.svn','entries'))
 data = f.read()
 f.close()

 if data.startswith('10') or data.startswith('9') or data.startswith('8'):
SVN 1.6 的 .svn/entries 文件头一行的版本标识是 10, svn1.5 是9, svn 1.4 是 8。

Hack: 从 Git-svn 版本控制系统获取版本号

其实也很简单,运行 git log 命令就可以看到 SVN 相应的版本号:
$ git log -1
commit 6a6a3a0f1f9e08f78d75bbe655637bbc95f52220
Author: jiangx <jiangx@39c8d0d3-2d71-4a2c-8909-36513c942afe>
Date:   Wed Jun 2 01:02:26 2010 +0000

 v0.4.1: Update svn hooks sync with ossxp-svn-tools; parse_ini.sh break if sh is dash instead of bash.

 git-svn-id: https://pysvnmanager.svn.sourceforge.net/svnroot/pysvnmanager/trunk@131 39c8d0d3-2d71-4a2c-8909-36513c942afe
只需要 Hack setuptools 中的一个文件就可以了:
--- /usr/lib/python2.6/dist-packages/setuptools/command/egg_info.py.0 2010-10-08 09:32:55.592618902 +0800                                                   
+++ /usr/lib/python2.6/dist-packages/setuptools/command/egg_info.py 2010-10-08 09:36:20.392683308 +0800
@@ -183,7 +183,7 @@
         if self.tag_build:
             version+=self.tag_build
         if self.tag_svn_revision and (
-            os.path.exists('.svn') or os.path.exists('PKG-INFO')
+            os.path.exists('.svn') or os.path.exists('PKG-INFO') or os.path.exists('.git/svn')
         ):  version += '-r%s' % self.get_svn_revision()
         if self.tag_date:
             import time; version += time.strftime("-%Y%m%d")
@@ -238,6 +238,17 @@
                 continue    # not part of the same svn tree, skip it
             revision = max(revision, localrev)

+        if revision == 0 and os.path.exists('.git/svn'):
+            from subprocess import Popen, PIPE, STDOUT
+            pattern = re.compile(r'git-svn-id:.*@([0-9]+)\s+.*$')
+            proc = Popen('git log -1', stdout=PIPE, shell=True)
+            for line in proc.stdout.readlines():
+                line = line.strip()
+                match = pattern.search(line)
+                if match:
+                    revision = match.group(1)
+                    break
+
         return str(revision or get_pkg_info_revision())
blog comments powered by Disqus