Bugtracker: Add support for commits.
This commit is contained in:
@ -24,7 +24,7 @@ import supybot.world as world
|
|||||||
|
|
||||||
from imp import reload
|
from imp import reload
|
||||||
|
|
||||||
__version__ = "4.2.0"
|
__version__ = "4.3.0"
|
||||||
__author__ = supybot.Author("Krytarik Raido", "krytarik", "krytarik@tuxgarage.com")
|
__author__ = supybot.Author("Krytarik Raido", "krytarik", "krytarik@tuxgarage.com")
|
||||||
__contributors__ = {
|
__contributors__ = {
|
||||||
supybot.Author("Dennis Kaarsemaker", "Seveas", "dennis@kaarsemaker.net"): ['Original Author'],
|
supybot.Author("Dennis Kaarsemaker", "Seveas", "dennis@kaarsemaker.net"): ['Original Author'],
|
||||||
|
@ -49,8 +49,9 @@ def configure(advanced):
|
|||||||
else:
|
else:
|
||||||
return repeatdelay
|
return repeatdelay
|
||||||
|
|
||||||
output("Each of the next 3 questions can be set per-channel with the '@config channel' command.")
|
output("Each of the next 4 questions can be set per-channel with the '@config channel' command.")
|
||||||
bugSnarfer = yn("Enable detecting bug numbers and URLs in all channels?", default=Bugtracker.bugSnarfer._default)
|
bugSnarfer = yn("Enable detecting bug numbers and URLs in all channels?", default=Bugtracker.bugSnarfer._default)
|
||||||
|
commitSnarfer = yn("Enable detecting commit hashes and URLs in all channels?", default=Bugtracker.commitSnarfer._default)
|
||||||
cveSnarfer = yn("Enable detecting CVE numbers and URLs in all channels?", default=Bugtracker.cveSnarfer._default)
|
cveSnarfer = yn("Enable detecting CVE numbers and URLs in all channels?", default=Bugtracker.cveSnarfer._default)
|
||||||
oopsSnarfer = yn("Enable detecting Launchpad OOPS IDs in all channels?", default=Bugtracker.oopsSnarfer._default)
|
oopsSnarfer = yn("Enable detecting Launchpad OOPS IDs in all channels?", default=Bugtracker.oopsSnarfer._default)
|
||||||
if advanced:
|
if advanced:
|
||||||
@ -72,6 +73,7 @@ def configure(advanced):
|
|||||||
saveDiscoveredTrackers = yn("Save automatically discovered trackers to configuration?", default=Bugtracker.saveDiscoveredTrackers._default)
|
saveDiscoveredTrackers = yn("Save automatically discovered trackers to configuration?", default=Bugtracker.saveDiscoveredTrackers._default)
|
||||||
|
|
||||||
Bugtracker.bugSnarfer.setValue(bugSnarfer)
|
Bugtracker.bugSnarfer.setValue(bugSnarfer)
|
||||||
|
Bugtracker.commitSnarfer.setValue(commitSnarfer)
|
||||||
Bugtracker.cveSnarfer.setValue(cveSnarfer)
|
Bugtracker.cveSnarfer.setValue(cveSnarfer)
|
||||||
Bugtracker.oopsSnarfer.setValue(oopsSnarfer)
|
Bugtracker.oopsSnarfer.setValue(oopsSnarfer)
|
||||||
Bugtracker.replyNoBugtracker.setValue(replyNoBugtracker)
|
Bugtracker.replyNoBugtracker.setValue(replyNoBugtracker)
|
||||||
@ -90,6 +92,11 @@ conf.registerChannelValue(Bugtracker, 'bugSnarfer',
|
|||||||
enabled, such that any bugtracker URLs and bug ### seen in the channel
|
enabled, such that any bugtracker URLs and bug ### seen in the channel
|
||||||
will have their information reported into the channel."""))
|
will have their information reported into the channel."""))
|
||||||
|
|
||||||
|
conf.registerChannelValue(Bugtracker, 'commitSnarfer',
|
||||||
|
registry.Boolean(False, """Determines whether the commit snarfer will be
|
||||||
|
enabled, such that any commit URLs and commit ### seen in the channel
|
||||||
|
will have their information reported into the channel."""))
|
||||||
|
|
||||||
conf.registerChannelValue(Bugtracker, 'cveSnarfer',
|
conf.registerChannelValue(Bugtracker, 'cveSnarfer',
|
||||||
registry.Boolean(False, """Determines whether the CVE snarfer will be
|
registry.Boolean(False, """Determines whether the CVE snarfer will be
|
||||||
enabled, such that any CVE URLs and CVE-????-???? seen in the channel
|
enabled, such that any CVE URLs and CVE-????-???? seen in the channel
|
||||||
|
@ -71,7 +71,7 @@ class Bugtracker(callbacks.PluginRegexp):
|
|||||||
"""Show a link to a bug report with a brief description"""
|
"""Show a link to a bug report with a brief description"""
|
||||||
threaded = True
|
threaded = True
|
||||||
callBefore = ('URL')
|
callBefore = ('URL')
|
||||||
regexps = ('turlSnarfer', 'bugSnarfer', 'cveSnarfer', 'oopsSnarfer')
|
regexps = ('bugSnarfer', 'bugUrlSnarfer', 'commitSnarfer', 'commitUrlSnarfer', 'cveSnarfer', 'oopsSnarfer')
|
||||||
|
|
||||||
def __init__(self, irc):
|
def __init__(self, irc):
|
||||||
self.__parent = super(Bugtracker, self)
|
self.__parent = super(Bugtracker, self)
|
||||||
@ -97,14 +97,14 @@ class Bugtracker(callbacks.PluginRegexp):
|
|||||||
supylog.warning("Bugtracker: Unknown trackertype '%s' (%s)" % (trackers[name].trackertype(), name))
|
supylog.warning("Bugtracker: Unknown trackertype '%s' (%s)" % (trackers[name].trackertype(), name))
|
||||||
self.shorthand = utils.abbrev(list(self.db.keys()))
|
self.shorthand = utils.abbrev(list(self.db.keys()))
|
||||||
|
|
||||||
def is_ok(self, channel, tracker, bug):
|
def is_ok(self, channel, tracker, bugid):
|
||||||
"""Flood/repeat protection"""
|
"""Flood/repeat protection"""
|
||||||
now = time.time()
|
now = time.time()
|
||||||
for k in list(self.shown.keys()):
|
for k in list(self.shown.keys()):
|
||||||
if self.shown[k] < now - self.registryValue('repeatdelay', channel):
|
if self.shown[k] < now - self.registryValue('repeatdelay', channel):
|
||||||
self.shown.pop(k)
|
self.shown.pop(k)
|
||||||
if (channel, tracker, bug) not in self.shown:
|
if (channel, tracker, bugid) not in self.shown:
|
||||||
self.shown[(channel, tracker, bug)] = now
|
self.shown[(channel, tracker, bugid)] = now
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -308,26 +308,39 @@ class Bugtracker(callbacks.PluginRegexp):
|
|||||||
|
|
||||||
def bugSnarfer(self, irc, msg, match):
|
def bugSnarfer(self, irc, msg, match):
|
||||||
r"(?P<bt>[a-z][^\s:]*(\s+(bug|ticket|issue|pull|pr|merge|mr)('?s)?)?):*\s+#?(?P<bug>\d+(?!\d*[-.]\d+)(\s*([,\s]+|[,\s]*(and|und|en|et|ir|[&+]+))\s*#?\d+(?!\d*[-.]\d+))*)"
|
r"(?P<bt>[a-z][^\s:]*(\s+(bug|ticket|issue|pull|pr|merge|mr)('?s)?)?):*\s+#?(?P<bug>\d+(?!\d*[-.]\d+)(\s*([,\s]+|[,\s]*(and|und|en|et|ir|[&+]+))\s*#?\d+(?!\d*[-.]\d+))*)"
|
||||||
|
self.termSnarfer(irc, msg, match, 'bug')
|
||||||
|
|
||||||
|
def commitSnarfer(self, irc, msg, match):
|
||||||
|
r"(?P<bt>[a-z][^\s:]*(\s+(commit)('?s)?)?):*\s+#?(?P<bug>[a-f0-9]{7,}(?![a-f0-9]*[-.][a-f0-9]{7,})(\s*([,\s]+|[,\s]*(and|und|en|et|ir|[&+]+))\s*#?[a-f0-9]{7,}(?![a-f0-9]*[-.][a-f0-9]{7,}))*)"
|
||||||
|
self.termSnarfer(irc, msg, match, 'commit')
|
||||||
|
|
||||||
|
def termSnarfer(self, irc, msg, match, termtype):
|
||||||
channel = msg.args[0] if ircutils.isChannel(msg.args[0]) else None
|
channel = msg.args[0] if ircutils.isChannel(msg.args[0]) else None
|
||||||
if checkAddressed(msg.args[1].strip(), channel):
|
if checkAddressed(msg.args[1].strip(), channel):
|
||||||
return
|
return
|
||||||
if not self.registryValue('bugSnarfer', channel):
|
if not self.registryValue('{}Snarfer'.format(termtype), channel):
|
||||||
return
|
return
|
||||||
nbugs = msg.tagged('nbugs') or 0
|
nbugs = msg.tagged('nbugs') or 0
|
||||||
if nbugs >= 5:
|
if nbugs >= 5:
|
||||||
return
|
return
|
||||||
|
|
||||||
bugids = re.split(r'[^\d]+', match.group('bug'))[:5-nbugs]
|
if termtype != 'commit':
|
||||||
|
bugids = re.findall(r'[0-9]+', match.group('bug'))[:5-nbugs]
|
||||||
|
else:
|
||||||
|
bugids = re.findall(r'[a-f0-9]{7,}', match.group('bug'))[:5-nbugs]
|
||||||
|
|
||||||
# Begin HACK
|
# Begin HACK
|
||||||
# Strings like "Ubuntu 1004" and "Ubuntu 1610" are false triggers for us
|
# Strings like "Ubuntu 1004" and "Ubuntu 1610" are false triggers for us
|
||||||
if match.group('bt').lower() == 'ubuntu':
|
if match.group('bt').lower() == 'ubuntu' and termtype == 'bug':
|
||||||
bugids = [x for x in bugids if not re.match(r'^([4-9]|[12][0-9])(04|10)$', x)]
|
bugids = [x for x in bugids if not re.match(r'^([4-9]|[12][0-9])(04|10)$', x)]
|
||||||
# End HACK
|
# End HACK
|
||||||
|
|
||||||
# Get tracker name
|
# Get tracker name
|
||||||
bt = [x.lower() for x in match.group('bt').split()]
|
bt = [x.lower() for x in match.group('bt').split()]
|
||||||
sure_bug = re.match(r"^(?P<type>bug|ticket|issue|pull|pr|merge|mr)('?s)?$", bt[-1])
|
if termtype != 'commit':
|
||||||
|
sure_bug = re.match(r"^(?P<type>bug|ticket|issue|pull|pr|merge|mr)('?s)?$", bt[-1])
|
||||||
|
else:
|
||||||
|
sure_bug = re.match(r"^(?P<type>commit)('?s)?$", bt[-1])
|
||||||
|
|
||||||
# Get bug type
|
# Get bug type
|
||||||
if sure_bug:
|
if sure_bug:
|
||||||
@ -337,7 +350,7 @@ class Bugtracker(callbacks.PluginRegexp):
|
|||||||
|
|
||||||
bugids = list(set(bugids)) # remove dupes
|
bugids = list(set(bugids)) # remove dupes
|
||||||
|
|
||||||
if not sure_bug:
|
if not sure_bug and termtype == 'bug':
|
||||||
bugids = [x for x in bugids if int(x) > 100]
|
bugids = [x for x in bugids if int(x) > 100]
|
||||||
|
|
||||||
msg.tag('nbugs', nbugs + len(bugids))
|
msg.tag('nbugs', nbugs + len(bugids))
|
||||||
@ -376,13 +389,12 @@ class Bugtracker(callbacks.PluginRegexp):
|
|||||||
return
|
return
|
||||||
|
|
||||||
for bugid in bugids:
|
for bugid in bugids:
|
||||||
bugid = int(bugid)
|
|
||||||
try:
|
try:
|
||||||
report = self.get_bug(channel or msg.nick, tracker, bugtype, bugid, self.registryValue('showassignee', channel),
|
report = self.get_bug(channel or msg.nick, tracker, bugtype, bugid, self.registryValue('showassignee', channel),
|
||||||
self.registryValue('extended', channel), do_tracker=showTracker)
|
self.registryValue('extended', channel), do_tracker=showTracker)
|
||||||
except trackers.BugNotFoundError:
|
except trackers.BugNotFoundError:
|
||||||
if self.registryValue('replyWhenNotFound'):
|
if self.registryValue('replyWhenNotFound'):
|
||||||
irc.error("Could not find %s bug %d" % (tracker.description, bugid))
|
irc.error("Could not find %s %s %s" % (tracker.description, termtype, bugid))
|
||||||
except trackers.BugtrackerError as e:
|
except trackers.BugtrackerError as e:
|
||||||
if self.registryValue('replyWhenError') and sure_bug:
|
if self.registryValue('replyWhenError') and sure_bug:
|
||||||
irc.error(str(e))
|
irc.error(str(e))
|
||||||
@ -390,19 +402,26 @@ class Bugtracker(callbacks.PluginRegexp):
|
|||||||
if report:
|
if report:
|
||||||
irc.reply(report)
|
irc.reply(report)
|
||||||
|
|
||||||
def turlSnarfer(self, irc, msg, match):
|
def bugUrlSnarfer(self, irc, msg, match):
|
||||||
r"(https?://)?((bugs\.debian\.org|pad\.lv)/|\S+/(show_bug\.cgi\?id=|bugreport\.cgi\?bug=|view\.php\?id=|bug=|bugs/|\+bug/|ticket/|feature-requests/|patches/|todo/|issues/|pulls?/|merge_requests/))(?P<bug>\d+)/?"
|
r"(https?://)?((bugs\.debian\.org|pad\.lv)/|\S+/(show_bug\.cgi\?id=|bugreport\.cgi\?bug=|view\.php\?id=|bug=|bugs/|\+bug/|ticket/|feature-requests/|patches/|todo/|issues/|pulls?/|merge_requests/))(?P<bug>\d+)"
|
||||||
|
self.urlSnarfer(irc, msg, match, 'bug')
|
||||||
|
|
||||||
|
def commitUrlSnarfer(self, irc, msg, match):
|
||||||
|
r"(https?://)?\S+/commits?/(?P<bug>[a-f0-9]{7,})"
|
||||||
|
self.urlSnarfer(irc, msg, match, 'commit')
|
||||||
|
|
||||||
|
def urlSnarfer(self, irc, msg, match, urltype):
|
||||||
channel = msg.args[0] if ircutils.isChannel(msg.args[0]) else None
|
channel = msg.args[0] if ircutils.isChannel(msg.args[0]) else None
|
||||||
if checkAddressed(msg.args[1].strip(), channel):
|
if checkAddressed(msg.args[1].strip(), channel):
|
||||||
return
|
return
|
||||||
if not self.registryValue('bugSnarfer', channel):
|
if not self.registryValue('{}Snarfer'.format(urltype), channel):
|
||||||
return
|
return
|
||||||
nbugs = msg.tagged('nbugs') or 0
|
nbugs = msg.tagged('nbugs') or 0
|
||||||
if nbugs >= 5:
|
if nbugs >= 5:
|
||||||
return
|
return
|
||||||
msg.tag('nbugs', nbugs+1)
|
msg.tag('nbugs', nbugs+1)
|
||||||
url = match.group(0)
|
url = match.group(0)
|
||||||
bugid = int(match.group('bug'))
|
bugid = match.group('bug')
|
||||||
if '://' in url:
|
if '://' in url:
|
||||||
url = url[url.rfind('://')+3:]
|
url = url[url.rfind('://')+3:]
|
||||||
try:
|
try:
|
||||||
@ -413,7 +432,7 @@ class Bugtracker(callbacks.PluginRegexp):
|
|||||||
self.registryValue('extended', channel), do_url=False)
|
self.registryValue('extended', channel), do_url=False)
|
||||||
except trackers.BugNotFoundError:
|
except trackers.BugNotFoundError:
|
||||||
if self.registryValue('replyWhenNotFound'):
|
if self.registryValue('replyWhenNotFound'):
|
||||||
irc.error("Could not find %s bug %s" % (tracker.description, match.group('bug')))
|
irc.error("Could not find %s %s %s" % (tracker.description, urltype, match.group('bug')))
|
||||||
except trackers.BugtrackerError as e:
|
except trackers.BugtrackerError as e:
|
||||||
if self.registryValue('replyWhenError'):
|
if self.registryValue('replyWhenError'):
|
||||||
irc.error(str(e))
|
irc.error(str(e))
|
||||||
@ -423,7 +442,7 @@ class Bugtracker(callbacks.PluginRegexp):
|
|||||||
|
|
||||||
# Only useful to Launchpad developers
|
# Only useful to Launchpad developers
|
||||||
def oopsSnarfer(self, irc, msg, match):
|
def oopsSnarfer(self, irc, msg, match):
|
||||||
r"(https?://\S+[=/])?OOPS-(?P<oopsid>[\dA-Za-z]{6,})"
|
r"(https?://\S+[=/])?OOPS-(?P<oopsid>[a-f0-9]{6,})"
|
||||||
channel = msg.args[0] if ircutils.isChannel(msg.args[0]) else None
|
channel = msg.args[0] if ircutils.isChannel(msg.args[0]) else None
|
||||||
if checkAddressed(msg.args[1].strip(), channel):
|
if checkAddressed(msg.args[1].strip(), channel):
|
||||||
return
|
return
|
||||||
@ -482,11 +501,11 @@ class Bugtracker(callbacks.PluginRegexp):
|
|||||||
tracker = trackers.SourceForge().get_tracker(snarfurl)
|
tracker = trackers.SourceForge().get_tracker(snarfurl)
|
||||||
elif 'github.com' in snarfurl:
|
elif 'github.com' in snarfurl:
|
||||||
tracker = trackers.GitHub().get_tracker(snarfurl)
|
tracker = trackers.GitHub().get_tracker(snarfurl)
|
||||||
elif re.match(r'[^\s/]+/[^\s/]+(/[^\s/]+)+/-/(issues|merge_requests)', snarfurl) \
|
elif re.match(r'[^\s/]+/[^\s/]+(/[^\s/]+)+/-/(issues|merge_requests|commits?)', snarfurl) \
|
||||||
or re.match(r'[^\s/]+/[^\s/]+(/[^\s/]+)+/merge_requests', snarfurl) \
|
or re.match(r'[^\s/]+/[^\s/]+(/[^\s/]+)+/merge_requests', snarfurl) \
|
||||||
or re.match(r'[^\s/]+/[^\s/]+(/[^\s/]+){2,}/issues', snarfurl):
|
or re.match(r'[^\s/]+/[^\s/]+(/[^\s/]+){2,}/(issues|commits?)', snarfurl):
|
||||||
tracker = trackers.GitLab().get_tracker(snarfurl, bugid)
|
tracker = trackers.GitLab().get_tracker(snarfurl, bugid)
|
||||||
elif re.match(r'[^\s/]+/[^\s/]+/[^\s/]+/issues', snarfurl):
|
elif re.match(r'[^\s/]+/[^\s/]+/[^\s/]+/(issues|commits?)', snarfurl):
|
||||||
tracker = trackers.GitLab().get_tracker(snarfurl, bugid)
|
tracker = trackers.GitLab().get_tracker(snarfurl, bugid)
|
||||||
if not tracker:
|
if not tracker:
|
||||||
tracker = trackers.Gitea().get_tracker(snarfurl, bugid)
|
tracker = trackers.Gitea().get_tracker(snarfurl, bugid)
|
||||||
@ -519,20 +538,20 @@ class Bugtracker(callbacks.PluginRegexp):
|
|||||||
if duplicate and not self.is_ok(channel, tracker, bugid):
|
if duplicate and not self.is_ok(channel, tracker, bugid):
|
||||||
return
|
return
|
||||||
|
|
||||||
bugtype = re.match(r'.*/(feature-)?(?P<type>request|patch|todo|issue|pull|merge|ticket)(_requests)?(e?s)?/[0-9]+/?$', url)
|
bugtype = re.match(r'.*/(feature-)?(?P<type>request|patch|todo|issue|pull|merge|ticket|commit)(_requests)?(e?s)?/[a-f0-9]+$', url)
|
||||||
if do_tracker and tracker.trackertype not in ('github', 'gitlab', 'gitea'):
|
if do_tracker and tracker.trackertype not in ('github', 'gitlab', 'gitea'):
|
||||||
if re.match(r'.*/(bugs|feature-requests|patches|todo|issues|pulls?|merge_requests|ticket)/?$', tracker.description):
|
if re.match(r'.*/(bugs|feature-requests|patches|todo|issues|pulls?|merge_requests|ticket|commits?)$', tracker.description):
|
||||||
report = '%s %d' % (tracker.description, bugid)
|
report = '%s %s' % (tracker.description, bugid)
|
||||||
else:
|
else:
|
||||||
if bugtype:
|
if bugtype:
|
||||||
report = '%s %s %d' % (tracker.description, bugtype.group('type'), bugid)
|
report = '%s %s %s' % (tracker.description, bugtype.group('type'), bugid)
|
||||||
else:
|
else:
|
||||||
report = '%s bug %d' % (tracker.description, bugid)
|
report = '%s bug %s' % (tracker.description, bugid)
|
||||||
else:
|
else:
|
||||||
if bugtype:
|
if bugtype:
|
||||||
report = '%s %d' % (bugtype.group('type').title(), bugid)
|
report = '%s %s' % (bugtype.group('type').title(), bugid)
|
||||||
else:
|
else:
|
||||||
report = 'Bug %d' % bugid
|
report = 'Bug %s' % bugid
|
||||||
|
|
||||||
if product:
|
if product:
|
||||||
report += ' in %s' % product
|
report += ' in %s' % product
|
||||||
@ -548,8 +567,10 @@ class Bugtracker(callbacks.PluginRegexp):
|
|||||||
severity_status = []
|
severity_status = []
|
||||||
if severity:
|
if severity:
|
||||||
severity_status.append(' '.join(word[0].upper() + word[1:].lower() for word in severity.split()))
|
severity_status.append(' '.join(word[0].upper() + word[1:].lower() for word in severity.split()))
|
||||||
severity_status.append(' '.join(word[0].upper() + word[1:].lower() for word in status.split()))
|
if status:
|
||||||
report += ' [%s]' % ', '.join(severity_status)
|
severity_status.append(' '.join(word[0].upper() + word[1:].lower() for word in status.split()))
|
||||||
|
if severity_status:
|
||||||
|
report += ' [%s]' % ', '.join(severity_status)
|
||||||
|
|
||||||
if duplicate:
|
if duplicate:
|
||||||
report += ' [duplicate: %s]' % duplicate[0]
|
report += ' [duplicate: %s]' % duplicate[0]
|
||||||
|
@ -114,7 +114,7 @@ class Bugzilla(IBugtracker):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def get_bug(self, bugtype, bugid):
|
def get_bug(self, bugtype, bugid):
|
||||||
url = "%s/rest/bug/%d" % (self.url, bugid)
|
url = "%s/rest/bug/%s" % (self.url, bugid)
|
||||||
try:
|
try:
|
||||||
bugjson = utils.web.getUrl(url)
|
bugjson = utils.web.getUrl(url)
|
||||||
bug = json.loads(bugjson.decode('utf-8'))['bugs'][0]
|
bug = json.loads(bugjson.decode('utf-8'))['bugs'][0]
|
||||||
@ -134,12 +134,12 @@ class Bugzilla(IBugtracker):
|
|||||||
else:
|
else:
|
||||||
assignee = ''
|
assignee = ''
|
||||||
return (bugid, bug['product'], bug['summary'], bug['severity'], status, assignee,
|
return (bugid, bug['product'], bug['summary'], bug['severity'], status, assignee,
|
||||||
"%s/show_bug.cgi?id=%d" % (self.url, bugid), [], [])
|
"%s/show_bug.cgi?id=%s" % (self.url, bugid), [], [])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BugtrackerError(self.errparse % (self.description, e, url))
|
raise BugtrackerError(self.errparse % (self.description, e, url))
|
||||||
|
|
||||||
def get_bug_old(self, bugtype, bugid): # Deprecated
|
def get_bug_old(self, bugtype, bugid): # Deprecated
|
||||||
url = "%s/show_bug.cgi?id=%d&ctype=xml" % (self.url, bugid)
|
url = "%s/show_bug.cgi?id=%s&ctype=xml" % (self.url, bugid)
|
||||||
try:
|
try:
|
||||||
bugxml = utils.web.getUrl(url)
|
bugxml = utils.web.getUrl(url)
|
||||||
zilladom = minidom.parseString(bugxml)
|
zilladom = minidom.parseString(bugxml)
|
||||||
@ -150,7 +150,7 @@ class Bugzilla(IBugtracker):
|
|||||||
errtxt = bug_n.getAttribute('error')
|
errtxt = bug_n.getAttribute('error')
|
||||||
if errtxt in ('NotFound', 'InvalidBugId'):
|
if errtxt in ('NotFound', 'InvalidBugId'):
|
||||||
raise BugNotFoundError
|
raise BugNotFoundError
|
||||||
s = 'Could not get %s bug #%d: %s' % (self.description, bugid, errtxt)
|
s = 'Could not get %s bug #%s: %s' % (self.description, bugid, errtxt)
|
||||||
raise BugtrackerError(s)
|
raise BugtrackerError(s)
|
||||||
try:
|
try:
|
||||||
title = _getnodetxt(bug_n.getElementsByTagName('short_desc')[0])
|
title = _getnodetxt(bug_n.getElementsByTagName('short_desc')[0])
|
||||||
@ -170,7 +170,7 @@ class Bugzilla(IBugtracker):
|
|||||||
assignee = ''
|
assignee = ''
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BugtrackerError(self.errparse % (self.description, e, url))
|
raise BugtrackerError(self.errparse % (self.description, e, url))
|
||||||
return (bugid, product, title, severity, status, assignee, "%s/show_bug.cgi?id=%d" % (self.url, bugid), [], [])
|
return (bugid, product, title, severity, status, assignee, "%s/show_bug.cgi?id=%s" % (self.url, bugid), [], [])
|
||||||
|
|
||||||
class Launchpad(IBugtracker):
|
class Launchpad(IBugtracker):
|
||||||
statuses = ("Unknown", "Invalid", "Opinion", "Won't Fix", "Fix Released", "Fix Committed", "New",
|
statuses = ("Unknown", "Invalid", "Opinion", "Won't Fix", "Fix Released", "Fix Committed", "New",
|
||||||
@ -259,7 +259,7 @@ class Launchpad(IBugtracker):
|
|||||||
|
|
||||||
def get_bug_new(self, bugtype, bugid): #TODO: Rename this method to 'get_bug'
|
def get_bug_new(self, bugtype, bugid): #TODO: Rename this method to 'get_bug'
|
||||||
try:
|
try:
|
||||||
bugdata = self.lp.bugs[bugid]
|
bugdata = self.lp.bugs[int(bugid)]
|
||||||
if bugdata.private:
|
if bugdata.private:
|
||||||
raise BugtrackerError("This bug is private")
|
raise BugtrackerError("This bug is private")
|
||||||
duplicate = []
|
duplicate = []
|
||||||
@ -287,27 +287,27 @@ class Launchpad(IBugtracker):
|
|||||||
if type(e).__name__ == 'HTTPError': # messy, but saves trying to import lazr.restfulclient.errors.HTPError
|
if type(e).__name__ == 'HTTPError': # messy, but saves trying to import lazr.restfulclient.errors.HTPError
|
||||||
if e.response.status == 404:
|
if e.response.status == 404:
|
||||||
bugNo = e.content.split()[-1][2:-1] # extract the real bug number
|
bugNo = e.content.split()[-1][2:-1] # extract the real bug number
|
||||||
if bugNo != str(bugid): # A duplicate of a private bug, at least we know it exists
|
if bugNo != bugid: # A duplicate of a private bug, at least we know it exists
|
||||||
raise BugtrackerError('Bug #%d is a duplicate of bug #%s, but it is private (%s/bugs/%s)' % (bugid, bugNo, self.url, bugNo))
|
raise BugtrackerError('Bug #%s is a duplicate of bug #%s, but it is private (%s/bugs/%s)' % (bugid, bugNo, self.url, bugNo))
|
||||||
raise BugtrackerError("Bug #%d is private or does not exist (%s/bugs/%d)" % (bugid, self.url, bugid)) # Could be private, could just not exist
|
raise BugtrackerError("Bug #%s is private or does not exist (%s/bugs/%s)" % (bugid, self.url, bugid)) # Could be private, could just not exist
|
||||||
raise BugtrackerError(self.errget % (self.description, e, '%s/bugs/%d' % (self.url, bugid)))
|
raise BugtrackerError(self.errget % (self.description, e, '%s/bugs/%s' % (self.url, bugid)))
|
||||||
elif isinstance(e, KeyError):
|
elif isinstance(e, KeyError):
|
||||||
raise BugNotFoundError
|
raise BugNotFoundError
|
||||||
raise BugtrackerError(self.errget % (self.description, e, '%s/bugs/%d' % (self.url, bugid)))
|
raise BugtrackerError(self.errget % (self.description, e, '%s/bugs/%s' % (self.url, bugid)))
|
||||||
|
|
||||||
return (bugdata.id, taskdata.bug_target_display_name, bugdata.title, taskdata.importance, taskdata.status,
|
return (bugdata.id, taskdata.bug_target_display_name, bugdata.title, taskdata.importance, taskdata.status,
|
||||||
assignee, "%s/bugs/%d" % (self.url, bugdata.id), extinfo, duplicate)
|
assignee, "%s/bugs/%s" % (self.url, bugdata.id), extinfo, duplicate)
|
||||||
|
|
||||||
def get_bug_old(self, bugtype, bugid, duplicate=None): # Deprecated
|
def get_bug_old(self, bugtype, bugid, duplicate=None): # Deprecated
|
||||||
try:
|
try:
|
||||||
bugdata = utils.web.getUrl("%s/bugs/%d/+text" % (self.url, bugid)).decode('utf-8')
|
bugdata = utils.web.getUrl("%s/bugs/%s/+text" % (self.url, bugid)).decode('utf-8')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if 'HTTP Error 404' in str(e):
|
if 'HTTP Error 404' in str(e):
|
||||||
if duplicate:
|
if duplicate:
|
||||||
raise BugtrackerError('Bug #%d is a duplicate of bug #%d, but it is private (%s/bugs/%d)' % (duplicate, bugid, self.url, bugid))
|
raise BugtrackerError('Bug #%s is a duplicate of bug #%s, but it is private (%s/bugs/%s)' % (duplicate, bugid, self.url, bugid))
|
||||||
else:
|
else:
|
||||||
raise BugNotFoundError
|
raise BugNotFoundError
|
||||||
raise BugtrackerError(self.errget % (self.description, e, '%s/bugs/%d' % (self.url, bugid)))
|
raise BugtrackerError(self.errget % (self.description, e, '%s/bugs/%s' % (self.url, bugid)))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Split bug data into separate pieces (bug data, task data)
|
# Split bug data into separate pieces (bug data, task data)
|
||||||
@ -324,16 +324,16 @@ class Launchpad(IBugtracker):
|
|||||||
else:
|
else:
|
||||||
assignee = ''
|
assignee = ''
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BugtrackerError(self.errparse % (self.description, e, '%s/bugs/%d' % (self.url, bugid)))
|
raise BugtrackerError(self.errparse % (self.description, e, '%s/bugs/%s' % (self.url, bugid)))
|
||||||
|
|
||||||
# Try and find duplicates
|
# Try and find duplicates
|
||||||
if bugdata['duplicate-of']:
|
if bugdata['duplicate-of']:
|
||||||
data = self.get_bug_old(bugtype, int(bugdata['duplicate-of']), duplicate or bugid)
|
data = self.get_bug_old(bugtype, bugdata['duplicate-of'], duplicate or bugid)
|
||||||
data[8].append(bugdata['bug'])
|
data[8].append(bugdata['bug'])
|
||||||
return data
|
return data
|
||||||
|
|
||||||
return (bugid, taskdata['task'], bugdata['title'], taskdata['importance'], taskdata['status'],
|
return (bugid, taskdata['task'], bugdata['title'], taskdata['importance'], taskdata['status'],
|
||||||
assignee, "%s/bugs/%d" % (self.url, bugid), [], [])
|
assignee, "%s/bugs/%s" % (self.url, bugid), [], [])
|
||||||
|
|
||||||
# <rant>
|
# <rant>
|
||||||
# Debbugs sucks donkeyballs
|
# Debbugs sucks donkeyballs
|
||||||
@ -351,7 +351,7 @@ class Debbugs(IBugtracker):
|
|||||||
self.soap_client = SoapClient("%s/cgi-bin/soap.cgi" % self.url, namespace="Debbugs/SOAP")
|
self.soap_client = SoapClient("%s/cgi-bin/soap.cgi" % self.url, namespace="Debbugs/SOAP")
|
||||||
|
|
||||||
def get_bug(self, bugtype, bugid):
|
def get_bug(self, bugtype, bugid):
|
||||||
url = "%s/cgi-bin/bugreport.cgi?bug=%d" % (self.url, bugid)
|
url = "%s/cgi-bin/bugreport.cgi?bug=%s" % (self.url, bugid)
|
||||||
try:
|
try:
|
||||||
raw = self.soap_client.get_status(bugs=bugid)
|
raw = self.soap_client.get_status(bugs=bugid)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -364,7 +364,7 @@ class Debbugs(IBugtracker):
|
|||||||
status = 'Fixed'
|
status = 'Fixed'
|
||||||
else:
|
else:
|
||||||
status = 'Open'
|
status = 'Open'
|
||||||
return (bugid, str(raw.package), str(raw.subject), str(raw.severity), status, '', "%s/%d" % (self.url, bugid), [], [])
|
return (bugid, str(raw.package), str(raw.subject), str(raw.severity), status, '', "%s/%s" % (self.url, bugid), [], [])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BugtrackerError(self.errparse % (self.description, e, url))
|
raise BugtrackerError(self.errparse % (self.description, e, url))
|
||||||
|
|
||||||
@ -380,7 +380,7 @@ class SourceForge(IBugtracker):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def get_bug(self, bugtype, bugid):
|
def get_bug(self, bugtype, bugid):
|
||||||
url = "%s/%d/" % (self.url.replace('sourceforge.net', 'sourceforge.net/rest'), bugid)
|
url = "%s/%s/" % (self.url.replace('sourceforge.net', 'sourceforge.net/rest'), bugid)
|
||||||
try:
|
try:
|
||||||
bugjson = utils.web.getUrl(url)
|
bugjson = utils.web.getUrl(url)
|
||||||
bug = json.loads(bugjson.decode('utf-8'))['ticket']
|
bug = json.loads(bugjson.decode('utf-8'))['ticket']
|
||||||
@ -393,31 +393,40 @@ class SourceForge(IBugtracker):
|
|||||||
if '_priority' in bug['custom_fields']:
|
if '_priority' in bug['custom_fields']:
|
||||||
severity = 'Pri: %s' % bug['custom_fields']['_priority']
|
severity = 'Pri: %s' % bug['custom_fields']['_priority']
|
||||||
return (bugid, product, bug['summary'], severity, ': '.join(bug['status'].split('-')),
|
return (bugid, product, bug['summary'], severity, ': '.join(bug['status'].split('-')),
|
||||||
bug['assigned_to'], "%s/%d/" % (self.url, bugid), [], [])
|
bug['assigned_to'], "%s/%s/" % (self.url, bugid), [], [])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BugtrackerError(self.errparse % (self.description, e, url))
|
raise BugtrackerError(self.errparse % (self.description, e, url))
|
||||||
|
|
||||||
class GitHub(IBugtracker):
|
class GitHub(IBugtracker):
|
||||||
def get_tracker(self, url):
|
def get_tracker(self, url):
|
||||||
try:
|
try:
|
||||||
match = re.match(r'github\.com/[^\s/]+/[^\s/]+/(issues|pulls?)', url)
|
match = re.match(r'github\.com/[^\s/]+/[^\s/]+/(issues|pulls?|commits?)', url)
|
||||||
desc = match.group(0)
|
desc = match.group(0)
|
||||||
url = 'https://%s' % desc
|
url = 'https://%s' % desc
|
||||||
# Pulls are inconsistent in main and single page URLs
|
# Pulls are inconsistent in main and single page URLs
|
||||||
desc = re.sub(r'/pull$', r'/pulls', desc)
|
desc = re.sub(r'/pull$', r'/pulls', desc)
|
||||||
|
# Commits are inconsistent in main and single page URLs
|
||||||
|
desc = re.sub(r'/commit$', r'/commits', desc)
|
||||||
name = desc.lower()
|
name = desc.lower()
|
||||||
return GitHub(name, url, desc, 'github')
|
return GitHub(name, url, desc, 'github')
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_bug(self, bugtype, bugid):
|
def get_bug(self, bugtype, bugid):
|
||||||
url = "%s/%d" % (self.url.replace('github.com', 'api.github.com/repos'), bugid)
|
url = "%s/%s" % (self.url.replace('github.com', 'api.github.com/repos'), bugid)
|
||||||
# Pulls are inconsistent in web and API URLs
|
# Pulls are inconsistent in web and API URLs
|
||||||
url = url.replace('/pull/', '/pulls/')
|
url = url.replace('/pull/', '/pulls/')
|
||||||
|
# Commits are inconsistent in web and API URLs
|
||||||
|
url = url.replace('/commit/', '/commits/')
|
||||||
if bugtype in ('issue', 'bug'):
|
if bugtype in ('issue', 'bug'):
|
||||||
url = url.replace('/pulls/', '/issues/')
|
url = url.replace('/pulls/', '/issues/')
|
||||||
|
url = url.replace('/commits/', '/issues/')
|
||||||
elif bugtype in ('pull', 'pr', 'merge', 'mr'):
|
elif bugtype in ('pull', 'pr', 'merge', 'mr'):
|
||||||
url = url.replace('/issues/', '/pulls/')
|
url = url.replace('/issues/', '/pulls/')
|
||||||
|
url = url.replace('/commits/', '/pulls/')
|
||||||
|
elif bugtype == 'commit':
|
||||||
|
url = url.replace('/issues/', '/commits/')
|
||||||
|
url = url.replace('/pulls/', '/commits/')
|
||||||
try:
|
try:
|
||||||
bugjson = utils.web.getUrl(url)
|
bugjson = utils.web.getUrl(url)
|
||||||
bug = json.loads(bugjson.decode('utf-8'))
|
bug = json.loads(bugjson.decode('utf-8'))
|
||||||
@ -425,27 +434,40 @@ class GitHub(IBugtracker):
|
|||||||
raise BugtrackerError(self.errget % (self.description, e, url))
|
raise BugtrackerError(self.errget % (self.description, e, url))
|
||||||
try:
|
try:
|
||||||
product = '/'.join(self.url.split('/')[-3:-1])
|
product = '/'.join(self.url.split('/')[-3:-1])
|
||||||
if 'merged' in bug and bug['merged']:
|
if '/commits/' not in url:
|
||||||
status = 'Merged'
|
title = bug['title']
|
||||||
else:
|
if 'merged' in bug and bug['merged']:
|
||||||
status = bug['state']
|
status = 'Merged'
|
||||||
if bug['assignee']:
|
else:
|
||||||
assignee = bug['assignee']['login']
|
status = bug['state']
|
||||||
|
if bug['assignee']:
|
||||||
|
assignee = bug['assignee']['login']
|
||||||
|
else:
|
||||||
|
assignee = ''
|
||||||
else:
|
else:
|
||||||
|
bugid = bug['sha'][:7]
|
||||||
|
title = bug['commit']['message'].split('\n', 1)[0]
|
||||||
|
status = ''
|
||||||
assignee = ''
|
assignee = ''
|
||||||
return (bugid, product, bug['title'], '', status, assignee, bug['html_url'], [], [])
|
return (bugid, product, title, '', status, assignee, bug['html_url'], [], [])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BugtrackerError(self.errparse % (self.description, e, url))
|
raise BugtrackerError(self.errparse % (self.description, e, url))
|
||||||
|
|
||||||
class GitLab(IBugtracker):
|
class GitLab(IBugtracker):
|
||||||
def get_tracker(self, url, bugid):
|
def get_tracker(self, url, bugid):
|
||||||
try:
|
try:
|
||||||
match = re.match(r'[^\s/]+/(?P<project>[^\s/]+/[^\s/]+(/[^\s/]+)*?)/(-/)?(issues|merge_requests)', url)
|
match = re.match(r'[^\s/]+/(?P<project>[^\s/]+/[^\s/]+(/[^\s/]+)*?)/(-/)?(issues|merge_requests|commits?)', url)
|
||||||
desc = match.group(0)
|
desc = match.group(0)
|
||||||
name = desc.lower()
|
|
||||||
url = 'https://%s' % desc
|
url = 'https://%s' % desc
|
||||||
bugurl = "%s/%d" % (re.sub(r'(://[^\s/]+)/[^\s/]+(/[^\s/]+)+/(-/)?',
|
# Commits are inconsistent in main and single page URLs
|
||||||
|
desc = re.sub(r'/commit$', r'/commits', desc)
|
||||||
|
name = desc.lower()
|
||||||
|
bugurl = "%s/%s" % (re.sub(r'(://[^\s/]+)/[^\s/]+(/[^\s/]+)+/(-/)?',
|
||||||
r'\g<1>/api/v4/projects/%s/' % match.group('project').replace('/', '%2F'), url), bugid)
|
r'\g<1>/api/v4/projects/%s/' % match.group('project').replace('/', '%2F'), url), bugid)
|
||||||
|
# Commits are inconsistent in web and API URLs
|
||||||
|
bugurl = bugurl.replace('/commit/', '/commits/')
|
||||||
|
# Commits need an extra bit on API URLs
|
||||||
|
bugurl = bugurl.replace('/commits/', '/repository/commits/')
|
||||||
bugjson = utils.web.getUrl(bugurl)
|
bugjson = utils.web.getUrl(bugurl)
|
||||||
bug = json.loads(bugjson.decode('utf-8'))
|
bug = json.loads(bugjson.decode('utf-8'))
|
||||||
return GitLab(name, url, desc, 'gitlab')
|
return GitLab(name, url, desc, 'gitlab')
|
||||||
@ -453,13 +475,22 @@ class GitLab(IBugtracker):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def get_bug(self, bugtype, bugid):
|
def get_bug(self, bugtype, bugid):
|
||||||
match = re.match(r'[^\s:]+://[^\s/]+/(?P<project>[^\s/]+/[^\s/]+(/[^\s/]+)*?)/(-/)?(issues|merge_requests)', self.url)
|
match = re.match(r'[^\s:]+://[^\s/]+/(?P<project>[^\s/]+/[^\s/]+(/[^\s/]+)*?)/(-/)?(issues|merge_requests|commits?)', self.url)
|
||||||
url = "%s/%d" % (re.sub(r'(://[^\s/]+)/[^\s/]+(/[^\s/]+)+/(-/)?',
|
url = "%s/%s" % (re.sub(r'(://[^\s/]+)/[^\s/]+(/[^\s/]+)+/(-/)?',
|
||||||
r'\g<1>/api/v4/projects/%s/' % match.group('project').replace('/', '%2F'), self.url), bugid)
|
r'\g<1>/api/v4/projects/%s/' % match.group('project').replace('/', '%2F'), self.url), bugid)
|
||||||
|
# Commits are inconsistent in web and API URLs
|
||||||
|
url = url.replace('/commit/', '/commits/')
|
||||||
if bugtype in ('issue', 'bug'):
|
if bugtype in ('issue', 'bug'):
|
||||||
url = url.replace('/merge_requests/', '/issues/')
|
url = url.replace('/merge_requests/', '/issues/')
|
||||||
|
url = url.replace('/commits/', '/issues/')
|
||||||
elif bugtype in ('merge', 'mr', 'pull', 'pr'):
|
elif bugtype in ('merge', 'mr', 'pull', 'pr'):
|
||||||
url = url.replace('/issues/', '/merge_requests/')
|
url = url.replace('/issues/', '/merge_requests/')
|
||||||
|
url = url.replace('/commits/', '/merge_requests/')
|
||||||
|
elif bugtype == 'commit':
|
||||||
|
url = url.replace('/issues/', '/commits/')
|
||||||
|
url = url.replace('/merge_requests/', '/commits/')
|
||||||
|
# Commits need an extra bit on API URLs
|
||||||
|
url = url.replace('/commits/', '/repository/commits/')
|
||||||
try:
|
try:
|
||||||
bugjson = utils.web.getUrl(url)
|
bugjson = utils.web.getUrl(url)
|
||||||
bug = json.loads(bugjson.decode('utf-8'))
|
bug = json.loads(bugjson.decode('utf-8'))
|
||||||
@ -467,27 +498,40 @@ class GitLab(IBugtracker):
|
|||||||
raise BugtrackerError(self.errget % (self.description, e, url))
|
raise BugtrackerError(self.errget % (self.description, e, url))
|
||||||
try:
|
try:
|
||||||
product = match.group('project')
|
product = match.group('project')
|
||||||
status = bug['state']
|
if '/commits/' not in url:
|
||||||
if bug['assignees']:
|
title = bug['title']
|
||||||
assino = len(bug['assignees'])
|
status = bug['state']
|
||||||
if assino == 1:
|
if bug['assignees']:
|
||||||
assignee = bug['assignees'][0]['name']
|
assino = len(bug['assignees'])
|
||||||
|
if assino == 1:
|
||||||
|
assignee = bug['assignees'][0]['name']
|
||||||
|
else:
|
||||||
|
assignee = '%d people' % assino
|
||||||
else:
|
else:
|
||||||
assignee = '%d people' % assino
|
assignee = ''
|
||||||
else:
|
else:
|
||||||
|
bugid = bug['id'][:7]
|
||||||
|
title = bug['message'].split('\n', 1)[0]
|
||||||
|
status = ''
|
||||||
assignee = ''
|
assignee = ''
|
||||||
return (bugid, product, bug['title'], '', status, assignee, bug['web_url'], [], [])
|
return (bugid, product, title, '', status, assignee, bug['web_url'], [], [])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BugtrackerError(self.errparse % (self.description, e, url))
|
raise BugtrackerError(self.errparse % (self.description, e, url))
|
||||||
|
|
||||||
class Gitea(IBugtracker):
|
class Gitea(IBugtracker):
|
||||||
def get_tracker(self, url, bugid):
|
def get_tracker(self, url, bugid):
|
||||||
try:
|
try:
|
||||||
match = re.match(r'[^\s/]+/[^\s/]+/[^\s/]+/(issues|pulls)', url)
|
match = re.match(r'[^\s/]+/[^\s/]+/[^\s/]+/(issues|pulls|commits?)', url)
|
||||||
desc = match.group(0)
|
desc = match.group(0)
|
||||||
name = desc.lower()
|
|
||||||
url = 'https://%s' % desc
|
url = 'https://%s' % desc
|
||||||
bugurl = '%s/%d' % (re.sub(r'(://[^\s/]+)/', r'\g<1>/api/v1/repos/', url), bugid)
|
# Commits are inconsistent in main and single page URLs
|
||||||
|
desc = re.sub(r'/commit$', r'/commits', desc)
|
||||||
|
name = desc.lower()
|
||||||
|
bugurl = '%s/%s' % (re.sub(r'(://[^\s/]+)/', r'\g<1>/api/v1/repos/', url), bugid)
|
||||||
|
# Commits are inconsistent in web and API URLs
|
||||||
|
bugurl = bugurl.replace('/commit/', '/commits/')
|
||||||
|
# Commits need an extra bit on API URLs
|
||||||
|
bugurl = bugurl.replace('/commits/', '/git/commits/')
|
||||||
bugjson = utils.web.getUrl(bugurl)
|
bugjson = utils.web.getUrl(bugurl)
|
||||||
bug = json.loads(bugjson.decode('utf-8'))
|
bug = json.loads(bugjson.decode('utf-8'))
|
||||||
return Gitea(name, url, desc, 'gitea')
|
return Gitea(name, url, desc, 'gitea')
|
||||||
@ -495,11 +539,20 @@ class Gitea(IBugtracker):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def get_bug(self, bugtype, bugid):
|
def get_bug(self, bugtype, bugid):
|
||||||
url = "%s/%d" % (re.sub(r'(://[^\s/]+)/', r'\g<1>/api/v1/repos/', self.url), bugid)
|
url = "%s/%s" % (re.sub(r'(://[^\s/]+)/', r'\g<1>/api/v1/repos/', self.url), bugid)
|
||||||
|
# Commits are inconsistent in web and API URLs
|
||||||
|
url = url.replace('/commit/', '/commits/')
|
||||||
if bugtype in ('issue', 'bug'):
|
if bugtype in ('issue', 'bug'):
|
||||||
url = url.replace('/pulls/', '/issues/')
|
url = url.replace('/pulls/', '/issues/')
|
||||||
|
url = url.replace('/commits/', '/issues/')
|
||||||
elif bugtype in ('pull', 'pr', 'merge', 'mr'):
|
elif bugtype in ('pull', 'pr', 'merge', 'mr'):
|
||||||
url = url.replace('/issues/', '/pulls/')
|
url = url.replace('/issues/', '/pulls/')
|
||||||
|
url = url.replace('/commits/', '/pulls/')
|
||||||
|
elif bugtype == 'commit':
|
||||||
|
url = url.replace('/issues/', '/commits/')
|
||||||
|
url = url.replace('/pulls/', '/commits/')
|
||||||
|
# Commits need an extra bit on API URLs
|
||||||
|
url = url.replace('/commits/', '/git/commits/')
|
||||||
try:
|
try:
|
||||||
bugjson = utils.web.getUrl(url)
|
bugjson = utils.web.getUrl(url)
|
||||||
bug = json.loads(bugjson.decode('utf-8'))
|
bug = json.loads(bugjson.decode('utf-8'))
|
||||||
@ -507,20 +560,27 @@ class Gitea(IBugtracker):
|
|||||||
raise BugtrackerError(self.errget % (self.description, e, url))
|
raise BugtrackerError(self.errget % (self.description, e, url))
|
||||||
try:
|
try:
|
||||||
product = '/'.join(self.url.split('/')[-3:-1])
|
product = '/'.join(self.url.split('/')[-3:-1])
|
||||||
if 'merged' in bug and bug['merged']:
|
if '/commits/' not in url:
|
||||||
status = 'Merged'
|
title = bug['title']
|
||||||
else:
|
if 'merged' in bug and bug['merged']:
|
||||||
status = bug['state']
|
status = 'Merged'
|
||||||
if bug['assignee']:
|
else:
|
||||||
assignee = bug['assignee']['username']
|
status = bug['state']
|
||||||
|
if bug['assignee']:
|
||||||
|
assignee = bug['assignee']['username']
|
||||||
|
else:
|
||||||
|
assignee = ''
|
||||||
else:
|
else:
|
||||||
|
bugid = bug['sha'][:7]
|
||||||
|
title = bug['commit']['message'].split('\n', 1)[0]
|
||||||
|
status = ''
|
||||||
assignee = ''
|
assignee = ''
|
||||||
# Issues have no 'html_url', but pulls do
|
# Issues have no 'html_url', but pulls and commits do
|
||||||
if 'html_url' in bug:
|
if 'html_url' in bug:
|
||||||
htmlurl = bug['html_url']
|
htmlurl = bug['html_url']
|
||||||
else:
|
else:
|
||||||
htmlurl = url.replace('/api/v1/repos/', '/')
|
htmlurl = url.replace('/api/v1/repos/', '/')
|
||||||
return (bugid, product, bug['title'], '', status, assignee, htmlurl, [], [])
|
return (bugid, product, title, '', status, assignee, htmlurl, [], [])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise BugtrackerError(self.errparse % (self.description, e, url))
|
raise BugtrackerError(self.errparse % (self.description, e, url))
|
||||||
|
|
||||||
@ -540,7 +600,7 @@ class Mantis(IBugtracker):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def get_bug(self, bugtype, bugid):
|
def get_bug(self, bugtype, bugid):
|
||||||
url = "%s/api/rest/issues/%d" % (self.url, bugid)
|
url = "%s/api/rest/issues/%s" % (self.url, bugid)
|
||||||
try:
|
try:
|
||||||
bugjson = utils.web.getUrl(url)
|
bugjson = utils.web.getUrl(url)
|
||||||
bug = json.loads(bugjson.decode('utf-8'))['issues'][0]
|
bug = json.loads(bugjson.decode('utf-8'))['issues'][0]
|
||||||
@ -555,11 +615,11 @@ class Mantis(IBugtracker):
|
|||||||
raise BugtrackerError(self.errparse % (self.description, e, url))
|
raise BugtrackerError(self.errparse % (self.description, e, url))
|
||||||
|
|
||||||
def get_bug_old(self, bugtype, bugid): # Deprecated
|
def get_bug_old(self, bugtype, bugid): # Deprecated
|
||||||
url = "%s/view.php?id=%d" % (self.url, bugid)
|
url = "%s/view.php?id=%s" % (self.url, bugid)
|
||||||
try:
|
try:
|
||||||
raw = self.soap_client.mc_issue_get(username='', password='', issue_id=bugid)
|
raw = self.soap_client.mc_issue_get(username='', password='', issue_id=bugid)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if 'Issue #%d not found' % bugid in str(e):
|
if 'Issue #%s not found' % bugid in str(e):
|
||||||
raise BugNotFoundError
|
raise BugNotFoundError
|
||||||
# Often SOAP is not enabled
|
# Often SOAP is not enabled
|
||||||
if '.' in self.name:
|
if '.' in self.name:
|
||||||
@ -589,7 +649,7 @@ class Trac(IBugtracker):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def get_bug(self, bugtype, bugid): # This is still a little rough, but it works :)
|
def get_bug(self, bugtype, bugid): # This is still a little rough, but it works :)
|
||||||
url = "%s/%d" % (self.url, bugid)
|
url = "%s/%s" % (self.url, bugid)
|
||||||
try:
|
try:
|
||||||
raw = utils.web.getUrl("%s?format=tab" % url).decode('utf-8')
|
raw = utils.web.getUrl("%s?format=tab" % url).decode('utf-8')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
Reference in New Issue
Block a user