mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-31 11:20:12 +01:00
contrib/bzutil: add filter FilterId and allow negation of filters
There is already the command line option --bz to add additional bugs to the output. The option --no-bz is to black list bugs. The new filter 'bz' allows you something similar, but contrary to --no-bz which acts at an earlier stage, this filters bugs after they are parsed from refs. Also, allow every filter to be negated by prepending it with ~ or !. Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
parent
d4be2c2da7
commit
25a57149aa
1 changed files with 110 additions and 59 deletions
|
|
@ -430,6 +430,37 @@ class BzInfo:
|
|||
def clearBZData(self):
|
||||
if hasattr(self, '_bzdata'):
|
||||
del self._bzdata
|
||||
@staticmethod
|
||||
def parse_bz(obz, no_bz=None):
|
||||
bz_tuples = [bz for bz in re.split('[,; ]', obz) if bz]
|
||||
result_man2 = []
|
||||
no_bz_skipped = []
|
||||
has_any = False
|
||||
for bzii in bz_tuples:
|
||||
bzi = bzii.partition(':')
|
||||
if not bzi[1] and not bzi[2]:
|
||||
bzi = bzii.partition('#')
|
||||
if not bzi[1] and not bzi[2]:
|
||||
bzi = ['rh',bzi[0]]
|
||||
else:
|
||||
bzi = bzi[::2]
|
||||
if not bzi[0] or not bzi[1] or not re.match('^[0-9]{4,7}$', bzi[1]):
|
||||
raise Exception('invalid bug specifier \"%s\" (%s)' % (obz, bzii))
|
||||
bz = None
|
||||
if bzi[0] == 'rhbz' or bzi[0] == 'rh':
|
||||
bz = BzInfoRhbz(bzi[1])
|
||||
elif bzi[0] == 'bgo' or bzi[0] == 'bg':
|
||||
bz = BzInfoBgo(bzi[1])
|
||||
else:
|
||||
raise Exception('invalid bug specifier \"%s\"' % obz)
|
||||
if no_bz is None or bz not in no_bz:
|
||||
result_man2.append(bz)
|
||||
else:
|
||||
no_bz_skipped.append(bz)
|
||||
has_any = True
|
||||
if not has_any:
|
||||
raise Exception('invalid bug specifier \"%s\": contains no bugs' % obz)
|
||||
return result_man2, no_bz_skipped
|
||||
|
||||
|
||||
class BzInfoBgo(BzInfo):
|
||||
|
|
@ -696,6 +727,8 @@ class FilterBase():
|
|||
s = s.replace("\n", "\\n")
|
||||
s = s.replace("\\", "\\\\")
|
||||
return "'" + s + "'"
|
||||
_regex_neg = '^([!~]*)'
|
||||
_regex_neg = re.compile(_regex_neg)
|
||||
@staticmethod
|
||||
def create_filter(args):
|
||||
if isinstance(args, basestring):
|
||||
|
|
@ -704,10 +737,16 @@ class FilterBase():
|
|||
raise Exception("Cannot parse empty filter")
|
||||
name = args[0]
|
||||
|
||||
neg = FilterBase._regex_neg.match(name)
|
||||
neg = neg.group(0)
|
||||
if neg:
|
||||
name = name[len(neg):]
|
||||
neg = len(neg) % 2 == 1
|
||||
|
||||
if name.lower() in FilterBase._mapping:
|
||||
filter_type = FilterBase._mapping[name.lower()]
|
||||
elif name.lower() in BzClient.DEFAULT_FIELDS:
|
||||
args = tuple(['match'] + list(args))
|
||||
args = tuple(['match', name] + list(args[1:]))
|
||||
filter_type = FilterBase._mapping['match']
|
||||
else:
|
||||
raise Exception("Invalid filter name \"%s\"" % name)
|
||||
|
|
@ -716,18 +755,30 @@ class FilterBase():
|
|||
f = filter_type.factory(args[1:])
|
||||
except Exception as e:
|
||||
raise Exception("Cannot create filter of type %s with arguments \"%r\": (%s)" % (filter_type.__name__, args[1:], str(e)))
|
||||
if neg:
|
||||
f = FilterNot.create(f)
|
||||
return f
|
||||
@staticmethod
|
||||
def parse(s):
|
||||
if s.lower() in FilterBase._mapping:
|
||||
filter_type = FilterBase._mapping[s.lower()]
|
||||
if not filter_type.allow_simple:
|
||||
raise Exception("Cannot create filter '%s' because it needs some arguments. Use full python syntax" % (s))
|
||||
try:
|
||||
f = filter_type.factory([])
|
||||
except Exception as e:
|
||||
raise Exception("Cannot create filter of type %s with arguments \"%r\": (%s)" % (filter_type.factory.__name__, args[1:], str(e)))
|
||||
return f
|
||||
if not isinstance(s, basestring):
|
||||
return FilterBase.create_filter(s)
|
||||
sl = s.lower()
|
||||
if sl in FilterBase._mapping:
|
||||
filter_type = FilterBase._mapping[sl]
|
||||
if filter_type.allow_simple:
|
||||
try:
|
||||
f = filter_type.factory([])
|
||||
except Exception as e:
|
||||
raise Exception("Cannot create filter of type %s with arguments \"%r\": (%s)" % (filter_type.factory.__name__, args[1:], str(e)))
|
||||
return f
|
||||
if sl.startswith("bz "):
|
||||
return FilterBz(s[3:].split())
|
||||
if sl.startswith("nobz "):
|
||||
return FilterBz.exclude(s[5:].split())
|
||||
if sl.startswith("not "):
|
||||
return FilterNot.create(filter=FilterBase.parse(s[4:]))
|
||||
if sl.startswith("!") or sl.startswith("~"):
|
||||
return FilterNot.create(filter=FilterBase.parse(s[1:]))
|
||||
try:
|
||||
expr = ast.literal_eval(s)
|
||||
except Exception as e:
|
||||
|
|
@ -771,7 +822,7 @@ class FilterNot(FilterBase):
|
|||
return
|
||||
if len(args) != 1:
|
||||
raise Exception("Filter of type FilterNot expects exactly one arguement (instead got \"%r\")" % (args))
|
||||
self._filter = FilterBase.create_filter(args[0])
|
||||
self._filter = FilterBase.parse(args[0])
|
||||
def __str__(self):
|
||||
return '(not %s)' % self._filter
|
||||
def __repr__(self):
|
||||
|
|
@ -784,17 +835,21 @@ class FilterAnd(FilterBase):
|
|||
@staticmethod
|
||||
def join(*args):
|
||||
if len(args) >= 2:
|
||||
return FilterAnd(None, filters=args)
|
||||
return FilterAnd(filters=args)
|
||||
return args[0]
|
||||
def __init__(self, args, filters=None):
|
||||
@staticmethod
|
||||
def create(args=None,filters=None):
|
||||
filter = FilterAnd(args=args, filters=filters)
|
||||
if len(filter._filters) == 0:
|
||||
return FilterTrue()
|
||||
if len(filter._filters) == 1:
|
||||
return filters[0]
|
||||
return filter
|
||||
def __init__(self, args=None, filters=None):
|
||||
if filters is None:
|
||||
if not args:
|
||||
raise Exception("Filter of type FilterAnd expects one or more filters (instead got \"%r\")" % (args))
|
||||
filters = [FilterBase.create_filter(f) for f in args]
|
||||
if len(filters) == 0:
|
||||
return FilterTrue()
|
||||
if len(filters) == 1:
|
||||
return filters[0]
|
||||
filters = [FilterBase.parse(f) for f in args]
|
||||
f = []
|
||||
for filter in filters:
|
||||
if isinstance(filter, FilterAnd):
|
||||
|
|
@ -818,17 +873,21 @@ class FilterOr(FilterBase):
|
|||
@staticmethod
|
||||
def join(*args):
|
||||
if len(args) >= 2:
|
||||
return FilterOr(None, filters=args)
|
||||
return FilterOr(filters=args)
|
||||
return args[0]
|
||||
def __init__(self, args, filters=None):
|
||||
@staticmethod
|
||||
def create(args=None,filters=None):
|
||||
filter = FilterOr(args=args, filters=filters)
|
||||
if len(filter._filters) == 0:
|
||||
return FilterTrue()
|
||||
if len(filter._filters) == 1:
|
||||
return filters[0]
|
||||
return filter
|
||||
def __init__(self, args=None, filters=None):
|
||||
if filters is None:
|
||||
if not args:
|
||||
raise Exception("Filter of type FilterOr expects one or more filters (instead got \"%r\")" % (args))
|
||||
filters = [FilterBase.create_filter(f) for f in args]
|
||||
if len(filters) == 0:
|
||||
return FilterFalse()
|
||||
if len(filters) == 1:
|
||||
return filters[0]
|
||||
filters = [FilterBase.parse(f) for f in args]
|
||||
f = []
|
||||
for filter in filters:
|
||||
if isinstance(filter, FilterOr):
|
||||
|
|
@ -872,6 +931,27 @@ class FilterBgo(FilterBase):
|
|||
return isinstance(bz, BzInfoBgo)
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, FilterBgo)
|
||||
class FilterBz(FilterBase):
|
||||
def __init__(self, args=None, bz=None):
|
||||
if bz is not None:
|
||||
self._bz = set(bz)
|
||||
else:
|
||||
self._bz = set([bz for arg in args for bz in BzInfo.parse_bz(arg)[0]])
|
||||
if not self._bz:
|
||||
raise Exception("Missing bz arguments for FilterBz")
|
||||
def __str__(self):
|
||||
return "(bz %s)" % (" ".join([FilterBase.escape(str(bz)) for bz in self._bz]))
|
||||
def __repr__(self):
|
||||
return "('bz' %s)" % (",".join([FilterBase.escape(str(bz)) for bz in self._bz]))
|
||||
def eval(self, bz):
|
||||
for bz2 in self._bz:
|
||||
if bz == bz2:
|
||||
return True
|
||||
return False
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, FilterBz):
|
||||
return other._bz == self._bz
|
||||
return False
|
||||
class FilterMatch(FilterBase):
|
||||
def __init__(self, args):
|
||||
if len(args) != 2 or not isinstance(args[0], basestring) or not isinstance(args[1], basestring):
|
||||
|
|
@ -881,7 +961,7 @@ class FilterMatch(FilterBase):
|
|||
def __str__(self):
|
||||
return '(match %s %s)' % (FilterBase.escape(self._name), FilterBase.escape(self._value))
|
||||
def __repr__(self):
|
||||
return "('match' %s %s)" % (FilterBase.escape(self._name), FilterBase.escape(self._value))
|
||||
return "('match', %s, %s)" % (FilterBase.escape(self._name), FilterBase.escape(self._value))
|
||||
def eval(self, bz):
|
||||
bzdata = bz.getBZData()
|
||||
if not bzdata or self._name not in bzdata:
|
||||
|
|
@ -946,6 +1026,7 @@ FilterBase._mapping = {
|
|||
'not': FilterMapping(FilterNot, False),
|
||||
'and': FilterMapping(FilterAnd, False),
|
||||
'or': FilterMapping(FilterOr, False),
|
||||
'bz': FilterMapping(FilterBz, False),
|
||||
'rhbz': FilterMapping(FilterRhbz),
|
||||
'bgo': FilterMapping(FilterBgo),
|
||||
'match': FilterMapping(FilterMatch, False),
|
||||
|
|
@ -1001,42 +1082,12 @@ class CmdParseCommitMessage(CmdBase):
|
|||
def _order_keys(keys, ordered):
|
||||
return [o for o in ordered if o in keys]
|
||||
|
||||
def _parse_bz(self, obz, no_bz):
|
||||
bz_tuples = [bz for bz in re.split('[,; ]', obz) if bz]
|
||||
result_man2 = []
|
||||
no_bz_skipped = []
|
||||
has_any = False
|
||||
for bzii in bz_tuples:
|
||||
bzi = bzii.partition(':')
|
||||
if not bzi[1] and not bzi[2]:
|
||||
bzi = bzii.partition('#')
|
||||
if not bzi[1] and not bzi[2]:
|
||||
bzi = ['rh',bzi[0]]
|
||||
else:
|
||||
bzi = bzi[::2]
|
||||
if not bzi[0] or not bzi[1] or not re.match('^[0-9]{4,7}$', bzi[1]):
|
||||
raise Exception('invalid bug specifier \"%s\" (%s)' % (obz, bzii))
|
||||
bz = None
|
||||
if bzi[0] == 'rhbz' or bzi[0] == 'rh':
|
||||
bz = BzInfoRhbz(bzi[1])
|
||||
elif bzi[0] == 'bgo' or bzi[0] == 'bg':
|
||||
bz = BzInfoBgo(bzi[1])
|
||||
else:
|
||||
raise Exception('invalid bug specifier \"%s\"' % obz)
|
||||
if no_bz is None or bz not in no_bz:
|
||||
result_man2.append(bz)
|
||||
else:
|
||||
no_bz_skipped.append(bz)
|
||||
has_any = True
|
||||
if not has_any:
|
||||
raise Exception('invalid bug specifier \"%s\": contains no bugs' % obz)
|
||||
return result_man2, no_bz_skipped
|
||||
def _parse_bzlist(self, bzlist, no_bz=None):
|
||||
i = 0
|
||||
result_man = []
|
||||
no_bz_skipped = []
|
||||
for obz in (bzlist if bzlist else []):
|
||||
result_man2, no_bz_skipped2 = self._parse_bz(obz, no_bz)
|
||||
result_man2, no_bz_skipped2 = BzInfo.parse_bz(obz, no_bz)
|
||||
result_man.append(UtilParseCommitMessage('bz:\"%s\"' % obz, result_man2, git_backend=False, commit_date=-1000+i))
|
||||
no_bz_skipped.extend(no_bz_skipped2)
|
||||
i = i + 1
|
||||
|
|
@ -1161,7 +1212,7 @@ class CmdParseCommitMessage(CmdBase):
|
|||
excluded = excluded + commit_data.filter_out(filter)
|
||||
|
||||
if excluded:
|
||||
print(" --no-bz '%s'" % ",".join([str(result) for result in excluded]))
|
||||
print(" ~bz %s" % ",".join([str(result) for result in excluded]))
|
||||
excluded =sorted(list(set(excluded)))
|
||||
for result in excluded:
|
||||
print(result.to_string(" ", 0, self.options.color))
|
||||
|
|
@ -1245,7 +1296,7 @@ class CmdParseCommitMessage(CmdBase):
|
|||
printed_something = True
|
||||
print('=== List by BZ (%s) ===' % (len(result_bz_keys)))
|
||||
if result_bz_keys:
|
||||
print(" --bz '%s'" % ",".join([str(result) for result in result_bz_keys]))
|
||||
print(" bz %s" % ",".join([str(result) for result in result_bz_keys]))
|
||||
for result in result_bz_keys:
|
||||
print(result.to_string(" ", self.options.verbose, self.options.color))
|
||||
for commit_data in sorted(result_bz[result], key=lambda commit_data: commit_data.get_commit_date(), reverse=True):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue