我有一个使用SVN管理的Python项目,并且希望在运行时显示版本号。是否有办法实现这一点(例如在提交代码时自动运行一个简短的脚本来更新版本文件,或者在Python中查询SVN存储库)?
我不确定Python的具体情况,但如果在文件中放置字符串$Revision$,并且在您的SVN配置中启用了enable-auto-props=true,它将被重写为类似$Revision: 144$的内容。然后,您可以在脚本中解析此内容。
这不会有任何开销,例如查询SVN repo,因为该字符串在提交或更新时已经硬编码到您的文件中。
我不确定您如何在Python中解析此内容,但在PHP中,我会这样做:
$revString = '$Revision: 144$';
if(preg_match('/: ([0-9]+)\$/', $revString, $matches) {
echo 'Revision is ' . $matches[1];
}
类似于 PHP 的答案,但更符合 Python 风格;将此放在模块的 __init__.py
中:
__version__ = filter(str.isdigit, "$Revision: 13 $")
并确保您添加了 Revision 属性:
svn propset svn:keywords Revision __init__.py
或者你可以这样做:
import re,subprocess
svn_info = subprocess.check_output("svn info")
print (re.search(ur"Revision:\s\d+", svn_info)).group()
在我的项目中它会打印"Revision: 2874"
或者是这样的:
print (subprocess.check_output("svnversion")).split(":")[0]
在我的项目中它会打印"2874"
编辑
对于新版本的Python(>=3.4)和明确的文件路径:
import re,subprocess
file_path = 'c:/foo'
svn_info = subprocess.check_output('svn info ' + file_path)
revision_string = re.search(r"Revision:\s\d+", str(svn_info)).group()
revision = revision_string.split(': ')[1]
print(revision)
例如打印
'8623'
hooks/pre-commit
文件是一个脚本或程序,将在成功提交之前执行。只需将其设置为一个脚本,当提交时更新您的文件并附带正确的版本号(版本号作为运行脚本时传递)。以下是编写预提交挂钩的示例教程:http://wordaligned.org/articles/a-subversion-pre-commit-hook。在Django中有一段代码片段可以帮助你实现这个功能,我建议你查看它。 http://code.djangoproject.com/browser/django/trunk/django/utils/version.py
我觉得“when it is run”这一部分有点含糊不清——从哪里运行?从 SVN checkout 还是从发布的代码?所有的解决方案都在某种程度上将 SVN 版本注入到 Python 源码中或者仓库的某个版本文件中。
版本文件会在新的 checkout 时被更改,因此在分发之前需要进行干净的 checkout。所以我的问题是程序在哪里运行。
重新回答,因为我在寻找Python 3的所有信息时遇到了麻烦。 在Python 3中,您可以使用以下内容:
import re
revstring = '$Revision: 123 $'
revnumber = re.sub(r'\D', '', revstring)
要让SVN替换数字,必须设置文件关键字“Revision”。您可以通过在终端中键入以下命令来实现:
svn propset svn:keywords Revision YOURFILE.py
enable-auto-props
必须设置为yes
。这应该已经是这种情况了。在Tortoise SVN中,可以通过单击常规设置选项卡中“Subversion配置文件”旁边的“编辑”按钮来访问此配置文件。def get_svn_rev(dir: Union[str, Path]) -> str:
"""Get the svn revision of the given directory"""
dir = str(dir)
svn_info_cmd = ['svn', 'info', '--xml', dir]
print(' '.join(svn_info_cmd))
svn_info_process = subprocess.run(svn_info_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if svn_info_process.returncode:
eprint(svn_info_process.stderr.decode().strip())
raise subprocess.CalledProcessError(returncode=svn_info_process.returncode, cmd=svn_info_cmd,
output=svn_info_process.stdout,
stderr=svn_info_process.stderr)
else:
info = ElementTree.fromstring(svn_info_process.stdout.decode().strip())
entry = info.find('entry')
revision = entry.get('revision')
return revision