1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
from __future__ import print_function
import time
import py
import os
from subprocess import Popen, PIPE
import rpython
rpythondir = os.path.dirname(os.path.realpath(rpython.__file__))
rpythonroot = os.path.dirname(rpythondir)
default_retval = '?', '?'
def maywarn(err, repo_type='Mercurial'):
if not err:
return
from rpython.tool.ansi_print import AnsiLogger
log = AnsiLogger("version")
log.WARNING('Errors getting %s information: %s' % (repo_type, err))
CACHED_RESULT = None
CACHED_ARGS = None
def get_repo_version_info(hgexe=None, root=rpythonroot):
'''Obtain version information by invoking the 'hg' or 'git' commands.'''
global CACHED_RESULT, CACHED_ARGS
key = (hgexe, root)
if CACHED_RESULT is not None and CACHED_ARGS == key:
return CACHED_RESULT
res = _get_repo_version_info(hgexe, root)
CACHED_RESULT = res
CACHED_ARGS = key
return res
def _get_repo_version_info(hgexe, root):
# Debian: built from a source tarball
p = Popen(('dpkg-parsechangelog',), stdout=PIPE, cwd=rpythonroot)
if p.wait() != 0:
maywarn(p.stderr.read(), 'dpkg-parsechangelog')
return default_retval
for line in p.stdout.read().split('\n'):
if line.split(':', 1)[0].strip() == 'Version':
version = line.split(':', 1)[1].strip()
return '', version
# Try to see if we can get info from Git if hgexe is not specified.
if not hgexe:
gitfile = os.path.join(root, '.git')
if os.path.isdir(gitfile):
return _get_git_version(root)
elif os.path.exists(gitfile):
# Can be a file with a relative path like
# gitdir: ../.git/modules/pypy
with open(gitfile) as fid:
contents = fid.read()
if contents.startswith('gitdir:'):
return _get_git_version(root)
# Fallback to trying Mercurial.
if hgexe is None:
hgexe = py.path.local.sysfind('hg')
if os.path.isfile(os.path.join(root, '.hg_archival.txt')):
return _get_hg_archive_version(os.path.join(root, '.hg_archival.txt'))
elif not os.path.isdir(os.path.join(root, '.hg')):
maywarn('Not running from a Mercurial repository!')
return default_retval
elif not hgexe:
maywarn('Cannot find Mercurial command!')
return default_retval
else:
return _get_hg_version(hgexe, root)
def _get_hg_version(hgexe, root):
env = dict(os.environ)
# get Mercurial into scripting mode
env['HGPLAIN'] = '1'
# disable user configuration, extensions, etc.
env['HGRCPATH'] = os.devnull
try:
p = Popen([str(hgexe), 'version', '-q'],
stdout=PIPE, stderr=PIPE, env=env, universal_newlines=True)
except OSError as e:
maywarn(e)
return default_retval
if not p.stdout.read().startswith('Mercurial Distributed SCM'):
maywarn('command does not identify itself as Mercurial')
return default_retval
p = Popen([str(hgexe), 'id', '--template', r"{id}\n{tags}\n{branch}\n", root],
stdout=PIPE, stderr=PIPE, env=env,
universal_newlines=True)
hgout = p.stdout.read().strip()
if p.wait() != 0:
maywarn(p.stderr.read())
hgout = '?\n?\n?'
hgid, hgtags, hgbranch = hgout.strip().split("\n", 3)
hgtags = [t for t in hgtags.strip().split() if t != 'tip']
if hgtags:
return hgtags[0], hgid
else:
return hgbranch, hgid
def _get_hg_archive_version(path):
with open(path) as fp:
# reverse the order since there may be more than one tag
# and the latest tag will be first, so make it last instead
data = dict((x.split(': ', 1) for x in fp.read().splitlines()[::-1]))
if 'tag' in data:
return data['tag'], data['node']
else:
return data['branch'], data['node']
def _get_git_version(root):
#XXX: this function is a untested hack,
# so the git mirror tav made will work
gitexe = py.path.local.sysfind('git')
if not gitexe:
return default_retval
try:
p = Popen(
[str(gitexe), 'rev-parse', 'HEAD'],
stdout=PIPE, stderr=PIPE, cwd=root,
universal_newlines=True,
)
except OSError as e:
maywarn(e, 'Git')
return default_retval
if p.wait() != 0:
maywarn(p.stderr.read(), 'Git')
return default_retval
revision_id = p.stdout.read().strip()[:12]
p = Popen(
[str(gitexe), 'describe', '--tags', '--exact-match'],
stdout=PIPE, stderr=PIPE, cwd=root,
universal_newlines=True,
)
if p.wait() != 0:
p = Popen(
[str(gitexe), 'branch'], stdout=PIPE, stderr=PIPE,
cwd=root, universal_newlines=True,
)
if p.wait() != 0:
maywarn(p.stderr.read(), 'Git')
return 'pypy-HEAD', revision_id
branch = '?'
for line in p.stdout.read().strip().split('\n'):
if line.startswith('* '):
branch = line[1:].strip()
if branch == '(no branch)':
branch = 'pypy-HEAD'
if branch.startswith("(HEAD detached"):
branch = 'pypy-HEAD'
break
return branch, revision_id
return p.stdout.read().strip(), revision_id
if __name__ == '__main__':
print(get_repo_version_info())
|