diff --git a/Bugtracker/__init__.py b/Bugtracker/__init__.py index c5fcd5e..9f4b02a 100644 --- a/Bugtracker/__init__.py +++ b/Bugtracker/__init__.py @@ -24,7 +24,7 @@ import supybot.world as world from imp import reload -__version__ = "4.3.0" +__version__ = "4.4.0" __author__ = supybot.Author("Krytarik Raido", "krytarik", "krytarik@tuxgarage.com") __contributors__ = { supybot.Author("Dennis Kaarsemaker", "Seveas", "dennis@kaarsemaker.net"): ['Original Author'], diff --git a/Bugtracker/config.py b/Bugtracker/config.py index 62f26dc..d5a158c 100644 --- a/Bugtracker/config.py +++ b/Bugtracker/config.py @@ -167,6 +167,7 @@ default_bugtrackers = { 'launchpad': ('https://launchpad.net', 'Launchpad', 'launchpad', ['lp', 'ubuntu', 'ubottu']), 'debian': ('https://bugs.debian.org', 'Debian', 'debbugs', []), 'irssi': ('https://github.com/irssi/irssi/issues', 'Irssi', 'github', []), + 'cgit': ('https://git.zx2c4.com/cgit/commit', 'CGit', 'cgit', []), 'mantis': ('https://www.mantisbt.org/bugs', 'Mantis', 'mantis', []), 'trac': ('https://trac.edgewall.org/ticket', 'Trac', 'trac', []), 'pidgin': ('https://developer.pidgin.im/ticket', 'Pidgin', 'trac', []) diff --git a/Bugtracker/plugin.py b/Bugtracker/plugin.py index 35d5e61..9d47aff 100644 --- a/Bugtracker/plugin.py +++ b/Bugtracker/plugin.py @@ -112,7 +112,7 @@ class Bugtracker(callbacks.PluginRegexp): """ [] Add a bugtracker to the list of defined bugtrackers. Currently supported types are - Launchpad, Debbugs, Bugzilla, SourceForge, GitHub, GitLab, Gitea, Mantis, and Trac. + Launchpad, Debbugs, Bugzilla, SourceForge, GitHub, GitLab, Gitea, CGit, Mantis, and Trac. will be used to reference the bugtracker in all commands. Unambiguous abbreviations of it will also be accepted. will be used to reference the bugtracker in the @@ -407,7 +407,7 @@ class Bugtracker(callbacks.PluginRegexp): self.urlSnarfer(irc, msg, match, 'bug') def commitUrlSnarfer(self, irc, msg, match): - r"(https?://)?\S+/commits?/(?P[a-f0-9]{7,})" + r"(https?://)?\S+/commits?/([^\s?]*\?([^\s?&]+&)?id=)?(?P[a-f0-9]{7,})" self.urlSnarfer(irc, msg, match, 'commit') def urlSnarfer(self, irc, msg, match, urltype): @@ -491,7 +491,8 @@ class Bugtracker(callbacks.PluginRegexp): for t in list(self.db.keys()): tracker = self.db[t] url = tracker.url[tracker.url.rfind('://')+3:] - if url in snarfurl: + if url in snarfurl and not (url == 'launchpad.net' \ + and snarfurl.startswith('git.launchpad.net')): return tracker # No tracker found, bummer. Let's try and get one @@ -501,6 +502,8 @@ class Bugtracker(callbacks.PluginRegexp): tracker = trackers.SourceForge().get_tracker(snarfurl) elif 'github.com' in snarfurl: tracker = trackers.GitHub().get_tracker(snarfurl) + elif re.match(r'\S+/commit/[^\s?]*\?([^\s?&]+&)?id=', snarfurl): + tracker = trackers.CGit().get_tracker(snarfurl, bugid) 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/]+){2,}/(issues|commits?)', snarfurl): @@ -538,9 +541,9 @@ class Bugtracker(callbacks.PluginRegexp): if duplicate and not self.is_ok(channel, tracker, bugid): return - bugtype = re.match(r'.*/(feature-)?(?Prequest|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 re.match(r'.*/(bugs|feature-requests|patches|todo|issues|pulls?|merge_requests|ticket|commits?)$', tracker.description): + bugtype = re.match(r'\S+/(feature-)?(?Prequest|patch|todo|issue|pull|merge|ticket|commit)(_requests)?(e?s)?/([^\s?]*\?([^\s?&]+&)?id=)?[a-f0-9]+$', url) + if do_tracker and tracker.trackertype not in ('github', 'gitlab', 'gitea', 'cgit'): + if re.match(r'\S+/(bugs|feature-requests|patches|todo|issues|pulls?|merge_requests|ticket|commits?)$', tracker.description): report = '%s %s' % (tracker.description, bugid) else: if bugtype: diff --git a/Bugtracker/trackers.py b/Bugtracker/trackers.py index 3af7e90..d43eb1f 100644 --- a/Bugtracker/trackers.py +++ b/Bugtracker/trackers.py @@ -66,21 +66,23 @@ class CVE: cvedata = utils.web.getUrl(url).decode('utf-8') except Exception as e: raise BugtrackerError('Could not get CVE data: %s (%s)' % (e, url)) - m = cvere.search(cvedata) - if m: - cve = utils.web.htmlToText(m.group('cve'), tagReplace='') + match = cvere.search(cvedata) + if match: + cve = utils.web.htmlToText(match.group('cve'), tagReplace='') if len(cve) > 380: cve = cve[:380] + '...' if do_url: cve += ' <%s>' % url return cve else: - m = cverre.search(cvedata) - if m: - cverr = utils.web.htmlToText(m.group('cverr'), tagReplace='') + match = cverre.search(cvedata) + if match: + cverr = utils.web.htmlToText(match.group('cverr'), tagReplace='') if "Couldn't find" in cverr: raise BugNotFoundError return cverr + else: + raise BugtrackerError('Could not parse CVE data (%s)' % url) # Define all bugtrackers class IBugtracker: @@ -92,6 +94,7 @@ class IBugtracker: self.aliases = set(aliases) self.errget = 'Could not get data from %s: %s (%s)' self.errparse = 'Could not parse data from %s: %s (%s)' + self.errparseno = 'Could not parse data from %s (%s)' def __str__(self): return self.name @@ -105,7 +108,7 @@ class IBugtracker: class Bugzilla(IBugtracker): def get_tracker(self, url): try: - match = re.match(r'(?P(?P[^\s/]+).*)/show_bug\.cgi', url) + match = re.match(r'(?P(?P[^\s/]+)\S*)/show_bug\.cgi', url) desc = match.group('desc') name = desc.lower() url = 'https://%s' % match.group('url') @@ -584,6 +587,38 @@ class Gitea(IBugtracker): except Exception as e: raise BugtrackerError(self.errparse % (self.description, e, url)) +cgitre = re.compile(r"""index : (?P[^\s<]+).*? +commit]* class='sha1'>(?P[a-f0-9]+).*? +
(?P.*?)
""", re.I | re.DOTALL) +class CGit(IBugtracker): + def get_tracker(self, url, bugid): + try: + match = re.match(r'(?P(?P[^\s/]+\S*)/commit)/[^\s?]*\?([^\s?&]+&)?id=', url) + desc = match.group('desc') + name = desc.lower() + url = 'https://%s' % match.group('url') + return CGit(name, url, desc, 'cgit') + except: + pass + + def get_bug(self, bugtype, bugid): + url = "%s/?id=%s" % (self.url, bugid) + try: + bugdata = utils.web.getUrl(url).decode('utf-8') + except Exception as e: + if re.match(r'HTTP Error (404|400)', str(e)): + raise BugNotFoundError + raise BugtrackerError(self.errget % (self.description, e, url)) + match = cgitre.search(bugdata) + if match: + bugid = match.group('hash')[:7] + title = utils.web.htmlToText(match.group('subj')) + title = re.sub(r'\s+', ' ', title) + product = match.group('repo') + return (bugid, product, title, '', '', '', url, [], []) + else: + raise BugtrackerError(self.errparseno % (self.description, url)) + class Mantis(IBugtracker): def __init__(self, *args, **kwargs): IBugtracker.__init__(self, *args, **kwargs) @@ -591,7 +626,7 @@ class Mantis(IBugtracker): def get_tracker(self, url): try: - match = re.match(r'(?P(?P[^\s/]+).*)/view\.php', url) + match = re.match(r'(?P(?P[^\s/]+)\S*)/view\.php', url) desc = match.group('desc') name = desc.lower() url = 'https://%s' % match.group('url') @@ -640,7 +675,7 @@ class Mantis(IBugtracker): class Trac(IBugtracker): def get_tracker(self, url): try: - match = re.match(r'(?P[^\s/]+).*/ticket', url) + match = re.match(r'(?P[^\s/]+)\S*/ticket', url) desc = match.group('desc') name = desc.lower() url = 'https://%s' % match.group(0)