mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-31 13:40:11 +01:00
contrib: add fetching data from bugzilla to bzutil.py
This is heavily borrowed from http://git.app.eng.bos.redhat.com/rcm/dist-git-utils.git/tree/src/gitbz Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
parent
b0eede287e
commit
c6b5a33ef4
1 changed files with 168 additions and 7 deletions
|
|
@ -5,6 +5,9 @@ import argparse
|
|||
import subprocess
|
||||
import os
|
||||
import re
|
||||
import kobo.xmlrpc
|
||||
import xmlrpclib
|
||||
import termcolor
|
||||
|
||||
|
||||
devnull = open(os.devnull, 'w')
|
||||
|
|
@ -17,6 +20,20 @@ def _call(args):
|
|||
sys.exit(1)
|
||||
return output
|
||||
|
||||
def _read_config_file(filename):
|
||||
values = {}
|
||||
with open(filename) as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if not line or line[0] == '#':
|
||||
continue
|
||||
name, var = line.partition("=")[::2]
|
||||
var = var.strip()
|
||||
if var and ((var[0]=='"' and var[-1]=='"') or (var[0]=="'" and var[-1]=="'")):
|
||||
var = var[1:-1]
|
||||
values[name.strip()] = var
|
||||
return values
|
||||
|
||||
def git_ref_list(commit):
|
||||
return _call(['git', 'rev-list', '--no-walk', commit]).splitlines()
|
||||
|
||||
|
|
@ -44,6 +61,9 @@ def git_get_commit_date(shaid):
|
|||
return _git_get_commit_date[shaid]
|
||||
|
||||
|
||||
class PasswordError(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
class CmdBase:
|
||||
def __init__(self, name):
|
||||
|
|
@ -54,6 +74,52 @@ class CmdBase:
|
|||
print_usage()
|
||||
|
||||
|
||||
class BzClient:
|
||||
COMMON_FIELDS = ['id', 'depends_on', 'blocks', 'flags', 'keywords', 'status', 'component']
|
||||
|
||||
def __init__(self, url, config):
|
||||
transport = None
|
||||
use_https = False
|
||||
if url.startswith('https://'):
|
||||
transport = kobo.xmlrpc.SafeCookieTransport()
|
||||
use_https = True
|
||||
else:
|
||||
transport = kobo.xmlrpc.CookieTransport()
|
||||
self._key_part = (url, use_https)
|
||||
self._client = xmlrpclib.ServerProxy(url, transport=transport)
|
||||
self._config = config
|
||||
|
||||
def _login(self, user, password):
|
||||
self._client.User.login({'login': user,
|
||||
'password': password})
|
||||
|
||||
_getBZDataCache = {}
|
||||
def getBZData(self, bzid, include_fields = COMMON_FIELDS):
|
||||
if not self._config.get('rhbz_passwd', None) or not self._config.get('rhbz_user', None):
|
||||
raise PasswordError('The Bugzilla password has not been set')
|
||||
user = self._config['rhbz_user'];
|
||||
passwd = self._config['rhbz_passwd']
|
||||
|
||||
key = sorted(include_fields)
|
||||
key.append(self._key_part)
|
||||
key.append(user)
|
||||
key.append(passwd)
|
||||
key.append(bzid)
|
||||
key = tuple(key)
|
||||
|
||||
if BzClient._getBZDataCache.has_key(key):
|
||||
return BzClient._getBZDataCache[key]
|
||||
|
||||
self._login(user, passwd)
|
||||
|
||||
bugs_data = self._client.Bug.get({'ids': bzid,
|
||||
'include_fields': include_fields})
|
||||
bug_data = bugs_data['bugs'][0]
|
||||
BzClient._getBZDataCache[key] = bug_data
|
||||
return bug_data
|
||||
|
||||
|
||||
|
||||
# class to hold information about a bugzilla entry
|
||||
class BzInfo:
|
||||
def __init__(self, bzid):
|
||||
|
|
@ -71,7 +137,20 @@ class BzInfo:
|
|||
def __str__(self):
|
||||
return "%s #%s" % (self.bztype, self.bzid)
|
||||
def __repr__(self):
|
||||
return "BzInfo(\"%s\", \"%s\")" % (self.bztype, self.bzid)
|
||||
return "(\"%s\", \"%s\")" % (self.bztype, self.bzid)
|
||||
|
||||
def getBZData(self, field=None):
|
||||
if not hasattr(self, '_bzdata'):
|
||||
self._bzdata = self._fetchBZData()
|
||||
if self._bzdata is None:
|
||||
self._bzdata = {}
|
||||
if field is None:
|
||||
return self._bzdata
|
||||
return self._bzdata.get(field, None)
|
||||
def _fetchBZData(self):
|
||||
return None
|
||||
|
||||
|
||||
|
||||
class BzInfoBgo(BzInfo):
|
||||
def __init__(self, bzid):
|
||||
|
|
@ -83,6 +162,7 @@ class BzInfoBgo(BzInfo):
|
|||
def url(self):
|
||||
return "https://bugzilla.gnome.org/show_bug.cgi?id=%s" % self.bzid
|
||||
|
||||
|
||||
class BzInfoRhbz(BzInfo):
|
||||
def __init__(self, bzid):
|
||||
BzInfo.__init__(self, bzid)
|
||||
|
|
@ -93,6 +173,10 @@ class BzInfoRhbz(BzInfo):
|
|||
def url(self):
|
||||
return "https://bugzilla.redhat.com/show_bug.cgi?id=%s" % self.bzid
|
||||
|
||||
def _fetchBZData(self):
|
||||
return BzClient('https://bugzilla.redhat.com/xmlrpc.cgi', config).getBZData(self.bzid)
|
||||
|
||||
|
||||
|
||||
class UtilParseCommitMessage(CmdBase):
|
||||
|
||||
|
|
@ -106,13 +190,15 @@ class UtilParseCommitMessage(CmdBase):
|
|||
]
|
||||
_patterns = [(re.compile(p[0]), p[1]) for p in _patterns]
|
||||
|
||||
def __init__(self, commit):
|
||||
def __init__(self, commit, result=None, git_backend=True, commit_date=0):
|
||||
self.commit = commit
|
||||
self._result = None
|
||||
self._result = result
|
||||
self._git_backend = git_backend
|
||||
self._commit_date = commit_date
|
||||
|
||||
@property
|
||||
def result(self):
|
||||
if not self._result:
|
||||
if not self._result and self._git_backend:
|
||||
message = git_commit_message(self.commit)
|
||||
data = []
|
||||
|
||||
|
|
@ -125,11 +211,27 @@ class UtilParseCommitMessage(CmdBase):
|
|||
self._result = list(set(data))
|
||||
return self._result
|
||||
|
||||
def __cmp__(self, other):
|
||||
if self._git_backend != other._git_backend:
|
||||
return cmp(self._git_backend, other._git_backend)
|
||||
return cmp(self.commit, other.commit)
|
||||
def __hash__(self):
|
||||
return hash(self.commit)
|
||||
def __str__(self):
|
||||
return str( (self.commit, self.result) )
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
|
||||
def commit_summary(self, color):
|
||||
if self._git_backend:
|
||||
return git_summary(self.commit, color)
|
||||
return self.commit
|
||||
def get_commit_date(self):
|
||||
if self._git_backend:
|
||||
return git_get_commit_date(self.commit)
|
||||
return self._commit_date
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -140,29 +242,88 @@ class CmdParseCommitMessage(CmdBase):
|
|||
|
||||
self.parser = argparse.ArgumentParser(prog=sys.argv[0] + " " + name, description='Parse commit messages.')
|
||||
self.parser.add_argument('--color', '-c', dest='color', action='store_true')
|
||||
self.parser.add_argument('--conf', metavar='conf', default=('%s/.bzutil.conf' % os.path.expanduser("~")))
|
||||
self.parser.add_argument('--bz', action='append')
|
||||
self.parser.add_argument('commit', metavar='commit', type=str, nargs='+',
|
||||
help='commit ids to parse')
|
||||
|
||||
@staticmethod
|
||||
def _order_keys(keys, ordered):
|
||||
return [o for o in ordered if o in keys]
|
||||
|
||||
_colormap_flag = {
|
||||
'+': 'green',
|
||||
'?': 'yellow',
|
||||
}
|
||||
_colormap_status = {
|
||||
'POST': 'green',
|
||||
'MODIFIED': 'yellow',
|
||||
'CLOSED': 'green',
|
||||
}
|
||||
|
||||
|
||||
def _colored(self, value, colormapping, defaultcolor='red'):
|
||||
v = '>> ' + value
|
||||
if not self.options.color:
|
||||
return v
|
||||
color = colormapping.get(value, defaultcolor)
|
||||
return termcolor.colored(v, color)
|
||||
|
||||
def run(self, argv):
|
||||
self.options = self.parser.parse_args(argv)
|
||||
|
||||
global config
|
||||
if not os.path.exists(self.options.conf):
|
||||
self.parser.error('config file does not exist: %s' % self.options.conf)
|
||||
config = _read_config_file(self.options.conf)
|
||||
|
||||
result_man = []
|
||||
obzi = 0
|
||||
for obz in self.options.bz:
|
||||
bz_tuples = [bz for bz in re.split('[,; ]', obz) if bz]
|
||||
result_man2 = []
|
||||
for bzii in bz_tuples:
|
||||
bzi = bzii.partition(':')[::2]
|
||||
if not bzi[0] or not bzi[1] or not re.match('^[0-9]{4,7}$', bzi[1]):
|
||||
raise self.parser.error('Invalid bugzilla option --bz \"%s\" (%s)' % (obz, bzii))
|
||||
if bzi[0] == 'rhbz' or bzi[0] == 'rh':
|
||||
result_man2.append(BzInfoRhbz(bzi[1]))
|
||||
elif bzi[0] == 'bgo' or bzi[0] == 'bg':
|
||||
result_man2.append(BzInfoBgo(bzi[1]))
|
||||
else:
|
||||
raise self.parser.error('Invalid bugzilla option --bz \"%s\"' % obz)
|
||||
if not result_man2:
|
||||
raise self.parser.error('Invalid bugzilla option --bz \"%s\"' % obz)
|
||||
result_man.append(UtilParseCommitMessage('bz \"%s\"' % obz, result_man2, git_backend=False, commit_date=-obzi))
|
||||
obzi = obzi + 1
|
||||
|
||||
result_all = [ (ref, [UtilParseCommitMessage(commit) for commit in git_ref_list(ref)]) for ref in self.options.commit]
|
||||
|
||||
for ref_data in result_all:
|
||||
print("ref: %s" % ref_data[0])
|
||||
for commit_data in ref_data[1]:
|
||||
print(" %s" % git_summary(commit_data.commit, self.options.color))
|
||||
print(" %s" % commit_data.commit_summary(self.options.color))
|
||||
for result in commit_data.result:
|
||||
print(" %-4s #%-8s %s" % (result.bztype, result.bzid, result.url))
|
||||
|
||||
|
||||
result_reduced = [ commit_data for ref_data in result_all for commit_data in ref_data[1] if commit_data.result ]
|
||||
result_reduced = result_reduced + result_man
|
||||
result_reduced = sorted(set(result_reduced), key=lambda commit_data: commit_data.get_commit_date(), reverse=True)
|
||||
|
||||
print
|
||||
print('sorted:')
|
||||
for commit_data in sorted(set(result_reduced), key=lambda commit_data: git_get_commit_date(commit_data.commit), reverse=True):
|
||||
print(" %s" % git_summary(commit_data.commit, self.options.color))
|
||||
for commit_data in result_reduced:
|
||||
print(" %s" % commit_data.commit_summary(self.options.color))
|
||||
for result in commit_data.result:
|
||||
print(" %-4s #%-8s %s" % (result.bztype, result.bzid, result.url))
|
||||
bzdata = result.getBZData()
|
||||
for k in CmdParseCommitMessage._order_keys(bzdata.keys(), ['status', 'flags']):
|
||||
if k == 'flags':
|
||||
for flag in bzdata[k]:
|
||||
print(" %-20s = %s" % ('#'+flag['name'], self._colored(flag['status'], CmdParseCommitMessage._colormap_flag)))
|
||||
elif k == 'status':
|
||||
print(" %-20s = %s" % (k, self._colored(bzdata[k], CmdParseCommitMessage._colormap_status)))
|
||||
print
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue