|
Michal Suchanek |
3a12a8 |
#!/usr/bin/python
|
|
Benjamin Poirier |
4e62ed |
# -*- coding: utf-8 -*-,
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
import sys
|
|
Jeff Mahoney |
89f2a2 |
import re
|
|
Jeff Mahoney |
89f2a2 |
from optparse import OptionParser
|
|
Jeff Mahoney |
89f2a2 |
from . import patch
|
|
Benjamin Poirier |
4e62ed |
from io import StringIO
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
diffstart = re.compile("^(---|\*\*\*|Index:|\+\+\+)[ \t][^ \t]\S+/|^diff -")
|
|
Jeff Mahoney |
89f2a2 |
tag_regex = re.compile("(\S+):[ \t]*(.*)")
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
tag_map = {
|
|
Jeff Mahoney |
89f2a2 |
'Patch-mainline' : {
|
|
Jeff Mahoney |
89f2a2 |
'required' : True,
|
|
Jeff Mahoney |
89f2a2 |
'accepted' : [
|
|
Jeff Mahoney |
89f2a2 |
{
|
|
Jeff Mahoney |
89f2a2 |
# In mainline repo, tagged for release
|
|
Jeff Mahoney |
89f2a2 |
'name' : 'Version',
|
|
Jeff Mahoney |
89f2a2 |
'match': 'v?(\d+\.)+\d+(-rc\d+)?\s*$',
|
|
Jeff Mahoney |
89f2a2 |
'requires' : [ 'Git-commit' ],
|
|
Jeff Mahoney |
89f2a2 |
'excludes' : [ 'Git-repo' ],
|
|
Jeff Mahoney |
89f2a2 |
}, { # In mainline repo but not tagged yet
|
|
Jeff Mahoney |
89f2a2 |
'name' : 'Version',
|
|
Jeff Mahoney |
89f2a2 |
'match': 'v?(\d+\.)+\d+(-rc\d+)?\s+or\s+v?(\d+\.)+\d+(-rc\d+)?\s+\(next release\)\s*$',
|
|
Jeff Mahoney |
89f2a2 |
'requires' : [ 'Git-commit' ],
|
|
Jeff Mahoney |
89f2a2 |
'excludes' : [ 'Git-repo' ],
|
|
Jeff Mahoney |
89f2a2 |
}, {
|
|
Jeff Mahoney |
89f2a2 |
# Queued in subsystem maintainer repo
|
|
Jeff Mahoney |
89f2a2 |
'name' : 'Queued',
|
|
Jeff Mahoney |
89f2a2 |
'match' : 'Queued(.*)',
|
|
Jeff Mahoney |
89f2a2 |
'requires' : [ 'Git-commit', 'Git-repo' ],
|
|
Jeff Mahoney |
89f2a2 |
}, {
|
|
Jeff Mahoney |
89f2a2 |
# Depends on another non-upstream patch
|
|
Jeff Mahoney |
89f2a2 |
'name' : 'Depends',
|
|
Jeff Mahoney |
89f2a2 |
'match' : 'Depends on\s+.+',
|
|
Jeff Mahoney |
89f2a2 |
'excludes' : [ 'Git-commit', 'Git-repo' ],
|
|
Jeff Mahoney |
89f2a2 |
}, {
|
|
Jeff Mahoney |
89f2a2 |
# No, typically used for patches that have review issues
|
|
Jeff Mahoney |
89f2a2 |
# but are not fundamentally rejected
|
|
Jeff Mahoney |
89f2a2 |
'name' : 'No',
|
|
Jeff Mahoney |
89f2a2 |
'match' : 'No,?\s+.+',
|
|
Jeff Mahoney |
89f2a2 |
'excludes' : [ 'Git-commit', 'Git-repo' ],
|
|
Jeff Mahoney |
89f2a2 |
}, {
|
|
Jeff Mahoney |
89f2a2 |
# Never, typically used for patches that have been rejected
|
|
Jeff Mahoney |
89f2a2 |
# for upstream inclusion but still have a compelling reason
|
|
Jeff Mahoney |
89f2a2 |
# for inclusion in a SUSE release or are otherwise
|
|
Jeff Mahoney |
89f2a2 |
# inappropriate for upstream inclusion (packaging, kABI,
|
|
Jeff Mahoney |
89f2a2 |
# SLES-only feature.)
|
|
Jeff Mahoney |
89f2a2 |
'name' : 'Never',
|
|
Jeff Mahoney |
89f2a2 |
'match' : 'Never,?\s+.+',
|
|
Jeff Mahoney |
89f2a2 |
'excludes' : [ 'Git-commit', 'Git-repo' ],
|
|
Jeff Mahoney |
89f2a2 |
}, {
|
|
Jeff Mahoney |
89f2a2 |
# Submitted upstream. Description should provide either
|
|
Jeff Mahoney |
89f2a2 |
# a date and a mailing list or a URL to an archived post.
|
|
Jeff Mahoney |
89f2a2 |
'name' : 'Submitted',
|
|
Jeff Mahoney |
89f2a2 |
'match' : 'Submitted,?\s+.+',
|
|
Jeff Mahoney |
89f2a2 |
'excludes' : [ 'Git-commit', 'Git-repo' ],
|
|
Jeff Mahoney |
89f2a2 |
}, {
|
|
Jeff Mahoney |
89f2a2 |
# Should be used rarely. Description should provide
|
|
Jeff Mahoney |
89f2a2 |
# reason for the patch not being accepted upstream.
|
|
Jeff Mahoney |
89f2a2 |
'name' : 'Not yet',
|
|
Jeff Mahoney |
89f2a2 |
'match' : 'Not yet,?\s+.+',
|
|
Jeff Mahoney |
89f2a2 |
'excludes' : [ 'Git-commit', 'Git-repo' ],
|
|
Jeff Mahoney |
89f2a2 |
}, {
|
|
Jeff Mahoney |
89f2a2 |
'match' : 'Submitted\s*$',
|
|
Jeff Mahoney |
89f2a2 |
'error' : 'Requires a description: <date> <list> or <url>',
|
|
Jeff Mahoney |
89f2a2 |
'excludes' : [ 'Git-commit', 'Git-repo' ],
|
|
Jeff Mahoney |
89f2a2 |
}, {
|
|
Jeff Mahoney |
89f2a2 |
'match' : 'Yes\s+$',
|
|
Jeff Mahoney |
89f2a2 |
'error' : 'Exact version required',
|
|
Jeff Mahoney |
89f2a2 |
}, {
|
|
Jeff Mahoney |
89f2a2 |
'match' : 'Yes.*(\d+\.)+\d+',
|
|
Jeff Mahoney |
89f2a2 |
'error' : '`Yes\' keyword is invalid',
|
|
Jeff Mahoney |
89f2a2 |
'excludes' : [ 'Git-commit', 'Git-repo' ],
|
|
Jeff Mahoney |
89f2a2 |
}, {
|
|
Jeff Mahoney |
89f2a2 |
'match' : '(Never|Not yet|No)\s*$',
|
|
Jeff Mahoney |
89f2a2 |
'error' : 'Requires a reason',
|
|
Jeff Mahoney |
89f2a2 |
'excludes' : [ 'Git-commit', 'Git-repo' ],
|
|
Jeff Mahoney |
89f2a2 |
},
|
|
Jeff Mahoney |
89f2a2 |
],
|
|
Jeff Mahoney |
89f2a2 |
'requires_any' : [ 'Signed-off-by:SUSE', 'Acked-by:SUSE', 'From:SUSE',
|
|
Jeff Mahoney |
89f2a2 |
'Reviewed-by:SUSE' ],
|
|
Jeff Mahoney |
89f2a2 |
},
|
|
Jeff Mahoney |
89f2a2 |
'Git-commit' : {
|
|
Jeff Mahoney |
89f2a2 |
'multi' : True,
|
|
Jeff Mahoney |
89f2a2 |
'accepted' : [
|
|
Jeff Mahoney |
89f2a2 |
{
|
|
Jeff Mahoney |
89f2a2 |
# 40-character SHA1 hash with optional partial tag
|
|
Jeff Mahoney |
89f2a2 |
'match' : '([0-9a-fA-F]){40}(\s+\(partial\))?',
|
|
Jeff Mahoney |
89f2a2 |
}
|
|
Jeff Mahoney |
89f2a2 |
],
|
|
Jeff Mahoney |
89f2a2 |
'requires_any' : [ 'Patch-mainline:Version', 'Patch-mainline:Queued' ],
|
|
Jeff Mahoney |
89f2a2 |
'error' : "requires full SHA1 hash and optional (partial) tag",
|
|
Jeff Mahoney |
89f2a2 |
},
|
|
Jeff Mahoney |
89f2a2 |
'Git-repo' : {
|
|
Jeff Mahoney |
89f2a2 |
'accepted' : [
|
|
Jeff Mahoney |
89f2a2 |
{
|
|
Jeff Mahoney |
89f2a2 |
# Weak match for URL. Abbreviated names are not acceptable.
|
|
Jeff Mahoney |
89f2a2 |
'match' : '.*/.*',
|
|
Jeff Mahoney |
89f2a2 |
}
|
|
Jeff Mahoney |
89f2a2 |
],
|
|
Jeff Mahoney |
89f2a2 |
'requires' : [ 'Git-commit' ],
|
|
Jeff Mahoney |
89f2a2 |
'error' : "must contain URL pointing to repository containing the commit (and branch, if not master)",
|
|
Jeff Mahoney |
89f2a2 |
},
|
|
Jeff Mahoney |
89f2a2 |
'Signed-off-by' : {
|
|
Jeff Mahoney |
89f2a2 |
'multi' : True,
|
|
Jeff Mahoney |
89f2a2 |
'accepted' : [
|
|
Jeff Mahoney |
89f2a2 |
{
|
|
Jeff Mahoney |
89f2a2 |
'name' : 'SUSE',
|
|
Michal Suchanek |
ffde1c |
'match' : '.*@suse\.(com|de|cz)',
|
|
Jeff Mahoney |
89f2a2 |
},
|
|
Jeff Mahoney |
89f2a2 |
{
|
|
Jeff Mahoney |
89f2a2 |
'match' : '.*',
|
|
Jeff Mahoney |
89f2a2 |
}
|
|
Jeff Mahoney |
89f2a2 |
],
|
|
Jeff Mahoney |
89f2a2 |
},
|
|
Jeff Mahoney |
89f2a2 |
'Acked-by' : {
|
|
Jeff Mahoney |
89f2a2 |
'multi' : True,
|
|
Jeff Mahoney |
89f2a2 |
'accepted' : [
|
|
Jeff Mahoney |
89f2a2 |
{
|
|
Jeff Mahoney |
89f2a2 |
'name' : 'SUSE',
|
|
Michal Suchanek |
ffde1c |
'match' : '.*@suse\.(com|de|cz)',
|
|
Jeff Mahoney |
89f2a2 |
},
|
|
Jeff Mahoney |
89f2a2 |
{
|
|
Jeff Mahoney |
89f2a2 |
'match' : '.*',
|
|
Jeff Mahoney |
89f2a2 |
}
|
|
Jeff Mahoney |
89f2a2 |
],
|
|
Jeff Mahoney |
89f2a2 |
},
|
|
Jeff Mahoney |
89f2a2 |
'Reviewed-by' : {
|
|
Jeff Mahoney |
89f2a2 |
'multi' : True,
|
|
Jeff Mahoney |
89f2a2 |
'accepted' : [
|
|
Jeff Mahoney |
89f2a2 |
{
|
|
Jeff Mahoney |
89f2a2 |
'name' : 'SUSE',
|
|
Michal Suchanek |
ffde1c |
'match' : '.*@suse\.(com|de|cz)',
|
|
Jeff Mahoney |
89f2a2 |
},
|
|
Jeff Mahoney |
89f2a2 |
{
|
|
Jeff Mahoney |
89f2a2 |
'match' : '.*',
|
|
Jeff Mahoney |
89f2a2 |
}
|
|
Jeff Mahoney |
89f2a2 |
],
|
|
Jeff Mahoney |
89f2a2 |
},
|
|
Jeff Mahoney |
89f2a2 |
'From' : {
|
|
Jeff Mahoney |
89f2a2 |
'multi' : True,
|
|
Jeff Mahoney |
d1e5de |
'required' : True,
|
|
Jeff Mahoney |
89f2a2 |
'accepted' : [
|
|
Jeff Mahoney |
89f2a2 |
{
|
|
Jeff Mahoney |
89f2a2 |
'name' : 'SUSE',
|
|
Michal Suchanek |
ffde1c |
'match' : '.*@suse\.(com|de|cz)',
|
|
Jeff Mahoney |
89f2a2 |
},
|
|
Jeff Mahoney |
89f2a2 |
{
|
|
Jeff Mahoney |
89f2a2 |
'match' : '.*',
|
|
Jeff Mahoney |
89f2a2 |
}
|
|
Jeff Mahoney |
89f2a2 |
],
|
|
Jeff Mahoney |
89f2a2 |
},
|
|
Jeff Mahoney |
d1e5de |
'Subject' : {
|
|
Jeff Mahoney |
d1e5de |
'required' : True,
|
|
Jeff Mahoney |
d1e5de |
'accepted' : [
|
|
Jeff Mahoney |
d1e5de |
{
|
|
Jeff Mahoney |
3b2ea9 |
'match' : '\S+',
|
|
Jeff Mahoney |
d1e5de |
},
|
|
Jeff Mahoney |
d1e5de |
],
|
|
Jeff Mahoney |
d1e5de |
},
|
|
Jeff Mahoney |
ae9d1c |
'References' : {
|
|
Jeff Mahoney |
ae9d1c |
'required' : True,
|
|
Jeff Mahoney |
37049b |
'required_on_update' : False,
|
|
Jeff Mahoney |
ae9d1c |
'multi' : True,
|
|
Jeff Mahoney |
ae9d1c |
'accepted' : [
|
|
Jeff Mahoney |
ae9d1c |
{
|
|
Jeff Mahoney |
ae9d1c |
'name' : 'SUSE',
|
|
Jeff Mahoney |
b7bee5 |
'match' : '((bsc|boo|bnc|fate)#\d+|jsc#\w+-\d+)',
|
|
Jeff Mahoney |
ae9d1c |
},
|
|
Jeff Mahoney |
ae9d1c |
{
|
|
Jeff Mahoney |
ae9d1c |
'match' : '\S+',
|
|
Jeff Mahoney |
ae9d1c |
},
|
|
Jeff Mahoney |
ae9d1c |
],
|
|
Jeff Mahoney |
ae9d1c |
'error' : "must contain list of references",
|
|
Jeff Mahoney |
ae9d1c |
# Enable to require real References tags
|
|
Jeff Mahoney |
ae9d1c |
# 'requires' : ['References:SUSE'],
|
|
Jeff Mahoney |
ae9d1c |
}
|
|
Jeff Mahoney |
89f2a2 |
}
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
class ValidationError(patch.ValidationError):
|
|
Jeff Mahoney |
89f2a2 |
def __init__(self, name, msg):
|
|
Jeff Mahoney |
89f2a2 |
super(ValidationError, self).__init__(msg)
|
|
Jeff Mahoney |
89f2a2 |
self.name = name
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
class FormatError(ValidationError):
|
|
Jeff Mahoney |
89f2a2 |
def __init__(self, name, value, error=None):
|
|
Jeff Mahoney |
89f2a2 |
name = name.capitalize()
|
|
Jeff Mahoney |
89f2a2 |
if error is None:
|
|
Jeff Mahoney |
89f2a2 |
error = "invalid value"
|
|
Jeff Mahoney |
89f2a2 |
msg = "%s: `%s': %s." % (name, value, error)
|
|
Jeff Mahoney |
89f2a2 |
super(FormatError, self).__init__(name, msg)
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
class MissingTagError(ValidationError):
|
|
Jeff Mahoney |
89f2a2 |
def __init__(self, tag, requires):
|
|
Jeff Mahoney |
89f2a2 |
if not tag:
|
|
Jeff Mahoney |
89f2a2 |
tag = Tag("Policy", None)
|
|
Jeff Mahoney |
89f2a2 |
msg = "%s%s requires %s%s." % (tag.name, \
|
|
Jeff Mahoney |
89f2a2 |
" (%s)" % tag.tagtype if tag.tagtype else "", \
|
|
Jeff Mahoney |
250320 |
requires['name'], \
|
|
Jeff Mahoney |
250320 |
" (%s)" % requires['type'] if 'type' in requires else "")
|
|
Jeff Mahoney |
89f2a2 |
self.target = [requires]
|
|
Jeff Mahoney |
89f2a2 |
super(MissingTagError, self).__init__(tag.name, msg)
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
class MissingMultiTagError(MissingTagError):
|
|
Jeff Mahoney |
89f2a2 |
def __init__(self, tag, requires):
|
|
Jeff Mahoney |
89f2a2 |
if not tag:
|
|
Jeff Mahoney |
89f2a2 |
tag = Tag("Policy", None)
|
|
Jeff Mahoney |
89f2a2 |
msg = "%s%s requires %s." % (tag.name, \
|
|
Jeff Mahoney |
89f2a2 |
" (%s)" % tag.tagtype if tag.tagtype else "", \
|
|
Jeff Mahoney |
250320 |
" or ".join(["%s%s" % (req['name'], \
|
|
Jeff Mahoney |
250320 |
" (%s)" % req['type'] if 'type' in req else "") for req in requires]))
|
|
Jeff Mahoney |
89f2a2 |
self.target = requires
|
|
Jeff Mahoney |
89f2a2 |
super(MissingTagError, self).__init__(tag.name, msg)
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
class ExcludedTagError(ValidationError):
|
|
Jeff Mahoney |
89f2a2 |
def __init__(self, tag, excludes):
|
|
Jeff Mahoney |
89f2a2 |
msg = "%s%s excludes %s%s." % (tag.name,
|
|
Jeff Mahoney |
89f2a2 |
" (%s)" % tag.tagtype if tag.tagtype else "", \
|
|
Jeff Mahoney |
250320 |
excludes['name'], \
|
|
Jeff Mahoney |
250320 |
" (%s)" % excludes['type'] if 'type' in excludes else "")
|
|
Jeff Mahoney |
89f2a2 |
super(ExcludedTagError, self).__init__(tag.name, msg)
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
class DuplicateTagError(ValidationError):
|
|
Jeff Mahoney |
89f2a2 |
def __init__(self, name):
|
|
Jeff Mahoney |
89f2a2 |
name = name.capitalize()
|
|
Jeff Mahoney |
89f2a2 |
msg = "%s must only be used once, even if it is identical." % name
|
|
Jeff Mahoney |
89f2a2 |
super(DuplicateTagError, self).__init__(name, msg)
|
|
Jeff Mahoney |
89f2a2 |
pass
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
class EmptyTagError(ValidationError):
|
|
Jeff Mahoney |
89f2a2 |
def __init__(self, name):
|
|
Jeff Mahoney |
89f2a2 |
name = name.capitalize()
|
|
Jeff Mahoney |
89f2a2 |
msg = "%s: Value cannot be empty." % name
|
|
Jeff Mahoney |
89f2a2 |
super(EmptyTagError, self).__init__(name, msg)
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
class HeaderException(patch.PatchException):
|
|
Jeff Mahoney |
89f2a2 |
def tag_is_missing(self, name):
|
|
Jeff Mahoney |
89f2a2 |
try:
|
|
Jeff Mahoney |
89f2a2 |
for err in self._errors:
|
|
Jeff Mahoney |
89f2a2 |
if isinstance(err, MissingTagError):
|
|
Jeff Mahoney |
89f2a2 |
for tag in err.target:
|
|
Jeff Mahoney |
250320 |
if tag['name'].lower() == name.lower():
|
|
Jeff Mahoney |
89f2a2 |
return True
|
|
Benjamin Poirier |
4e62ed |
except KeyError as e:
|
|
Jeff Mahoney |
89f2a2 |
pass
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
return False
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
class Tag:
|
|
Jeff Mahoney |
89f2a2 |
def __init__(self, name, value):
|
|
Jeff Mahoney |
89f2a2 |
self.name = name.lower().capitalize()
|
|
Jeff Mahoney |
89f2a2 |
self.value = value
|
|
Jeff Mahoney |
89f2a2 |
self.tagtype = None
|
|
Jeff Mahoney |
89f2a2 |
self.valid = False
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
def __str__(self):
|
|
Jeff Mahoney |
89f2a2 |
return "%s: %s" % (self.name, self.value)
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
def __repr__(self):
|
|
Jeff Mahoney |
89f2a2 |
type = "<none>"
|
|
Jeff Mahoney |
89f2a2 |
if self.tagtype:
|
|
Jeff Mahoney |
89f2a2 |
type = self.tagtype
|
|
Jeff Mahoney |
89f2a2 |
valid = "No"
|
|
Jeff Mahoney |
89f2a2 |
if self.valid:
|
|
Jeff Mahoney |
89f2a2 |
valid = "Yes"
|
|
Jeff Mahoney |
89f2a2 |
return "<Tag: name=%s value='%s' type='%s' valid='%s'>" % \
|
|
Jeff Mahoney |
89f2a2 |
(self.name, self.value, type, valid)
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
def match_req(self, req):
|
|
Jeff Mahoney |
250320 |
if self.name == req['name']:
|
|
Jeff Mahoney |
250320 |
if 'type' not in req or self.tagtype == req['type']:
|
|
Jeff Mahoney |
89f2a2 |
if self.valid:
|
|
Jeff Mahoney |
89f2a2 |
return True
|
|
Jeff Mahoney |
89f2a2 |
return False
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
class HeaderChecker(patch.PatchChecker):
|
|
Jeff Mahoney |
37049b |
def __init__(self, stream, updating=False):
|
|
Jeff Mahoney |
89f2a2 |
patch.PatchChecker.__init__(self)
|
|
Jeff Mahoney |
37049b |
self.updating = updating
|
|
Jeff Mahoney |
89f2a2 |
if isinstance(stream, str):
|
|
Jeff Mahoney |
89f2a2 |
stream = StringIO(stream)
|
|
Jeff Mahoney |
37049b |
self.stream = stream
|
|
Jeff Mahoney |
37049b |
|
|
Jeff Mahoney |
37049b |
self.requires = {}
|
|
Jeff Mahoney |
37049b |
self.requires_any = {}
|
|
Jeff Mahoney |
37049b |
self.excludes = {}
|
|
Jeff Mahoney |
37049b |
self.tags = []
|
|
Jeff Mahoney |
37049b |
self.errors = []
|
|
Jeff Mahoney |
37049b |
|
|
Jeff Mahoney |
37049b |
self.do_patch()
|
|
Jeff Mahoney |
37049b |
|
|
Jeff Mahoney |
37049b |
def get_rulename(self, ruleset, rulename):
|
|
Jeff Mahoney |
37049b |
if rulename in ruleset:
|
|
Jeff Mahoney |
37049b |
if self.updating:
|
|
Jeff Mahoney |
4ceadb |
updating_rule = "%s_on_update" % rulename
|
|
Jeff Mahoney |
37049b |
if updating_rule in ruleset:
|
|
Jeff Mahoney |
37049b |
return updating_rule
|
|
Jeff Mahoney |
37049b |
return rulename
|
|
Jeff Mahoney |
37049b |
return None
|
|
Jeff Mahoney |
37049b |
|
|
Jeff Mahoney |
37049b |
def handle_requires(self, tag, ruleset, rulename):
|
|
Jeff Mahoney |
37049b |
target = getattr(self, rulename)
|
|
Jeff Mahoney |
37049b |
|
|
Jeff Mahoney |
37049b |
rulename = self.get_rulename(ruleset, rulename)
|
|
Jeff Mahoney |
37049b |
if not rulename:
|
|
Jeff Mahoney |
37049b |
return
|
|
Jeff Mahoney |
37049b |
|
|
Jeff Mahoney |
37049b |
if isinstance(tag, str):
|
|
Jeff Mahoney |
37049b |
tag = Tag(tag, None)
|
|
Jeff Mahoney |
37049b |
|
|
Jeff Mahoney |
37049b |
for req in ruleset[rulename]:
|
|
Jeff Mahoney |
37049b |
s = req.split(':')
|
|
Jeff Mahoney |
37049b |
new_req = {
|
|
Jeff Mahoney |
37049b |
'name' : s[0]
|
|
Jeff Mahoney |
37049b |
}
|
|
Jeff Mahoney |
37049b |
if len(s) > 1:
|
|
Jeff Mahoney |
37049b |
new_req['type'] = s[1]
|
|
Jeff Mahoney |
37049b |
if not tag in target:
|
|
Jeff Mahoney |
37049b |
target[tag] = []
|
|
Jeff Mahoney |
37049b |
target[tag].append(new_req)
|
|
Jeff Mahoney |
37049b |
|
|
Jeff Mahoney |
37049b |
def do_patch(self):
|
|
Benjamin Poirier |
4e62ed |
for line in self.stream:
|
|
Jeff Mahoney |
89f2a2 |
if diffstart.match(line):
|
|
Jeff Mahoney |
89f2a2 |
break
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
m = tag_regex.match(line)
|
|
Jeff Mahoney |
89f2a2 |
if m:
|
|
Jeff Mahoney |
89f2a2 |
tag = Tag(m.group(1), m.group(2))
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
if tag.name not in tag_map:
|
|
Jeff Mahoney |
89f2a2 |
continue;
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
if re.match("\s*$", tag.value):
|
|
Jeff Mahoney |
37049b |
self.errors.append(EmptyTagError(tag.name))
|
|
Jeff Mahoney |
89f2a2 |
continue
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
mapping = tag_map[tag.name]
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
try:
|
|
Jeff Mahoney |
89f2a2 |
multi = mapping['multi']
|
|
Benjamin Poirier |
4e62ed |
except KeyError as e:
|
|
Jeff Mahoney |
89f2a2 |
multi = False
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
37049b |
for t in self.tags:
|
|
Jeff Mahoney |
89f2a2 |
if tag.name == t.name and not multi:
|
|
Jeff Mahoney |
37049b |
self.errors.append(DuplicateTagError(tag.name))
|
|
Jeff Mahoney |
89f2a2 |
continue
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
# No rules to process
|
|
Jeff Mahoney |
89f2a2 |
if 'accepted' not in mapping:
|
|
Jeff Mahoney |
37049b |
self.tags.append(tag)
|
|
Jeff Mahoney |
89f2a2 |
continue
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
match = False
|
|
Jeff Mahoney |
89f2a2 |
error = False
|
|
Jeff Mahoney |
89f2a2 |
for rule in mapping['accepted']:
|
|
Jeff Mahoney |
89f2a2 |
if not re.match(rule['match'], tag.value, re.I):
|
|
Jeff Mahoney |
89f2a2 |
continue
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
match = True
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
if 'name' in rule:
|
|
Jeff Mahoney |
89f2a2 |
tag.tagtype = rule['name']
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
if 'error' in rule:
|
|
Jeff Mahoney |
89f2a2 |
error = True
|
|
Jeff Mahoney |
37049b |
self.errors.append(FormatError(tag.name, tag.value,
|
|
Jeff Mahoney |
89f2a2 |
rule['error']))
|
|
Jeff Mahoney |
89f2a2 |
break
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
tag.valid = True
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
250320 |
# Handle rule-level dependencies
|
|
Jeff Mahoney |
37049b |
self.handle_requires(tag, rule, 'requires')
|
|
Jeff Mahoney |
37049b |
self.handle_requires(tag, rule, 'requires_any')
|
|
Jeff Mahoney |
37049b |
self.handle_requires(tag, rule, 'excludes')
|
|
Jeff Mahoney |
89f2a2 |
break
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
250320 |
# Handle tag-level dependencies
|
|
Jeff Mahoney |
89f2a2 |
if tag.valid:
|
|
Jeff Mahoney |
37049b |
self.handle_requires(tag, mapping, 'requires')
|
|
Jeff Mahoney |
37049b |
self.handle_requires(tag, mapping, 'requires_any')
|
|
Jeff Mahoney |
37049b |
self.handle_requires(tag, mapping, 'excludes')
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
37049b |
self.tags.append(tag)
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
if error:
|
|
Jeff Mahoney |
89f2a2 |
continue
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
if not match:
|
|
Jeff Mahoney |
89f2a2 |
errmsg = None
|
|
Jeff Mahoney |
89f2a2 |
if 'error' in mapping:
|
|
Jeff Mahoney |
89f2a2 |
errmsg = mapping['error']
|
|
Jeff Mahoney |
37049b |
self.errors.append(FormatError(tag.name, tag.value, errmsg))
|
|
Jeff Mahoney |
89f2a2 |
continue
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
37049b |
for reqtag in self.requires:
|
|
Jeff Mahoney |
37049b |
for req in self.requires[reqtag]:
|
|
Jeff Mahoney |
89f2a2 |
found = False
|
|
Jeff Mahoney |
37049b |
for tag in self.tags:
|
|
Jeff Mahoney |
cf012c |
found = tag.match_req(req)
|
|
Jeff Mahoney |
89f2a2 |
if found:
|
|
Jeff Mahoney |
89f2a2 |
break
|
|
Jeff Mahoney |
89f2a2 |
if not found:
|
|
Jeff Mahoney |
37049b |
self.errors.append(MissingTagError(reqtag, req))
|
|
Jeff Mahoney |
cf012c |
|
|
Jeff Mahoney |
37049b |
for reqtag in self.requires_any:
|
|
Jeff Mahoney |
cf012c |
found = False
|
|
Jeff Mahoney |
37049b |
for req in self.requires_any[reqtag]:
|
|
Jeff Mahoney |
37049b |
for tag in self.tags:
|
|
Jeff Mahoney |
cf012c |
found = tag.match_req(req)
|
|
Jeff Mahoney |
cf012c |
if found:
|
|
Jeff Mahoney |
cf012c |
break
|
|
Jeff Mahoney |
cf012c |
if found:
|
|
Jeff Mahoney |
cf012c |
break
|
|
Jeff Mahoney |
cf012c |
if not found:
|
|
Jeff Mahoney |
37049b |
self.errors.append(
|
|
Jeff Mahoney |
37049b |
MissingMultiTagError(reqtag, self.requires_any[reqtag]))
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
37049b |
for reqtag in self.excludes:
|
|
Jeff Mahoney |
37049b |
for req in self.excludes[reqtag]:
|
|
Jeff Mahoney |
cf012c |
found = False
|
|
Jeff Mahoney |
37049b |
for tag in self.tags:
|
|
Jeff Mahoney |
cf012c |
found = tag.match_req(req)
|
|
Jeff Mahoney |
89f2a2 |
if found:
|
|
Jeff Mahoney |
cf012c |
break
|
|
Jeff Mahoney |
cf012c |
if found:
|
|
Jeff Mahoney |
37049b |
self.errors.append(ExcludedTagError(reqtag, req))
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
for entry in tag_map:
|
|
Jeff Mahoney |
89f2a2 |
if 'required' in tag_map[entry]:
|
|
Jeff Mahoney |
89f2a2 |
found = False
|
|
Jeff Mahoney |
37049b |
for tag in self.tags:
|
|
Jeff Mahoney |
89f2a2 |
if entry == tag.name:
|
|
Jeff Mahoney |
89f2a2 |
found = True
|
|
Jeff Mahoney |
89f2a2 |
if not found:
|
|
Jeff Mahoney |
37049b |
required = True
|
|
Jeff Mahoney |
37049b |
if self.updating and 'required_on_update' in tag_map[entry]:
|
|
Jeff Mahoney |
37049b |
if not tag_map[entry]['required_on_update']:
|
|
Jeff Mahoney |
37049b |
required = False
|
|
Jeff Mahoney |
37049b |
if required:
|
|
Jeff Mahoney |
37049b |
self.errors.append(MissingTagError(None,
|
|
Jeff Mahoney |
37049b |
{ 'name' : entry }))
|
|
Jeff Mahoney |
37049b |
|
|
Jeff Mahoney |
37049b |
if self.errors:
|
|
Jeff Mahoney |
37049b |
raise HeaderException(self.errors)
|
|
Jeff Mahoney |
89f2a2 |
|
|
Jeff Mahoney |
89f2a2 |
Checker = HeaderChecker
|